-
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-5531-mobile-ui-Create-Input-Percentage-component (#52)
* Component implementation * Add tests for component * Add tests for component, adjust supporting text for padding values
- Loading branch information
1 parent
a8b30e7
commit 9420dc6
Showing
7 changed files
with
455 additions
and
4 deletions.
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/InputPercentageScreen.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.InputPercentage | ||
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 InputPercentageScreen() { | ||
ColumnComponentContainer { | ||
Title("Input Percentage component", textColor = TextColor.OnSurfaceVariant) | ||
SubTitle("Basic Percentage ", textColor = TextColor.OnSurfaceVariant) | ||
var inputValue1 by rememberSaveable { mutableStateOf("12") } | ||
|
||
InputPercentage( | ||
title = "Label", | ||
inputText = inputValue1, | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue1 = it | ||
} | ||
}, | ||
) | ||
SubTitle("Basic Percentage required field", textColor = TextColor.OnSurfaceVariant) | ||
var inputValueRequired by rememberSaveable { mutableStateOf("") } | ||
|
||
InputPercentage( | ||
title = "Label", | ||
inputText = inputValueRequired, | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValueRequired = it | ||
} | ||
}, | ||
state = InputShellState.ERROR, | ||
isRequiredField = true, | ||
) | ||
var inputValue2 by rememberSaveable { mutableStateOf("") } | ||
SubTitle("Input Percentage with legend", textColor = TextColor.OnSurfaceVariant) | ||
InputPercentage( | ||
title = "Label", | ||
inputText = inputValue2, | ||
legendData = LegendData(SurfaceColor.CustomGreen, "Legend"), | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue2 = it | ||
} | ||
}, | ||
) | ||
|
||
var inputValue3 by rememberSaveable { mutableStateOf("") } | ||
|
||
SubTitle("Input Percentage with Supporting text", textColor = TextColor.OnSurfaceVariant) | ||
InputPercentage( | ||
title = "Label", | ||
inputText = inputValue3, | ||
supportingText = listOf(SupportingTextData("Supporting text", SupportingTextState.DEFAULT)), | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue3 = it | ||
} | ||
}, | ||
) | ||
|
||
var inputValue4 by rememberSaveable { mutableStateOf("") } | ||
|
||
SubTitle("Input Percentage with Supporting text and legend", textColor = TextColor.OnSurfaceVariant) | ||
|
||
InputPercentage( | ||
title = "Label", | ||
inputText = inputValue4, | ||
supportingText = listOf( | ||
SupportingTextData( | ||
"Supporting text", | ||
SupportingTextState.DEFAULT, | ||
), | ||
), | ||
legendData = LegendData(SurfaceColor.CustomGreen, "Legend"), | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue4 = it | ||
} | ||
}, | ||
) | ||
SubTitle("Input Percentage with error, warning text and legend", textColor = TextColor.OnSurfaceVariant) | ||
var inputValue5 by rememberSaveable { mutableStateOf("") } | ||
|
||
InputPercentage( | ||
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 Percentage ", textColor = TextColor.OnSurfaceVariant) | ||
InputPercentage( | ||
title = "Label", | ||
inputText = inputValue6, | ||
state = InputShellState.DISABLED, | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue6 = it | ||
} | ||
}, | ||
) | ||
|
||
var inputValue7 by rememberSaveable { mutableStateOf("1234") } | ||
|
||
SubTitle("Disabled Percentage with content ", textColor = TextColor.OnSurfaceVariant) | ||
InputPercentage( | ||
title = "Label", | ||
inputText = inputValue7, | ||
state = InputShellState.DISABLED, | ||
onValueChanged = { | ||
if (it != null) { | ||
inputValue7 = it | ||
} | ||
}, | ||
) | ||
} | ||
} |
122 changes: 122 additions & 0 deletions
122
...m/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputPercentage.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,122 @@ | ||
package org.hisp.dhis.mobile.ui.designsystem.component | ||
|
||
import androidx.compose.foundation.layout.padding | ||
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 | ||
import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing | ||
|
||
/** | ||
* DHIS2 Input percentage. Wraps DHIS · [InputShell]. | ||
* Only integers allowed | ||
* @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 InputPercentage( | ||
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("^([1-9]|[1-9][0-9]|100)\$") } | ||
val keyboardOptions = KeyboardOptions(imeAction = imeAction, keyboardType = KeyboardType.Number) | ||
InputShell( | ||
modifier = modifier.testTag("INPUT_PERCENTAGE"), | ||
isRequiredField = isRequiredField, | ||
title = title, | ||
primaryButton = { | ||
if (deleteButtonIsVisible) { | ||
IconButton( | ||
modifier = Modifier.testTag("INPUT_PERCENTAGE_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_PERCENTAGE_LEGEND")) | ||
} | ||
}, | ||
supportingText = { | ||
supportingText?.forEach { | ||
label -> | ||
SupportingText( | ||
label.text, | ||
label.state, | ||
modifier = Modifier.testTag("INPUT_PERCENTAGE_SUPPORTING_TEXT").padding( | ||
start = Spacing.Spacing16, | ||
top = Spacing.Spacing4, | ||
end = Spacing.Spacing16, | ||
), | ||
) | ||
} | ||
}, | ||
inputField = { | ||
BasicInput( | ||
modifier = Modifier.testTag("INPUT_PERCENTAGE_FIELD"), | ||
helper = "%", | ||
helperStyle = InputStyle.WITH_HELPER_AFTER, | ||
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) | ||
} | ||
}, | ||
) | ||
}, | ||
) | ||
} |
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
Oops, something went wrong.