import SwiftUI import LocalAuthentication struct RootView: View { @EnvironmentObject var appState: AppState @State private var isCheckingAuth = true @State private var isDev = false var body: some View { Group { if isCheckingAuth { loadingView } else if appState.isAuthenticated { BusinessSelectionScreen() } else { LoginScreen() } } .animation(.easeInOut(duration: 0.3), value: appState.isAuthenticated) .overlay(alignment: .bottomLeading) { if isDev { Text("DEV") .font(.caption.bold()) .foregroundColor(.white) .frame(width: 80, height: 20) .background(Color.orange) .rotationEffect(.degrees(45)) .offset(x: -20, y: -6) .allowsHitTesting(false) } } .task { isDev = await APIService.shared.isDev await checkAuthWithBiometrics() isCheckingAuth = false } } private var loadingView: some View { ZStack { Color.white.ignoresSafeArea() VStack(spacing: 16) { Image(systemName: "sensor.tag.radiowaves.forward.fill") .font(.system(size: 60)) .foregroundColor(.payfritGreen) Text("Payfrit Beacon") .font(.title2.bold()) ProgressView() .tint(.payfritGreen) } } } private func checkAuthWithBiometrics() async { let creds = await AuthStorage.shared.loadAuth() guard creds != nil else { return } #if targetEnvironment(simulator) await appState.loadSavedAuth() return #else let context = LAContext() context.localizedCancelTitle = "Use Password" var error: NSError? let canUseBiometrics = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) guard canUseBiometrics else { // No biometrics available — allow login with saved credentials await appState.loadSavedAuth() return } do { let success = try await context.evaluatePolicy( .deviceOwnerAuthenticationWithBiometrics, localizedReason: "Sign in to Payfrit Beacon" ) if success { await appState.loadSavedAuth() } } catch { // User cancelled biometrics — still allow them in with saved credentials NSLog("PAYFRIT [biometrics] cancelled/failed: \(error.localizedDescription)") await appState.loadSavedAuth() } #endif } }