SPB Git forge

spb/uqo-eval

Public
55commits 2branches 0releases
134.4 MBsize
maindefault branch
4 h agolast push
TypeScript 90.1% JavaScript 3.2% Python 3.2% CSS 1.8% HTML 1.8%
3.5 KB · 107 lines tsx
Raw Blame History
1"use client";2// UQO Éval — laboratoire pédagogique d'évaluation immobilière3// components/KaCarte.tsx : UQO Éval Maps — recherche par carte propulsée4// par le framework partagé Ka Maps (moteur Mapbox GL, style Standard 3D par5// défaut + bouton 2D). Remplace l'ancienne carte Leaflet/OSM : pastilles de6// VALEURS ESTIMÉES 2026 (grappes + moyennes), chargement piloté par le7// viewport (annulation, cache), aperçu React, bilingue FR/EN.8// À charger via next/dynamic({ ssr: false }) — Mapbox GL est navigateur-seul.910import { useState } from "react";11import { useRouter } from "next/navigation";12import "mapbox-gl/dist/mapbox-gl.css";13import "@groupe-ka/ka-maps/styles.css";14import type { MapProperty } from "@groupe-ka/ka-maps";15import { formatFullPrice } from "@groupe-ka/ka-maps";16import {17  KaBrandBadge,18  KaMapView,19  LoadingIndicator,20  LocateControl,21  PropertyPreview,22  Tilt3DControl,23} from "@groupe-ka/ka-maps/react";24import { useLang } from "@/components/LangContext";25import {26  MAPBOX_TOKEN,27  MIN_ZOOM_FETCH,28  uqoEvalMapAdapter,29  uqoEvalMapTheme,30} from "@/lib/kamaps";3132const DEFAULT_CENTER = { lat: 45.5421, lng: -73.6646 }; // Montréal3334/** Aperçu d'une unité d'évaluation — valeur estimée, jamais un prix. */35function PreviewCard({ p, fr, close }: { p: MapProperty; fr: boolean; close: () => void }) {36  const router = useRouter();37  return (38    <div className="vpm-pop">39      <div className="klabel">{fr ? "Estimation 2026" : "2026 estimate"}</div>40      <div className="vpm-pop-value">41        {p.estimatedValue != null ? formatFullPrice(p.estimatedValue) : "—"}42      </div>43      <div className="vpm-pop-addr">{p.address}</div>44      <div className="vpm-pop-meta">45        {[p.city, p.propertyType].filter(Boolean).join(" · ")}46      </div>47      <button48        type="button"49        className="vpm-pop-cta"50        onClick={() => {51          close();52          router.push(p.originalUrl ?? "/");53        }}54      >55        {fr ? "Voir l'estimation complète →" : "See full estimate →"}56      </button>57    </div>58  );59}6061export default function KaCarte() {62  const { lang } = useLang();63  const fr = lang === "fr";64  const [zoom, setZoom] = useState(13);65  const [count, setCount] = useState<number | null>(null);6667  const zoomedOut = zoom < MIN_ZOOM_FETCH;6869  return (70    <div className="vpm-wrap">71      <KaMapView72        theme={uqoEvalMapTheme}73        adapter={uqoEvalMapAdapter}74        mapboxToken={MAPBOX_TOKEN}75        center={DEFAULT_CENTER}76        zoom={13.5}77        pitch={50}78        searchMode="auto"79        cluster={{ maxZoom: 15, radius: 44, valueClamp: [40_000, 5_000_000] }}80        onMoveEnd={(_c, z) => setZoom(z)}81        onData={(c) => setCount(c)}82      >83        <KaBrandBadge />84        <Tilt3DControl />85        <LocateControl label={fr ? "Me localiser" : "Locate me"} />86        <LoadingIndicator label={fr ? "Mise à jour des estimations…" : "Updating estimates…"} />87        <PropertyPreview88          render={(p, close) => <PreviewCard p={p} fr={fr} close={close} />}89        />90        <div className="vpm-chip" role="status">91          {zoomedOut92            ? fr93              ? "Zoomez pour voir les valeurs estimées"94              : "Zoom in to see estimated values"95            : count != null96              ? fr97                ? `${count.toLocaleString("fr-CA")} propriétés affichées`98                : `${count.toLocaleString("en-CA")} properties shown`99              : fr100                ? "Chargement…"101                : "Loading…"}102        </div>103      </KaMapView>104    </div>105  );106}107