scroll stick

This commit is contained in:
Daniel Arantes Loverde
2026-02-12 15:05:09 -03:00
parent 38fc71718b
commit b027a10c8d
5 changed files with 1044 additions and 13 deletions

View File

@@ -179,6 +179,16 @@ final class ApiService {
let req = ApiRequest(path: "/api/app/stores", method: "GET", module: .app, requiresAuth: true, queryItems: items)
return try await sendEnvelope(req)
}
func storeInfo(storeId: String) async throws -> ApiEnvelope<StoreInfoResult> {
let req = ApiRequest(path: "/api/store/\(storeId)/info", method: "GET", module: .store, requiresAuth: true)
return try await sendEnvelope(req)
}
func storeCatalog(storeId: String) async throws -> ApiEnvelope<[StoreCatalogCategory]> {
let req = ApiRequest(path: "/api/store/\(storeId)/catalog", method: "GET", module: .store, requiresAuth: true)
return try await sendEnvelope(req)
}
}
// MARK: - DTOs
@@ -254,6 +264,175 @@ struct StoreSummary: Decodable {
let statusLabel: String?
}
struct StoreInfoResult: Decodable {
let isOpen: Bool?
let statusLabel: String?
let deliveryTime: String?
let minOrder: Double?
let address: StoreAddressInfo?
let paymentMethods: StorePaymentMethodsInfo?
enum CodingKeys: String, CodingKey {
case isOpen
case statusLabel
case deliveryTime
case minOrder
case address
case paymentMethods
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
isOpen = try? container.decode(Bool.self, forKey: .isOpen)
statusLabel = try? container.decode(String.self, forKey: .statusLabel)
deliveryTime = try? container.decode(String.self, forKey: .deliveryTime)
minOrder = ApiService.decodeFlexibleDouble(from: container, keys: [.minOrder])
address = try? container.decode(StoreAddressInfo.self, forKey: .address)
paymentMethods = try? container.decode(StorePaymentMethodsInfo.self, forKey: .paymentMethods)
}
}
struct StoreAddressInfo: Decodable {
let street: String?
let number: String?
let neighborhood: String?
let city: String?
let state: String?
let latitude: Double?
let longitude: Double?
enum CodingKeys: String, CodingKey {
case street
case number
case neighborhood
case city
case state
case latitude
case longitude
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
street = try? container.decode(String.self, forKey: .street)
number = try? container.decode(String.self, forKey: .number)
neighborhood = try? container.decode(String.self, forKey: .neighborhood)
city = try? container.decode(String.self, forKey: .city)
state = try? container.decode(String.self, forKey: .state)
latitude = ApiService.decodeFlexibleDouble(from: container, keys: [.latitude])
longitude = ApiService.decodeFlexibleDouble(from: container, keys: [.longitude])
}
}
struct StorePaymentMethodsInfo: Decodable {
let acceptPix: Bool?
let acceptCash: Bool?
let acceptCreditCard: Bool?
let acceptDebitCard: Bool?
}
struct StoreCatalogCategory: Decodable {
let id: String
let name: String
let products: [StoreCatalogProduct]
enum CodingKeys: String, CodingKey {
case id
case name
case products
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = (try? container.decode(String.self, forKey: .id)) ?? UUID().uuidString
name = (try? container.decode(String.self, forKey: .name)) ?? "Categoria"
products = (try? container.decode([StoreCatalogProduct].self, forKey: .products)) ?? []
}
}
struct StoreCatalogProduct: Decodable, Identifiable {
let id: String
let name: String
let description: String?
let image: String?
let price: Double?
let originalPrice: Double?
let addonGroups: [StoreAddonGroup]
enum CodingKeys: String, CodingKey {
case id
case name
case description
case desc
case image
case cover
case photo
case price
case originalPrice
case oldPrice
case addonGroups
case addons
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = (try? container.decode(String.self, forKey: .id)) ?? UUID().uuidString
name = (try? container.decode(String.self, forKey: .name)) ?? "Produto"
description = (try? container.decode(String.self, forKey: .description)) ?? (try? container.decode(String.self, forKey: .desc))
image = (try? container.decode(String.self, forKey: .image))
?? (try? container.decode(String.self, forKey: .cover))
?? (try? container.decode(String.self, forKey: .photo))
price = ApiService.decodeFlexibleDouble(from: container, keys: [.price])
originalPrice = ApiService.decodeFlexibleDouble(from: container, keys: [.originalPrice, .oldPrice])
addonGroups = (try? container.decode([StoreAddonGroup].self, forKey: .addonGroups))
?? (try? container.decode([StoreAddonGroup].self, forKey: .addons))
?? []
}
}
struct StoreAddonGroup: Decodable, Identifiable {
let id: String
let name: String
let minSelectors: Int?
let maxSelectors: Int?
let items: [StoreAddonItem]
enum CodingKeys: String, CodingKey {
case id
case name
case minSelectors
case maxSelectors
case items
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = (try? container.decode(String.self, forKey: .id)) ?? UUID().uuidString
name = (try? container.decode(String.self, forKey: .name)) ?? "Adicionais"
minSelectors = try? container.decode(Int.self, forKey: .minSelectors)
maxSelectors = try? container.decode(Int.self, forKey: .maxSelectors)
items = (try? container.decode([StoreAddonItem].self, forKey: .items)) ?? []
}
}
struct StoreAddonItem: Decodable, Identifiable {
let id: String
let name: String
let price: Double?
enum CodingKeys: String, CodingKey {
case id
case name
case price
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = (try? container.decode(String.self, forKey: .id)) ?? UUID().uuidString
name = (try? container.decode(String.self, forKey: .name)) ?? "Item"
price = ApiService.decodeFlexibleDouble(from: container, keys: [.price])
}
}
struct PublicCategory: Decodable {
let id: String
let name: String
@@ -422,3 +601,25 @@ struct CepLookupResult: Decodable {
return nil
}
}
private extension ApiService {
static func decodeFlexibleDouble<K: CodingKey>(from container: KeyedDecodingContainer<K>, keys: [K]) -> Double? {
for key in keys {
if let value = try? container.decode(Double.self, forKey: key) {
return value
}
if let asInt = try? container.decode(Int.self, forKey: key) {
return Double(asInt)
}
if let asString = try? container.decode(String.self, forKey: key) {
let normalized = asString
.trimmingCharacters(in: .whitespacesAndNewlines)
.replacingOccurrences(of: ",", with: ".")
if let parsed = Double(normalized) {
return parsed
}
}
}
return nil
}
}