From 790419b59c6b81a1e1221ba2d3150380b889b7ce Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Wed, 11 Sep 2024 18:08:28 +0530 Subject: [PATCH 1/3] Fix date time format for `InputAge` component --- .../screens/actionInputs/InputAgeScreen.kt | 111 +++--- .../parameter/ParameterSelectorScreen.kt | 17 +- .../ui/designsystem/InputAgeSnapshotTest.kt | 84 ++-- .../ui/designsystem/component/InputAge.kt | 372 +++++++++++++++++- .../designsystem/component/InputDateTime.kt | 2 +- .../component/internal/DateTimeUtils.kt | 62 ++- .../component/state/InputAgeState.kt | 66 ++++ .../ui/designsystem/component/InputAgeTest.kt | 99 +++-- 8 files changed, 645 insertions(+), 168 deletions(-) create mode 100644 designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/state/InputAgeState.kt diff --git a/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/actionInputs/InputAgeScreen.kt b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/actionInputs/InputAgeScreen.kt index 733b5a0ba..6af361b3c 100644 --- a/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/actionInputs/InputAgeScreen.kt +++ b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/actionInputs/InputAgeScreen.kt @@ -11,10 +11,11 @@ import org.hisp.dhis.mobile.ui.designsystem.component.AgeInputType import org.hisp.dhis.mobile.ui.designsystem.component.ColumnComponentContainer import org.hisp.dhis.mobile.ui.designsystem.component.ColumnScreenContainer import org.hisp.dhis.mobile.ui.designsystem.component.InputAge -import org.hisp.dhis.mobile.ui.designsystem.component.InputAgeModel 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.TimeUnitValues +import org.hisp.dhis.mobile.ui.designsystem.component.state.InputAgeData +import org.hisp.dhis.mobile.ui.designsystem.component.state.rememberInputAgeState import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor @Composable @@ -24,100 +25,108 @@ fun InputAgeScreen() { ColumnComponentContainer("Input Age Component - Idle") { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = inputType, - onValueChanged = { newInputType -> - inputType = newInputType - }, ), + onValueChanged = { newInputType -> + inputType = newInputType ?: AgeInputType.None + }, ) } ColumnComponentContainer("Input Age Component - Idle Disabled") { InputAge( - InputAgeModel( - title = "Label", - inputType = AgeInputType.None, - state = InputShellState.DISABLED, - onValueChanged = { newInputType -> - inputType = newInputType - }, + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), + inputState = InputShellState.DISABLED, ), + onValueChanged = { newInputType -> + inputType = newInputType ?: AgeInputType.None + }, ) } ColumnComponentContainer("Input Age Component - Date Of Birth") { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = AgeInputType.DateOfBirth(TextFieldValue("01011985")), - state = InputShellState.DISABLED, - - onValueChanged = { newInputType -> - inputType = newInputType - }, + inputState = InputShellState.DISABLED, ), + onValueChanged = { newInputType -> + inputType = newInputType ?: AgeInputType.None + }, ) } ColumnComponentContainer("Input Age Component - Date Of Birth Required Error") { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + isRequired = true, + ), inputType = AgeInputType.DateOfBirth(TextFieldValue("010")), - state = InputShellState.ERROR, - isRequired = true, - - onValueChanged = { - // no-op - }, + inputState = InputShellState.ERROR, ), + onValueChanged = { + // no-op + }, ) } ColumnComponentContainer("Input Age Component - Age Disabled") { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = AgeInputType.Age(value = TextFieldValue("56"), unit = TimeUnitValues.YEARS), - state = InputShellState.DISABLED, - - onValueChanged = { newInputType -> - inputType = newInputType - }, + inputState = InputShellState.DISABLED, ), + onValueChanged = { newInputType -> + inputType = newInputType ?: AgeInputType.None + }, ) } ColumnComponentContainer("Input Age Component - Age Required Error") { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + isRequired = true, + ), inputType = AgeInputType.Age(value = TextFieldValue("56"), unit = TimeUnitValues.YEARS), - state = InputShellState.ERROR, - isRequired = true, - - onValueChanged = { - // no-op - }, + inputState = InputShellState.ERROR, ), + onValueChanged = { + // no-op + }, ) } ColumnComponentContainer("Input Age Component - Legend") { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + isRequired = true, + ), inputType = AgeInputType.Age(value = TextFieldValue("56"), unit = TimeUnitValues.YEARS), - state = InputShellState.ERROR, - isRequired = true, - - onValueChanged = { - // no-op - }, + inputState = InputShellState.ERROR, legendData = LegendData(SurfaceColor.CustomGreen, "Legend", popUpLegendDescriptionData = regularLegendList), ), + onValueChanged = { + // no-op + }, ) } } diff --git a/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/parameter/ParameterSelectorScreen.kt b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/parameter/ParameterSelectorScreen.kt index 794a3ff28..46b103fab 100644 --- a/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/parameter/ParameterSelectorScreen.kt +++ b/common/src/commonMain/kotlin/org/hisp/dhis/common/screens/parameter/ParameterSelectorScreen.kt @@ -17,7 +17,6 @@ import org.hisp.dhis.mobile.ui.designsystem.component.ColumnScreenContainer import org.hisp.dhis.mobile.ui.designsystem.component.DateTimeActionType import org.hisp.dhis.mobile.ui.designsystem.component.DropdownItem import org.hisp.dhis.mobile.ui.designsystem.component.InputAge -import org.hisp.dhis.mobile.ui.designsystem.component.InputAgeModel import org.hisp.dhis.mobile.ui.designsystem.component.InputBarCode import org.hisp.dhis.mobile.ui.designsystem.component.InputCheckBox import org.hisp.dhis.mobile.ui.designsystem.component.InputDateTime @@ -43,7 +42,9 @@ import org.hisp.dhis.mobile.ui.designsystem.component.parameter.model.ParameterS import org.hisp.dhis.mobile.ui.designsystem.component.parameter.model.ParameterSelectorItemModel.Status.CLOSED import org.hisp.dhis.mobile.ui.designsystem.component.parameter.model.ParameterSelectorItemModel.Status.FOCUSED import org.hisp.dhis.mobile.ui.designsystem.component.parameter.model.ParameterSelectorItemModel.Status.UNFOCUSED +import org.hisp.dhis.mobile.ui.designsystem.component.state.InputAgeData import org.hisp.dhis.mobile.ui.designsystem.component.state.InputDateTimeData +import org.hisp.dhis.mobile.ui.designsystem.component.state.rememberInputAgeState import org.hisp.dhis.mobile.ui.designsystem.component.state.rememberInputDateTimeState import org.hisp.dhis.mobile.ui.designsystem.resource.provideDHIS2Icon import org.hisp.dhis.mobile.ui.designsystem.theme.SurfaceColor @@ -134,14 +135,16 @@ fun ParameterSelectorScreen() { helper = "Optional", inputField = { InputAge( - InputAgeModel( - title = "Age parameter", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Age parameter", + inputStyle = InputStyle.ParameterInputStyle(), + ), inputType = ageInputType, - inputStyle = InputStyle.ParameterInputStyle(), - onValueChanged = { - ageInputType = it - }, ), + onValueChanged = { + ageInputType = it ?: AgeInputType.None + }, ) }, status = when (ageInputType) { diff --git a/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt b/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt index 0b5d7bf56..fe3b002a6 100644 --- a/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt +++ b/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt @@ -4,10 +4,11 @@ import androidx.compose.ui.text.input.TextFieldValue import org.hisp.dhis.mobile.ui.designsystem.component.AgeInputType import org.hisp.dhis.mobile.ui.designsystem.component.ColumnScreenContainer import org.hisp.dhis.mobile.ui.designsystem.component.InputAge -import org.hisp.dhis.mobile.ui.designsystem.component.InputAgeModel import org.hisp.dhis.mobile.ui.designsystem.component.InputShellState import org.hisp.dhis.mobile.ui.designsystem.component.SubTitle import org.hisp.dhis.mobile.ui.designsystem.component.TimeUnitValues +import org.hisp.dhis.mobile.ui.designsystem.component.state.InputAgeData +import org.hisp.dhis.mobile.ui.designsystem.component.state.rememberInputAgeState import org.junit.Rule import org.junit.Test @@ -22,74 +23,81 @@ class InputAgeSnapshotTest { ColumnScreenContainer { SubTitle("Input Age Component - Idle") InputAge( - InputAgeModel( - title = "Label", - inputType = AgeInputType.None, - - onValueChanged = { - }, + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), ), + onValueChanged = { + }, ) SubTitle("Input Age Component - Idle Disabled") InputAge( - InputAgeModel( - title = "Label", - inputType = AgeInputType.None, - state = InputShellState.DISABLED, - onValueChanged = { - }, + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), + inputState = InputShellState.DISABLED, ), + onValueChanged = { + }, ) SubTitle("Input Age Component - Date Of Birth") InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = AgeInputType.DateOfBirth( TextFieldValue("01011985"), ), - state = InputShellState.DISABLED, - onValueChanged = { - }, + inputState = InputShellState.DISABLED, ), + onValueChanged = { + }, ) SubTitle("Input Age Component - Date Of Birth Required Error") InputAge( - InputAgeModel( - title = "Label", - inputType = AgeInputType.DateOfBirth(TextFieldValue("010")), - state = InputShellState.ERROR, - isRequired = true, - onValueChanged = { - // no-op - }, + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), + inputType = AgeInputType.DateOfBirth( + TextFieldValue("010"), + ), + inputState = InputShellState.ERROR, ), + onValueChanged = { + }, ) SubTitle("Input Age Component - Age Disabled") InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = AgeInputType.Age(value = TextFieldValue("56"), unit = TimeUnitValues.YEARS), - state = InputShellState.DISABLED, - onValueChanged = { - }, + inputState = InputShellState.DISABLED, ), + onValueChanged = { + }, ) SubTitle("Input Age Component - Age Required Error") InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = AgeInputType.Age(value = TextFieldValue("56"), unit = TimeUnitValues.YEARS), - state = InputShellState.ERROR, - isRequired = true, - onValueChanged = { - // no-op - }, + inputState = InputShellState.ERROR, ), + onValueChanged = { + }, ) } } diff --git a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAge.kt b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAge.kt index 1784560f3..ff01da68e 100644 --- a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAge.kt +++ b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAge.kt @@ -21,8 +21,10 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.ImeAction @@ -36,8 +38,12 @@ import org.hisp.dhis.mobile.ui.designsystem.component.TimeUnitValues.YEARS import org.hisp.dhis.mobile.ui.designsystem.component.internal.DateTransformation.Companion.DATE_MASK import org.hisp.dhis.mobile.ui.designsystem.component.internal.RegExValidations import org.hisp.dhis.mobile.ui.designsystem.component.internal.dateIsInRange +import org.hisp.dhis.mobile.ui.designsystem.component.internal.formatStoredDateToUI +import org.hisp.dhis.mobile.ui.designsystem.component.internal.formatUIDateToStored +import org.hisp.dhis.mobile.ui.designsystem.component.internal.getDateSupportingText +import org.hisp.dhis.mobile.ui.designsystem.component.internal.getSelectableDates import org.hisp.dhis.mobile.ui.designsystem.component.internal.isValidDate -import org.hisp.dhis.mobile.ui.designsystem.component.internal.parseStringDateToMillis +import org.hisp.dhis.mobile.ui.designsystem.component.state.InputAgeState import org.hisp.dhis.mobile.ui.designsystem.resource.provideStringResource import org.hisp.dhis.mobile.ui.designsystem.theme.DHIS2LightColorScheme import org.hisp.dhis.mobile.ui.designsystem.theme.Outline @@ -53,6 +59,8 @@ import java.util.Calendar * @param uiModel: data class [InputAgeModel] with all parameters for component. * @param modifier: optional modifier. */ +@Suppress("DEPRECATION") +@Deprecated("This component is deprecated and will be removed in the next release. Use InputDateTime instead.") @OptIn(ExperimentalMaterial3Api::class) @Composable fun InputAge( @@ -117,6 +125,7 @@ fun InputAge( previousInputType == None && (uiModel.inputType is DateOfBirth || uiModel.inputType is Age) -> { focusRequester.requestFocus() } + else -> { // no-op } @@ -154,6 +163,7 @@ fun InputAge( enabled = uiModel.state != InputShellState.DISABLED, ) } + is DateOfBirth, is Age -> { BasicTextField( modifier = Modifier @@ -255,7 +265,8 @@ fun InputAge( showDatePicker = false if (uiModel.inputType is DateOfBirth) { datePickerState.selectedDateMillis?.let { - val newInputType: AgeInputType = updateDateOfBirth(uiModel.inputType, TextFieldValue(getDate(it), TextRange(getDate(it).length))) + val newInputType: AgeInputType = + updateDateOfBirth(uiModel.inputType, TextFieldValue(getDate(it), TextRange(getDate(it).length))) uiModel.onValueChanged.invoke(newInputType) } } @@ -268,7 +279,6 @@ fun InputAge( ButtonStyle.TEXT, ColorStyle.DEFAULT, uiModel.cancelText ?: provideStringResource("cancel"), - ) { showDatePicker = false } @@ -296,30 +306,315 @@ fun InputAge( } } -private fun transformInputText(inputType: AgeInputType): String { - return when (inputType) { - is Age -> inputType.value.text - is DateOfBirth -> inputType.value.text - None -> "" - } -} +/** + * DHIS2 Input Age + * Input field to enter age. It will format content based on given visual + * transformation. + * component uses Material 3 [DatePicker] + * input formats supported are mentioned in the age input ui model documentation. + * [DatePicker] Input mode will always follow locale format. + * @param state: an [InputAgeState] with all the parameters for the input + * @param modifier: optional modifier. + */ -private fun getTextFieldValue(inputType: AgeInputType): TextFieldValue { - return when (inputType) { - is Age -> TextFieldValue(transformInputText(inputType), inputType.value.selection) - is DateOfBirth -> TextFieldValue(transformInputText(inputType), inputType.value.selection) - None -> TextFieldValue() +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun InputAge( + state: InputAgeState, + onValueChanged: (AgeInputType?) -> Unit, + onNextClicked: (() -> Unit)? = null, + modifier: Modifier = Modifier, +) { + val uiData = state.uiData + val inputType = state.inputType + val uiValue = remember(getTextFieldValue(inputType)) { formatStoredDateToUI(getTextFieldValue(inputType), DateTimeActionType.DATE) } + val focusManager = LocalFocusManager.current + val focusRequester = remember { FocusRequester() } + + val maxAgeCharLimit = 3 + var showDatePicker by rememberSaveable { mutableStateOf(false) } + + val helperText = remember(inputType) { + if (inputType is Age) { + inputType.unit.value + } else { + null + } } -} + val helperStyle = remember(inputType) { + when (inputType) { + None -> HelperStyle.NONE + is DateOfBirth -> HelperStyle.WITH_DATE_OF_BIRTH_HELPER + is Age -> HelperStyle.WITH_HELPER_AFTER + } + } + val selectableDates = uiData.selectableDates ?: SelectableDates( + MIN_DATE, + SimpleDateFormat(DATE_FORMAT).format(Calendar.getInstance().time), + ) -private fun updateDateOfBirth(inputType: DateOfBirth, newText: TextFieldValue): AgeInputType { - return if (newText.text.length <= DATE_MASK.length) { - inputType.copy(value = newText) + val datePickerState = rememberDatePickerState( + selectableDates = getSelectableDates(selectableDates), + ) + + val calendarButton: (@Composable () -> Unit)? = if (inputType is DateOfBirth) { + @Composable { + SquareIconButton( + modifier = Modifier.testTag("INPUT_AGE_OPEN_CALENDAR_BUTTON"), + icon = { + Icon( + imageVector = Icons.Filled.Event, + contentDescription = null, + ) + }, + onClick = { + focusRequester.requestFocus() + showDatePicker = !showDatePicker + }, + enabled = state.inputState != InputShellState.DISABLED, + ) + } } else { - inputType + null } + + var previousInputType by remember { mutableStateOf(inputType) } + LaunchedEffect(inputType) { + when { + previousInputType == None && (inputType is DateOfBirth || inputType is Age) -> { + focusRequester.requestFocus() + } + + else -> { + // no-op + } + } + + if (previousInputType != inputType) { + previousInputType = inputType + } + } + + val dateOutOfRangeText = "${provideStringResource("date_out_of_range")} (" + + formatStringToDate(selectableDates.initialDate) + " - " + + formatStringToDate(selectableDates.endDate) + ")" + val dateOutOfRangeItem = SupportingTextData( + text = dateOutOfRangeText, + SupportingTextState.ERROR, + ) + val incorrectDateFormatItem = SupportingTextData( + text = provideStringResource("incorrect_date_format"), + SupportingTextState.ERROR, + ) + + val supportingTextList = provideSupportingText( + inputType, + uiValue, + state.supportingText, + dateOutOfRangeItem, + incorrectDateFormatItem, + selectableDates, + ) + + InputShell( + modifier = modifier.testTag("INPUT_AGE").focusRequester(focusRequester), + title = uiData.title, + state = getInputState(supportingTextList, dateOutOfRangeItem, incorrectDateFormatItem, state.inputState), + isRequiredField = uiData.isRequired, + inputField = { + when (inputType) { + None -> { + TextButtonSelector( + modifier = Modifier.testTag("INPUT_AGE_MODE_SELECTOR"), + firstOptionText = uiData.dateOfBirthLabel ?: provideStringResource("date_birth"), + onClickFirstOption = { + onValueChanged.invoke(DateOfBirth.EMPTY) + }, + middleText = uiData.orLabel ?: provideStringResource("or"), + secondOptionText = uiData.ageLabel ?: provideStringResource("age"), + onClickSecondOption = { + onValueChanged.invoke(Age.EMPTY) + }, + enabled = state.inputState != InputShellState.DISABLED, + ) + } + + is DateOfBirth, is Age -> { + BasicTextField( + modifier = Modifier + .testTag("INPUT_AGE_TEXT_FIELD") + .fillMaxWidth(), + inputTextValue = uiValue, + helper = if (helperText != null) provideStringResource(helperText).lowercase() else null, + isSingleLine = true, + helperStyle = helperStyle, + onInputChanged = { newText -> + if ((inputType is Age && newText.text.length > maxAgeCharLimit) || + (inputType is DateOfBirth && newText.text.length > DATE_MASK.length) + ) { + return@BasicTextField + } + manageOnValueChanged(newText, inputType, onValueChanged) + }, + enabled = state.inputState != InputShellState.DISABLED, + state = state.inputState, + keyboardOptions = KeyboardOptions(imeAction = uiData.imeAction, keyboardType = KeyboardType.Number), + onNextClicked = { + if (onNextClicked != null) { + onNextClicked.invoke() + } else { + focusManager.moveFocus(FocusDirection.Down) + } + }, + ) + } + } + }, + primaryButton = { + if (inputType != None && state.inputState != InputShellState.DISABLED) { + IconButton( + modifier = Modifier.testTag("INPUT_AGE_RESET_BUTTON").padding(Spacing.Spacing0), + icon = { + Icon( + imageVector = Icons.Outlined.Cancel, + contentDescription = "Icon Button", + ) + }, + onClick = { + focusRequester.requestFocus() + onValueChanged.invoke(None) + }, + ) + } + }, + secondaryButton = calendarButton, + supportingText = { + supportingTextList.forEach { label -> + SupportingText( + label.text, + label.state, + modifier = Modifier.testTag("INPUT_AGE_SUPPORTING_TEXT"), + ) + } + }, + legend = { + if (inputType is Age) { + TimeUnitSelector( + modifier = Modifier.fillMaxWidth() + .testTag("INPUT_AGE_TIME_UNIT_SELECTOR"), + orientation = Orientation.HORIZONTAL, + optionSelected = YEARS, + enabled = state.inputState != InputShellState.DISABLED, + onClick = { timeUnit -> + onValueChanged.invoke(inputType.copy(unit = timeUnit)) + }, + ) + } + + state.legendData?.let { + Legend(it, Modifier.testTag("INPUT_AGE_LEGEND")) + } + }, + inputStyle = uiData.inputStyle, + ) + + if (showDatePicker) { + MaterialTheme( + colorScheme = DHIS2LightColorScheme.copy( + outlineVariant = Outline.Medium, + ), + ) { + DatePickerDialog( + modifier = Modifier.testTag("DATE_PICKER"), + onDismissRequest = { showDatePicker = false }, + confirmButton = { + Button( + enabled = true, + ButtonStyle.TEXT, + ColorStyle.DEFAULT, + uiData.acceptText ?: provideStringResource("ok"), + ) { + showDatePicker = false + if (inputType is DateOfBirth) { + datePickerState.selectedDateMillis?.let { + val newInputType: AgeInputType = updateDateOfBirth( + inputType, + TextFieldValue(getDate(it), TextRange(getDate(it).length)), + ) + onValueChanged.invoke(newInputType) + } + } + } + }, + colors = datePickerColors(), + dismissButton = { + Button( + enabled = true, + ButtonStyle.TEXT, + ColorStyle.DEFAULT, + uiData.cancelText ?: provideStringResource("cancel"), + ) { + showDatePicker = false + } + }, + properties = DialogProperties( + dismissOnBackPress = true, + dismissOnClickOutside = true, + usePlatformDefaultWidth = true, + ), + ) { + DatePicker( + title = { + Text( + text = uiData.title, + style = MaterialTheme.typography.bodyLarge, + modifier = Modifier.padding(start = Spacing.Spacing24, top = Spacing.Spacing24), + ) + }, + state = datePickerState, + showModeToggle = true, + modifier = Modifier.padding(Spacing.Spacing0), + ) + } + } + } +} + +private fun getInputState( + supportingTextList: List, + dateOutOfRangeItem: SupportingTextData, + incorrectDateFormatItem: SupportingTextData, + currentState: InputShellState, +): InputShellState { + return if (supportingTextList.contains(dateOutOfRangeItem) || supportingTextList.contains(incorrectDateFormatItem)) InputShellState.ERROR else currentState +} + +@Composable +private fun provideSupportingText( + inputType: AgeInputType, + uiValue: TextFieldValue, + supportingText: List?, + dateOutOfRangeItem: SupportingTextData, + incorrectDateFormatItem: SupportingTextData, + selectableDates: SelectableDates, +): List { + val supportingTextList = supportingText?.toMutableList() ?: mutableListOf() + + return (inputType as? DateOfBirth)?.value?.let { + getDateSupportingText( + uiValue = uiValue, + selectableDates = selectableDates, + actionType = DateTimeActionType.DATE, + yearRange = IntRange(MIN_YEAR, MAX_YEAR), + supportingTextList = supportingTextList, + dateOutOfRangeItem = dateOutOfRangeItem, + incorrectDateFormatItem = incorrectDateFormatItem, + ) + } ?: supportingTextList } +@Suppress("DEPRECATION") +@Deprecated("This component is deprecated and will be removed in the next release. Use InputDateTime instead.") @Composable private fun provideSupportingText( uiModel: InputAgeModel, @@ -355,7 +650,44 @@ private fun provideSupportingText( } } ?: uiModel.supportingText +private fun manageOnValueChanged(newText: TextFieldValue, inputType: AgeInputType, onValueChanged: (AgeInputType?) -> Unit) { + val allowedCharacters = RegExValidations.DATE_TIME.regex + if (allowedCharacters.containsMatchIn(newText.text) || newText.text.isBlank()) { + when (inputType) { + is Age -> onValueChanged.invoke((inputType as? Age)?.copy(value = newText)) + is DateOfBirth -> onValueChanged.invoke(DateOfBirth(formatUIDateToStored(newText, DateTimeActionType.DATE))) + None -> onValueChanged.invoke(None) + } + } +} + +private fun transformInputText(inputType: AgeInputType): String { + return when (inputType) { + is Age -> inputType.value.text + is DateOfBirth -> inputType.value.text + None -> "" + } +} + +private fun getTextFieldValue(inputType: AgeInputType): TextFieldValue { + return when (inputType) { + is Age -> TextFieldValue(transformInputText(inputType), inputType.value.selection) + is DateOfBirth -> TextFieldValue(transformInputText(inputType), inputType.value.selection) + None -> TextFieldValue() + } +} + +private fun updateDateOfBirth(inputType: DateOfBirth, newText: TextFieldValue): AgeInputType { + return if (newText.text.length <= DATE_MASK.length) { + inputType.copy(value = newText) + } else { + inputType + } +} + internal const val MIN_DATE = "10111901" +internal const val MIN_YEAR = 1901 +internal val MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) internal const val DATE_FORMAT = "ddMMYYYY" sealed interface AgeInputType { diff --git a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputDateTime.kt b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputDateTime.kt index 35ff1aa58..62aa976e9 100644 --- a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputDateTime.kt +++ b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputDateTime.kt @@ -393,7 +393,7 @@ fun InputDateTime( } } -fun getInputState(supportingTextList: List, dateOutOfRangeItem: SupportingTextData, incorrectDateFormatItem: SupportingTextData, currentState: InputShellState): InputShellState { +private fun getInputState(supportingTextList: List, dateOutOfRangeItem: SupportingTextData, incorrectDateFormatItem: SupportingTextData, currentState: InputShellState): InputShellState { return if (supportingTextList.contains(dateOutOfRangeItem) || supportingTextList.contains(incorrectDateFormatItem)) InputShellState.ERROR else currentState } diff --git a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/internal/DateTimeUtils.kt b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/internal/DateTimeUtils.kt index 6bae3eb58..015542824 100644 --- a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/internal/DateTimeUtils.kt +++ b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/internal/DateTimeUtils.kt @@ -271,7 +271,12 @@ fun getSelectableDates(selectableDates: SelectableDates): androidx.compose.mater @Deprecated("This function is deprecated and will be removed in the next release. Use overloaded fun instead.") @Suppress("DEPRECATION") -fun getSupportingTextList(uiModel: InputDateTimeModel, dateOutOfRangeItem: SupportingTextData, incorrectHourFormatItem: SupportingTextData, incorrectDateFormatItem: SupportingTextData): List { +fun getSupportingTextList( + uiModel: InputDateTimeModel, + dateOutOfRangeItem: SupportingTextData, + incorrectHourFormatItem: SupportingTextData, + incorrectDateFormatItem: SupportingTextData, +): List { val supportingTextList = mutableListOf() uiModel.supportingText?.forEach { item -> @@ -291,6 +296,7 @@ fun getSupportingTextList(uiModel: InputDateTimeModel, dateOutOfRangeItem: Suppo uiModel.supportingText } } + DateTimeActionType.DATE_TIME -> { if (uiModel.inputTextFieldValue?.text!!.length == 12) { dateIsInRange = dateIsInRange( @@ -307,6 +313,7 @@ fun getSupportingTextList(uiModel: InputDateTimeModel, dateOutOfRangeItem: Suppo if (!isValidHourFormat) supportingTextList.add(incorrectHourFormatItem) } } + DateTimeActionType.DATE -> { if (uiModel.inputTextFieldValue?.text!!.length == 8) { dateIsInRange = dateIsInRange(parseStringDateToMillis(uiModel.inputTextFieldValue.text), uiModel.selectableDates, uiModel.format) @@ -328,7 +335,6 @@ fun getSupportingTextList( dateOutOfRangeItem: SupportingTextData, incorrectHourFormatItem: SupportingTextData, incorrectDateFormatItem: SupportingTextData, - ): List { val supportingTextList = state.supportingText?.toMutableList() ?: mutableListOf() @@ -337,22 +343,48 @@ fun getSupportingTextList( DateTimeActionType.TIME -> { getTimeSupportingTextList(uiValue, supportingTextList, incorrectHourFormatItem) } + DateTimeActionType.DATE_TIME -> { - getDateTimeSupportingTextList(uiValue, dateOutOfRangeItem, incorrectDateFormatItem, incorrectHourFormatItem, state, data, supportingTextList) + getDateTimeSupportingTextList( + uiValue, + dateOutOfRangeItem, + incorrectDateFormatItem, + incorrectHourFormatItem, + state, + data, + supportingTextList, + ) } + DateTimeActionType.DATE -> { - getDateSupportingText(uiValue, data, supportingTextList, dateOutOfRangeItem, incorrectDateFormatItem) + getDateSupportingText( + uiValue, + data.selectableDates, + data.actionType, + data.yearRange, + supportingTextList, + dateOutOfRangeItem, + incorrectDateFormatItem, + ) } } } return supportingTextList.toList() } -fun getDateSupportingText(uiValue: TextFieldValue, data: InputDateTimeData, supportingTextList: MutableList, dateOutOfRangeItem: SupportingTextData, incorrectDateFormatItem: SupportingTextData): List { +fun getDateSupportingText( + uiValue: TextFieldValue, + selectableDates: SelectableDates, + actionType: DateTimeActionType, + yearRange: IntRange, + supportingTextList: MutableList, + dateOutOfRangeItem: SupportingTextData, + incorrectDateFormatItem: SupportingTextData, +): List { if (uiValue.text.length == 8) { - val dateIsInRange = dateIsInRange(parseStringDateToMillis(uiValue.text), data.selectableDates) + val dateIsInRange = dateIsInRange(parseStringDateToMillis(uiValue.text), selectableDates) val isValidDateFormat = isValidDate(uiValue.text) - val dateIsInYearRange = yearIsInRange(uiValue.text, getDefaultFormat(data.actionType), data.yearRange) + val dateIsInYearRange = yearIsInRange(uiValue.text, getDefaultFormat(actionType), yearRange) if (!dateIsInRange || !dateIsInYearRange) supportingTextList.add(dateOutOfRangeItem) if (!isValidDateFormat) supportingTextList.add(incorrectDateFormatItem) } @@ -385,7 +417,11 @@ fun getDateTimeSupportingTextList( return supportingTextList } -fun getTimeSupportingTextList(inputTextFieldValue: TextFieldValue?, supportingTextList: MutableList, incorrectHourFormatItem: SupportingTextData): List { +fun getTimeSupportingTextList( + inputTextFieldValue: TextFieldValue?, + supportingTextList: MutableList, + incorrectHourFormatItem: SupportingTextData, +): List { if (inputTextFieldValue?.text!!.length == 4 && !isValidHourFormat(inputTextFieldValue.text)) { supportingTextList.add(incorrectHourFormatItem) } @@ -395,7 +431,10 @@ fun getTimeSupportingTextList(inputTextFieldValue: TextFieldValue?, supportingTe @Composable @OptIn(ExperimentalMaterial3Api::class) internal fun getTimePickerState(state: InputDateTimeState, uiData: InputDateTimeData): TimePickerState { - return if (state.inputTextFieldValue?.text?.isNotEmpty() == true && uiData.actionType == DateTimeActionType.TIME && isValidHourFormat(state.inputTextFieldValue?.text ?: "")) { + return if (state.inputTextFieldValue?.text?.isNotEmpty() == true && uiData.actionType == DateTimeActionType.TIME && isValidHourFormat( + state.inputTextFieldValue?.text ?: "", + ) + ) { rememberTimePickerState( initialHour = state.inputTextFieldValue!!.text.substring(0, 2) .toInt(), @@ -404,7 +443,10 @@ internal fun getTimePickerState(state: InputDateTimeState, uiData: InputDateTime ) } else if (state.inputTextFieldValue?.text?.length == 12 && isValidHourFormat(state.inputTextFieldValue!!.text.substring(8, 12))) { rememberTimePickerState( - initialHour = state.inputTextFieldValue?.text?.substring(state.inputTextFieldValue!!.text.length - 4, state.inputTextFieldValue!!.text.length - 2)!! + initialHour = state.inputTextFieldValue?.text?.substring( + state.inputTextFieldValue!!.text.length - 4, + state.inputTextFieldValue!!.text.length - 2, + )!! .toInt(), state.inputTextFieldValue!!.text.substring(state.inputTextFieldValue!!.text.length - 2, state.inputTextFieldValue!!.text.length).toInt(), is24Hour = uiData.is24hourFormat, diff --git a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/state/InputAgeState.kt b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/state/InputAgeState.kt new file mode 100644 index 000000000..a4bfc7672 --- /dev/null +++ b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/state/InputAgeState.kt @@ -0,0 +1,66 @@ +package org.hisp.dhis.mobile.ui.designsystem.component.state + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.remember +import androidx.compose.ui.text.input.ImeAction +import org.hisp.dhis.mobile.ui.designsystem.component.AgeInputType +import org.hisp.dhis.mobile.ui.designsystem.component.InputShellState +import org.hisp.dhis.mobile.ui.designsystem.component.InputStyle +import org.hisp.dhis.mobile.ui.designsystem.component.LegendData +import org.hisp.dhis.mobile.ui.designsystem.component.SelectableDates +import org.hisp.dhis.mobile.ui.designsystem.component.SupportingTextData + +@Stable +interface InputAgeState { + val uiData: InputAgeData + val inputType: AgeInputType + val inputState: InputShellState + val legendData: LegendData? + val supportingText: List? +} + +@Stable +internal class InputAgeStateImpl( + override val uiData: InputAgeData, + override val inputType: AgeInputType, + override val inputState: InputShellState, + override val legendData: LegendData?, + override val supportingText: List?, +) : InputAgeState + +@Composable +fun rememberInputAgeState( + inputAgeData: InputAgeData, + inputType: AgeInputType = AgeInputType.None, + inputState: InputShellState = InputShellState.UNFOCUSED, + legendData: LegendData? = null, + supportingText: List? = null, +): InputAgeState = remember( + inputType, + inputState, + legendData, + supportingText, +) { + InputAgeStateImpl( + inputAgeData, + inputType, + inputState, + legendData, + supportingText, + ) +} + +data class InputAgeData( + val title: String, + val inputStyle: InputStyle = InputStyle.DataInputStyle(), + val isRequired: Boolean = false, + val imeAction: ImeAction = ImeAction.Next, + val dateOfBirthLabel: String? = null, + val orLabel: String? = null, + val ageLabel: String? = null, + val acceptText: String? = null, + val cancelText: String? = null, + val is24hourFormat: Boolean = false, + val selectableDates: SelectableDates? = null, +) diff --git a/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAgeTest.kt b/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAgeTest.kt index c3dbd2a6f..20a789566 100644 --- a/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAgeTest.kt +++ b/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAgeTest.kt @@ -8,6 +8,8 @@ import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextClearance import androidx.compose.ui.test.performTextInput +import org.hisp.dhis.mobile.ui.designsystem.component.state.InputAgeData +import org.hisp.dhis.mobile.ui.designsystem.component.state.rememberInputAgeState import org.junit.Rule import org.junit.Test import java.text.SimpleDateFormat @@ -22,12 +24,14 @@ class InputAgeTest { fun modeSelectionShouldBeShownWhenComponentIsInitialised() { rule.setContent { InputAge( - InputAgeModel( - title = "Label", - onValueChanged = { - // no-op - }, + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), ), + onValueChanged = { + // no-op + }, ) } @@ -42,13 +46,15 @@ class InputAgeTest { fun dateOfBirthFieldShouldBeShownCorrectly() { rule.setContent { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = AgeInputType.DateOfBirth.EMPTY, - onValueChanged = { - // no-op - }, ), + onValueChanged = { + // no-op + }, ) } @@ -64,13 +70,15 @@ class InputAgeTest { var inputType by mutableStateOf(AgeInputType.None) rule.setContent { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = AgeInputType.DateOfBirth.EMPTY, - onValueChanged = { - inputType = it - }, ), + onValueChanged = { + inputType = it ?: AgeInputType.None + }, ) } @@ -84,13 +92,15 @@ class InputAgeTest { fun ageFieldShouldBeShownCorrectly() { rule.setContent { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = AgeInputType.Age.EMPTY, - onValueChanged = { - // no-op - }, ), + onValueChanged = { + // no-op + }, ) } @@ -106,13 +116,15 @@ class InputAgeTest { var inputType by mutableStateOf(AgeInputType.None) rule.setContent { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = AgeInputType.Age.EMPTY, - onValueChanged = { - inputType = it - }, ), + onValueChanged = { + inputType = it ?: AgeInputType.None + }, ) } @@ -127,13 +139,15 @@ class InputAgeTest { rule.setContent { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = inputType, - onValueChanged = { - inputType = it - }, ), + onValueChanged = { + inputType = it ?: AgeInputType.None + }, ) } @@ -156,14 +170,15 @@ class InputAgeTest { rule.setContent { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = inputType, - onValueChanged = { - inputType = it - }, ), - + onValueChanged = { + inputType = it ?: AgeInputType.None + }, ) } @@ -178,13 +193,15 @@ class InputAgeTest { rule.setContent { InputAge( - InputAgeModel( - title = "Label", + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), inputType = inputType, - onValueChanged = { - inputType = it - }, ), + onValueChanged = { + inputType = it ?: AgeInputType.None + }, ) } From 8ce8aa88f5d49b78747067c71c405d5baee119b1 Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Thu, 12 Sep 2024 12:27:25 +0530 Subject: [PATCH 2/3] Add unit test for negative scenarios --- .../ui/designsystem/InputAgeSnapshotTest.kt | 18 +++++- .../ui/designsystem/component/InputAge.kt | 2 +- .../ui/designsystem/component/InputAgeTest.kt | 60 ++++++++++++++++++ ...AgeSnapshotTest_launchInputAgeSnapshot.png | Bin 130 -> 69894 bytes 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt b/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt index fe3b002a6..98cff1266 100644 --- a/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt +++ b/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt @@ -44,7 +44,7 @@ class InputAgeSnapshotTest { }, ) - SubTitle("Input Age Component - Date Of Birth") + SubTitle("Input Age Component - Invalid Date Of Birth") InputAge( state = rememberInputAgeState( inputAgeData = InputAgeData( @@ -59,6 +59,22 @@ class InputAgeSnapshotTest { }, ) + SubTitle("Input Age Component - Date Of Birth") + InputAge( + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), + inputType = AgeInputType.DateOfBirth( + TextFieldValue("1991-11-27"), + ), + inputState = InputShellState.DISABLED, + ), + onValueChanged = { + }, + ) + + SubTitle("Input Age Component - Date Of Birth Required Error") InputAge( state = rememberInputAgeState( diff --git a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAge.kt b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAge.kt index ff01da68e..b8133c932 100644 --- a/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAge.kt +++ b/designsystem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAge.kt @@ -60,7 +60,7 @@ import java.util.Calendar * @param modifier: optional modifier. */ @Suppress("DEPRECATION") -@Deprecated("This component is deprecated and will be removed in the next release. Use InputDateTime instead.") +@Deprecated("This component is deprecated and will be removed in the next release. Use InputAge instead.") @OptIn(ExperimentalMaterial3Api::class) @Composable fun InputAge( diff --git a/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAgeTest.kt b/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAgeTest.kt index 20a789566..fcbcb815f 100644 --- a/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAgeTest.kt +++ b/designsystem/src/desktopTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputAgeTest.kt @@ -3,11 +3,13 @@ package org.hisp.dhis.mobile.ui.designsystem.component import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue +import androidx.compose.ui.test.assertTextEquals import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextClearance import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.text.input.TextFieldValue import org.hisp.dhis.mobile.ui.designsystem.component.state.InputAgeData import org.hisp.dhis.mobile.ui.designsystem.component.state.rememberInputAgeState import org.junit.Rule @@ -223,4 +225,62 @@ class InputAgeTest { assert(newInputDaysType.value.text == "28") assert(newInputDaysType.unit == TimeUnitValues.DAYS) } + + @Test + fun shouldFormatDateCorrectly() { + rule.setContent { + InputAge( + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), + inputType = AgeInputType.DateOfBirth(TextFieldValue("1991-11-27")), + ), + onValueChanged = { + // no-op + }, + ) + } + + rule.onNodeWithTag("INPUT_AGE_TEXT_FIELD").assertExists().assertTextEquals("27/11/1991") + } + + @Test + fun shouldShowErrorForOutsideRangeDate() { + rule.setContent { + InputAge( + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), + inputType = AgeInputType.DateOfBirth(TextFieldValue("2025-11-27")), + ), + onValueChanged = { + // no-op + }, + ) + } + + rule.onNodeWithTag("INPUT_AGE_TEXT_FIELD").assertExists().assertTextEquals("27/11/2025") + rule.onNodeWithTag("INPUT_AGE_SUPPORTING_TEXT").assertExists() + } + + @Test + fun shouldWorkWithInvalidDate() { + rule.setContent { + InputAge( + state = rememberInputAgeState( + inputAgeData = InputAgeData( + title = "Label", + ), + inputType = AgeInputType.DateOfBirth(TextFieldValue("1004-9999-9999")), + ), + onValueChanged = { + // no-op + }, + ) + } + + rule.onNodeWithTag("INPUT_AGE_TEXT_FIELD").assertExists().assertTextEquals("99/99/9999") + } } diff --git a/designsystem/src/test/snapshots/images/org.hisp.dhis.mobile.ui.designsystem_InputAgeSnapshotTest_launchInputAgeSnapshot.png b/designsystem/src/test/snapshots/images/org.hisp.dhis.mobile.ui.designsystem_InputAgeSnapshotTest_launchInputAgeSnapshot.png index e093a22a53c3bfac9c6f780f2b609c8b6ca8ad3e..4b2f2f983aecf073d38d2dbebee5455b88eb0df8 100644 GIT binary patch literal 69894 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 B;tl`+ literal 130 zcmWN?OA^8$3;@tQr{Dq>2sEU<4WA&)sB}#2!qe;9yo=v5=1ceUJY+ZKKF-^t$@0H{ z@>1s0$ic;2PR&uZ^aLyJl^GBm1xV;2T7->}(2;Wx64}Tl6E@$th8%qjl_**c5VjO4 MWhLXw8p-3Te!12ry#N3J From 1d8b0b2b9ab207401dad3f2c3f8989992e503502 Mon Sep 17 00:00:00 2001 From: Siddharth Agarwal Date: Thu, 12 Sep 2024 14:15:21 +0530 Subject: [PATCH 3/3] Fix lint error --- .../org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt b/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt index 98cff1266..c4b79d1ca 100644 --- a/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt +++ b/designsystem/src/androidUnitTest/kotlin/org/hisp/dhis/mobile/ui/designsystem/InputAgeSnapshotTest.kt @@ -74,7 +74,6 @@ class InputAgeSnapshotTest { }, ) - SubTitle("Input Age Component - Date Of Birth Required Error") InputAge( state = rememberInputAgeState(