SPB Git

spb/qwhpi Public

QHPI — Quebec Housing Price Index: quality-adjusted, hierarchically pooled housing price indexes.

Python 63.9% TypeScript 25.4% CSS 5.5% TeX 3.5% SQL 0.8% Makefile 0.5% Dockerfile 0.5%
1.8 KB · 55 lines tsx
Raw Blame History
1/**2 * =============================================================================3 * QWHPI — Quebec Weekly Housing Price Index4 * Author  : Simon-Pierre Boucher5 * Contact : contact@spboucher.ai6 * File    : web/components/Ticker.tsx7 * Purpose : Bloomberg-style infinite ticker tape — regions & cities YoY.8 * =============================================================================9 */10"use client";1112import { useEffect, useState } from "react";13import Link from "next/link";14import { fetchOverview, type OverviewRow } from "../lib/api";1516export default function Ticker({ ptype = "all" }: { ptype?: string }) {17  const [rows, setRows] = useState<OverviewRow[]>([]);1819  useEffect(() => {20    Promise.all([21      fetchOverview("region", ptype),22      fetchOverview("municipality", ptype),23    ])24      .then(([r, m]) => setRows([...m.rows, ...r.rows]))25      .catch(() => setRows([]));26  }, [ptype]);2728  if (!rows.length) return <div className="ticker-shell" aria-hidden />;2930  const items = rows.map((r) => (31    <Link32      key={r.geography_id}33      className="ticker-item"34      href={`/explore?geography=${r.geography_id}&type=${ptype}`}35    >36      <span className="ticker-name">{r.geography_name}</span>37      <span className="ticker-val">{r.index.toFixed(1)}</span>38      <span className={r.yoy_pct != null && r.yoy_pct < 0 ? "delta down" : "delta up"}>39        {r.yoy_pct == null ? "—"40          : `${r.yoy_pct >= 0 ? "▲" : "▼"}${Math.abs(r.yoy_pct).toFixed(1)}%`}41      </span>42    </Link>43  ));4445  return (46    <div className="ticker-shell" role="marquee"47         aria-label="Latest year-over-year appreciation by geography">48      <div className="ticker-track">49        <div className="ticker-group">{items}</div>50        <div className="ticker-group" aria-hidden>{items}</div>51      </div>52    </div>53  );54}55