spb/auto-ka Public
Python 81.9%
TypeScript 12.4%
CSS 5.5%
1// -----------------------------------------------------------------------------2// Auto-Ka — Agrégateur de voitures usagées à vendre (province de Québec)3// Auteur : Simon-Pierre Boucher — contact@spboucher.ai4// App.tsx : layout global (header + ticker en direct + footer encre) et routage5// -----------------------------------------------------------------------------6import { useEffect, useState } from "react";7import { NavLink, Route, Routes } from "react-router-dom";8import { fetchFacets, fetchSources, fetchStats, registerSourceNames } from "./api";9import Home from "./pages/Home";10import VehiclePage from "./pages/Vehicle";11import SourcesPage from "./pages/Sources";12import StatsPage from "./pages/Stats";1314function Ticker() {15 const [items, setItems] = useState<string[]>([]);1617 useEffect(() => {18 Promise.all([fetchStats(), fetchFacets(), fetchSources()])19 .then(([stats, facets, src]) => {20 registerSourceNames(src.sources);21 const parts: string[] = [22 `${stats.total.toLocaleString("fr-CA")} véhicules à vendre`,23 `${stats.sources} concessionnaires connectés`,24 ];25 if (stats.avg_price != null)26 parts.push(`Prix moyen ${Math.round(stats.avg_price).toLocaleString("fr-CA")} $`);27 for (const r of stats.by_region.slice(0, 8))28 parts.push(`${r.region} · ${r.n}`);29 for (const m of facets.makes.slice(0, 8))30 parts.push(`${m.make} · ${m.n}`);31 parts.push("Directement des sites des concessionnaires");32 setItems(parts);33 })34 .catch(() => setItems(["Auto-Ka — voitures usagées à vendre au Québec"]));35 }, []);3637 if (items.length === 0) return null;38 // contenu doublé pour une boucle de défilement continue39 return (40 <div className="ticker" aria-hidden="true">41 <div className="ticker-track">42 {[...items, ...items].map((t, i) => (43 <span key={i}>{t}</span>44 ))}45 </div>46 </div>47 );48}4950function Header() {51 return (52 <>53 <header className="header">54 <div className="container header-inner">55 <NavLink to="/" className="brand" aria-label="Auto-Ka — accueil">56 Auto<span className="ka">Ka</span>57 <span className="brand-tag">Voitures usagées · tout le Québec · toujours à jour</span>58 </NavLink>59 <nav className="nav" aria-label="Navigation principale">60 <NavLink to="/" end className={({ isActive }) => (isActive ? "active" : "")}>61 Véhicules62 </NavLink>63 <NavLink to="/stats" className={({ isActive }) => (isActive ? "active" : "")}>64 Stats65 </NavLink>66 <NavLink to="/sources" className={({ isActive }) => (isActive ? "active" : "")}>67 Sources68 </NavLink>69 </nav>70 </div>71 </header>72 <Ticker />73 </>74 );75}7677function Footer() {78 return (79 <footer className="footer">80 <div className="container">81 <div className="fbrand">82 Auto<span className="ka">Ka</span>83 </div>84 <div className="frow">85 <b>Agrégateur indépendant</b> de voitures usagées à vendre dans la86 province de Québec. Les annonces proviennent directement des sites87 publics des concessionnaires — pas des plateformes d'annonces — et88 sont rafraîchies automatiquement. Chaque fiche renvoie vers l'annonce89 originale du commerçant.90 </div>91 <div className="fmono">92 © {new Date().getFullYear()} Simon-Pierre Boucher — contact@spboucher.ai93 </div>94 </div>95 </footer>96 );97}9899export default function App() {100 return (101 <>102 <Header />103 <main>104 <Routes>105 <Route path="/" element={<Home />} />106 <Route path="/vehicule/:uid" element={<VehiclePage />} />107 <Route path="/stats" element={<StatsPage />} />108 <Route path="/sources" element={<SourcesPage />} />109 <Route110 path="*"111 element={112 <div className="notice container">113 <div className="big">🧭</div>114 <h2>Page introuvable</h2>115 <p>Le lien demandé n'existe pas.</p>116 </div>117 }118 />119 </Routes>120 </main>121 <Footer />122 </>123 );124}125