Python 49.6%
TypeScript 25.5%
CSS 24.1%
1// -----------------------------------------------------------------------------2// Author: Simon-Pierre Boucher3// Contact: contact@spboucher.ai4// Project: Groupe Ka / Ka Maps (Home-Ka integration)5// kamaps/adapter.ts : Home-Ka → MapProperty adapter. Viewport-driven data via6// /api/listings.geojson?bbox=… (cancellable requests, never a storm).7// -----------------------------------------------------------------------------8import type {9 BoundsQuery,10 BoundsQueryResult,11 KaAppSource,12 KaDataAdapter,13 MapProperty,14} from "@groupe-ka/ka-maps";15import { bboxToString } from "@groupe-ka/ka-maps";16import type { ListingFilters } from "../api";1718/** ka-maps ships a closed KaAppSource union (pre-Home-Ka) — cast our id. */19export const HOMEKA_APP_SOURCE = "home-ka" as KaAppSource;2021interface HomeKaFeatureProps {22 uid: string;23 title: string | null;24 address: string | null;25 price: number | null;26 price_label: string | null;27 property_type: string | null;28 bedrooms: number | null;29 bathrooms: number | null;30 source: string;31 city: string | null;32 state: string | null;33 image: string | null;34}3536interface HomeKaFC {37 type: "FeatureCollection";38 features: {39 geometry: { coordinates: [number, number] };40 properties: HomeKaFeatureProps;41 }[];42 totalGeocoded?: number;43 totalMatching?: number;44}4546function toMapProperty(47 coords: [number, number],48 p: HomeKaFeatureProps,49): MapProperty {50 return {51 id: p.uid,52 appSource: HOMEKA_APP_SOURCE,53 longitude: coords[0],54 latitude: coords[1],55 kind: "listing",56 listingType: "sale",57 price: p.price ?? undefined,58 propertyType: p.property_type ?? undefined,59 bedrooms: p.bedrooms ?? undefined,60 bathrooms: p.bathrooms ?? undefined,61 address: p.address ?? p.title ?? undefined,62 city: p.city ?? undefined,63 region: p.state ?? undefined,64 thumbnailUrl: p.image ?? undefined,65 originalUrl: `/property/${encodeURIComponent(p.uid)}`,66 extra: {67 title: p.title,68 priceLabel: p.price_label,69 source: p.source,70 state: p.state,71 },72 };73}7475/** Viewport→data adapter for the Home-Ka map. */76export const homeKaMapAdapter: KaDataAdapter = {77 id: "home-ka-listings",78 appSource: HOMEKA_APP_SOURCE,79 async fetchInBounds(query: BoundsQuery): Promise<BoundsQueryResult> {80 const params = new URLSearchParams();81 const filters = (query.filters ?? {}) as Partial<ListingFilters>;82 for (const [k, v] of Object.entries(filters)) {83 if (v && k !== "sort") params.set(k, String(v));84 }85 params.set("bbox", bboxToString(query.bbox));86 params.set("limit", "3000");8788 const res = await fetch(`/api/listings.geojson?${params}`, {89 signal: query.signal,90 });91 if (!res.ok) throw new Error(`Map: API ${res.status}`);92 const data = (await res.json()) as HomeKaFC;9394 return {95 properties: data.features.map((f) =>96 toMapProperty(f.geometry.coordinates, f.properties),97 ),98 totalCount: data.totalMatching,99 };100 },101};102