-
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-5573-mobile-ui-Create-InputDate-component (#105)
* Add support for passing visual transformation in `BasicTextField` * Rename `DateOfBirthTransformation` to `DateTransformation` * Move `DATE_MASK` inside `DateTransformation` * Rename `DATE_OF_BIRTH` regex to `DATE_TIME` fixup! a73dafd80fb5810cadea87a3893b652f4338165c * Add time transformation * Make date and time transformation classes public * Add a common interface for date time visual transformations * Add date time transformation * Add input date time component * Rename `ActionIconType` to `DateTimeActionIconType` * Update date time transformation mask * Run code format * Add legend data as param to `InputDateTime` * Display input reset button if the input value is not null or blank * Fix broken test * Run code formatting
- Loading branch information
1 parent
15c2833
commit 671506d
Showing
11 changed files
with
550 additions
and
26 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
81 changes: 81 additions & 0 deletions
81
common/src/commonMain/kotlin/org/hisp/dhis/common/screens/InputDateTimeScreen.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,81 @@ | ||
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.remember | ||
import androidx.compose.runtime.setValue | ||
import org.hisp.dhis.mobile.ui.designsystem.component.ColumnComponentContainer | ||
import org.hisp.dhis.mobile.ui.designsystem.component.DateTimeActionIconType | ||
import org.hisp.dhis.mobile.ui.designsystem.component.InputDateTime | ||
import org.hisp.dhis.mobile.ui.designsystem.component.InputShellState | ||
import org.hisp.dhis.mobile.ui.designsystem.component.internal.DateTimeTransformation | ||
import org.hisp.dhis.mobile.ui.designsystem.component.internal.DateTransformation | ||
import org.hisp.dhis.mobile.ui.designsystem.component.internal.TimeTransformation | ||
|
||
@Composable | ||
fun InputDateTimeScreen() { | ||
ColumnComponentContainer { | ||
var date by remember { mutableStateOf("") } | ||
var time by remember { mutableStateOf("") } | ||
var dateTime by remember { mutableStateOf("") } | ||
|
||
InputDateTime( | ||
title = "Label", | ||
value = date, | ||
visualTransformation = DateTransformation(), | ||
actionIconType = DateTimeActionIconType.DATE, | ||
onActionClicked = { | ||
// no-op | ||
}, | ||
onValueChanged = { date = it }, | ||
) | ||
|
||
InputDateTime( | ||
title = "Label", | ||
value = time, | ||
visualTransformation = TimeTransformation(), | ||
actionIconType = DateTimeActionIconType.TIME, | ||
onActionClicked = { | ||
// no-op | ||
}, | ||
onValueChanged = { time = it }, | ||
) | ||
|
||
InputDateTime( | ||
title = "Label", | ||
value = dateTime, | ||
visualTransformation = DateTimeTransformation(), | ||
actionIconType = DateTimeActionIconType.DATE_TIME, | ||
onActionClicked = { | ||
// no-op | ||
}, | ||
onValueChanged = { dateTime = it }, | ||
) | ||
|
||
InputDateTime( | ||
title = "Label", | ||
value = "", | ||
state = InputShellState.DISABLED, | ||
onActionClicked = { | ||
// no-op | ||
}, | ||
onValueChanged = { | ||
// no-op | ||
}, | ||
) | ||
|
||
InputDateTime( | ||
title = "Label", | ||
value = "", | ||
isRequired = true, | ||
state = InputShellState.ERROR, | ||
onActionClicked = { | ||
// no-op | ||
}, | ||
onValueChanged = { | ||
// no-op | ||
}, | ||
) | ||
} | ||
} |
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
136 changes: 136 additions & 0 deletions
136
...tem/src/commonMain/kotlin/org/hisp/dhis/mobile/ui/designsystem/component/InputDateTime.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,136 @@ | ||
package org.hisp.dhis.mobile.ui.designsystem.component | ||
|
||
import androidx.compose.foundation.focusable | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.text.KeyboardOptions | ||
import androidx.compose.material.icons.Icons | ||
import androidx.compose.material.icons.filled.Event | ||
import androidx.compose.material.icons.filled.Schedule | ||
import androidx.compose.material.icons.outlined.Cancel | ||
import androidx.compose.material3.Icon | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Modifier | ||
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.component.internal.DateTimeVisualTransformation | ||
import org.hisp.dhis.mobile.ui.designsystem.component.internal.DateTransformation | ||
import org.hisp.dhis.mobile.ui.designsystem.component.internal.RegExValidations | ||
import org.hisp.dhis.mobile.ui.designsystem.theme.Spacing | ||
|
||
/** | ||
* Input field to enter date, time or date&time. It will format content based on given visual | ||
* transformation | ||
* | ||
* @param title: Label of the component. | ||
* @param value: Input of the component in the format of DDMMYYYY/HHMM/DDMMYYYYHHMM | ||
* @param actionIconType: Type of action icon to display. [DateTimeActionIconType.DATE_TIME], [DateTimeActionIconType.DATE], [DateTimeActionIconType.TIME] | ||
* @param onActionClicked: Callback to handle the action when the calendar icon is clicked. | ||
* @param state: [InputShellState] | ||
* @param legendData: [LegendData] | ||
* @param supportingText: List of [SupportingTextData] that manages all the messages to be shown. | ||
* @param isRequired: Mark this input as marked | ||
* @param visualTransformation: Pass a visual transformation to format the date input visually. By default uses [DateTransformation] | ||
* @param onValueChanged: Callback to receive changes in the input in the format of DDMMYYYY/HHMM/DDMMYYYYHHMM | ||
*/ | ||
@Composable | ||
fun InputDateTime( | ||
title: String, | ||
value: String?, | ||
actionIconType: DateTimeActionIconType = DateTimeActionIconType.DATE_TIME, | ||
onActionClicked: () -> Unit, | ||
modifier: Modifier = Modifier, | ||
state: InputShellState = InputShellState.UNFOCUSED, | ||
legendData: LegendData? = null, | ||
supportingText: List<SupportingTextData>? = null, | ||
isRequired: Boolean = false, | ||
imeAction: ImeAction = ImeAction.Next, | ||
visualTransformation: DateTimeVisualTransformation = DateTransformation(), | ||
onFocusChanged: ((Boolean) -> Unit) = {}, | ||
onValueChanged: (String) -> Unit, | ||
) { | ||
val allowedCharacters = RegExValidations.DATE_TIME.regex | ||
|
||
InputShell( | ||
modifier = modifier.testTag("INPUT_DATE_TIME"), | ||
title = title, | ||
state = state, | ||
isRequiredField = isRequired, | ||
onFocusChanged = onFocusChanged, | ||
inputField = { | ||
BasicTextField( | ||
modifier = Modifier | ||
.testTag("INPUT_DATE_TIME_TEXT_FIELD") | ||
.fillMaxWidth(), | ||
inputText = value.orEmpty(), | ||
isSingleLine = true, | ||
onInputChanged = { newText -> | ||
if (newText.length > visualTransformation.maskLength) { | ||
return@BasicTextField | ||
} | ||
|
||
if (allowedCharacters.containsMatchIn(newText) || newText.isBlank()) { | ||
onValueChanged.invoke(newText) | ||
} | ||
}, | ||
enabled = state != InputShellState.DISABLED, | ||
state = state, | ||
keyboardOptions = KeyboardOptions(imeAction = imeAction, keyboardType = KeyboardType.Number), | ||
visualTransformation = visualTransformation, | ||
) | ||
}, | ||
primaryButton = { | ||
if (!value.isNullOrBlank() && state != InputShellState.DISABLED) { | ||
IconButton( | ||
modifier = Modifier.testTag("INPUT_DATE_TIME_RESET_BUTTON").padding(Spacing.Spacing0), | ||
icon = { | ||
Icon( | ||
imageVector = Icons.Outlined.Cancel, | ||
contentDescription = "Icon Button", | ||
) | ||
}, | ||
onClick = { | ||
onValueChanged.invoke("") | ||
}, | ||
) | ||
} | ||
}, | ||
secondaryButton = { | ||
val icon = when (actionIconType) { | ||
DateTimeActionIconType.DATE, DateTimeActionIconType.DATE_TIME -> Icons.Filled.Event | ||
DateTimeActionIconType.TIME -> Icons.Filled.Schedule | ||
} | ||
|
||
SquareIconButton( | ||
modifier = Modifier.testTag("INPUT_DATE_TIME_ACTION_BUTTON") | ||
.focusable(), | ||
icon = { | ||
Icon( | ||
imageVector = icon, | ||
contentDescription = null, | ||
) | ||
}, | ||
onClick = onActionClicked, | ||
enabled = state != InputShellState.DISABLED, | ||
) | ||
}, | ||
supportingText = { | ||
supportingText?.forEach { label -> | ||
SupportingText( | ||
label.text, | ||
label.state, | ||
) | ||
} | ||
}, | ||
legend = { | ||
legendData?.let { | ||
Legend(legendData, Modifier.testTag("INPUT_DATE_TIME_LEGEND")) | ||
} | ||
}, | ||
) | ||
} | ||
|
||
enum class DateTimeActionIconType { | ||
DATE, TIME, DATE_TIME | ||
} |
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.