SPB Git

spb/immo-ka Public

Immo-Ka — agrégateur des propriétés à vendre au Québec (73 connecteurs, ~40 000 annonces, React+FastAPI)

Python 67.2% TypeScript 19.4% CSS 12.9% HTML 0.5%
2.0 KB · 53 lines tsx
Raw Blame History
1// -----------------------------------------------------------------------------2// Immo-Ka — Agrégateur de propriétés à vendre (province de Québec)3// Auteur : Simon-Pierre Boucher — contact@spboucher.ai4// components/ListingCard.tsx : carte de propriété (grille de résultats)5// -----------------------------------------------------------------------------6import { Link } from "react-router-dom";7import { Listing, fmtArea, fmtPrice, sourceName } from "../api";89export default function ListingCard({ l }: { l: Listing }) {10  const img = l.images && l.images.length > 0 ? l.images[0] : null;11  const meta: string[] = [];12  if (l.bedrooms != null) meta.push(`${l.bedrooms} ch.`);13  if (l.bathrooms != null) meta.push(`${l.bathrooms} sdb`);14  const area = fmtArea(l.area_sqft);15  if (area) meta.push(area);1617  return (18    <Link to={`/propriete/${encodeURIComponent(l.uid)}`} className="card">19      <div className="card-img">20        {img ? (21          <img src={img} alt={l.title || l.address} loading="lazy" />22        ) : (23          <div className="noimg">🏠</div>24        )}25        {l.property_type && <span className="badge type">{l.property_type}</span>}26        {l.images.length > 1 && (27          <span className="badge right">📷 {l.images.length}</span>28        )}29      </div>30      <div className="card-body">31        <div className="card-price">{fmtPrice(l.price, l.price_label)}</div>32        <div className="card-title">{l.address || l.title}</div>33        <div className="card-meta">34          {l.sector && <span>{l.sector}</span>}35          {l.sector && l.city && <span className="sep" />}36          {l.city && <span>{l.city}</span>}37        </div>38        {meta.length > 0 && (39          <div className="card-specs">40            {meta.map((m) => (41              <span key={m}>{m}</span>42            ))}43          </div>44        )}45        <div className="card-foot">46          <span className="source-tag">{sourceName(l.source)}</span>47          {l.mls && <span className="avail">MLS {l.mls}</span>}48        </div>49      </div>50    </Link>51  );52}53