feat: implement dashboard page with store-specific stats, announcement modals, and DLC alerts

This commit is contained in:
Michael committed 2026-04-02 09:25:09 +02:00
1 parent b090c8f36a
commit 475c52cede
3 files changed
+7 -94

No files matched your search

+2 -50
View File
@@ -28,9 +28,7 @@ export default function Layout({ children }: LayoutProps) {
const [selectedStoreId, setSelectedStoreId] = useState<number | null>(() => { const [selectedStoreId, setSelectedStoreId] = useState<number | null>(() => {
// Restaurer le selectedStoreId depuis localStorage si disponible // Restaurer le selectedStoreId depuis localStorage si disponible
const saved = localStorage.getItem('selectedStoreId'); const saved = localStorage.getItem('selectedStoreId');
const restoredId = saved ? parseInt(saved) : null; return saved ? parseInt(saved) : null;
console.log('🏪 Layout - Restoring selectedStoreId from localStorage:', { saved, restoredId });
return restoredId;
}); });
const [storeInitialized, setStoreInitialized] = useState(false); const [storeInitialized, setStoreInitialized] = useState(false);
@@ -39,10 +37,8 @@ export default function Layout({ children }: LayoutProps) {
// Restaurer l'état de la sidebar depuis localStorage, mais forcer collapsed sur mobile // Restaurer l'état de la sidebar depuis localStorage, mais forcer collapsed sur mobile
try { try {
const saved = localStorage.getItem('sidebarCollapsed'); const saved = localStorage.getItem('sidebarCollapsed');
console.log('🔧 Layout - Restoring sidebar state:', { saved, isMobile });
return isMobile ? true : (saved ? JSON.parse(saved) : false); return isMobile ? true : (saved ? JSON.parse(saved) : false);
} catch (error) { } catch {
console.error('Error reading sidebar state from localStorage:', error);
return isMobile ? true : false; return isMobile ? true : false;
} }
}); });
@@ -63,55 +59,21 @@ export default function Layout({ children }: LayoutProps) {
if (selectedStoreId) { if (selectedStoreId) {
const storeExists = stores.find(store => store.id === selectedStoreId); const storeExists = stores.find(store => store.id === selectedStoreId);
if (!storeExists) { if (!storeExists) {
console.log('🏪 Selected store not found in available stores, clearing selection:', {
selectedStoreId,
userRole: user.role,
availableStores: stores.map(s => s.id)
});
setSelectedStoreId(null); setSelectedStoreId(null);
localStorage.removeItem('selectedStoreId'); localStorage.removeItem('selectedStoreId');
needsUpdate = true; needsUpdate = true;
} else {
console.log('🏪 Selected store validated successfully:', {
selectedStoreId,
userRole: user.role,
storeName: storeExists.name
});
} }
} }
// IMPORTANT FIX: Pour les rôles directeur/manager, forcer la sélection d'un magasin spécifique // IMPORTANT FIX: Pour les rôles directeur/manager, forcer la sélection d'un magasin spécifique
// si aucun n'est sélectionné et qu'ils n'ont accès qu'à un seul magasin // si aucun n'est sélectionné et qu'ils n'ont accès qu'à un seul magasin
if ((user.role === 'directeur' || user.role === 'manager') && !selectedStoreId && stores.length === 1 && !needsUpdate) { if ((user.role === 'directeur' || user.role === 'manager') && !selectedStoreId && stores.length === 1 && !needsUpdate) {
console.log('🏪 Auto-selecting single available store for directeur/manager:', {
storeId: stores[0].id,
storeName: stores[0].name,
userRole: user.role,
userId: user.id,
previousSelectedStoreId: selectedStoreId,
timestamp: new Date().toISOString()
});
const singleStoreId = stores[0].id; const singleStoreId = stores[0].id;
setSelectedStoreId(singleStoreId); setSelectedStoreId(singleStoreId);
localStorage.setItem('selectedStoreId', singleStoreId.toString()); localStorage.setItem('selectedStoreId', singleStoreId.toString());
} }
// VALIDATION CRITIQUE: Pour les directeurs/managers, s'assurer qu'un magasin est toujours sélectionné // VALIDATION CRITIQUE: Pour les directeurs/managers, s'assurer qu'un magasin est toujours sélectionné
if ((user.role === 'directeur' || user.role === 'manager') && !selectedStoreId && !needsUpdate) {
console.log('🚨 CRITICAL: Directeur/Manager has no store selected, this will cause empty data display:', {
userId: user.id,
userRole: user.role,
availableStores: stores.map(s => ({ id: s.id, name: s.name }))
});
}
console.log('🏪 Store initialization complete:', {
user: user.role,
selectedStoreId,
storesCount: stores.length,
validatedStore: selectedStoreId ? stores.find(s => s.id === selectedStoreId)?.name : 'None',
autoSelected: (user.role === 'directeur' || user.role === 'manager') && !selectedStoreId && stores.length === 1
});
setStoreInitialized(true); setStoreInitialized(true);
} }
}, [user, stores, selectedStoreId]); }, [user, stores, selectedStoreId]);
@@ -172,15 +134,7 @@ export default function Layout({ children }: LayoutProps) {
<Select <Select
value={selectedStoreId?.toString() || (user.role === 'admin' ? "all" : "")} value={selectedStoreId?.toString() || (user.role === 'admin' ? "all" : "")}
onValueChange={(value) => { onValueChange={(value) => {
console.log('🏪 Store selector changed:', {
value,
userRole: user.role,
parsed: value === "all" ? null : parseInt(value)
});
const newStoreId = value === "all" ? null : parseInt(value); const newStoreId = value === "all" ? null : parseInt(value);
// Invalider toutes les variantes de queryKey pour changement magasin
console.log('🧹 Invalidating data caches for store change');
queryClient.invalidateQueries({ queryClient.invalidateQueries({
predicate: (query) => { predicate: (query) => {
const key = query.queryKey; const key = query.queryKey;
@@ -194,10 +148,8 @@ export default function Layout({ children }: LayoutProps) {
// Sauvegarder dans localStorage et mettre à jour l'état // Sauvegarder dans localStorage et mettre à jour l'état
if (newStoreId) { if (newStoreId) {
localStorage.setItem('selectedStoreId', newStoreId.toString()); localStorage.setItem('selectedStoreId', newStoreId.toString());
console.log('💾 Store saved to localStorage:', newStoreId);
} else { } else {
localStorage.removeItem('selectedStoreId'); localStorage.removeItem('selectedStoreId');
console.log('🗑️ Store removed from localStorage');
} }
setSelectedStoreId(newStoreId); setSelectedStoreId(newStoreId);
}} }}
+3 -23
View File
@@ -184,11 +184,6 @@ export default function Sidebar() {
} }
}; };
// Debug logging pour production
console.log('Sidebar - User:', user);
console.log('Sidebar - isLoading:', isLoading);
console.log('Sidebar - error:', error);
const handleLogout = async () => { const handleLogout = async () => {
try { try {
// Force logout via fetch to ensure session is destroyed // Force logout via fetch to ensure session is destroyed
@@ -206,13 +201,11 @@ export default function Sidebar() {
const toggleSidebar = () => { const toggleSidebar = () => {
const newCollapsed = !sidebarCollapsed; const newCollapsed = !sidebarCollapsed;
console.log('🔧 Sidebar - Toggling sidebar:', { from: sidebarCollapsed, to: newCollapsed });
setSidebarCollapsed(newCollapsed); setSidebarCollapsed(newCollapsed);
try { try {
localStorage.setItem('sidebarCollapsed', JSON.stringify(newCollapsed)); localStorage.setItem('sidebarCollapsed', JSON.stringify(newCollapsed));
console.log('💾 Sidebar state saved to localStorage:', newCollapsed); } catch {
} catch (error) { // ignore
console.error('Error saving sidebar state:', error);
} }
}; };
@@ -363,12 +356,7 @@ export default function Sidebar() {
]; ];
const hasPermission = (roles: string[]) => { const hasPermission = (roles: string[]) => {
const hasRole = user?.role && roles.includes(user.role); return user?.role && roles.includes(user.role);
// Debug uniquement en développement pour éviter spam console
if (import.meta.env.MODE === 'development') {
console.log('hasPermission check:', { userRole: user?.role, roles, hasRole });
}
return hasRole;
}; };
@@ -391,14 +379,6 @@ export default function Sidebar() {
const sidebarClasses = getSidebarClasses(); const sidebarClasses = getSidebarClasses();
// Debug log pour vérifier l'état de la sidebar
console.log('🔧 Sidebar Debug:', {
isMobile,
sidebarCollapsed,
mobileMenuOpen,
width: sidebarCollapsed ? 'collapsed (64px)' : 'expanded (256px)',
classes: sidebarClasses
});
// Si l'utilisateur n'est pas encore chargé, afficher un état de chargement // Si l'utilisateur n'est pas encore chargé, afficher un état de chargement
if (isLoading) { if (isLoading) {
+2 -21
View File
@@ -308,15 +308,9 @@ export default function Dashboard() {
}) : []; // Afficher toutes les commandes en attente }) : []; // Afficher toutes les commandes en attente
const upcomingDeliveries = Array.isArray(allDeliveries) ? allDeliveries const upcomingDeliveries = Array.isArray(allDeliveries) ? allDeliveries
.filter((d: any) => { .filter((d: any) => d.status === 'planned')
const isPlanned = d.status === 'planned';
console.log('🚚 Dashboard - Delivery filter:', { id: d.id, status: d.status, isPlanned, scheduledDate: d.scheduledDate });
return isPlanned;
})
.sort((a: any, b: any) => new Date(a.scheduledDate).getTime() - new Date(b.scheduledDate).getTime()) .sort((a: any, b: any) => new Date(a.scheduledDate).getTime() - new Date(b.scheduledDate).getTime())
.slice(0, 4) : []; // Afficher les 4 prochaines livraisons .slice(0, 4) : [];
console.log('🚚 Dashboard - Upcoming deliveries result:', upcomingDeliveries.length, upcomingDeliveries);
// Calculs pour les statistiques // Calculs pour les statistiques
const pendingOrdersCount = Array.isArray(allOrders) ? allOrders.filter((order: any) => order.status === 'pending').length : 0; const pendingOrdersCount = Array.isArray(allOrders) ? allOrders.filter((order: any) => order.status === 'pending').length : 0;
@@ -373,19 +367,6 @@ export default function Dashboard() {
} }
}; };
console.log('📊 Dashboard Debug - Raw Data:', {
allOrders: Array.isArray(allOrders) ? allOrders.length : 'NOT_ARRAY',
allDeliveries: Array.isArray(allDeliveries) ? allDeliveries.length : 'NOT_ARRAY',
customerOrders: Array.isArray(customerOrders) ? customerOrders.length : 'NOT_ARRAY',
upcomingPublicities: Array.isArray(upcomingPublicities) ? upcomingPublicities.length : 'NOT_ARRAY',
stats: stats,
samples: {
order: Array.isArray(allOrders) && allOrders.length > 0 ? allOrders[0] : null,
delivery: Array.isArray(allDeliveries) && allDeliveries.length > 0 ? allDeliveries[0] : null,
customerOrder: Array.isArray(customerOrders) && customerOrders.length > 0 ? customerOrders[0] : null,
publicity: Array.isArray(upcomingPublicities) && upcomingPublicities.length > 0 ? upcomingPublicities[0] : null
}
});
// Statistiques pour les commandes clients // Statistiques pour les commandes clients
const ordersByStatus = { const ordersByStatus = {