CardEditFields.kt

3.4 KB · raw

1package com.peachpasswords.ui.vault23import androidx.compose.foundation.clickable4import androidx.compose.foundation.layout.padding5import androidx.compose.foundation.shape.RoundedCornerShape6import androidx.compose.material3.Text7import androidx.compose.runtime.Composable8import androidx.compose.ui.Modifier9import androidx.compose.ui.draw.clip10import androidx.compose.ui.text.input.KeyboardType11import androidx.compose.ui.text.input.PasswordVisualTransformation12import androidx.compose.ui.text.input.VisualTransformation13import androidx.compose.ui.unit.dp14import androidx.compose.ui.unit.sp15import com.peachpasswords.ui.theme.LocalPeachAccent16import com.peachpasswords.ui.theme.peachColors17import com.peachpasswords.ui.theme.PeachType1819/**20 * D2 — EntryEdit CARD field block. Self-contained: drop a single call to21 * [CardEditFields] in place of the login fields when `f.type == "card"`.22 *23 * Mirrors the existing private `Field` underline style in EntryEditScreen.kt24 * (1.dp T3 border, mono 13sp, accent cursor). Includes its own label+box25 * primitive (`CardField`) so it does not depend on that file's private members.26 *27 * Network is detected live from the card number; CVC maxLength + PAN grouping28 * follow the detected network (Amex 15/4, others 16/3).29 */30@Composable31fun CardEditFields(32    cardNickname: String,33    cardNumber: String,34    cardholderName: String,35    expiry: String,36    cvc: String,37    showCvc: Boolean,38    network: String,39    onCardNickname: (String) -> Unit,40    onCardNumber: (String) -> Unit,41    onCardholder: (String) -> Unit,42    onExpiry: (String) -> Unit,43    onCvc: (String) -> Unit,44    onToggleShowCvc: () -> Unit,45) {46    PeachField(47        label = "nickname",48        value = cardNickname,49        onChange = onCardNickname,50        mono = false,51    )5253    // CARD NUMBER — auto-formatted, network label beside the label.54    PeachField(55        label = "card number",56        value = cardNumber,57        onChange = { raw -> onCardNumber(CardFieldUtils.formatPan(raw)) },58        keyboardType = KeyboardType.Number,59        labelTrailing = {60            val net = CardFieldUtils.networkLabel(network)61            if (net.isNotEmpty()) {62                Text(net, color = peachColors.T2, fontFamily = PeachType.Mono, fontSize = 9.sp)63            }64        },65    )6667    // CARDHOLDER — Inter body, not mono.68    PeachField(69        label = "cardholder",70        value = cardholderName,71        onChange = onCardholder,72        mono = false,73    )7475    // EXPIRY — auto "MM/YY".76    PeachField(77        label = "expiry",78        value = expiry,79        onChange = { raw -> onExpiry(CardFieldUtils.formatExpiry(raw)) },80        keyboardType = KeyboardType.Number,81    )8283    // CVC — masked by default, eye toggle, maxLength by network.84    val cvcMax = CardFieldUtils.cvcMaxDigits(network)85    PeachField(86        label = "cvc",87        value = cvc,88        onChange = { raw -> onCvc(raw.filter { it.isDigit() }.take(cvcMax)) },89        keyboardType = KeyboardType.NumberPassword,90        visualTransformation = if (showCvc) VisualTransformation.None else PasswordVisualTransformation(),91        trailing = {92            Text(93                if (showCvc) "hide" else "show",94                color = LocalPeachAccent.current, fontFamily = PeachType.Mono, fontSize = 9.sp,95                modifier = Modifier.clip(RoundedCornerShape(6.dp)).clickable(onClick = onToggleShowCvc).padding(6.dp),96            )97        },98    )99}