TypeScript 87.7%
CSS 12.3%
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