SPB Git forge

spb/vrai-prix

Public

Vrai-Prix — l'évaluation du vrai prix des propriétés résidentielles au Québec.

60commits 1branches 0releases
12.3 MBsize
maindefault branch
17 days agolast push
TypeScript 90.2% JavaScript 3.5% Python 3.4% CSS 1.9% HTML 0.6%
3.6 KB · 120 lines typescript
Raw Blame History
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// Projet : Groupe Ka / Ka Maps (intégration Vrai-Prix)3// lib/kamaps.ts : thème Vrai-Prix Maps + adaptateur /api/nearby.4// La carte affiche des VALEURS ESTIMÉES (jamais des prix demandés) :5// pastilles encre à liseré rouge #ff5148, sélection rouge — le langage6// visuel du site (encre #141814, « lime » rouge, bordeaux #9e2a25).78import type {9  BoundsQuery,10  BoundsQueryResult,11  KaDataAdapter,12  KaMapTheme,13  MapProperty,14} from "@groupe-ka/ka-maps";1516const INK = "#141814";17const RED = "#ff5148"; // --lime (nom hérité)18const BORDEAUX = "#9e2a25"; // --green (nom hérité)1920export const MAPBOX_TOKEN: string =21  process.env.NEXT_PUBLIC_MAPBOX_TOKEN ??22  "pk.eyJ1Ijoic3Bib3VjaGVyIiwiYSI6ImNtc3Fyb3k4djAwOTgyenB3dWt6NHBjc2kifQ.poqLf0ADy3lIh28O-pFI2Q";2324/** Zoom minimal de chargement : sous ce niveau, on invite à zoomer. */25export const MIN_ZOOM_FETCH = 12;2627export const TYPE_FR: Record<string, string> = {28  unifamilial: "Unifamiliale",29  condo_ou_multi: "Condo / multi",30  plex: "Plex",31  chalet: "Chalet",32  terrain: "Terrain",33  maison_mobile: "Maison mobile",34  autre: "Autre",35};3637export const vraiPrixMapTheme: KaMapTheme = {38  id: "vrai-prix",39  productName: "Vrai-Prix Maps",40  accent: RED,41  onAccent: "#ffffff",42  fontFamily: "var(--font-inter), system-ui, sans-serif",43  markers: {44    sale: {45      background: INK,46      text: "#ffffff",47      halo: RED,48      selectedBackground: RED,49      selectedText: "#ffffff",50    },51    // Valeurs estimées : pastille encre, liseré rouge — visuellement52    // distinctes d'un prix demandé (jamais présentées comme une annonce).53    valuation: {54      background: INK,55      text: "#ffffff",56      halo: RED,57      selectedBackground: RED,58      selectedText: "#ffffff",59    },60  },61  cluster: {62    background: BORDEAUX,63    text: "#ffffff",64    border: "rgba(255,81,72,0.5)",65  },66  supportsDark: false,67};6869interface NearbyUnit {70  id: string;71  adresse: string | null;72  apt: string | null;73  municipalite: string | null;74  typeProp: string | null;75  lat: number;76  lng: number;77  est2026: number | null;78}7980function toMapProperty(u: NearbyUnit): MapProperty {81  return {82    id: u.id,83    appSource: "vrai-prix",84    latitude: u.lat,85    longitude: u.lng,86    kind: "valuation",87    estimatedValue: u.est2026 ?? undefined,88    propertyType: u.typeProp ? TYPE_FR[u.typeProp] ?? u.typeProp : undefined,89    address: u.apt ? `${u.adresse} app. ${u.apt}` : u.adresse ?? undefined,90    city: u.municipalite ?? undefined,91    originalUrl: `/estimation/${u.id}`,92    extra: { typeProp: u.typeProp },93  };94}9596/** Adaptateur viewport→données : /api/nearby (contrat partagé avec iOS). */97export const vraiPrixMapAdapter: KaDataAdapter = {98  id: "vrai-prix-nearby",99  appSource: "vrai-prix",100  async fetchInBounds(query: BoundsQuery): Promise<BoundsQueryResult> {101    if (query.zoom < MIN_ZOOM_FETCH) return { properties: [] };102    const { bbox } = query;103    const lat = (bbox.north + bbox.south) / 2;104    const lng = (bbox.east + bbox.west) / 2;105    const halfLat = Math.abs(bbox.north - lat);106    const halfLng = Math.abs(bbox.east - lng);107    const params = new URLSearchParams({108      lat: lat.toFixed(6),109      lng: lng.toFixed(6),110      halfLat: halfLat.toFixed(6),111      halfLng: halfLng.toFixed(6),112      limit: "1500",113    });114    const res = await fetch(`/api/nearby?${params}`, { signal: query.signal });115    if (!res.ok) throw new Error(`Carte : API ${res.status}`);116    const data = (await res.json()) as { results: NearbyUnit[] };117    return { properties: data.results.map(toMapProperty) };118  },119};120