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%
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// À propos : la méthodologie en bref, les chiffres de validation, la conformité.3import SwiftUI45struct AboutView: View {6 var body: some View {7 NavigationStack {8 ScrollView {9 VStack(alignment: .leading, spacing: 18) {10 VStack(alignment: .leading, spacing: 10) {11 Wordmark(size: 34)12 Text("La vraie valeur, sans boîte noire")13 .font(.vpDisplay(19))14 .foregroundStyle(Color.vpInk)15 .textCase(.uppercase)16 Text("Moteur d'évaluation immobilière transparent pour le Québec. Chaque calcul est montré en entier : comparables, ajustements en dollars, pondération, fourchette et confiance.")17 .font(.vpBody(14.5))18 .foregroundStyle(Color.vpInk2)19 }20 .padding(.top, 8)2122 statsCard23 methodCard24 complianceCard2526 VStack(alignment: .leading, spacing: 8) {27 Link("www.vrai-prix.com", destination: URL(string: "https://www.vrai-prix.com")!)28 .font(.vpDisplayMedium(15))29 .foregroundStyle(Color.vpGreen)30 Link("Méthodologie complète", destination: URL(string: "https://www.vrai-prix.com/methodologie")!)31 .font(.vpBody(13.5))32 .foregroundStyle(Color.vpInk2)33 Link("Conditions d'utilisation", destination: URL(string: "https://www.vrai-prix.com/conditions")!)34 .font(.vpBody(13.5))35 .foregroundStyle(Color.vpInk2)36 Link("Politique de confidentialité", destination: URL(string: "https://www.vrai-prix.com/confidentialite")!)37 .font(.vpBody(13.5))38 .foregroundStyle(Color.vpInk2)39 Text("Simon-Pierre Boucher — contact@spboucher.ai")40 .font(.vpMono(10))41 .foregroundStyle(Color.vpInk3)42 .padding(.top, 6)43 }44 .padding(.bottom, 16)45 }46 .padding(16)47 }48 .background(Color.vpPaper)49 .toolbar {50 ToolbarItem(placement: .principal) { Wordmark(size: 20) }51 }52 .navigationBarTitleDisplayMode(.inline)53 .toolbarBackground(Color.vpPaper, for: .navigationBar)54 .toolbarBackground(.visible, for: .navigationBar)55 }56 }5758 private var statsCard: some View {59 VStack(alignment: .leading, spacing: 12) {60 Kicker(text: "Les chiffres qui comptent")61 LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 14) {62 stat("3 747 008", "unités d'évaluation")63 stat("745 119", "ventes réelles")64 stat("11,0 %", "erreur médiane (MdAPE)")65 stat("0,995", "ratio médian (IAAO ✓)")66 stat("2,01 billions $", "valeur de la province")67 stat("99,88 %", "fusion spatiale réussie")68 }69 }70 .padding(18)71 .vpCard()72 }7374 private func stat(_ value: String, _ label: String) -> some View {75 VStack(alignment: .leading, spacing: 3) {76 Text(value)77 .font(.vpDisplay(19))78 .foregroundStyle(Color.vpInk)79 .minimumScaleFactor(0.7)80 .lineLimit(1)81 Text(label.uppercased())82 .font(.vpMono(8.5))83 .tracking(0.6)84 .foregroundStyle(Color.vpInk3)85 }86 .frame(maxWidth: .infinity, alignment: .leading)87 }8889 private var methodCard: some View {90 VStack(alignment: .leading, spacing: 12) {91 Kicker(text: "Le moteur en cinq étapes")92 step(1, "Comparables", "Ventes candidates dans un rayon adaptatif (2,2 → 28 km), filtrées par type et superficie.")93 step(2, "Ajustements en dollars", "Conditions de marché (indice mensuel $/m²), superficie (50 % du $/m² marginal), âge (0,5 %/an).")94 step(3, "Pondération gaussienne", "Distance (σ 1 500 m), récence (σ 24 mois), similarité de superficie (σ 25 %).")95 step(4, "Fusion", "65 % modèle hédonique LightGBM + 35 % médiane pondérée des comparables.")96 step(5, "Confiance", "Nombre de comparables, dispersion et largeur de fourchette → indice A/B/C/D.")97 }98 .padding(18)99 .vpCard()100 }101102 private func step(_ n: Int, _ title: String, _ text: String) -> some View {103 HStack(alignment: .top, spacing: 12) {104 Text("0\(n)")105 .font(.vpMonoBold(11))106 .foregroundStyle(Color.vpGreen)107 .padding(.top, 2)108 VStack(alignment: .leading, spacing: 3) {109 Text(title.uppercased())110 .font(.vpDisplay(13.5))111 .foregroundStyle(Color.vpInk)112 Text(text)113 .font(.vpBody(13))114 .foregroundStyle(Color.vpInk2)115 }116 }117 }118119 private var complianceCard: some View {120 VStack(alignment: .leading, spacing: 10) {121 Kicker(text: "Données et conformité")122 Text("Données sources : rôles d'évaluation foncière du Québec (MAMH, licence ouverte), 6 millésimes 2021-2026. Les renseignements des propriétaires sont caviardés à la source. Conformité Loi 25.")123 .font(.vpBody(13.5))124 .foregroundStyle(Color.vpInk2)125 Text("Estimations statistiques à titre indicatif — ne remplacent pas une évaluation par un évaluateur agréé (OEAQ).")126 .font(.vpMono(9.5))127 .foregroundStyle(Color.vpInk3)128 }129 .padding(18)130 .vpCard()131 }132}133134#Preview {135 AboutView()136}137