import Foundation struct AppState { var session = SessionState() var profile = ProfileState() var cart = CartState() var address = AddressState() var favorites = FavoritesState() var featureFlags = FeatureFlagsState() var homeFilters = HomeFiltersState() var activeModal: AppModal? = nil var shouldNavigateToOrders: Bool = false } enum FeatureFlagValue: Codable, Equatable { case boolean(Bool) case text(String) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() if let boolValue = try? container.decode(Bool.self) { self = .boolean(boolValue) return } if let stringValue = try? container.decode(String.self) { self = .text(stringValue) return } if let intValue = try? container.decode(Int.self) { self = .text(String(intValue)) return } if let doubleValue = try? container.decode(Double.self) { self = .text(String(doubleValue)) return } self = .text("off") } func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .boolean(let value): try container.encode(value) case .text(let value): try container.encode(value) } } var boolValue: Bool { switch self { case .boolean(let value): return value case .text(let value): return value.lowercased() == "on" || value.lowercased() == "true" } } } struct FeatureFlagsState: Codable, Equatable { var configVersion: Int = 0 var evaluatedAt: String? = nil var source: String = "default" var values: [String: FeatureFlagValue] = [:] var raw: [String: FeatureControlRawFlag] = [:] func isEnabled(_ key: String, default defaultValue: Bool = false) -> Bool { if let rawValue = raw[key] { return rawValue.enabled || rawValue.variant.lowercased() == "on" } if let mapped = values[key] { return mapped.boolValue } return defaultValue } } enum AppModal: String, Identifiable { case addressPicker case filters var id: String { rawValue } } struct SessionState { var isAuthenticated: Bool = false var jwt: String? = nil } struct ProfileState { var id: String? = nil var name: String = "" var email: String = "" var phone: String = "" var profilePicture: String = "" var cpf: String = "" } struct AddressState { var selectedId: String? = nil var display: String = "Defina seu endereco" var latitude: Double? = nil var longitude: Double? = nil var onboardingMessage: String? = nil } struct FavoritesState { var storeIds: Set = [] } enum HomeSortOption: String, CaseIterable, Identifiable { case relevance case rating case deliveryTime case price var id: String { rawValue } var title: String { switch self { case .relevance: return "Relevância" case .rating: return "Avaliação" case .deliveryTime: return "Tempo de entrega" case .price: return "Preço" } } var icon: String { switch self { case .relevance: return "checkmark.seal.fill" case .rating: return "star.fill" case .deliveryTime: return "clock.fill" case .price: return "dollarsign" } } } enum HomePriceTier: String, CaseIterable, Identifiable { case low = "$" case medium = "$$" case high = "$$$" case veryHigh = "$$$$" var id: String { rawValue } } struct HomeFiltersState { var sortOption: HomeSortOption = .relevance var selectedCategories: Set = [] var selectedPriceTier: HomePriceTier? = nil var maxDistanceKm: Double = 10 var availableCategories: [String] = [] mutating func reset() { sortOption = .relevance selectedCategories = [] selectedPriceTier = nil maxDistanceKm = 10 } } struct CartState { var storeId: String? = nil var storeName: String? = nil var items: [CartItemState] = [] var total: Double = 0 } struct CartItemState: Identifiable { let id: String var productId: String var storeId: String var name: String var imageURL: String? = nil var details: String? = nil var choices: [String]? = nil var addons: [CartItemAddonState] = [] var quantity: Int var unitPrice: Double } struct CartItemAddonState: Identifiable, Hashable { let id: String var name: String var quantity: Int var unitPrice: Double } extension CartState { var totalItems: Int { items.reduce(0) { $0 + $1.quantity } } mutating func recalculateTotal() { total = items.reduce(0) { $0 + (Double($1.quantity) * $1.unitPrice) } } mutating func clear() { storeId = nil storeName = nil items = [] total = 0 SessionStateStore.clearCart() } mutating func add(item: CartItemState) { if let index = items.firstIndex(where: { $0.id == item.id }) { items[index].quantity += item.quantity } else { items.append(item) } recalculateTotal() SessionStateStore.saveCart(self) } mutating func set(item: CartItemState) { if let index = items.firstIndex(where: { $0.id == item.id }) { if item.quantity <= 0 { items.remove(at: index) } else { items[index] = item } } else if item.quantity > 0 { items.append(item) } if items.isEmpty { storeId = nil storeName = nil } recalculateTotal() if items.isEmpty { SessionStateStore.clearCart() } else { SessionStateStore.saveCart(self) } } mutating func increment(itemId: String) { guard let index = items.firstIndex(where: { $0.id == itemId }) else { return } items[index].quantity += 1 recalculateTotal() SessionStateStore.saveCart(self) } mutating func decrement(itemId: String) { guard let index = items.firstIndex(where: { $0.id == itemId }) else { return } items[index].quantity -= 1 if items[index].quantity <= 0 { items.remove(at: index) } if items.isEmpty { storeId = nil storeName = nil } recalculateTotal() if items.isEmpty { SessionStateStore.clearCart() } else { SessionStateStore.saveCart(self) } } func toOrderItemsPayload() -> [CreateOrderItemPayload] { items.map { item in CreateOrderItemPayload( productId: item.productId, name: item.name, qty: item.quantity, price: item.unitPrice, addons: item.addons .filter { $0.quantity > 0 } .map { CreateOrderAddonPayload( addonId: $0.id, name: $0.name, qty: $0.quantity, price: $0.unitPrice ) }, choices: item.choices?.isEmpty == false ? item.choices : nil ) } } }