Lou·Ka — tous les logements à louer du Québec, un seul endroit.
HTML 98.9%
Python 0.6%
1// -----------------------------------------------------------------------------2// Author: Simon-Pierre Boucher3// Contact: contact@spboucher.ai4// Project: Groupe Ka / Ka Maps (Lou-Ka — location court terme)5// kamaps/ctAdapter.ts : adaptateur /api/ct/listings.geojson → MapProperty.6// -----------------------------------------------------------------------------7import type {8 BoundsQuery,9 BoundsQueryResult,10 KaDataAdapter,11 MapProperty,12} from "@groupe-ka/ka-maps";13import { bboxToString } from "@groupe-ka/ka-maps";14import type { CtFilters } from "../ctapi";1516interface CtFeatureProps {17 uid: string;18 title: string | null;19 property_type: string | null;20 city: string | null;21 region: string | null;22 price_night: number | null;23 price_label: string | null;24 capacity: number | null;25 bedrooms: number | null;26 rating: number | null;27 source: string;28 image: string | null;29}3031interface CtFC {32 type: "FeatureCollection";33 features: {34 geometry: { coordinates: [number, number] };35 properties: CtFeatureProps;36 }[];37 totalGeocoded?: number;38}3940function toMapProperty(coords: [number, number], p: CtFeatureProps): MapProperty {41 return {42 id: p.uid,43 appSource: "lou-ka",44 longitude: coords[0],45 latitude: coords[1],46 kind: "listing",47 listingType: "rent",48 price: p.price_night ?? undefined,49 propertyType: p.property_type ?? undefined,50 address: p.title ?? undefined,51 city: p.city ?? undefined,52 region: p.region ?? undefined,53 thumbnailUrl: p.image ?? undefined,54 originalUrl: `/court-terme/${encodeURIComponent(p.uid)}`,55 extra: {56 title: p.title,57 priceLabel: p.price_label,58 capacity: p.capacity,59 bedrooms: p.bedrooms,60 rating: p.rating,61 source: p.source,62 },63 };64}6566/** Adaptateur viewport→données pour la carte court terme. */67export const ctMapAdapter: KaDataAdapter = {68 id: "lou-ka-ct-listings",69 appSource: "lou-ka",70 async fetchInBounds(query: BoundsQuery): Promise<BoundsQueryResult> {71 const params = new URLSearchParams();72 const filters = (query.filters ?? {}) as Partial<CtFilters>;73 for (const [k, v] of Object.entries(filters)) {74 if (v) params.set(k, String(v));75 }76 params.set("bbox", bboxToString(query.bbox));77 params.set("limit", "4000");7879 const res = await fetch(`/api/ct/listings.geojson?${params}`, {80 signal: query.signal,81 });82 if (!res.ok) throw new Error(`Carte : API ${res.status}`);83 const data = (await res.json()) as CtFC;8485 return {86 properties: data.features.map((f) =>87 toMapProperty(f.geometry.coordinates, f.properties),88 ),89 };90 },91};92