SPB Git forge

spb/toveli

Public
14commits 1branches 0releases
1.1 MBsize
maindefault branch
3 h agolast push
TypeScript 50.6% JavaScript 46.1% SQL 2.1% Shell 0.6% CSS 0.5%
3.0 KB · 41 lines tsx
Raw Blame History
1import type { Metadata } from "next";2import Link from "next/link";3import { searchRoleUnits } from "@/lib/queries";4import { dbAvailable } from "@/lib/db";5import { fmtPrice, fmtInt } from "@/lib/format";6import { Notice } from "@/components/ui";7import { EstimateSearch } from "./estimate-search";8import { ManualEstimate } from "./manual-estimate";9export const dynamic = "force-dynamic";10export const metadata: Metadata = { title: "Estimer une propriété", description: "Estimation de la valeur d'une propriété au Québec à partir du rôle d'évaluation, d'un modèle hédonique et de ventes comparables ajustées, avec fourchette et niveau de confiance." };11export default async function Estimer({ searchParams }: { searchParams: Promise<{ q?: string }> }) {12  const { q } = await searchParams;13  const units = q && dbAvailable() ? searchRoleUnits(q, 12) : [];14  return (15    <div className="mx-auto max-w-5xl px-4 py-8">16      <h1 className="text-3xl md:text-4xl font-extrabold tracking-tight">Estimer une propriété</h1>17      <p className="mt-2 text-ink-2 max-w-2xl">Entrez une adresse : Toveli retrouve l'unité au rôle d'évaluation (3,7 M d'unités du Québec), puis combine un modèle hédonique et des ventes comparables ajustées. Résultat avec fourchette, confiance, méthode et limites.</p>18      <div className="mt-5"><EstimateSearch initial={q ?? ""} /></div>19      {q && (20        <section className="mt-6">21          <h2 className="font-bold text-lg mb-2">{units.length ? `${units.length} résultat${units.length > 1 ? "s" : ""} pour « ${q} »` : `Aucune unité trouvée pour « ${q} »`}</h2>22          <ul className="tv-card divide-y divide-line">23            {units.map((u) => (24              <li key={u.id}><Link href={`/estimer/${encodeURIComponent(u.id)}`} className="flex items-center justify-between gap-3 p-3 hover:bg-surface-2">25                <span><span className="font-medium">{u.address}{u.unit ? `, app. ${u.unit}` : ""}</span><span className="block text-xs text-ink-3">{u.city} · {u.type_prop}{u.year_built ? ` · ${u.year_built}` : ""}{u.floor_area_m2 ? ` · ${fmtInt(u.floor_area_m2)} m²` : ""}</span></span>26                <span className="text-right text-sm shrink-0"><span className="block tabular-nums font-semibold">{u.est ? fmtPrice(u.est) : "—"}</span><span className="block text-xs text-ink-3">rôle {fmtPrice(u.role_value)}</span></span>27              </Link></li>28            ))}29          </ul>30          {!units.length && <Notice>Essayez avec le numéro civique et le nom de rue seulement (ex. « 1234 Érables »), ou utilisez l'estimation manuelle ci-dessous.</Notice>}31        </section>32      )}33      <section className="mt-10">34        <h2 className="font-bold text-xl mb-1">Estimation manuelle</h2>35        <p className="text-sm text-ink-2 mb-3">Sans adresse au rôle : indiquez un point sur la carte et quelques caractéristiques. L'estimation repose alors uniquement sur les ventes comparables.</p>36        <ManualEstimate />37      </section>38    </div>39  );40}41