segregate files
This commit is contained in:
126
pedi-foods/Sources/PediFoods/Views/Main/HomeView+Data.swift
Normal file
126
pedi-foods/Sources/PediFoods/Views/Main/HomeView+Data.swift
Normal file
@@ -0,0 +1,126 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
extension HomeView {
|
||||
func buildCategories(from stores: [StoreSummary]) -> [CategoryModel] {
|
||||
var unique: [CategoryModel] = [
|
||||
.init(id: "all", title: "Todas", systemIcon: "line.3.horizontal.decrease.circle", emojiIcon: nil)
|
||||
]
|
||||
var seen = Set<String>()
|
||||
|
||||
for store in stores {
|
||||
let raw = (store.category ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if raw.isEmpty { continue }
|
||||
let dedupe = raw.lowercased()
|
||||
if seen.contains(dedupe) { continue }
|
||||
seen.insert(dedupe)
|
||||
unique.append(.init(id: raw, title: raw, systemIcon: categoryIcon(for: raw), emojiIcon: nil))
|
||||
}
|
||||
return unique
|
||||
}
|
||||
|
||||
@MainActor
|
||||
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)
|
||||
}
|
||||
|
||||
func mapPublicCategories(_ remote: [PublicCategory]) -> [CategoryModel] {
|
||||
var mapped: [CategoryModel] = []
|
||||
var seen = Set<String>()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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" }
|
||||
if value.contains("lanche") || value.contains("hamburg") || value.contains("burger") { return "fork.knife" }
|
||||
if value.contains("cafe") || value.contains("breakfast") { return "sun.max" }
|
||||
if value.contains("doce") || value.contains("sobremesa") || value.contains("dessert") { return "cup.and.saucer" }
|
||||
return "storefront"
|
||||
}
|
||||
|
||||
@MainActor
|
||||
func resolveCoordinates(forceRefresh: Bool) async -> (Double, Double)? {
|
||||
if !forceRefresh {
|
||||
if let lat = appState.address.latitude, let lng = appState.address.longitude {
|
||||
return (lat, lng)
|
||||
}
|
||||
if let cached = LocationService.shared.cachedLocation() {
|
||||
appState.address.latitude = cached.0
|
||||
appState.address.longitude = cached.1
|
||||
return cached
|
||||
}
|
||||
if hasConfiguredAddress() == false {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
let coordinate = await LocationService.shared.requestLocationAsync(timeoutSeconds: 3)
|
||||
if let coordinate {
|
||||
appState.address.latitude = coordinate.0
|
||||
appState.address.longitude = coordinate.1
|
||||
}
|
||||
return coordinate
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
func storesUserMessage(_ error: Error) -> String {
|
||||
if let service = error as? ApiServiceError {
|
||||
return service.errorDescription ?? "Não foi possível carregar os estabelecimentos."
|
||||
}
|
||||
if let network = error as? NetworkError {
|
||||
return network.errorDescription ?? "Não foi possível carregar os estabelecimentos."
|
||||
}
|
||||
return "Não foi possível carregar os estabelecimentos."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user