// -----------------------------------------------------------------------------
// Immo-Ka — Agrégateur de propriétés à vendre (province de Québec)
// Auteur : Simon-Pierre Boucher — contact@spboucher.ai
// pages/Category.tsx : pages programmatiques /a-vendre/{ville}[/{type}] et
// /type/{type} — mêmes URL que le rendu SEO serveur (immoka/seo.py), le SPA
// prend le relais au montage. Résolution slug → valeurs via /api/seo/resolve.
// -----------------------------------------------------------------------------
import { useEffect, useState } from "react";
import { Link, useParams, useSearchParams } from "react-router-dom";
import {
Listing, fetchListings, fetchSources, fmtPrice, registerSourceNames,
resolveSeo, setDocTitle,
} from "../api";
import ListingCard from "../components/ListingCard";
import { Ico } from "../components/Icons";
const PAGE_SIZE = 48; // aligné sur immoka/seo.py
export default function CategoryPage() {
const { ville, type } = useParams<{ ville?: string; type?: string }>();
const [params, setParams] = useSearchParams();
const page = Math.max(1, Number(params.get("page")) || 1);
const [labels, setLabels] = useState<{ city?: string; property_type?: string } | null>(null);
const [listings, setListings] = useState
(null);
const [total, setTotal] = useState(0);
const [error, setError] = useState(null);
useEffect(() => {
fetchSources().then((r) => registerSourceNames(r.sources)).catch(() => {});
}, []);
useEffect(() => {
setLabels(null); setListings(null); setError(null);
resolveSeo(ville, type)
.then(setLabels)
.catch(() => setError("Page introuvable."));
}, [ville, type]);
useEffect(() => {
if (!labels) return;
setListings(null);
fetchListings(
{ city: labels.city, property_type: labels.property_type, sort: "price_asc" },
PAGE_SIZE, (page - 1) * PAGE_SIZE)
.then((r) => { setListings(r.listings); setTotal(r.total); })
.catch((e) => setError(String(e)));
window.scrollTo(0, 0);
}, [labels, page]);
const h1 = labels
? labels.city && labels.property_type
? `${labels.property_type} à vendre à ${labels.city}`
: labels.city
? `Propriétés à vendre à ${labels.city}`
: `${labels.property_type} à vendre au Québec`
: "";
useEffect(() => { if (h1) setDocTitle(h1); }, [h1]);
if (error)
return (
Page introuvable
{error}
Toutes les propriétés
);
const pages = Math.max(1, Math.ceil(total / PAGE_SIZE));
const refine = new URLSearchParams();
if (labels?.city) refine.set("city", labels.city);
if (labels?.property_type) refine.set("property_type", labels.property_type);
return (
{h1 || "Chargement…"}
{listings && (
{total.toLocaleString("fr-CA")} annonces
{listings.length > 0 && listings[0].price != null && (
<> · à partir de {fmtPrice(listings[0].price)}>
)}
{" · "}
Affiner la recherche (carte, filtres)
)}
{!listings && !error && (
{Array.from({ length: 8 }).map((_, i) => (
))}
)}
{listings && (
{listings.map((l) => )}
)}
{pages > 1 && (
)}
);
}