// Auteur : Simon-Pierre Boucher — contact@spboucher.ai // À propos : la méthodologie en bref, les chiffres de validation, la conformité. import SwiftUI struct AboutView: View { var body: some View { NavigationStack { ScrollView { VStack(alignment: .leading, spacing: 18) { VStack(alignment: .leading, spacing: 10) { Wordmark(size: 34) Text("La vraie valeur, sans boîte noire") .font(.vpDisplay(19)) .foregroundStyle(Color.vpInk) .textCase(.uppercase) 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.") .font(.vpBody(14.5)) .foregroundStyle(Color.vpInk2) } .padding(.top, 8) statsCard methodCard complianceCard VStack(alignment: .leading, spacing: 8) { Link("www.vrai-prix.com", destination: URL(string: "https://www.vrai-prix.com")!) .font(.vpDisplayMedium(15)) .foregroundStyle(Color.vpGreen) Link("Méthodologie complète", destination: URL(string: "https://www.vrai-prix.com/methodologie")!) .font(.vpBody(13.5)) .foregroundStyle(Color.vpInk2) Link("Conditions d'utilisation", destination: URL(string: "https://www.vrai-prix.com/conditions")!) .font(.vpBody(13.5)) .foregroundStyle(Color.vpInk2) Link("Politique de confidentialité", destination: URL(string: "https://www.vrai-prix.com/confidentialite")!) .font(.vpBody(13.5)) .foregroundStyle(Color.vpInk2) Text("Simon-Pierre Boucher — contact@spboucher.ai") .font(.vpMono(10)) .foregroundStyle(Color.vpInk3) .padding(.top, 6) } .padding(.bottom, 16) } .padding(16) } .background(Color.vpPaper) .toolbar { ToolbarItem(placement: .principal) { Wordmark(size: 20) } } .navigationBarTitleDisplayMode(.inline) .toolbarBackground(Color.vpPaper, for: .navigationBar) .toolbarBackground(.visible, for: .navigationBar) } } private var statsCard: some View { VStack(alignment: .leading, spacing: 12) { Kicker(text: "Les chiffres qui comptent") LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 14) { stat("3 747 008", "unités d'évaluation") stat("745 119", "ventes réelles") stat("11,0 %", "erreur médiane (MdAPE)") stat("0,995", "ratio médian (IAAO ✓)") stat("2,01 billions $", "valeur de la province") stat("99,88 %", "fusion spatiale réussie") } } .padding(18) .vpCard() } private func stat(_ value: String, _ label: String) -> some View { VStack(alignment: .leading, spacing: 3) { Text(value) .font(.vpDisplay(19)) .foregroundStyle(Color.vpInk) .minimumScaleFactor(0.7) .lineLimit(1) Text(label.uppercased()) .font(.vpMono(8.5)) .tracking(0.6) .foregroundStyle(Color.vpInk3) } .frame(maxWidth: .infinity, alignment: .leading) } private var methodCard: some View { VStack(alignment: .leading, spacing: 12) { Kicker(text: "Le moteur en cinq étapes") step(1, "Comparables", "Ventes candidates dans un rayon adaptatif (2,2 → 28 km), filtrées par type et superficie.") step(2, "Ajustements en dollars", "Conditions de marché (indice mensuel $/m²), superficie (50 % du $/m² marginal), âge (0,5 %/an).") step(3, "Pondération gaussienne", "Distance (σ 1 500 m), récence (σ 24 mois), similarité de superficie (σ 25 %).") step(4, "Fusion", "65 % modèle hédonique LightGBM + 35 % médiane pondérée des comparables.") step(5, "Confiance", "Nombre de comparables, dispersion et largeur de fourchette → indice A/B/C/D.") } .padding(18) .vpCard() } private func step(_ n: Int, _ title: String, _ text: String) -> some View { HStack(alignment: .top, spacing: 12) { Text("0\(n)") .font(.vpMonoBold(11)) .foregroundStyle(Color.vpGreen) .padding(.top, 2) VStack(alignment: .leading, spacing: 3) { Text(title.uppercased()) .font(.vpDisplay(13.5)) .foregroundStyle(Color.vpInk) Text(text) .font(.vpBody(13)) .foregroundStyle(Color.vpInk2) } } } private var complianceCard: some View { VStack(alignment: .leading, spacing: 10) { Kicker(text: "Données et conformité") 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.") .font(.vpBody(13.5)) .foregroundStyle(Color.vpInk2) Text("Estimations statistiques à titre indicatif — ne remplacent pas une évaluation par un évaluateur agréé (OEAQ).") .font(.vpMono(9.5)) .foregroundStyle(Color.vpInk3) } .padding(18) .vpCard() } } #Preview { AboutView() }