SPB Git forge

spb/home-ka

Public
10commits 1branches 0releases
793.0 KBsize
maindefault branch
20 days agolast push
Python 49.6% TypeScript 25.5% CSS 24.1%
3.0 KB · 102 lines typescript
Raw Blame History
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