SPB Git forge

spb/immo-ka

Public

Immo-Ka — agrégateur des propriétés à vendre au Québec (73 connecteurs, ~40 000 annonces, React+FastAPI)

112commits 1branches 0releases
125.4 MBsize
maindefault branch
13 days agolast push
Python 47.5% HTML 27.9% TypeScript 15.5% CSS 7.2% JavaScript 2%
3.1 KB · 84 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// account.tsx : contexte de compte partagé — profil connecté + favoris ♥5//   Un seul fetch au montage de l'app ; le cœur des cartes, la fiche et le6//   menu compte lisent le même état. Les favoris vivent au HUB Groupe KA7//   (magasin central « Mon univers Ka ») : le toggle est optimiste à l'écran8//   et poussé au serveur qui relaie au hub. Non connecté -> clic ♥ redirige9//   vers la connexion KA ID (retour sur la page courante).10// -----------------------------------------------------------------------------11import {12  ReactNode, createContext, useCallback, useContext, useEffect, useState,13} from "react";14import {15  Listing, User, favItemFromListing, fetchFavorites, fetchMe, toggleFavorite,16} from "./api";1718interface AccountState {19  user: User | null;20  enabled: boolean;                   // connexion configurée côté serveur21  loaded: boolean;                    // premier fetch terminé22  favs: Set<string>;                  // uids favoris (miroir du hub)23  toggleFav: (l: Listing) => void;24  refresh: () => void;                // re-fetch profil + favoris (après login)25}2627const Ctx = createContext<AccountState>({28  user: null, enabled: false, loaded: false, favs: new Set(),29  toggleFav: () => {}, refresh: () => {},30});3132export const useAccount = () => useContext(Ctx);3334/** Redirige vers la connexion KA ID, avec retour sur la page courante. */35export function kaLogin() {36  const next = window.location.pathname + window.location.search;37  window.location.href = `/api/auth/ka/login?next=${encodeURIComponent(next)}`;38}3940export function AccountProvider({ children }: { children: ReactNode }) {41  const [user, setUser] = useState<User | null>(null);42  const [enabled, setEnabled] = useState(false);43  const [loaded, setLoaded] = useState(false);44  const [favs, setFavs] = useState<Set<string>>(new Set());4546  const refresh = useCallback(() => {47    fetchMe()48      .then((r) => {49        setUser(r.user);50        setEnabled(r.enabled !== false);51        setLoaded(true);52        if (r.user && r.user.ka_id) {53          fetchFavorites()54            .then((f) => setFavs(new Set(f.ids)))55            .catch(() => setFavs(new Set()));56        } else {57          setFavs(new Set());58        }59      })60      .catch(() => { setUser(null); setLoaded(true); });61  }, []);6263  useEffect(() => { refresh(); }, [refresh]);6465  const toggleFav = useCallback((l: Listing) => {66    if (!user || !user.ka_id) { kaLogin(); return; }   // ♥ = compte KA requis67    setFavs((prev) => {68      const next = new Set(prev);69      const on = !next.has(l.uid);70      if (on) next.add(l.uid); else next.delete(l.uid);71      toggleFavorite(on, favItemFromListing(l)).catch((e) => {72        if (String(e).includes("401")) kaLogin();      // session expirée73      });74      return next;75    });76  }, [user]);7778  return (79    <Ctx.Provider value={{ user, enabled, loaded, favs, toggleFav, refresh }}>80      {children}81    </Ctx.Provider>82  );83}84