|
@@ -40,8 +40,12 @@ import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|
|
import androidx.compose.ui.platform.SoftwareKeyboardController
|
|
|
import androidx.compose.ui.res.colorResource
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
+import androidx.compose.ui.text.AnnotatedString
|
|
|
import androidx.compose.ui.text.input.ImeAction
|
|
|
import androidx.compose.ui.text.input.KeyboardType
|
|
|
+import androidx.compose.ui.text.input.OffsetMapping
|
|
|
+import androidx.compose.ui.text.input.TransformedText
|
|
|
+import androidx.compose.ui.text.input.VisualTransformation
|
|
|
import androidx.compose.ui.text.style.TextAlign
|
|
|
import androidx.compose.ui.unit.dp
|
|
|
import androidx.compose.ui.unit.sp
|
|
@@ -71,29 +75,60 @@ fun AddPaymentCardFormScreen() {
|
|
|
.verticalScroll(rememberScrollState())
|
|
|
) {
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
|
- NameTextFieldAPCFS(keyboardController = keyboardController, focusManager = focusManager, labelText = R.string.title)
|
|
|
+ NameTextFieldAPCFS(
|
|
|
+ keyboardController = keyboardController,
|
|
|
+ focusManager = focusManager,
|
|
|
+ labelText = R.string.title
|
|
|
+ )
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
|
- NameTextFieldAPCFS(keyboardController = keyboardController, focusManager = focusManager, labelText = R.string.name_on_card)
|
|
|
+ NameTextFieldAPCFS(
|
|
|
+ keyboardController = keyboardController,
|
|
|
+ focusManager = focusManager,
|
|
|
+ labelText = R.string.name_on_card
|
|
|
+ )
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
|
- NameTextFieldAPCFS(keyboardController = keyboardController, focusManager = focusManager, labelText = R.string.type)
|
|
|
+ NameTextFieldAPCFS(
|
|
|
+ keyboardController = keyboardController,
|
|
|
+ focusManager = focusManager,
|
|
|
+ labelText = R.string.type
|
|
|
+ )
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
|
- NumberTextFieldAPCFS(keyboardController = keyboardController, focusManager = focusManager, labelText = R.string.number, placeholder = "1234 1234 1234 1234")
|
|
|
+ NumberTextFieldAPCFS(
|
|
|
+ keyboardController = keyboardController,
|
|
|
+ focusManager = focusManager,
|
|
|
+ labelText = R.string.number,
|
|
|
+ placeholder = "1234 1234 1234 1234"
|
|
|
+ )
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
|
- NumberTextFieldAPCFS(keyboardController = keyboardController, focusManager = focusManager, labelText = R.string.security_code, placeholder = "CVV")
|
|
|
+ NumberTextFieldAPCFS(
|
|
|
+ keyboardController = keyboardController,
|
|
|
+ focusManager = focusManager,
|
|
|
+ labelText = R.string.security_code,
|
|
|
+ placeholder = "CVV"
|
|
|
+ )
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
|
- NumberTextFieldAPCFS(keyboardController = keyboardController, focusManager = focusManager, labelText = R.string.start_date, placeholder = "MM/YYYY")
|
|
|
+ NumberDateFieldAPCFS(
|
|
|
+ keyboardController = keyboardController,
|
|
|
+ focusManager = focusManager,
|
|
|
+ labelText = R.string.start_date,
|
|
|
+ placeholder = "MM/YY"
|
|
|
+ )
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
|
- NumberTextFieldAPCFS(keyboardController = keyboardController, focusManager = focusManager, labelText = R.string.expiration_date, placeholder = "MM/YYYY")
|
|
|
+ NumberDateFieldAPCFS(
|
|
|
+ keyboardController = keyboardController,
|
|
|
+ focusManager = focusManager,
|
|
|
+ labelText = R.string.expiration_date,
|
|
|
+ placeholder = "MM/YY"
|
|
|
+ )
|
|
|
Spacer(modifier = Modifier.height(20.dp))
|
|
|
NotesTextFieldAPCFS(keyboardController, focusManager)
|
|
|
// Spacer(modifier = Modifier.height(25.dp))
|
|
|
// SaveButtonAPCFS(buttonText = R.string.save)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
|
|
|
+
|
|
|
@Composable
|
|
|
fun ColumnScope.NameTextFieldAPCFS(
|
|
|
keyboardController: SoftwareKeyboardController?,
|
|
@@ -237,6 +272,114 @@ fun ColumnScope.NumberTextFieldAPCFS(
|
|
|
}
|
|
|
|
|
|
@Composable
|
|
|
+fun ColumnScope.NumberDateFieldAPCFS(
|
|
|
+ keyboardController: SoftwareKeyboardController?,
|
|
|
+ focusManager: FocusManager,
|
|
|
+ labelText: Int,
|
|
|
+ placeholder: String
|
|
|
+) {
|
|
|
+ var text by remember { mutableStateOf("") }
|
|
|
+ val maxLength = 4
|
|
|
+
|
|
|
+ TextField(
|
|
|
+ value = text,
|
|
|
+ onValueChange = { input ->
|
|
|
+ if (input.length <= maxLength) {
|
|
|
+ text = input.filter { it.isDigit() }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ textStyle = MaterialTheme.typography.displayMedium,
|
|
|
+ modifier = Modifier
|
|
|
+ .align(Alignment.Start)
|
|
|
+ .fillMaxWidth()
|
|
|
+ .defaultMinSize(minHeight = 60.dp)
|
|
|
+ .wrapContentHeight()
|
|
|
+ .border(
|
|
|
+ 1.dp,
|
|
|
+ color = colorResource(id = R.color.gray_border_textfield),
|
|
|
+ shape = RoundedCornerShape(16.dp)
|
|
|
+ )
|
|
|
+ .background(color = colorResource(id = R.color.transparent)),
|
|
|
+ shape = RoundedCornerShape(16.dp),
|
|
|
+ placeholder = {
|
|
|
+ Text(
|
|
|
+ text = placeholder,
|
|
|
+ style = MaterialTheme.typography.titleSmall.copy(
|
|
|
+ color = colorResource(id = R.color.gray_text)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ },
|
|
|
+ label = {
|
|
|
+ Text(text = stringResource(id = labelText),
|
|
|
+ style = MaterialTheme.typography.titleSmall.copy(
|
|
|
+ color = colorResource(id = R.color.gray_text)
|
|
|
+ )
|
|
|
+ )
|
|
|
+ },
|
|
|
+ colors = TextFieldDefaults.colors(
|
|
|
+ focusedLabelColor = colorResource(id = R.color.gray_splash),
|
|
|
+ unfocusedContainerColor = colorResource(id = R.color.transparent),
|
|
|
+ focusedContainerColor = colorResource(id = R.color.transparent),
|
|
|
+ focusedIndicatorColor = colorResource(id = R.color.transparent),
|
|
|
+ disabledIndicatorColor = colorResource(id = R.color.transparent),
|
|
|
+ unfocusedIndicatorColor = colorResource(id = R.color.transparent),
|
|
|
+ cursorColor = colorResource(id = R.color.gray_splash),
|
|
|
+ ),
|
|
|
+ keyboardOptions = KeyboardOptions(
|
|
|
+ keyboardType = KeyboardType.Number,
|
|
|
+ imeAction = ImeAction.Next
|
|
|
+ ),
|
|
|
+ keyboardActions = KeyboardActions(
|
|
|
+ onDone = {
|
|
|
+ focusManager.clearFocus()
|
|
|
+ keyboardController?.hide()
|
|
|
+ }
|
|
|
+ ),
|
|
|
+ visualTransformation = DateTransformation()
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+fun validateMMYY(input: String): Boolean {
|
|
|
+ val parts = input.split("/")
|
|
|
+ if (parts.size != 2) return false
|
|
|
+ val month = parts[0].toIntOrNull() ?: return false
|
|
|
+ val year = parts[1].toIntOrNull() ?: return false
|
|
|
+ return month in 1..12 && parts[1].length == 2
|
|
|
+}
|
|
|
+
|
|
|
+class DateTransformation() : VisualTransformation {
|
|
|
+ override fun filter(text: AnnotatedString): TransformedText {
|
|
|
+ return dateFilter(text)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+fun dateFilter(text: AnnotatedString): TransformedText {
|
|
|
+
|
|
|
+ val trimmed = if (text.text.length >= 4) text.text.substring(0..3) else text.text
|
|
|
+ var out = ""
|
|
|
+ for (i in trimmed.indices) {
|
|
|
+ out += trimmed[i]
|
|
|
+ if (i == 1 && trimmed.length > 2) out += "/"
|
|
|
+ }
|
|
|
+
|
|
|
+ val numberOffsetTranslator = object : OffsetMapping {
|
|
|
+ override fun originalToTransformed(offset: Int): Int {
|
|
|
+ if (offset <= 2) return offset
|
|
|
+ if (offset <= 4) return offset +1
|
|
|
+ return 5
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun transformedToOriginal(offset: Int): Int {
|
|
|
+ if (offset <=2) return offset
|
|
|
+ if (offset <=5) return offset -1
|
|
|
+ return 4
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return TransformedText(AnnotatedString(out), numberOffsetTranslator)
|
|
|
+}
|
|
|
+
|
|
|
+@Composable
|
|
|
fun ColumnScope.NotesTextFieldAPCFS(
|
|
|
keyboardController: SoftwareKeyboardController?,
|
|
|
focusManager: FocusManager
|