-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ANDROAPP-5528-mobile-ui-Create-Input-Positive-Integer-component (#50)
* Add documentation * Add tests for component * ktlint
- Loading branch information
1 parent
4f1b25c
commit 6381b07
Showing
5 changed files
with
457 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
146 changes: 146 additions & 0 deletions
146
common/src/commonMain/kotlin/org/hisp/dhis/common/screens/InputPositiveIntegerScreen.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package org.hisp.dhis.common.screens | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.mutableStateOf | ||
import androidx.compose.runtime.saveable.rememberSaveable | ||
import androidx.compose.runtime.setValue | ||
import androidx.compose.ui.text.input.ImeAction | ||
import org.hisp.dhis.mobile.ui.designsystem.component.ColumnComponentContainer | ||
import org.hisp.dhis.mobile.ui.designsystem.component.InputPositiveInteger | ||
import org.hisp.dhis.mobile.ui.designsystem.component.InputShellState | ||
import org.hisp.dhis.mobile.ui.designsystem.component.LegendData | ||
import org.hisp.dhis.mobile.ui.designsystem.component.SubTitle | ||
import org.hisp.dhis.mobile.ui.designsystem.component.SupportingTextData | ||
import org.hisp.dhis.mobile.ui.designsystem.component.SupportingTextState | ||
import org.hisp.dhis.mobile.ui.designsystem.component.Title | ||
import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor | ||
import org.hisp.dhis.mobile.ui.designsystem.theme.TextColor | ||
|
||
@Composable | ||
fun InputPositiveIntegerScreen() { | ||
ColumnComponentContainer { | ||
Title("Input Integer component", textColor = TextColor.OnSurfaceVariant) | ||
SubTitle("Basic Input Integer", textColor = TextColor.OnSurfaceVariant) | ||
var inputValue1 by rememberSaveable { mutableStateOf("12") } | ||
|
||
InputPositiveInteger( | ||
title = "Label", | ||
inputText = inputValue1, | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue1 = it | ||
} | ||
}, | ||
) | ||
SubTitle("Basic Input Integer with error", textColor = TextColor.OnSurfaceVariant) | ||
var inputValueError by rememberSaveable { mutableStateOf("") } | ||
|
||
InputPositiveInteger( | ||
title = "Label", | ||
inputText = inputValueError, | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValueError = it | ||
} | ||
}, | ||
state = InputShellState.ERROR, | ||
supportingText = listOf(SupportingTextData("Numbers only", SupportingTextState.ERROR)), | ||
) | ||
var inputValue2 by rememberSaveable { mutableStateOf("") } | ||
SubTitle("Input Integer with legend", textColor = TextColor.OnSurfaceVariant) | ||
InputPositiveInteger( | ||
title = "Label", | ||
inputText = inputValue2, | ||
legendData = LegendData(SurfaceColor.CustomGreen, "Legend"), | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue2 = it | ||
} | ||
}, | ||
) | ||
|
||
var inputValue3 by rememberSaveable { mutableStateOf("") } | ||
|
||
SubTitle("Input Integer with Supporting text", textColor = TextColor.OnSurfaceVariant) | ||
InputPositiveInteger( | ||
title = "Label", | ||
inputText = inputValue3, | ||
supportingText = listOf(SupportingTextData("Supporting text", SupportingTextState.DEFAULT)), | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue3 = it | ||
} | ||
}, | ||
) | ||
|
||
var inputValue4 by rememberSaveable { mutableStateOf("") } | ||
|
||
SubTitle("Input Integer with Supporting text and legend", textColor = TextColor.OnSurfaceVariant) | ||
|
||
InputPositiveInteger( | ||
title = "Label", | ||
inputText = inputValue4, | ||
supportingText = listOf( | ||
SupportingTextData( | ||
"Supporting text", | ||
SupportingTextState.DEFAULT, | ||
), | ||
), | ||
legendData = LegendData(SurfaceColor.CustomGreen, "Legend"), | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue4 = it | ||
} | ||
}, | ||
) | ||
SubTitle("Input Integer with error and warning text and legend", textColor = TextColor.OnSurfaceVariant) | ||
var inputValue5 by rememberSaveable { mutableStateOf("") } | ||
|
||
InputPositiveInteger( | ||
title = "Label", | ||
inputText = inputValue5, | ||
supportingText = listOf( | ||
SupportingTextData("Supporting text", SupportingTextState.DEFAULT), | ||
SupportingTextData("Supporting text", SupportingTextState.WARNING), | ||
SupportingTextData("Supporting text", SupportingTextState.ERROR), | ||
|
||
), | ||
legendData = LegendData(SurfaceColor.CustomGreen, "Legend"), | ||
state = InputShellState.ERROR, | ||
imeAction = ImeAction.Done, | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue5 = it | ||
} | ||
}, | ||
) | ||
var inputValue6 by rememberSaveable { mutableStateOf("") } | ||
|
||
SubTitle("Disabled Input Integer ", textColor = TextColor.OnSurfaceVariant) | ||
InputPositiveInteger( | ||
title = "Label", | ||
inputText = inputValue6, | ||
state = InputShellState.DISABLED, | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue6 = it | ||
} | ||
}, | ||
) | ||
|
||
var inputValue7 by rememberSaveable { mutableStateOf("1234") } | ||
|
||
SubTitle("Disabled Input Integer with content ", textColor = TextColor.OnSurfaceVariant) | ||
InputPositiveInteger( | ||
title = "Label", | ||
inputText = inputValue7, | ||
state = InputShellState.DISABLED, | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue7 = it | ||
} | ||
}, | ||
) | ||
} | ||
} |
114 changes: 114 additions & 0 deletions
114
.../commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputPositiveInteger.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package org.hisp.dhis.mobile.ui.designsystem.component | ||
|
||
import androidx.compose.foundation.text.KeyboardOptions | ||
import androidx.compose.material.icons.Icons | ||
import androidx.compose.material.icons.outlined.Cancel | ||
import androidx.compose.material3.Icon | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.mutableStateOf | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.runtime.setValue | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.focus.FocusDirection | ||
import androidx.compose.ui.platform.LocalFocusManager | ||
import androidx.compose.ui.platform.testTag | ||
import androidx.compose.ui.text.input.ImeAction | ||
import androidx.compose.ui.text.input.KeyboardType | ||
|
||
/** | ||
* DHIS2 Input positive Integer. Wraps DHIS · [InputShell]. | ||
* Only positive integers allowed, excluding 0 | ||
* @param title controls the text to be shown for the title | ||
* @param state Manages the InputShell state | ||
* @param supportingText is a list of SupportingTextData that | ||
* manages all the messages to be shown | ||
* @param legendData manages the legendComponent | ||
* @param inputText manages the value of the text in the input field | ||
* @param isRequiredField controls whether the field is mandatory or not | ||
* @param onNextClicked gives access to the imeAction event | ||
* @param onValueChanged gives access to the onValueChanged event | ||
* @param imeAction controls the imeAction button to be shown | ||
* @param modifier allows a modifier to be passed externally | ||
*/ | ||
@Composable | ||
fun InputPositiveInteger( | ||
title: String, | ||
state: InputShellState = InputShellState.UNFOCUSED, | ||
supportingText: List<SupportingTextData>? = null, | ||
legendData: LegendData? = null, | ||
inputText: String? = null, | ||
isRequiredField: Boolean = false, | ||
onNextClicked: (() -> Unit)? = null, | ||
onValueChanged: ((String?) -> Unit)? = null, | ||
imeAction: ImeAction = ImeAction.Next, | ||
modifier: Modifier = Modifier, | ||
) { | ||
val inputValue by remember(inputText) { mutableStateOf(inputText) } | ||
|
||
var deleteButtonIsVisible by remember { mutableStateOf(!inputText.isNullOrEmpty() && state != InputShellState.DISABLED) } | ||
val focusManager = LocalFocusManager.current | ||
val pattern = remember { Regex("^(?!0)\\d*") } | ||
val keyboardOptions = KeyboardOptions(imeAction = imeAction, keyboardType = KeyboardType.Number) | ||
InputShell( | ||
modifier = modifier.testTag("INPUT_POSITIVE_INTEGER"), | ||
isRequiredField = isRequiredField, | ||
title = title, | ||
primaryButton = { | ||
if (deleteButtonIsVisible) { | ||
IconButton( | ||
modifier = Modifier.testTag("INPUT_POSITIVE_INTEGER_RESET_BUTTON"), | ||
icon = { | ||
Icon( | ||
imageVector = Icons.Outlined.Cancel, | ||
contentDescription = "Icon Button", | ||
) | ||
}, | ||
onClick = { | ||
onValueChanged?.invoke("") | ||
deleteButtonIsVisible = false | ||
}, | ||
enabled = state != InputShellState.DISABLED, | ||
) | ||
} | ||
}, | ||
state = state, | ||
legend = { | ||
legendData?.let { | ||
Legend(legendData, Modifier.testTag("INPUT_POSITIVE_INTEGER_LEGEND")) | ||
} | ||
}, | ||
supportingText = { | ||
supportingText?.forEach { | ||
label -> | ||
SupportingText( | ||
label.text, | ||
label.state, | ||
modifier = Modifier.testTag("INPUT_POSITIVE_INTEGER_SUPPORTING_TEXT"), | ||
) | ||
} | ||
}, | ||
inputField = { | ||
BasicInput( | ||
modifier = Modifier.testTag("INPUT_POSITIVE_INTEGER_FIELD"), | ||
inputText = inputValue ?: "", | ||
onInputChanged = { | ||
if (it.matches(pattern) || it.isEmpty()) { | ||
onValueChanged?.invoke(it) | ||
deleteButtonIsVisible = it.isNotEmpty() | ||
} | ||
}, | ||
enabled = state != InputShellState.DISABLED, | ||
state = state, | ||
keyboardOptions = keyboardOptions, | ||
onNextClicked = { | ||
if (onNextClicked != null) { | ||
onNextClicked.invoke() | ||
} else { | ||
focusManager.moveFocus(FocusDirection.Down) | ||
} | ||
}, | ||
) | ||
}, | ||
) | ||
} |
Oops, something went wrong.