spb/toit-ka Public
Toit-Ka — louer ou acheter un toit au Québec, un seul endroit (fusion Lou-Ka × Immo-Ka) — www.toit-ka.com
Python 40.2%
TypeScript 39%
CSS 20.2%
HTML 0.7%
1// -----------------------------------------------------------------------------2// Author: Simon-Pierre Boucher3// Contact: contact@spboucher.ai4// Project: Toit-Ka5// account.tsx : contexte de compte partagé — profil connecté + favoris ♥6// Un seul fetch au montage ; les favoris vivent au HUB Groupe KA (magasin7// central « Mon univers Ka ») : toggle optimiste, poussé au serveur qui8// relaie au hub. Non connecté -> clic ♥ redirige vers la connexion KA ID.9// -----------------------------------------------------------------------------10import {11 ReactNode, createContext, useCallback, useContext, useEffect, useState,12} from "react";13import {14 Listing, User, favItemFromListing, fetchFavorites, fetchMe, toggleFavorite,15} from "./api";1617interface AccountState {18 user: User | null;19 enabled: boolean;20 loaded: boolean;21 favs: Set<string>;22 toggleFav: (l: Listing) => void;23 refresh: () => void;24}2526const Ctx = createContext<AccountState>({27 user: null, enabled: false, loaded: false, favs: new Set(),28 toggleFav: () => {}, refresh: () => {},29});3031export const useAccount = () => useContext(Ctx);3233/** Redirige vers la connexion KA ID, avec retour sur la page courante. */34export function kaLogin() {35 const next = window.location.pathname + window.location.search;36 window.location.href = `/api/auth/ka/login?next=${encodeURIComponent(next)}`;37}3839export function AccountProvider({ children }: { children: ReactNode }) {40 const [user, setUser] = useState<User | null>(null);41 const [enabled, setEnabled] = useState(false);42 const [loaded, setLoaded] = useState(false);43 const [favs, setFavs] = useState<Set<string>>(new Set());4445 const refresh = useCallback(() => {46 fetchMe()47 .then((r) => {48 setUser(r.user);49 setEnabled(r.enabled !== false);50 setLoaded(true);51 if (r.user && r.user.ka_id) {52 fetchFavorites()53 .then((f) => setFavs(new Set(f.ids)))54 .catch(() => setFavs(new Set()));55 } else {56 setFavs(new Set());57 }58 })59 .catch(() => { setUser(null); setLoaded(true); });60 }, []);6162 useEffect(() => { refresh(); }, [refresh]);6364 const toggleFav = useCallback((l: Listing) => {65 if (!user || !user.ka_id) { kaLogin(); return; }66 setFavs((prev) => {67 const next = new Set(prev);68 const on = !next.has(l.uid);69 if (on) next.add(l.uid); else next.delete(l.uid);70 toggleFavorite(on, favItemFromListing(l)).catch((e) => {71 if (String(e).includes("401")) kaLogin();72 });73 return next;74 });75 }, [user]);7677 return (78 <Ctx.Provider value={{ user, enabled, loaded, favs, toggleFav, refresh }}>79 {children}80 </Ctx.Provider>81 );82}83