SPB Git

spb/ora-ka Public

Ora-Ka — cinq agrégateurs Ka, une barre de recherche hybride (exact + sémantique)

Python 80% TypeScript 12.9% CSS 6.8%
2.2 KB · 54 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";8import { Ico } from "./Icons";910export default function ListingCard({ l }: { l: Listing }) {11  const img = l.images && l.images.length > 0 ? l.images[0] : null;12  const meta: { ico: string; txt: string }[] = [];13  if (l.bedrooms != null) meta.push({ ico: "bed", txt: `${l.bedrooms} ch.` });14  if (l.bathrooms != null) meta.push({ ico: "bath", txt: `${l.bathrooms} sdb` });15  const area = fmtArea(l.area_sqft);16  if (area) meta.push({ ico: "area", txt: area });1718  return (19    <Link to={`/propriete/${encodeURIComponent(l.uid)}`} className="card">20      <div className="card-img">21        {img ? (22          <img src={img} alt={l.title || l.address} loading="lazy" />23        ) : (24          <div className="noimg"><Ico name="home" size={34} /></div>25        )}26        {l.property_type && <span className="badge type">{l.property_type}</span>}27        {l.images.length > 1 && (28          <span className="badge right"><Ico name="camera" size={12} /> {l.images.length}</span>29        )}30      </div>31      <div className="card-body">32        <div className="card-price">{fmtPrice(l.price, l.price_label)}</div>33        <div className="card-title">{l.address || l.title}</div>34        <div className="card-meta">35          {l.sector && <span>{l.sector}</span>}36          {l.sector && l.city && <span className="sep" />}37          {l.city && <span>{l.city}</span>}38        </div>39        {meta.length > 0 && (40          <div className="card-specs">41            {meta.map((m) => (42              <span key={m.ico}><Ico name={m.ico} size={13} /> {m.txt}</span>43            ))}44          </div>45        )}46        <div className="card-foot">47          <span className="source-tag">{sourceName(l.source)}</span>48          {l.mls && <span className="avail">MLS {l.mls}</span>}49        </div>50      </div>51    </Link>52  );53}54