SPB Git forge

spb/rent-ka

Public
8commits 1branches 0releases
7.4 MBsize
maindefault branch
19 days agolast push
Python 68.8% TypeScript 18.6% CSS 8.7% JavaScript 3.3% HTML 0.6%
2.5 KB · 66 lines tsx
Raw Blame History
1// -----------------------------------------------------------------------------2// Rent-Ka — Rental listings aggregator (Canada, outside Québec)3// Author: Simon-Pierre Boucher — contact@spboucher.ai4// components/KaScoreBadge.tsx: KA Score badges (Groupe-KA design system).5//   · compact: "KA 78" on listing cards and mini-sheets;6//   · circle: circular gauge of a sub-score on the detail page.7// -----------------------------------------------------------------------------8import { kaLabel } from "../api";910/** Tint class per bracket (styles in styles.css). */11export function kaTint(score: number | null | undefined): string {12  if (score == null) return "na";13  if (score >= 70) return "haut";14  if (score >= 55) return "bon";15  if (score >= 40) return "moyen";16  return "bas";17}1819/** Compact "KA 78" badge — list cards, carousel, mini-sheets. */20export default function KaScoreBadge({ score, title }: {21  score: number | null | undefined;22  title?: string;23}) {24  if (score == null) return null;25  return (26    <span27      className={`ka-badge ka-${kaTint(score)}`}28      title={title ?? `KA Score ${Math.round(score)} — ${kaLabel(score)} · see the methodology at /ka-scores`}29      aria-label={`KA Score ${Math.round(score)} out of 100, ${kaLabel(score)}`}30    >31      <span className="ka-badge-logo">KA</span> {Math.round(score)}32    </span>33  );34}3536/** Circular gauge of a sub-score (listing detail, methodology page). */37export function KaScoreCircle({ score, nom, note }: {38  score: number | null;39  nom: string;40  note?: string | null;41}) {42  const r = 26;43  const c = 2 * Math.PI * r;44  const part = score == null ? 0 : Math.max(0, Math.min(1, score / 100));45  return (46    <div className={`ka-circle ka-${kaTint(score)}`} role="img"47      aria-label={`${nom} : ${score == null ? note ?? "insufficient data" : `${Math.round(score)} out of 100`}`}>48      <svg viewBox="0 0 64 64" width="64" height="64" aria-hidden="true">49        <circle cx="32" cy="32" r={r} className="ka-circle-fond" />50        <circle51          cx="32" cy="32" r={r} className="ka-circle-arc"52          strokeDasharray={`${c * part} ${c}`}53          transform="rotate(-90 32 32)"54        />55        <text x="32" y="37" textAnchor="middle" className="ka-circle-val">56          {score == null ? "—" : Math.round(score)}57        </text>58      </svg>59      <div className="ka-circle-nom">{nom}</div>60      <div className="ka-circle-label">61        {score == null ? (note ?? "Insufficient data") : kaLabel(score)}62      </div>63    </div>64  );65}66