1515
1616package com.amplifyframework.ui.authenticator.ui
1717
18+ import android.widget.DatePicker
1819import androidx.compose.foundation.layout.fillMaxWidth
1920import androidx.compose.foundation.text.KeyboardActions
2021import androidx.compose.foundation.text.KeyboardOptions
22+ import androidx.compose.material3.Button
23+ import androidx.compose.material3.DatePicker
24+ import androidx.compose.material3.DatePickerDialog
25+ import androidx.compose.material3.ExperimentalMaterial3Api
26+ import androidx.compose.material3.Icon
27+ import androidx.compose.material3.IconButton
2128import androidx.compose.material3.OutlinedTextField
2229import androidx.compose.material3.Text
30+ import androidx.compose.material3.rememberDatePickerState
2331import androidx.compose.runtime.Composable
32+ import androidx.compose.runtime.getValue
33+ import androidx.compose.runtime.mutableStateOf
34+ import androidx.compose.runtime.remember
35+ import androidx.compose.runtime.setValue
2436import androidx.compose.ui.Modifier
2537import androidx.compose.ui.focus.FocusDirection
2638import androidx.compose.ui.platform.LocalFocusManager
39+ import androidx.compose.ui.res.painterResource
40+ import androidx.compose.ui.res.stringResource
2741import androidx.compose.ui.text.AnnotatedString
2842import androidx.compose.ui.text.input.ImeAction
2943import androidx.compose.ui.text.input.KeyboardType
3044import androidx.compose.ui.text.input.OffsetMapping
3145import androidx.compose.ui.text.input.TransformedText
3246import androidx.compose.ui.text.input.VisualTransformation
47+ import com.amplifyframework.ui.authenticator.R
3348import com.amplifyframework.ui.authenticator.forms.FieldConfig
3449import com.amplifyframework.ui.authenticator.forms.MutableFieldState
3550import com.amplifyframework.ui.authenticator.strings.StringResolver
51+ import java.time.Duration
52+ import java.time.LocalDate
3653
3754private val invalidDateChars = """ [^\d-]+""" .toRegex()
3855
@@ -70,6 +87,7 @@ private object DateVisualTransformation : VisualTransformation {
7087 }
7188}
7289
90+ @OptIn(ExperimentalMaterial3Api ::class )
7391@Composable
7492internal fun DateInputField (
7593 fieldConfig : FieldConfig .Date ,
@@ -81,6 +99,9 @@ internal fun DateInputField(
8199
82100 val label = StringResolver .label(fieldConfig)
83101 val hint = StringResolver .hint(fieldConfig)
102+
103+ var dialogVisible by remember { mutableStateOf(false ) }
104+
84105 OutlinedTextField (
85106 modifier = modifier,
86107 enabled = enabled,
@@ -98,6 +119,14 @@ internal fun DateInputField(
98119 keyboardActions = KeyboardActions (
99120 onNext = { focusManager.moveFocus(FocusDirection .Next ) }
100121 ),
122+ trailingIcon = {
123+ IconButton (onClick = { dialogVisible = true }) {
124+ Icon (
125+ painter = painterResource(R .drawable.ic_authenticator_calendar),
126+ contentDescription = stringResource(R .string.amplify_ui_authenticator_field_a11y_date_picker)
127+ )
128+ }
129+ },
101130 supportingText = {
102131 AuthenticatorFieldError (
103132 modifier = Modifier .fillMaxWidth(),
@@ -106,6 +135,28 @@ internal fun DateInputField(
106135 )
107136 }
108137 )
138+
139+ if (dialogVisible) {
140+ val datePickerState = rememberDatePickerState()
141+ DatePickerDialog (
142+ onDismissRequest = { dialogVisible = false },
143+ confirmButton = {
144+ Button (
145+ onClick = {
146+ datePickerState.selectedDateMillis?.let {
147+ // Convert the UTC milliseconds into an ISO 8601 date string
148+ fieldState.content = LocalDate .ofEpochDay(Duration .ofMillis(it).toDays()).toString()
149+ }
150+ dialogVisible = false
151+ }
152+ ) {
153+ Text (stringResource(R .string.amplify_ui_authenticator_button_submit))
154+ }
155+ }
156+ ) {
157+ DatePicker (state = datePickerState, showModeToggle = false )
158+ }
159+ }
109160}
110161
111162private fun filterDate (value : String ): String {
0 commit comments