From 38fc71718b90c4fd5050aaf32fe0cf2e6669339a Mon Sep 17 00:00:00 2001 From: Daniel Arantes Loverde Date: Thu, 12 Feb 2026 09:44:40 -0300 Subject: [PATCH] login flow --- .../Contents.json | 12 + .../placeholder-product.png | Bin 0 -> 59974 bytes .../PediFoods/Components/StoreCard.swift | 67 ++++-- .../Sources/PediFoods/ContentView.swift | 213 +++++++++++++++--- .../PediFoods/Resources/Localizable.xcstrings | 19 +- .../Resources/placeholder-product.png | Bin 0 -> 59974 bytes .../PediFoods/Services/ApiClient.swift | 62 ++++- .../PediFoods/Services/ApiService.swift | 66 ++++-- .../Services/SessionStateStore.swift | 139 ++++++++++++ .../PediFoods/Views/Auth/OtpView.swift | 40 +++- .../PediFoods/Views/Main/HomeView.swift | 137 +++++++++-- .../PediFoods/Views/Main/ProfileView.swift | 66 +++++- 12 files changed, 710 insertions(+), 111 deletions(-) create mode 100644 pedi-foods/Darwin/Assets.xcassets/placeholder-product.imageset/Contents.json create mode 100644 pedi-foods/Darwin/Assets.xcassets/placeholder-product.imageset/placeholder-product.png create mode 100644 pedi-foods/Sources/PediFoods/Resources/placeholder-product.png create mode 100644 pedi-foods/Sources/PediFoods/Services/SessionStateStore.swift diff --git a/pedi-foods/Darwin/Assets.xcassets/placeholder-product.imageset/Contents.json b/pedi-foods/Darwin/Assets.xcassets/placeholder-product.imageset/Contents.json new file mode 100644 index 0000000..7e07a38 --- /dev/null +++ b/pedi-foods/Darwin/Assets.xcassets/placeholder-product.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "placeholder-product.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/pedi-foods/Darwin/Assets.xcassets/placeholder-product.imageset/placeholder-product.png b/pedi-foods/Darwin/Assets.xcassets/placeholder-product.imageset/placeholder-product.png new file mode 100644 index 0000000000000000000000000000000000000000..889fa6cb9c8f1113c6e85065ac963533a17c3929 GIT binary patch literal 59974 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 ScaCQO0000;Lk7s literal 0 HcmV?d00001 diff --git a/pedi-foods/Sources/PediFoods/Components/StoreCard.swift b/pedi-foods/Sources/PediFoods/Components/StoreCard.swift index 0d64168..d3a6b0d 100644 --- a/pedi-foods/Sources/PediFoods/Components/StoreCard.swift +++ b/pedi-foods/Sources/PediFoods/Components/StoreCard.swift @@ -6,19 +6,7 @@ struct FeaturedStoreCard: View { var body: some View { VStack(alignment: .leading, spacing: 12) { ZStack(alignment: .topLeading) { - RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous) - .fill(AppColors.brandSoft) - .frame(height: 120) - .overlay( - Circle() - .fill(AppColors.surface) - .frame(width: 64, height: 64) - .overlay( - Image(systemName: store.iconName) - .font(.title2) - .foregroundStyle(AppColors.primary) - ) - ) + mediaBlock if let promo = store.promoText { Text(promo) @@ -76,6 +64,58 @@ struct FeaturedStoreCard: View { .background(AppColors.surface) .clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusXL, style: .continuous)) } + + private var mediaBlock: some View { + ZStack { + RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous) + .fill(AppColors.brandSoft) + + mediaImage + } + .frame(height: 120) + .clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)) + } + + @ViewBuilder + private var mediaImage: some View { + if let imageURL = store.imageURL, + let url = URL(string: imageURL) { + AsyncImage(url: url) { phase in + switch phase { + case .success(let image): + image + .resizable() + .scaledToFill() + default: + storeIconPlaceholder + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .clipped() + } else { + storeIconPlaceholder + } + } + + private var storeIconPlaceholder: some View { + ZStack { + Image("placeholder-product") + .resizable() + .scaledToFill() + .opacity(0.7) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .clipped() + + Circle() + .fill(AppColors.surface.opacity(0.92)) + .frame(width: 64, height: 64) + .overlay( + Image(systemName: store.iconName) + .font(.title2) + .foregroundStyle(AppColors.primary) + ) + } + } } struct FeaturedStoreCardModel: Identifiable { @@ -88,6 +128,7 @@ struct FeaturedStoreCardModel: Identifiable { let promoText: String? let isFavorite: Bool let iconName: String + let imageURL: String? } struct SpecialOfferCard: View { diff --git a/pedi-foods/Sources/PediFoods/ContentView.swift b/pedi-foods/Sources/PediFoods/ContentView.swift index 790ef4c..8100c91 100644 --- a/pedi-foods/Sources/PediFoods/ContentView.swift +++ b/pedi-foods/Sources/PediFoods/ContentView.swift @@ -5,6 +5,10 @@ struct ContentView: View { @State var selectedTab: MainTab = .home private let tokenStore: TokenStore = DefaultTokenStore() @State var appState = AppState() + @State var isBootstrappingSession = false + #if os(iOS) + @State private var sessionExpiredObserver: NSObjectProtocol? + #endif #if os(Android) @State var snackbarCenter = SnackbarCenter.shared #else @@ -18,7 +22,11 @@ struct ContentView: View { case .auth: AuthFlowView(root: $root, selectedTab: $selectedTab, tokenStore: tokenStore, appState: $appState) case .main: - MainTabView(selectedTab: $selectedTab, root: $root, tokenStore: tokenStore, appState: $appState) + if isBootstrappingSession { + sessionBootstrapLoadingView + } else { + MainTabView(selectedTab: $selectedTab, root: $root, tokenStore: tokenStore, appState: $appState) + } } } @@ -32,48 +40,187 @@ struct ContentView: View { FiltersModalView() } } + .onChange(of: appState.address.display) { _, _ in + dismissAddressPickerIfAddressExists() + } + .onChange(of: appState.address.selectedId) { _, _ in + dismissAddressPickerIfAddressExists() + } + .onChange(of: appState.address.latitude) { _, _ in + dismissAddressPickerIfAddressExists() + } + .onChange(of: appState.address.longitude) { _, _ in + dismissAddressPickerIfAddressExists() + } + .task(id: root) { + await bootstrapSessionStateIfNeeded() + } + .onAppear { + #if os(iOS) + attachSessionExpiredObserverIfNeeded() + #endif + } + .onDisappear { + #if os(iOS) + detachSessionExpiredObserver() + #endif + } } + + private var sessionBootstrapLoadingView: some View { + VStack(spacing: 12) { + ProgressView() + Text("Carregando sua sessão...") + .font(AppTypography.body) + .foregroundStyle(AppColors.textMuted) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(AppColors.backgroundLight) + } + + @MainActor + private func bootstrapSessionStateIfNeeded() async { + guard root == .main else { return } + guard isBootstrappingSession == false else { return } + + isBootstrappingSession = true + + if let jwt = tokenStore.jwt { + appState.session.jwt = jwt + appState.session.isAuthenticated = true + } + + if let cachedAddress = SessionStateStore.loadAddress() { + appState.address = cachedAddress + dismissAddressPickerIfAddressExists() + } + + // Only refresh profile when there is no local address cache. + // This avoids forcing Profile flow on startup and still recovers + // existing addresses already registered in backend. + if hasConfiguredAddress() == false { + do { + let response = try await ApiService().profile() + if response.error == false, let customer = response.result { + hydrateAppState(with: customer) + } + } catch let error as ApiServiceError { + if case .sessionExpired = error { + forceLogoutToStart() + } + } catch { + // Keep local state when backend refresh fails transiently. + } + } + + isBootstrappingSession = false + } + + @MainActor + private func hydrateAppState(with customer: CustomerProfile) { + appState.profile.id = customer.id + appState.profile.name = customer.name + appState.profile.email = customer.email + appState.profile.phone = customer.phoneNumber ?? "" + SessionStateStore.setActiveUserKey( + SessionStateStore.makeUserKey(profileId: customer.id, email: customer.email) + ) + + let addresses = customer.addressBook ?? [] + guard addresses.isEmpty == false else { + return + } + + let preferredAddress = addresses.first(where: { $0.id == appState.address.selectedId }) ?? addresses.first + if let preferredAddress { + applyAddress(preferredAddress) + SessionStateStore.saveAddress(appState.address) + } + } + + @MainActor + private func applyAddress(_ address: CustomerAddress) { + appState.address.selectedId = address.id + + let cleanLabel = (address.label ?? "") + .trimmingCharacters(in: .whitespacesAndNewlines) + if cleanLabel.isEmpty == false { + appState.address.display = cleanLabel + } + + if let lat = address.latLong?.first, let lng = address.latLong?.dropFirst().first { + appState.address.latitude = lat + appState.address.longitude = lng + } + } + + @MainActor + private func forceLogoutToStart() { + tokenStore.clear() + SessionStateStore.clearActiveUser() + isBootstrappingSession = false + appState = AppState() + selectedTab = .home + root = .auth + } + + private func hasConfiguredAddress() -> Bool { + if appState.address.selectedId != nil { + return true + } + if appState.address.latitude != nil, appState.address.longitude != nil { + return true + } + let normalized = appState.address.display + .trimmingCharacters(in: .whitespacesAndNewlines) + .lowercased() + return normalized.isEmpty == false && normalized != "defina seu endereco" + } + + @MainActor + private func dismissAddressPickerIfAddressExists() { + guard appState.activeModal == .addressPicker else { return } + if hasConfiguredAddress() { + appState.activeModal = nil + } + } + + #if os(iOS) + private func attachSessionExpiredObserverIfNeeded() { + guard sessionExpiredObserver == nil else { return } + sessionExpiredObserver = NotificationCenter.default.addObserver( + forName: .sessionExpired, + object: nil, + queue: .main + ) { _ in + Task { @MainActor in + forceLogoutToStart() + } + } + } + + private func detachSessionExpiredObserver() { + guard let observer = sessionExpiredObserver else { return } + NotificationCenter.default.removeObserver(observer) + sessionExpiredObserver = nil + } + #endif } struct AddressPickerModalView: View { @Binding var appState: AppState @Binding var selectedTab: MainTab - @Environment(\.dismiss) var dismiss var body: some View { NavigationStack { - VStack(spacing: 12) { - if let message = appState.address.onboardingMessage { - Text(message) - .font(AppTypography.body) - .multilineTextAlignment(.center) - .foregroundStyle(AppColors.textPrimary) - .padding(.horizontal, 16) - .padding(.vertical, 12) - .frame(maxWidth: .infinity) - .background(AppColors.brandSoft) - .clipShape(RoundedRectangle(cornerRadius: 14, style: .continuous)) - .padding(.horizontal, 20) - } - - Text("Selecionar endereco") - .font(AppTypography.heading2) - Text("Fluxo de endereco sera implementado na etapa de checkout/perfil.") - .font(AppTypography.body) - .multilineTextAlignment(.center) - .foregroundStyle(AppColors.textMuted) - - Button("Ir para Perfil > Endereços") { - selectedTab = .profile - dismiss() - } - .font(AppTypography.heading3) - .foregroundStyle(AppColors.primary) - .padding(.top, 8) + AddressesView( + message: appState.address.onboardingMessage, + appState: $appState, + selectionMode: true + ) + .onAppear { + appState.address.onboardingMessage = nil } - .padding(24) - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(AppColors.backgroundLight) } } } diff --git a/pedi-foods/Sources/PediFoods/Resources/Localizable.xcstrings b/pedi-foods/Sources/PediFoods/Resources/Localizable.xcstrings index 8b02950..38eba85 100644 --- a/pedi-foods/Sources/PediFoods/Resources/Localizable.xcstrings +++ b/pedi-foods/Sources/PediFoods/Resources/Localizable.xcstrings @@ -156,6 +156,10 @@ } } }, + "Carregando sua sessão..." : { + "comment" : "A loading message displayed while bootstrapping the user's session.", + "isCommentAutoGenerated" : true + }, "Carrinho" : { "comment" : "A label for the cart section of the app.", "isCommentAutoGenerated" : true @@ -314,10 +318,6 @@ "comment" : "A description of the filters feature that will be added to the home screen.", "isCommentAutoGenerated" : true }, - "Fluxo de endereco sera implementado na etapa de checkout/perfil." : { - "comment" : "A message explaining that the address selection feature will be implemented in the checkout and profile screens.", - "isCommentAutoGenerated" : true - }, "Hello [%@](https://skip.tools)!" : { "comment" : "Welcome tab contents", "extractionState" : "stale", @@ -385,10 +385,6 @@ "comment" : "A description below the text field where the user inputs their OTP code.", "isCommentAutoGenerated" : true }, - "Ir para Perfil > Endereços" : { - "comment" : "A button that navigates to the user profile screen when pressed.", - "isCommentAutoGenerated" : true - }, "Já tem uma conta?" : { "comment" : "A question displayed below the \"Cadastrar e Receber Código\" button in the registration view. The text is a hyperlink to the login view.", "isCommentAutoGenerated" : true @@ -513,6 +509,9 @@ "O que vai querer \npedir hoje?" : { "comment" : "A title displayed above the search bar in the home view.", "isCommentAutoGenerated" : true + }, + "O que vai querer pedir hoje?\n " : { + }, "para %@" : { "comment" : "A text label displaying the email address to which the one-time password (OTP) was sent. The text is truncated to fit within one line.", @@ -618,10 +617,6 @@ } } }, - "Selecionar endereco" : { - "comment" : "A title for the address picker modal view.", - "isCommentAutoGenerated" : true - }, "Settings" : { "comment" : "Tab bar item title for the Settings tab", "extractionState" : "stale", diff --git a/pedi-foods/Sources/PediFoods/Resources/placeholder-product.png b/pedi-foods/Sources/PediFoods/Resources/placeholder-product.png new file mode 100644 index 0000000000000000000000000000000000000000..889fa6cb9c8f1113c6e85065ac963533a17c3929 GIT binary patch literal 59974 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 ScaCQO0000;Lk7s literal 0 HcmV?d00001 diff --git a/pedi-foods/Sources/PediFoods/Services/ApiClient.swift b/pedi-foods/Sources/PediFoods/Services/ApiClient.swift index 7a4a1ac..e044f5a 100644 --- a/pedi-foods/Sources/PediFoods/Services/ApiClient.swift +++ b/pedi-foods/Sources/PediFoods/Services/ApiClient.swift @@ -39,6 +39,11 @@ enum NetworkError: Error, LocalizedError { } } +private struct ApiErrorDescriptor { + let code: String? + let message: String? +} + struct ApiRequest: Sendable { let path: String let method: String @@ -166,6 +171,10 @@ private extension ApiClient { let nsError = error as NSError let apiMessage = serverMessage(from: nsError) + let payload = serverPayload(from: nsError) + if isSessionExpiredPayload(code: payload?.code, message: payload?.message ?? apiMessage) { + return .unauthorized(payload?.message ?? apiMessage) + } switch nsError.code { case 401, 403: @@ -228,6 +237,11 @@ private extension ApiClient { throw NetworkError.invalidResponse } + let payload = serverPayload(from: data) + if isSessionExpiredPayload(code: payload?.code, message: payload?.message) { + throw NetworkError.unauthorized(payload?.message) + } + if http.statusCode == 429 { let retryAfter = Int(http.value(forHTTPHeaderField: "Retry-After") ?? "") throw NetworkError.rateLimited(retryAfter) @@ -283,19 +297,44 @@ private extension ApiClient { } func serverMessage(from data: Data) -> String? { + let payload = serverPayload(from: data) + if let message = payload?.message, message.isEmpty == false { + return message + } + if let code = payload?.code, code.isEmpty == false { + return "Erro: \(code)" + } + return String(data: data, encoding: .utf8) + } + + func serverPayload(from data: Data) -> ApiErrorDescriptor? { if let envelope = try? JSONDecoder().decode(ApiEnvelope.self, from: data) { - return envelope.message + return ApiErrorDescriptor(code: envelope.code, message: envelope.message) } if let object = try? JSONSerialization.jsonObject(with: data) as? [String: Any] { - if let message = object["message"] as? String { - return message - } - if let code = object["code"] as? String { - return "Erro: \(code)" + let code = object["code"] as? String + let message = object["message"] as? String + if code != nil || message != nil { + return ApiErrorDescriptor(code: code, message: message) } } - return String(data: data, encoding: .utf8) + + return nil + } + + func isSessionExpiredPayload(code: String?, message: String?) -> Bool { + let normalizedCode = (code ?? "").lowercased() + let normalizedMessage = (message ?? "").lowercased() + + if normalizedCode.contains("auth") || normalizedCode.contains("token") || normalizedCode.contains("unauthorized") { + return true + } + if normalizedMessage.contains("token") && (normalizedMessage.contains("expir") || normalizedMessage.contains("invalid") || normalizedMessage.contains("sess")) { + return true + } + + return false } #if canImport(LCEssentials) && os(iOS) @@ -318,6 +357,15 @@ private extension ApiClient { return nil } + + func serverPayload(from error: NSError) -> ApiErrorDescriptor? { + if let reason = error.userInfo[NSLocalizedFailureReasonErrorKey] as? String, + let data = reason.data(using: .utf8), + let payload = serverPayload(from: data) { + return payload + } + return nil + } #endif func buildURL(path: String, query: [URLQueryItem]) throws -> URL { diff --git a/pedi-foods/Sources/PediFoods/Services/ApiService.swift b/pedi-foods/Sources/PediFoods/Services/ApiService.swift index d0289e1..c5482f9 100644 --- a/pedi-foods/Sources/PediFoods/Services/ApiService.swift +++ b/pedi-foods/Sources/PediFoods/Services/ApiService.swift @@ -32,14 +32,40 @@ final class ApiService { return try await client.send(req) } catch let error as NetworkError { if case .unauthorized(let message) = error { - tokenStore.clear() - NotificationCenter.default.post(name: .sessionExpired, object: message) + expireSession(message) throw ApiServiceError.sessionExpired(message) } throw error } } + private func sendEnvelope(_ req: ApiRequest) async throws -> ApiEnvelope { + let envelope: ApiEnvelope = try await send(req) + if isSessionExpiredEnvelope(envelope) { + expireSession(envelope.message) + throw ApiServiceError.sessionExpired(envelope.message) + } + return envelope + } + + private func isSessionExpiredEnvelope(_ envelope: ApiEnvelope) -> Bool { + guard envelope.error else { return false } + let code = (envelope.code ?? "").lowercased() + let message = (envelope.message ?? "").lowercased() + if code.contains("auth") || code.contains("token") || code.contains("unauthorized") { + return true + } + if message.contains("token") && (message.contains("expir") || message.contains("invalid") || message.contains("sess")) { + return true + } + return false + } + + private func expireSession(_ message: String?) { + tokenStore.clear() + NotificationCenter.default.post(name: .sessionExpired, object: message) + } + // MARK: - Auth func registerCustomer(name: String, email: String, phoneNumber: String, birthDate: String? = nil) async throws -> ApiEnvelope { @@ -53,19 +79,19 @@ final class ApiService { } let body = try JSONEncoder().encode(payload) let req = ApiRequest(path: "/api/customer", method: "POST", module: .customer, requiresAuth: false, body: body) - return try await send(req) + return try await sendEnvelope(req) } func requestOtp(email: String, phoneNumber: String) async throws -> ApiEnvelope { let body = try makeLoginBody(email: email, phoneNumber: phoneNumber, otp: nil) let req = ApiRequest(path: "/api/customer/login", method: "POST", module: .customer, requiresAuth: false, body: body) - return try await send(req) + return try await sendEnvelope(req) } func validateOtp(email: String, phoneNumber: String, otp: String) async throws -> ApiEnvelope { let body = try makeLoginBody(email: email, phoneNumber: phoneNumber, otp: otp) let req = ApiRequest(path: "/api/customer/login", method: "POST", module: .customer, requiresAuth: false, body: body) - let response: ApiEnvelope = try await send(req) + let response: ApiEnvelope = try await sendEnvelope(req) if let token = response.result?.token { tokenStore.jwt = token } @@ -97,7 +123,7 @@ final class ApiService { func profile() async throws -> ApiEnvelope { let req = ApiRequest(path: "/api/customer/profile", method: "GET", module: .customer, requiresAuth: true) - return try await send(req) + return try await sendEnvelope(req) } func addCustomerAddress(_ address: CustomerAddress) async throws -> ApiEnvelope { @@ -112,7 +138,7 @@ final class ApiService { let payload = CustomerProfileUpdatePayload(addressBook: addressBook) let body = try JSONEncoder().encode(payload) let req = ApiRequest(path: "/api/customer/\(customer.id)", method: "POST", module: .customer, requiresAuth: true, body: body) - return try await send(req) + return try await sendEnvelope(req) } func lookupZipCode(_ zipCode: String) async throws -> ApiEnvelope { @@ -128,16 +154,22 @@ final class ApiService { } let req = ApiRequest(path: "/api/public/cep/\(formatted)", method: "GET", module: .none, requiresAuth: true) - return try await send(req) + return try await sendEnvelope(req) } // MARK: - Stores - func listStores(lat: Double, lng: Double, category: String? = nil, search: String? = nil) async throws -> ApiEnvelope<[StoreSummary]> { - var items = [ - URLQueryItem(name: "lat", value: String(lat)), - URLQueryItem(name: "lng", value: String(lng)) - ] + func listPublicCategories() async throws -> ApiEnvelope<[PublicCategory]> { + let req = ApiRequest(path: "/api/public/categories", method: "GET", module: .none, requiresAuth: false) + return try await sendEnvelope(req) + } + + func listStores(lat: Double? = nil, lng: Double? = nil, category: String? = nil, search: String? = nil) async throws -> ApiEnvelope<[StoreSummary]> { + var items: [URLQueryItem] = [] + if let lat, let lng { + items.append(URLQueryItem(name: "lat", value: String(lat))) + items.append(URLQueryItem(name: "lng", value: String(lng))) + } if let category { items.append(URLQueryItem(name: "category", value: category)) } @@ -145,7 +177,7 @@ final class ApiService { items.append(URLQueryItem(name: "search", value: search)) } let req = ApiRequest(path: "/api/app/stores", method: "GET", module: .app, requiresAuth: true, queryItems: items) - return try await send(req) + return try await sendEnvelope(req) } } @@ -222,6 +254,12 @@ struct StoreSummary: Decodable { let statusLabel: String? } +struct PublicCategory: Decodable { + let id: String + let name: String + let icon: String? +} + struct CustomerProfileUpdatePayload: Encodable { let addressBook: [CustomerAddressPayload] diff --git a/pedi-foods/Sources/PediFoods/Services/SessionStateStore.swift b/pedi-foods/Sources/PediFoods/Services/SessionStateStore.swift new file mode 100644 index 0000000..8dcf9e1 --- /dev/null +++ b/pedi-foods/Sources/PediFoods/Services/SessionStateStore.swift @@ -0,0 +1,139 @@ +import Foundation + +private struct PersistedAddressState: Codable { + let selectedId: String? + let display: String + let latitude: Double? + let longitude: Double? +} + +enum SessionStateStore { + private static let legacyAddressKey = "session.address.state.v1" + private static let addressKeyPrefix = "session.address.state.v2." + private static let activeUserKey = "session.active.user.v1" + + static func makeUserKey(profileId: String?, email: String?) -> String? { + let id = (profileId ?? "") + .trimmingCharacters(in: .whitespacesAndNewlines) + .lowercased() + if id.isEmpty == false { + return "id:\(id)" + } + + let mail = (email ?? "") + .trimmingCharacters(in: .whitespacesAndNewlines) + .lowercased() + if mail.isEmpty == false { + return "email:\(mail)" + } + + return nil + } + + static func setActiveUserKey(_ userKey: String?) { + let trimmed = (userKey ?? "").trimmingCharacters(in: .whitespacesAndNewlines) + if trimmed.isEmpty { + UserDefaults.standard.removeObject(forKey: activeUserKey) + } else { + UserDefaults.standard.set(trimmed, forKey: activeUserKey) + } + } + + static func loadActiveUserKey() -> String? { + let value = UserDefaults.standard.string(forKey: activeUserKey)? + .trimmingCharacters(in: .whitespacesAndNewlines) + if let value, value.isEmpty == false { + return value + } + return nil + } + + private static func addressStorageKey(for userKey: String?) -> String { + let key = (userKey ?? loadActiveUserKey() ?? "anonymous") + .trimmingCharacters(in: .whitespacesAndNewlines) + let safe = key.replacingOccurrences(of: " ", with: "_") + return addressKeyPrefix + safe + } + + static func loadAddress() -> AddressState? { + let defaults = UserDefaults.standard + let activeKey = loadActiveUserKey() + let scopedKey = addressStorageKey(for: activeKey) + + if let data = defaults.data(forKey: scopedKey), + let decoded = try? JSONDecoder().decode(PersistedAddressState.self, from: data) { + return AddressState( + selectedId: decoded.selectedId, + display: decoded.display.isEmpty ? "Defina seu endereco" : decoded.display, + latitude: decoded.latitude, + longitude: decoded.longitude, + onboardingMessage: nil + ) + } + + // Backward-compatible fallback for data persisted before user scoping. + let anonymousKey = addressStorageKey(for: "anonymous") + if let data = defaults.data(forKey: anonymousKey), + let decoded = try? JSONDecoder().decode(PersistedAddressState.self, from: data) { + let recovered = AddressState( + selectedId: decoded.selectedId, + display: decoded.display.isEmpty ? "Defina seu endereco" : decoded.display, + latitude: decoded.latitude, + longitude: decoded.longitude, + onboardingMessage: nil + ) + + // Migrate anonymous cache into the current active user namespace. + if let activeKey, activeKey.isEmpty == false { + let payload = PersistedAddressState( + selectedId: recovered.selectedId, + display: recovered.display, + latitude: recovered.latitude, + longitude: recovered.longitude + ) + if let migratedData = try? JSONEncoder().encode(payload) { + defaults.set(migratedData, forKey: scopedKey) + } + } + + return recovered + } + + guard let data = defaults.data(forKey: legacyAddressKey), + let decoded = try? JSONDecoder().decode(PersistedAddressState.self, from: data) else { + return nil + } + + let migrated = AddressState( + selectedId: decoded.selectedId, + display: decoded.display.isEmpty ? "Defina seu endereco" : decoded.display, + latitude: decoded.latitude, + longitude: decoded.longitude, + onboardingMessage: nil + ) + saveAddress(migrated) + defaults.removeObject(forKey: legacyAddressKey) + return migrated + } + + static func saveAddress(_ state: AddressState) { + let payload = PersistedAddressState( + selectedId: state.selectedId, + display: state.display, + latitude: state.latitude, + longitude: state.longitude + ) + guard let data = try? JSONEncoder().encode(payload) else { return } + UserDefaults.standard.set(data, forKey: addressStorageKey(for: nil)) + } + + static func clearAddress() { + let defaults = UserDefaults.standard + defaults.removeObject(forKey: addressStorageKey(for: nil)) + defaults.removeObject(forKey: legacyAddressKey) + } + + static func clearActiveUser() { + UserDefaults.standard.removeObject(forKey: activeUserKey) + } +} diff --git a/pedi-foods/Sources/PediFoods/Views/Auth/OtpView.swift b/pedi-foods/Sources/PediFoods/Views/Auth/OtpView.swift index 488ac3d..896a78b 100644 --- a/pedi-foods/Sources/PediFoods/Views/Auth/OtpView.swift +++ b/pedi-foods/Sources/PediFoods/Views/Auth/OtpView.swift @@ -187,7 +187,7 @@ struct OtpView: View { SnackbarCenter.shared.show(title: "Login realizado com sucesso.", style: .success, icon: "checkmark.seal.fill", duration: 2.5) appState.session.isAuthenticated = true appState.session.jwt = response.result?.token - appState.profile.email = email + hydrateUserState(from: response.result?.customer) routeAfterLogin() } } catch { @@ -221,6 +221,44 @@ struct OtpView: View { root = .main } + private func hydrateUserState(from customer: CustomerProfile?) { + if let customer { + appState.profile.id = customer.id + appState.profile.name = customer.name + appState.profile.email = customer.email + appState.profile.phone = customer.phoneNumber ?? "" + SessionStateStore.setActiveUserKey( + SessionStateStore.makeUserKey(profileId: customer.id, email: customer.email) + ) + + if let preferred = customer.addressBook?.first { + appState.address.selectedId = preferred.id + let label = (preferred.label ?? "").trimmingCharacters(in: .whitespacesAndNewlines) + appState.address.display = label.isEmpty ? "Defina seu endereco" : label + if let lat = preferred.latLong?.first, let lng = preferred.latLong?.dropFirst().first { + appState.address.latitude = lat + appState.address.longitude = lng + } + SessionStateStore.saveAddress(appState.address) + } else if let cached = SessionStateStore.loadAddress() { + appState.address = cached + } else { + appState.address = AddressState() + } + return + } + + appState.profile.email = email + SessionStateStore.setActiveUserKey( + SessionStateStore.makeUserKey(profileId: nil, email: email) + ) + if let cached = SessionStateStore.loadAddress() { + appState.address = cached + } else { + appState.address = AddressState() + } + } + private func hasConfiguredAddress() -> Bool { if appState.address.selectedId != nil { return true diff --git a/pedi-foods/Sources/PediFoods/Views/Main/HomeView.swift b/pedi-foods/Sources/PediFoods/Views/Main/HomeView.swift index 425505a..481dc0a 100644 --- a/pedi-foods/Sources/PediFoods/Views/Main/HomeView.swift +++ b/pedi-foods/Sources/PediFoods/Views/Main/HomeView.swift @@ -1,6 +1,7 @@ import Foundation import SwiftUI #if os(iOS) +import LCEssentials import UIKit #endif @@ -9,7 +10,7 @@ struct HomeView: View { @State var searchText = "" @State var selectedCategory = "all" @State var categories: [CategoryModel] = [ - .init(id: "all", title: "Todas", systemIcon: "line.3.horizontal.decrease.circle") + .init(id: "all", title: "Todas", systemIcon: "line.3.horizontal.decrease.circle", emojiIcon: nil) ] @State var scrollOffset: CGFloat = 0 @State var collapseBaseOffset: CGFloat = 0 @@ -120,7 +121,8 @@ struct HomeView: View { Task { await bootstrapStoresFlow( forceLocationRefresh: true, - category: selectedCategory == "all" ? nil : selectedCategory + category: selectedCategory == "all" ? nil : selectedCategory, + refreshCategories: true ) } } @@ -166,13 +168,15 @@ struct HomeView: View { .foregroundStyle(AppColors.brandDark) ) - VStack(alignment: .leading, spacing: 4) { + VStack(alignment: .center, spacing: 4) { Text("DELIVERY LOCATION") .font(AppTypography.overline) .tracking(AppTypography.captionLetterSpacing) .foregroundStyle(AppColors.brandSoft) + .multilineTextAlignment(.center) Button { + appState.address.onboardingMessage = nil appState.activeModal = .addressPicker } label: { HStack(spacing: 6) { @@ -186,8 +190,7 @@ struct HomeView: View { } .buttonStyle(.plain) } - - Spacer() + .frame(maxWidth: .infinity, alignment: .center) Circle() .fill(Color.white.opacity(0.18)) @@ -199,13 +202,21 @@ struct HomeView: View { } .opacity(topRowOpacity) .offset(y: collapseProgress * -12) - - Text("O que vai querer \npedir hoje?") - .font(AppTypography.heading2) - .foregroundStyle(AppColors.textInverse) - .opacity(titleOpacity) - .offset(y: collapseProgress * -20) - + + if UIDevice().modelName.lowercased().contains("se") || UIDevice().modelName.lowercased().contains("16e") { + Text("O que vai querer \npedir hoje?") + .font(AppTypography.heading2) + .foregroundStyle(AppColors.textInverse) + .opacity(titleOpacity) + .offset(y: collapseProgress * -20) + } else { + Text("O que vai querer pedir hoje?\n ") + .font(AppTypography.heading2) + .foregroundStyle(AppColors.textInverse) + .opacity(titleOpacity) + .offset(y: collapseProgress * -20) + } + SearchBar(placeholder: "Search menu, restaurant or craving", text: $searchText) { appState.activeModal = .filters } @@ -240,6 +251,7 @@ struct HomeView: View { CategoryChip( title: category.title, systemIcon: category.systemIcon, + emojiIcon: category.emojiIcon, isActive: category.id == selectedCategory ) .onTapGesture { @@ -293,10 +305,27 @@ struct HomeView: View { category: store.category ?? "Loja", promoText: nil, isFavorite: appState.favorites.storeIds.contains(store.id), - iconName: "storefront" + iconName: "storefront", + imageURL: resolveStoreImageURL(logo: store.logo, cover: store.cover) ) } + private func resolveStoreImageURL(logo: String?, cover: String?) -> String? { + let preferred = [logo, cover] + .compactMap { $0?.trimmingCharacters(in: .whitespacesAndNewlines) } + .first { $0.isEmpty == false } + + guard let raw = preferred else { return nil } + + if raw.lowercased().hasPrefix("http://") || raw.lowercased().hasPrefix("https://") { + return raw + } + + let base = ApiConfig.baseURL.absoluteString.trimmingCharacters(in: CharacterSet(charactersIn: "/")) + let path = raw.hasPrefix("/") ? raw : "/\(raw)" + return "\(base)\(path)" + } + private func formatDistance(_ distance: Double?) -> String { guard let distance else { return "Distância indisponível" } if distance >= 1 { @@ -314,7 +343,10 @@ struct HomeView: View { isLoadingStores = true storesError = nil - guard let coordinate = await resolveCoordinates(forceRefresh: forceLocationRefresh) else { + let coordinate = await resolveCoordinates(forceRefresh: forceLocationRefresh) + let hasAddress = hasConfiguredAddress() + + if coordinate == nil && hasAddress == false { isLoadingStores = false stores = [] storesError = "Defina um endereço para visualizar os estabelecimentos mais próximos." @@ -324,7 +356,11 @@ struct HomeView: View { } do { - let response = try await ApiService().listStores(lat: coordinate.0, lng: coordinate.1, category: category) + let response = try await ApiService().listStores( + lat: coordinate?.0, + lng: coordinate?.1, + category: category + ) isLoadingStores = false if response.error { stores = [] @@ -333,8 +369,8 @@ struct HomeView: View { } let results = response.result ?? [] stores = results - if refreshCategories { - categories = buildCategories(from: results) + if refreshCategories || (category == nil && categories.count <= 1) { + await loadHomeCategories(withFallbackStores: results) if categories.contains(where: { $0.id == selectedCategory }) == false { selectedCategory = "all" } @@ -349,7 +385,7 @@ struct HomeView: View { private func buildCategories(from stores: [StoreSummary]) -> [CategoryModel] { var unique: [CategoryModel] = [ - .init(id: "all", title: "Todas", systemIcon: "line.3.horizontal.decrease.circle") + .init(id: "all", title: "Todas", systemIcon: "line.3.horizontal.decrease.circle", emojiIcon: nil) ] var seen = Set() @@ -359,11 +395,59 @@ struct HomeView: View { let dedupe = raw.lowercased() if seen.contains(dedupe) { continue } seen.insert(dedupe) - unique.append(.init(id: raw, title: raw, systemIcon: categoryIcon(for: raw))) + unique.append(.init(id: raw, title: raw, systemIcon: categoryIcon(for: raw), emojiIcon: nil)) } return unique } + @MainActor + private func loadHomeCategories(withFallbackStores stores: [StoreSummary]) async { + do { + let response = try await ApiService().listPublicCategories() + if response.error == false, let remote = response.result, remote.isEmpty == false { + categories = mapPublicCategories(remote) + return + } + } catch { + // Fallback handled below. + } + + categories = buildCategories(from: stores) + } + + private func mapPublicCategories(_ remote: [PublicCategory]) -> [CategoryModel] { + var mapped: [CategoryModel] = [] + var seen = Set() + + for item in remote { + let id = item.id.trimmingCharacters(in: .whitespacesAndNewlines) + let title = item.name.trimmingCharacters(in: .whitespacesAndNewlines) + if id.isEmpty || title.isEmpty { continue } + if seen.contains(id.lowercased()) { continue } + seen.insert(id.lowercased()) + mapped.append( + .init( + id: id, + title: title, + systemIcon: id.lowercased() == "all" ? "line.3.horizontal.decrease.circle" : nil, + emojiIcon: item.icon + ) + ) + } + + if mapped.contains(where: { $0.id.lowercased() == "all" }) == false { + mapped.insert(.init(id: "all", title: "Todas", systemIcon: "line.3.horizontal.decrease.circle", emojiIcon: nil), at: 0) + } else { + mapped.sort { lhs, rhs in + if lhs.id.lowercased() == "all" { return true } + if rhs.id.lowercased() == "all" { return false } + return lhs.title < rhs.title + } + } + + return mapped + } + private func categoryIcon(for category: String) -> String { let value = category.folding(options: [.diacriticInsensitive, .caseInsensitive], locale: .current).lowercased() if value.contains("pizza") { return "takeoutbag.and.cup.and.straw" } @@ -440,18 +524,25 @@ struct HomeView: View { struct CategoryModel: Identifiable { let id: String let title: String - let systemIcon: String + let systemIcon: String? + let emojiIcon: String? } struct CategoryChip: View { let title: String - let systemIcon: String + let systemIcon: String? + let emojiIcon: String? let isActive: Bool var body: some View { HStack(spacing: 8) { - Image(systemName: systemIcon) - .font(.caption) + if let emojiIcon, emojiIcon.isEmpty == false { + Text(emojiIcon) + .font(.body) + } else if let systemIcon, systemIcon.isEmpty == false { + Image(systemName: systemIcon) + .font(.caption) + } Text(title) .font(AppTypography.heading3) } diff --git a/pedi-foods/Sources/PediFoods/Views/Main/ProfileView.swift b/pedi-foods/Sources/PediFoods/Views/Main/ProfileView.swift index ed40ce2..542bbf6 100644 --- a/pedi-foods/Sources/PediFoods/Views/Main/ProfileView.swift +++ b/pedi-foods/Sources/PediFoods/Views/Main/ProfileView.swift @@ -32,8 +32,8 @@ struct ProfileView: View { SecondaryButton(title: "Sair") { tokenStore.clear() - appState.session.isAuthenticated = false - appState.session.jwt = nil + SessionStateStore.clearActiveUser() + appState = AppState() root = .auth } .padding(.horizontal, 20) @@ -81,6 +81,7 @@ struct ProfileView: View { struct AddressesView: View { let message: String? @Binding var appState: AppState + var selectionMode: Bool = false @Environment(\.dismiss) var dismiss @State var isLoading = false @State var errorMessage: String? = nil @@ -127,7 +128,23 @@ struct AddressesView: View { .padding(.top, 24) } else { ForEach(Array(addresses.enumerated()), id: \.offset) { index, address in - AddressCard(item: addressToListItem(address, isPrimary: index == 0)) + let isSelected: Bool = { + if let selectedId = appState.address.selectedId { + return address.id == selectedId + } + return index == 0 + }() + + if selectionMode { + Button { + selectAddress(address) + } label: { + AddressCard(item: addressToListItem(address, isPrimary: isSelected)) + } + .buttonStyle(.plain) + } else { + AddressCard(item: addressToListItem(address, isPrimary: isSelected)) + } } } } @@ -159,6 +176,7 @@ struct AddressesView: View { appState.address.latitude = nil appState.address.longitude = nil } + SessionStateStore.saveAddress(appState.address) SnackbarCenter.shared.show(title: "Endereço adicionado com sucesso.", style: .success, icon: "checkmark.seal.fill", duration: 3.0) } } @@ -219,6 +237,26 @@ struct AddressesView: View { } } + private func selectAddress(_ address: CustomerAddress) { + appState.address.selectedId = address.id + let label = (address.label ?? "").trimmingCharacters(in: .whitespacesAndNewlines) + appState.address.display = label.isEmpty ? "Defina seu endereco" : label + + if let lat = address.latLong?.first, let lng = address.latLong?.dropFirst().first { + appState.address.latitude = lat + appState.address.longitude = lng + } else { + appState.address.latitude = nil + appState.address.longitude = nil + } + + SessionStateStore.saveAddress(appState.address) + + if selectionMode { + dismiss() + } + } + func addressToListItem(_ address: CustomerAddress, isPrimary: Bool) -> AddressListItem { let title = address.label?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false ? (address.label ?? "Endereço") : "Endereço" let line1 = [address.address, address.number] @@ -266,14 +304,26 @@ struct AddressesView: View { return } - addresses = response.result?.addressBook ?? [] - if let first = addresses.first { - appState.address.selectedId = first.id - appState.address.display = first.label ?? "Defina seu endereco" - if let lat = first.latLong?.first, let lng = first.latLong?.dropFirst().first { + if let customer = response.result { + appState.profile.id = customer.id + appState.profile.name = customer.name + appState.profile.email = customer.email + appState.profile.phone = customer.phoneNumber ?? appState.profile.phone + SessionStateStore.setActiveUserKey( + SessionStateStore.makeUserKey(profileId: customer.id, email: customer.email) + ) + addresses = customer.addressBook ?? [] + } else { + addresses = [] + } + if let selected = addresses.first(where: { $0.id == appState.address.selectedId }) ?? addresses.first { + appState.address.selectedId = selected.id + appState.address.display = selected.label ?? "Defina seu endereco" + if let lat = selected.latLong?.first, let lng = selected.latLong?.dropFirst().first { appState.address.latitude = lat appState.address.longitude = lng } + SessionStateStore.saveAddress(appState.address) } } catch { errorMessage = error.localizedDescription