Resto·Ka — tous les restaurants du Québec, menus complets et prix réels (famille ·Ka)
Python 69.3%
TypeScript 16.7%
CSS 7.9%
JavaScript 4.7%
HTML 1.4%
1// ==============================================================================2// Author: Simon-Pierre Boucher <contact@spboucher.ai>3// File: pages/Favoris.tsx4// Desc: Restos favoris ♥ « Mon univers Ka » du membre connecté — lus au hub5// Groupe KA (groupe-ka.com), magasin central des favoris du groupe :6// les mêmes ♥ suivent le membre sur toutes les plateformes ·Ka.7// ==============================================================================8import { useEffect, useState } from "react";9import { Link } from "react-router-dom";10import { useAccount } from "../account";11import { Restaurant, fetchFavorites } from "../api";12import RestoCard from "../components/RestoCard";13import { useFav } from "../favorites";1415export default function FavorisPage() {16 const { me } = useAccount();17 const { ready, connected, ids, items } = useFav();18 const [restos, setRestos] = useState<Restaurant[]>([]);19 const [loading, setLoading] = useState(true);2021 useEffect(() => {22 if (!ready) return;23 if (!connected) { setLoading(false); return; }24 fetchFavorites()25 .then((f) => setRestos(f.restaurants))26 .catch(() => {})27 .finally(() => setLoading(false));28 }, [ready, connected]);2930 if (ready && !connected) {31 return (32 <div className="notice container">33 <h2>Connectez-vous pour vos favoris</h2>34 <p>35 <a className="login-btn" href="/api/auth/ka/login" style={{ display: "inline-flex" }}>36 <span className="ka-badge" aria-hidden="true">KA</span>37 Se connecter avec KA ID38 </a>39 </p>40 <p>41 Un seul compte Groupe KA : vos ♥ vous suivent sur Resto·Ka, Lou·Ka,42 Food·Ka et toutes les plateformes ·Ka — c'est « Mon univers Ka ».43 </p>44 </div>45 );46 }4748 // fiches locales encore en favoris (le toggle retire la carte sans recharger)49 const shown = restos.filter((r) => ids.has(r.uid));50 // favoris du hub sans fiche locale (resto retiré du catalogue) : carte simple51 const known = new Set(restos.map((r) => r.uid));52 const extras = items.filter((i) => i.item_id && !known.has(i.item_id));5354 return (55 <div className="container sources">56 <span className="kicker">Mon univers Ka{me?.ka_id ? ` — ${me.ka_id}` : ""}</span>57 <h1>Mes restos favoris</h1>58 <p className="sub">59 Vos ♥ sont conservés au hub Groupe KA : les mêmes favoris, sur tous vos60 appareils et toutes les plateformes ·Ka.61 </p>62 {loading || !ready ? (63 <p>Chargement…</p>64 ) : shown.length === 0 && extras.length === 0 ? (65 <div className="notice">66 <h2>Aucun favori pour l'instant</h2>67 <p>Touchez le ♥ sur une fiche de resto pour l'épingler ici.</p>68 </div>69 ) : (70 <div className="grid">71 {shown.map((r) => <RestoCard key={r.uid} r={r} />)}72 {extras.map((i) => (73 <Link key={i.item_id} className="card"74 to={`/resto/${encodeURIComponent(i.item_id)}`}>75 <div className="card-img">76 {i.image_url77 ? <img src={i.image_url} alt={i.title} loading="lazy" />78 : <div className="noimg" />}79 </div>80 <div className="card-body">81 {i.price_label && <div className="card-price">{i.price_label}</div>}82 <div className="card-title">{i.title}</div>83 {i.subtitle && <div className="card-meta"><span>{i.subtitle}</span></div>}84 </div>85 </Link>86 ))}87 </div>88 )}89 </div>90 );91}92