import { useQuery } from "@tanstack/react-query"; import { Plus, Upload } from "lucide-react"; import { api } from "@/lib/api"; import { queryKeys } from "@/lib/queryKeys"; import { Button } from "@/components/ui/Button"; import { AppSidebar } from "./AppSidebar"; import { AppTopbar } from "./AppTopbar"; import { MobileTabBar } from "./MobileTabBar"; /** * Shell de l'app authentifiée : * - Desktop : sidebar fixe à gauche + main + topbar sticky en haut * - Mobile : pas de sidebar, topbar avec brand, tab bar fixe en bas * * Le bottom-padding mobile (pb-20) évite que le tab bar masque le contenu. */ type AppLayoutProps = { children: React.ReactNode; /** Titre du topbar (sinon greeting + date). */ title?: string; subtitle?: string; /** Actions à droite du topbar. */ actions?: React.ReactNode; }; type DashboardKpis = { rubisCount: number; rubisThisMonth: number; hoursLiberatedThisMonth: number; encaisseCents: number; encaisseDeltaCents: number; dsoDays: number; dsoDeltaDays: number; factureToRelance: number; factureInRelance: number; factureNewToday: number; miseEnDemeurePending: number; }; export function AppLayout({ children, title, subtitle, actions }: AppLayoutProps) { // KPIs partagés layout ↔ dashboard : on les charge ici pour que le sidebar // affiche le compteur sans attendre le rendu du dashboard. const { data: kpis } = useQuery({ queryKey: queryKeys.dashboard.kpis(), queryFn: () => api.get("/api/v1/dashboard/kpis"), staleTime: 30_000, }); // Actions globales par défaut (visibles desktop seulement). Sur mobile, // chaque route gère ses propres CTA en tête de contenu (cf. wireframe 4.3). const defaultActions = (
); return (
{children}
); }