diff --git a/client/src/components/RouterProduction.tsx b/client/src/components/RouterProduction.tsx index 06d4f79..225106b 100644 --- a/client/src/components/RouterProduction.tsx +++ b/client/src/components/RouterProduction.tsx @@ -30,6 +30,7 @@ import PaymentSchedulePage from "@/pages/PaymentSchedulePage"; import Layout from "@/components/Layout"; // Mobile pages +import MobileApp from "@/pages/mobile/MobileApp"; import MobileDashboardPage from "@/pages/mobile/DashboardPage"; import MobileOrdersPage from "@/pages/mobile/OrdersPage"; import MobileDeliveriesPage from "@/pages/mobile/DeliveriesPage"; @@ -85,44 +86,46 @@ function RouterProduction() { ); } - // ===== MOBILE ROUTES (sans Layout standard) ===== + // ===== MOBILE ROUTES (avec MobileApp pour StoreProvider) ===== if (isMobile) { return ( - - - - - - + + + + + + + - {/* Pages sans version mobile - utiliser version desktop dans Layout pour l'instant */} - - - - - - - - - - - - - + {/* Pages sans version mobile - utiliser version desktop pour l'instant */} + + + + + + + + + + + + + - {/* Redirection /auth vers dashboard */} - - {() => { - if (typeof window !== 'undefined') { - window.location.href = '/dashboard'; - } - return ; - }} - + {/* Redirection /auth vers dashboard */} + + {() => { + if (typeof window !== 'undefined') { + window.location.href = '/dashboard'; + } + return ; + }} + - - - + + + + ); } diff --git a/client/src/pages/mobile/MobileApp.tsx b/client/src/pages/mobile/MobileApp.tsx new file mode 100644 index 0000000..70c1c07 --- /dev/null +++ b/client/src/pages/mobile/MobileApp.tsx @@ -0,0 +1,71 @@ +/** + * MobileApp - Wrapper pour l'application mobile avec StoreProvider + * Fournit le contexte Store à toutes les pages mobiles + */ +import { ReactNode, useState, useEffect } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { useAuthUnified } from "@/hooks/useAuthUnified"; +import { StoreProvider } from "@/contexts/StoreContext"; +import type { Group } from "@shared/schema"; + +interface MobileAppProps { + children: ReactNode; +} + +export default function MobileApp({ children }: MobileAppProps) { + const { user } = useAuthUnified(); + + // Store state management + const [selectedStoreId, setSelectedStoreId] = useState(() => { + if (typeof window === 'undefined') return null; + const saved = localStorage.getItem('selectedStoreId'); + return saved ? parseInt(saved) : null; + }); + const [sidebarCollapsed, setSidebarCollapsed] = useState(false); + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + const [storeInitialized, setStoreInitialized] = useState(false); + + // Fetch stores + const { data: stores = [] } = useQuery({ + queryKey: ['/api/groups'], + enabled: !!user, + }); + + // Initialize store selection + useEffect(() => { + if (user && stores.length > 0) { + if ((user.role === 'directeur' || user.role === 'manager') && !selectedStoreId && stores.length === 1) { + const singleStoreId = stores[0].id; + setSelectedStoreId(singleStoreId); + localStorage.setItem('selectedStoreId', singleStoreId.toString()); + } + setStoreInitialized(true); + } + }, [user, stores, selectedStoreId]); + + // Sync selectedStoreId to localStorage + useEffect(() => { + if (selectedStoreId) { + localStorage.setItem('selectedStoreId', selectedStoreId.toString()); + } else { + localStorage.removeItem('selectedStoreId'); + } + }, [selectedStoreId]); + + const storeContextValue = { + selectedStoreId, + setSelectedStoreId, + stores, + sidebarCollapsed, + setSidebarCollapsed, + mobileMenuOpen, + setMobileMenuOpen, + storeInitialized + }; + + return ( + + {children} + + ); +} diff --git a/client/src/pages/mobile/MobileLayout.tsx b/client/src/pages/mobile/MobileLayout.tsx index 1937781..6e1532a 100644 --- a/client/src/pages/mobile/MobileLayout.tsx +++ b/client/src/pages/mobile/MobileLayout.tsx @@ -1,13 +1,12 @@ /** * MobileLayout - Layout dédié pour l'application mobile * Affiche le magasin sélectionné de manière visible et une navigation bottom - * Inclut son propre StoreProvider + * Note: Le StoreProvider est fourni par MobileApp au niveau supérieur */ -import { ReactNode, useState, useEffect } from "react"; -import { useQuery } from "@tanstack/react-query"; +import { ReactNode, useState } from "react"; import { Menu, Store, ChevronDown, LogOut } from "lucide-react"; import { useAuthUnified } from "@/hooks/useAuthUnified"; -import { StoreProvider } from "@/contexts/StoreContext"; +import { useStore } from "@/contexts/StoreContext"; import { Button } from "@/components/ui/button"; import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/components/ui/sheet"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; @@ -19,15 +18,9 @@ interface MobileLayoutProps { title?: string; } -// Inner component that uses the store context -function MobileLayoutInner({ children, title, selectedStoreId, setSelectedStoreId, stores, user }: { - children: ReactNode; - title?: string; - selectedStoreId: number | null; - setSelectedStoreId: (id: number | null) => void; - stores: Group[]; - user: any; -}) { +export default function MobileLayout({ children, title }: MobileLayoutProps) { + const { user } = useAuthUnified(); + const { selectedStoreId, setSelectedStoreId, stores } = useStore(); const [menuOpen, setMenuOpen] = useState(false); // Get selected store name @@ -183,61 +176,3 @@ function MobileLayoutInner({ children, title, selectedStoreId, setSelectedStoreI ); } - -// Main MobileLayout component with StoreProvider -export default function MobileLayout({ children, title }: MobileLayoutProps) { - const { user } = useAuthUnified(); - - // Store state management - const [selectedStoreId, setSelectedStoreId] = useState(() => { - const saved = localStorage.getItem('selectedStoreId'); - return saved ? parseInt(saved) : null; - }); - const [sidebarCollapsed, setSidebarCollapsed] = useState(false); - const [mobileMenuOpen, setMobileMenuOpen] = useState(false); - const [storeInitialized, setStoreInitialized] = useState(false); - - // Fetch stores - const { data: stores = [] } = useQuery({ - queryKey: ['/api/groups'], - enabled: !!user, - }); - - // Initialize store selection - useEffect(() => { - if (user && stores.length > 0) { - if ((user.role === 'directeur' || user.role === 'manager') && !selectedStoreId && stores.length === 1) { - const singleStoreId = stores[0].id; - setSelectedStoreId(singleStoreId); - localStorage.setItem('selectedStoreId', singleStoreId.toString()); - } - setStoreInitialized(true); - } - }, [user, stores, selectedStoreId]); - - const storeContextValue = { - selectedStoreId, - setSelectedStoreId, - stores, - sidebarCollapsed, - setSidebarCollapsed, - mobileMenuOpen, - setMobileMenuOpen, - storeInitialized - }; - - return ( - - - {children} - - - ); -} -