SPB Git

spb/lou-ka-ios Public

Lou·Ka iOS — app SwiftUI native de l'agrégateur de logements du Québec : filtres avancés, carte, stats, et mode Découverte (swipe) avec recommandation on-device

Swift 100%
3.3 KB · 91 lines swift
Raw Blame History
1// -----------------------------------------------------------------------------2// Lou-Ka — Agrégateur de logements à louer (province de Québec)3// Auteur : Simon-Pierre Boucher — contact@spboucher.ai4// App.swift : point d'entrée, modèle global (facettes / sources / stats), onglets5// -----------------------------------------------------------------------------6import SwiftUI7import Observation89@MainActor10@Observable11final class AppModel {12    var facets: Facets?13    var sources: [SourceInfo] = []14    var stats: Stats?1516    private var loaded = false1718    func loadGlobals(force: Bool = false) async {19        if loaded && !force { return }20        loaded = true21        async let facetsTask = try? API.facets()22        async let sourcesTask = try? API.sources()23        async let statsTask = try? API.stats()24        let (f, s, st) = await (facetsTask, sourcesTask, statsTask)25        if let f { facets = f }26        if let s { sources = s.sources }27        if let st { stats = st }28    }2930    /// id de source → nom lisible (ex. « logisco » → « Logisco »)31    func sourceName(_ id: String) -> String {32        sources.first(where: { $0.id == id })?.name ?? id33    }34}3536@main37struct LouKaApp: App {38    @State private var model = AppModel()39    @State private var reco = RecoEngine()4041    init() {42        // Barre de navigation « éditoriale » : papier opaque, trait encre,43        // titres en Space Grotesk — cohérent sur toutes les pages.44        let nav = UINavigationBarAppearance()45        nav.configureWithOpaqueBackground()46        nav.backgroundColor = UIColor(LK.paper)47        nav.shadowColor = UIColor(LK.ink)48        var titleAttrs: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor(LK.ink)]49        var largeAttrs = titleAttrs50        if let f = UIFont(name: "SpaceGrotesk-Bold", size: 17) { titleAttrs[.font] = f }51        if let f = UIFont(name: "SpaceGrotesk-Bold", size: 30) { largeAttrs[.font] = f }52        nav.titleTextAttributes = titleAttrs53        nav.largeTitleTextAttributes = largeAttrs54        UINavigationBar.appearance().standardAppearance = nav55        UINavigationBar.appearance().scrollEdgeAppearance = nav56    }5758    var body: some Scene {59        WindowGroup {60            RootView()61                .environment(model)62                .environment(reco)63                .tint(LK.ink)64                // Le design Lou-Ka est un thème clair (papier/encre) : on le force65                // pour que les couleurs système (titres, champs, pickers) ne passent66                // jamais au blanc en mode sombre → texte invisible.67                .preferredColorScheme(.light)68        }69    }70}7172struct RootView: View {73    @Environment(AppModel.self) private var model7475    var body: some View {76        TabView {77            HomeView()78                .tabItem { Label("Annonces", systemImage: "list.bullet.rectangle.portrait") }79            DiscoverView()80                .tabItem { Label("Découvrir", systemImage: "rectangle.stack.badge.play") }81            MapTabView()82                .tabItem { Label("Carte", systemImage: "map") }83            StatsView()84                .tabItem { Label("Stats", systemImage: "chart.bar.xaxis") }85            SourcesView()86                .tabItem { Label("Sources", systemImage: "building.2") }87        }88        .task { await model.loadGlobals() }89    }90}91