SPB Git

spb/vrai-prix-ios Public

App iOS native de Vrai-Prix — estimation immobilière transparente pour le Québec (SwiftUI, MapKit, Swift Charts)

Swift 100%
3.9 KB · 158 lines swift
Raw Blame History
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// Modèles Codable — miroir des types de l'API Vrai-Prix (src/lib/estimator.ts, engine.ts).3import Foundation45// MARK: - Recherche d'adresse (/api/search)67struct SearchResponse: Decodable {8    let results: [SearchResult]9}1011struct SearchResult: Decodable, Identifiable, Hashable {12    let id: String13    let adresse: String?14    let apt: String?15    let municipalite: String?16    let typeProp: String?17}1819// MARK: - Estimation (/api/estimate)2021struct UnitEstimate: Decodable {22    let unit: PropertyUnit?23    let result: EstimateResult24}2526struct PropertyUnit: Decodable {27    let id: String28    let adresse: String?29    let municipalite: String?30    let typeProp: String31    let cubfLibelle: String?32    let anneeConstruction: Int?33    let aireEtagesM2: Double?34    let superficieTerrainM2: Double?35    let nbLogements: Int?36    let valeurRole: Double?37    let lat: Double38    let lng: Double39    let history: [HistoryPoint]40    let specs: UnitSpecs41}4243struct HistoryPoint: Decodable, Identifiable {44    let year: Int45    let value: Double?46    var id: Int { year }47}4849struct UnitSpecs: Decodable {50    let cubf: Int?51    let cubfLibelle: String?52    let anneeEstimee: String?53    let frontTerrainM: Double?54    let nbEtages: Int?55    let nbLocauxNonResid: Int?56    let nbChambresLocatives: Int?57    let lienPhysique: String?58    let genreConstruction: String?59    let matricule: String?60    let uniteVoisinage: String?61    let nAdresses: Int?62    let datCondMarche: String?63    let valeurTerrain: Double?64    let valeurBatiment: Double?65    let valeurAnterieure: Double?66    let arrond: String?67    let apt: String?68}6970struct EstimateResult: Decodable {71    let estimate: Double72    let low: Double73    let high: Double74    let confidencePct: Double75    let confidenceLevel: String // A | B | C | D76    let modelEstimate: Double?77    let compsEstimate: Double?78    let modelWeight: Double79    let comps: [AdjustedComp]80    let nCompsUsed: Int81    let compsDispersionPct: Double?82}8384struct AdjustedComp: Decodable, Identifiable {85    let id: String86    let date: String // YYYY-MM-DD87    let amount: Double88    let lat: Double89    let lng: Double90    let propertyType: String?91    let yearBuilt: Int?92    let floorArea: Double?93    let street: String?94    let city: String?95    let distanceM: Double96    let monthsAgo: Double97    let adjTime: Double98    let adjArea: Double99    let adjAge: Double100    let adjustedPrice: Double101    let weight: Double102}103104// MARK: - Recherche par carte (/api/nearby)105106struct NearbyResponse: Decodable {107    let results: [NearbyUnit]108}109110struct NearbyUnit: Decodable, Identifiable, Hashable {111    let id: String112    let adresse: String?113    let apt: String?114    let municipalite: String?115    let typeProp: String116    let lat: Double117    let lng: Double118    let est2026: Double?119120    /// Pour réutiliser EstimateLoaderView (même écran que la recherche texte).121    var asSearchResult: SearchResult {122        SearchResult(id: id, adresse: adresse, apt: apt, municipalite: municipalite, typeProp: typeProp)123    }124}125126/// Erreur renvoyée par l'API ({"error": "..."}).127struct APIErrorPayload: Decodable {128    let error: String129}130131/// Libellés français des types de propriété (mêmes clés que le moteur).132enum PropType: String, CaseIterable, Identifiable {133    case unifamilial134    case plex135    case condoOuMulti = "condo_ou_multi"136    case chalet137    case maisonMobile = "maison_mobile"138    case terrain139140    var id: String { rawValue }141142    var label: String {143        switch self {144        case .unifamilial: return "Unifamiliale"145        case .plex: return "Plex"146        case .condoOuMulti: return "Condo / multi"147        case .chalet: return "Chalet"148        case .maisonMobile: return "Maison mobile"149        case .terrain: return "Terrain"150        }151    }152153    static func label(for raw: String?) -> String {154        guard let raw, let t = PropType(rawValue: raw) else { return raw ?? "—" }155        return t.label156    }157}158