SPB Git forge

spb/lou-ka

Public

Lou·Ka — tous les logements à louer du Québec, un seul endroit.

232commits 1branches 0releases
172.9 MBsize
maindefault branch
2 days agolast push
HTML 98.9% Python 0.6%
4.0 KB · 107 lines tsx
Raw Blame History
1// -----------------------------------------------------------------------------2// Lou-Ka — Agrégateur de logements à louer (province de Québec)3// Auteur : Simon-Pierre Boucher — contact@spboucher.ai4// pages/GestionPublic.tsx : page publique d'une gestion immobilière — /g/{source}5//   Bandeau personnalisé par le gestionnaire (accroche, description, contact,6//   logo) + inventaire relié automatiquement (12/page, pagination).7// -----------------------------------------------------------------------------8import { useEffect, useState } from "react";9import { Link, useParams } from "react-router-dom";10import { Listing, OrgProfile, fetchListings, fetchOrg } from "../api";11import ListingCard from "../components/ListingCard";12import Pager from "../components/Pager";13import { IcoCompass, IcoPin } from "../components/Icons";1415const PAGE_SIZE = 12;1617export default function GestionPublicPage() {18  const { sourceId = "" } = useParams();19  const [org, setOrg] = useState<OrgProfile | null | undefined>(undefined);20  const [listings, setListings] = useState<Listing[] | null>(null);21  const [total, setTotal] = useState(0);22  const [page, setPage] = useState(1);2324  useEffect(() => {25    fetchOrg(sourceId).then(setOrg).catch(() => setOrg(null));26    setPage(1);27  }, [sourceId]);2829  useEffect(() => {30    setListings(null);31    fetchListings({ source: sourceId }, PAGE_SIZE, (page - 1) * PAGE_SIZE)32      .then((r) => { setListings(r.listings); setTotal(r.total); })33      .catch(() => setListings([]));34  }, [sourceId, page]);3536  if (org === undefined) {37    return <div className="container profil"><div className="notice">Chargement…</div></div>;38  }39  if (org === null) {40    return (41      <div className="container notice">42        <div className="big"><IcoCompass size={40} /></div>43        <h2>Page introuvable</h2>44        <p>Cette gestion n'existe pas sur Lou-Ka.</p>45        <Link className="btn btn-primary" to="/">Explorer les logements</Link>46      </div>47    );48  }4950  return (51    <div className="container profil orgpub">52      <div className="orgpub-head">53        {org.logo_url && (54          <img className="orgpub-logo" src={org.logo_url} alt="" referrerPolicy="no-referrer" />55        )}56        <div className="orgpub-id">57          <span className="kicker">Gestion immobilière</span>58          <h1>{org.name}</h1>59          {org.tagline && <p className="orgpub-tagline">{org.tagline}</p>}60          <div className="orgpub-meta">61            <span className="stat-chip"><b>{org.active_listings}</b> logements actifs</span>62            {org.claimed && <span className="stat-chip orgpub-verified">Page gérée par l'organisation</span>}63            {org.phone && <a className="stat-chip" href={`tel:${org.phone}`}>{org.phone}</a>}64            {org.email && <a className="stat-chip" href={`mailto:${org.email}`}>{org.email}</a>}65            {org.website && (66              <a className="stat-chip" href={org.website} target="_blank" rel="noopener noreferrer">67                Site web ↗68              </a>69            )}70          </div>71        </div>72      </div>7374      {org.description && <p className="orgpub-desc">{org.description}</p>}7576      <div className="results-head">77        <h2><IcoPin size={16} /> Logements offerts</h2>78        <div className="results-tools">79          {listings && <span>{total} résultat{total > 1 ? "s" : ""}</span>}80        </div>81      </div>8283      {listings === null && (84        <div className="grid" aria-busy="true">85          {Array.from({ length: 4 }).map((_, i) => (86            <div className="skel" key={i}>87              <div className="sk-img" /><div className="sk-line" /><div className="sk-line short" />88            </div>89          ))}90        </div>91      )}9293      {listings !== null && (94        <>95          <div className="grid">96            {listings.map((l) => <ListingCard key={l.uid} l={l} />)}97          </div>98          <Pager page={page} pageSize={PAGE_SIZE} total={total} onPage={(p) => {99            setPage(p);100            window.scrollTo({ top: 0, behavior: "smooth" });101          }} />102        </>103      )}104    </div>105  );106}107