TypeScript 50.6%
JavaScript 46.1%
SQL 2.1%
Shell 0.6%
CSS 0.5%
1import type { SearchParams, Market } from "./types";2export type SP = Record<string, string | string[] | undefined>;3const s = (v: string | string[] | undefined) => (Array.isArray(v) ? v[0] : v) ?? undefined;4const n = (v: string | string[] | undefined) => { const x = Number(s(v)); return Number.isFinite(x) && x > 0 ? x : undefined; };5/** URL (fr) → SearchParams. marche=achat|location, ville, region, type=a,b, prix_min, prix_max, chambres, sdb, superficie, annee, tri, page, bbox */6export function fromUrl(sp: SP, perPage = 24): SearchParams & { page: number } {7 const market: Market = s(sp.marche) === "location" ? "rent" : "sale";8 const page = Math.max(1, Math.floor(n(sp.page) ?? 1));9 const bboxRaw = s(sp.bbox)?.split(",").map(Number);10 const bbox = bboxRaw && bboxRaw.length === 4 && bboxRaw.every(Number.isFinite) ? (bboxRaw as [number, number, number, number]) : undefined;11 const sort = s(sp.tri) as SearchParams["sort"];12 return { market, q: s(sp.q), city: s(sp.ville), region: s(sp.region), category: s(sp.type)?.split(",").filter(Boolean), priceMin: n(sp.prix_min), priceMax: n(sp.prix_max),13 bedroomsMin: n(sp.chambres), bathroomsMin: n(sp.sdb), areaMin: n(sp.superficie), yearMin: n(sp.annee), bbox, sort: sort && ["recent", "price_asc", "price_desc", "deal", "area_desc"].includes(sort) ? sort : "recent",14 limit: perPage, offset: (page - 1) * perPage, page };15}16export function describe(p: SearchParams, total: number): string {17 const what = p.market === "rent" ? "logements à louer" : "propriétés à vendre";18 const where = p.city ? ` à ${p.city}` : p.region ? ` — ${p.region}` : p.q ? ` pour « ${p.q} »` : " au Québec";19 return `${total.toLocaleString("fr-CA")} ${what}${where}`;20}21