import SwiftUI struct PinLockView: View { let onUnlocked: () -> Void @State private var pin = "" @State private var error: String? var body: some View { PinPadView(title: "Enter PIN", pin: $pin, error: $error) { if PinStore.shared.verifyPin(pin) { onUnlocked() } else { error = "Incorrect PIN. Try again." pin = "" } } } } struct PinLockOverlay: View { let onUnlocked: () -> Void @State private var pin = "" @State private var error: String? var body: some View { ZStack { LadillColors.page.ignoresSafeArea() PinPadView(title: "Enter PIN", pin: $pin, error: $error) { if PinStore.shared.verifyPin(pin) { onUnlocked() } else { error = "Incorrect PIN. Try again." pin = "" } } } } } struct PinSetupView: View { let onPinSet: () -> Void @State private var pin = "" @State private var confirm = "" @State private var step = 0 @State private var error: String? var body: some View { PinPadView(title: step == 0 ? "Set a PIN" : "Confirm PIN", pin: step == 0 ? $pin : $confirm, error: $error) { if step == 0 { step = 1 } else if pin == confirm { PinStore.shared.savePin(pin) onPinSet() } else { error = "PINs don't match." confirm = "" step = 0 pin = "" } } } } private struct PinPadView: View { let title: String @Binding var pin: String @Binding var error: String? let onComplete: () -> Void var body: some View { VStack(spacing: 24) { Spacer() Image(systemName: "lock.fill") .font(.system(size: 32)) .foregroundStyle(LadillColors.indigo) Text(title) .font(.ladill(size: 22, weight: .semibold)) .foregroundStyle(LadillColors.ink) HStack(spacing: 12) { ForEach(0..<4, id: \.self) { i in Circle() .fill(i < pin.count ? LadillColors.indigo : LadillColors.border) .frame(width: 14, height: 14) } } if let error { Text(error) .font(.ladill(size: 13)) .foregroundStyle(LadillColors.red) } let keys = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "", "0", "⌫"] LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3), spacing: 16) { ForEach(keys, id: \.self) { key in if key.isEmpty { Color.clear.frame(height: 56) } else { Button { if key == "⌫" { if !pin.isEmpty { pin.removeLast() } } else if pin.count < 4 { pin.append(key) if pin.count == 4 { onComplete() } } } label: { Text(key) .font(.ladill(size: 24, weight: .medium)) .frame(maxWidth: .infinity) .frame(height: 56) .background(LadillColors.surface) .clipShape(Circle()) } .buttonStyle(.plain) } } } .padding(.horizontal, 40) Spacer() } .background(LadillColors.page) } }