diff --git a/pedi-foods/Sources/PediFoods/Resources/alelocard_logo.png b/pedi-foods/Sources/PediFoods/Resources/alelocard_logo.png new file mode 100644 index 0000000..9201194 Binary files /dev/null and b/pedi-foods/Sources/PediFoods/Resources/alelocard_logo.png differ diff --git a/pedi-foods/Sources/PediFoods/Resources/amexcard_logo.png b/pedi-foods/Sources/PediFoods/Resources/amexcard_logo.png new file mode 100644 index 0000000..42edc89 Binary files /dev/null and b/pedi-foods/Sources/PediFoods/Resources/amexcard_logo.png differ diff --git a/pedi-foods/Sources/PediFoods/Resources/hipercard_logo.png b/pedi-foods/Sources/PediFoods/Resources/hipercard_logo.png new file mode 100644 index 0000000..a184c60 Binary files /dev/null and b/pedi-foods/Sources/PediFoods/Resources/hipercard_logo.png differ diff --git a/pedi-foods/Sources/PediFoods/Resources/mastercard_logo.png b/pedi-foods/Sources/PediFoods/Resources/mastercard_logo.png new file mode 100644 index 0000000..fefd01b Binary files /dev/null and b/pedi-foods/Sources/PediFoods/Resources/mastercard_logo.png differ diff --git a/pedi-foods/Sources/PediFoods/Resources/sodexo_logo.png b/pedi-foods/Sources/PediFoods/Resources/sodexo_logo.png new file mode 100644 index 0000000..1aefb69 Binary files /dev/null and b/pedi-foods/Sources/PediFoods/Resources/sodexo_logo.png differ diff --git a/pedi-foods/Sources/PediFoods/Resources/visacard_logo.png b/pedi-foods/Sources/PediFoods/Resources/visacard_logo.png new file mode 100644 index 0000000..279c267 Binary files /dev/null and b/pedi-foods/Sources/PediFoods/Resources/visacard_logo.png differ diff --git a/pedi-foods/Sources/PediFoods/Views/Main/CheckoutView.swift b/pedi-foods/Sources/PediFoods/Views/Main/CheckoutView.swift index 3f03913..5882547 100644 --- a/pedi-foods/Sources/PediFoods/Views/Main/CheckoutView.swift +++ b/pedi-foods/Sources/PediFoods/Views/Main/CheckoutView.swift @@ -760,6 +760,46 @@ struct PaymentCardView: View { @State var latestOrder: PublicOrderResult? = nil @State var hasOpenedTracking = false + private var detectedBrandLogo: String? { + let clean = cardNumber.filter(\.isNumber) + guard !clean.isEmpty else { return nil } + + // Sodexo + if clean.hasPrefix("506766") || clean.hasPrefix("603389") { + return "sodexo_logo" + } + + // Alelo + if clean.hasPrefix("5067") || clean.hasPrefix("5078") || clean.hasPrefix("6278") || clean.hasPrefix("6367") { + return "alelocard_logo" + } + + // Hipercard + if clean.hasPrefix("3841") || clean.hasPrefix("606282") || clean.hasPrefix("637095") || clean.hasPrefix("637568") { + return "hipercard_logo" + } + + // Visa + if clean.hasPrefix("4") { + return "visacard_logo" + } + + // Mastercard + if (51...55).contains(Int(clean.prefix(2)) ?? 0) { + return "mastercard_logo" + } + if let prefix4 = Int(clean.prefix(4)), (2221...2720).contains(prefix4) { + return "mastercard_logo" + } + + // Amex + if clean.hasPrefix("34") || clean.hasPrefix("37") { + return "amexcard_logo" + } + + return nil + } + var body: some View { ScrollView(showsIndicators: false) { VStack(alignment: .leading, spacing: 14) { @@ -786,11 +826,38 @@ struct PaymentCardView: View { .foregroundStyle(AppColors.textPrimary) VStack(spacing: 10) { - labeledField("Número do Cartão", placeholder: "0000 0000 0000 0000", text: $cardNumber) + labeledField("Número do Cartão", placeholder: "0000 0000 0000 0000", text: $cardNumber, brandLogo: detectedBrandLogo) + .keyboardType(.numberPad) + .onChange(of: cardNumber) { _, v in + let d = String(v.filter(\.isNumber).prefix(16)) + let masked = stride(from: 0, to: d.count, by: 4) + .map { i -> String in + let start = d.index(d.startIndex, offsetBy: i) + let end = d.index(start, offsetBy: min(4, d.count - i)) + return String(d[start..) -> some View { + private func labeledField(_ label: String, placeholder: String, text: Binding, brandLogo: String? = nil) -> some View { VStack(alignment: .leading, spacing: 6) { Text(label) .font(AppTypography.caption) .foregroundStyle(AppColors.textMuted) - TextField(placeholder, text: text) - .appNoAutoCap() - .padding(.horizontal, 12) - .frame(height: 46) - .background(AppColors.backgroundLight) - .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous)) + HStack(spacing: 8) { + TextField(placeholder, text: text) + .appNoAutoCap() + if let brandLogo, brandLogo.isEmpty == false { + Image(brandLogo) + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + } + } + .padding(.horizontal, 12) + .frame(height: 46) + .background(AppColors.backgroundLight) + .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous)) } }