SPB Git forge

spb/ka-maps

Public
6commits 1branches 0releases
448.0 KBsize
maindefault branch
29 days agolast push
TypeScript 87.7% CSS 12.3%
4.3 KB · 150 lines typescript
Raw Blame History
1/**2 * Author: Simon-Pierre Boucher3 * Contact: contact@spboucher.ai4 * Project: Groupe Ka / Ka Maps5 *6 * Canonical types shared by every Groupe Ka application.7 * Each app maps its own domain model into these shapes at the adapter8 * boundary — no app-specific field ever lives here.9 */1011/** Which Groupe Ka application produced a map item. */12export type KaAppSource = "lou-ka" | "immo-ka" | "vrai-prix";1314/** Canonical geographic representation of a property-like item. */15export interface MapProperty {16  id: string;17  appSource: KaAppSource;18  latitude: number;19  longitude: number;20  kind: "listing" | "valuation" | "transaction";21  listingType?: "sale" | "rent";22  price?: number;23  estimatedValue?: number;24  /** 0–1 (or letter grade mapped to 0–1 by the adapter). */25  valuationConfidence?: number;26  propertyType?: string;27  bedrooms?: number;28  bathrooms?: number;29  address?: string;30  city?: string;31  region?: string;32  daysOnMarket?: number;33  /** Relative price change since listing, e.g. -0.05 for a 5 % cut. */34  priceChange?: number;35  thumbnailUrl?: string;36  originalUrl?: string;37  /** App-defined emphasis (e.g. Immo-Ka "sous l'estimation Vrai-Prix"). */38  highlight?: boolean;39  /** Opaque app-owned payload carried through to previews/cards40   *  (availability, source, confidence…). Never read by the framework. */41  extra?: Record<string, unknown>;42}4344/** Geographic bounding box, always [west, south, east, north]. */45export interface BBox {46  west: number;47  south: number;48  east: number;49  north: number;50}5152/** Serializable map camera + interaction state. */53export interface KaMapState {54  center: { lat: number; lng: number };55  zoom: number;56  bearing: number;57  pitch: number;58  bounds: BBox | null;59  selectedPropertyId: string | null;60  hoveredPropertyId: string | null;61  activeLayers: string[];62  /** True when the viewport moved away from the last searched area. */63  searchAreaDirty: boolean;64  /** GeoJSON geometry drawn with Ka Lens, if any. */65  drawnGeometry: GeoJSON.Polygon | null;66}6768/** Aggregated market statistics for an administrative geography. */69export interface GeographicMarketSummary {70  geographyId: string;71  geographyType:72    | "province"73    | "region"74    | "municipality"75    | "borough"76    | "neighbourhood";77  name: string;78  listingCount: number;79  medianListingPrice?: number;80  medianSalePrice?: number;81  medianEstimatedValue?: number;82  medianRent?: number;83  medianDaysOnMarket?: number;84  change7d?: number;85  change30d?: number;86  change1y?: number;87}8889/** Metrics accepted by the generic heatmap infrastructure. */90export type HeatmapMetric =91  | "listing_density"92  | "median_price"93  | "estimated_value"94  | "price_per_sqft"95  | "yoy_change"96  | "days_on_market";9798/** Statistics computed by Ka Lens over a drawn or visible area. */99export interface KaLensStats {100  count: number;101  medianPrice?: number;102  medianEstimatedValue?: number;103  medianPricePerSqft?: number;104  change30d?: number;105  change1y?: number;106  medianDaysOnMarket?: number;107  priceCutShare?: number;108  stale90dShare?: number;109  /** Property-type mix, e.g. { "Maison": 0.52, "Condo": 0.41 }. */110  typeMix?: Record<string, number>;111}112113/** Query sent to an app's data adapter when the viewport settles. */114export interface BoundsQuery {115  bbox: BBox;116  zoom: number;117  /** Opaque app-owned filter payload, forwarded verbatim to the adapter. */118  filters?: Record<string, unknown>;119  signal: AbortSignal;120}121122/** Result returned by an app's data adapter. */123export interface BoundsQueryResult {124  properties: MapProperty[];125  /** Total matching server-side (may exceed properties.length). */126  totalCount?: number;127}128129/**130 * The single integration seam between an app and Ka Maps: how that app's131 * listings/valuations become MapProperty objects for a given viewport.132 */133export interface KaDataAdapter {134  /** Stable id, used for cache keys and telemetry. */135  id: string;136  appSource: KaAppSource;137  fetchInBounds(query: BoundsQuery): Promise<BoundsQueryResult>;138}139140/** Declaration of one toggleable map layer in the per-app registry. */141export interface KaLayerDefinition {142  id: string;143  /** Display group, e.g. "property" | "market" | "land" | "lifestyle" | "investment". */144  group: string;145  label: string;146  /** Only layers with available data should be marked supported. */147  supported: boolean;148  defaultActive?: boolean;149}150