mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-23 06:58:19 +02:00
Merge pull request #170 from R0m1k3/1.1
Ensure tasks display correctly for selected stores by admins
This commit is contained in:
3 files changed
+47
-8
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
import { ReactNode, useState, createContext, useContext } from "react";
|
import { ReactNode, useState, createContext, useContext, useEffect } from "react";
|
||||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -18,6 +18,7 @@ interface StoreContextType {
|
|||||||
setSidebarCollapsed: (collapsed: boolean) => void;
|
setSidebarCollapsed: (collapsed: boolean) => void;
|
||||||
mobileMenuOpen: boolean;
|
mobileMenuOpen: boolean;
|
||||||
setMobileMenuOpen: (open: boolean) => void;
|
setMobileMenuOpen: (open: boolean) => void;
|
||||||
|
storeInitialized: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StoreContext = createContext<StoreContextType | undefined>(undefined);
|
const StoreContext = createContext<StoreContextType | undefined>(undefined);
|
||||||
@@ -46,6 +47,8 @@ export default function Layout({ children }: LayoutProps) {
|
|||||||
console.log('🏪 Layout - Restoring selectedStoreId from localStorage:', { saved, restoredId });
|
console.log('🏪 Layout - Restoring selectedStoreId from localStorage:', { saved, restoredId });
|
||||||
return restoredId;
|
return restoredId;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [storeInitialized, setStoreInitialized] = useState(false);
|
||||||
|
|
||||||
const [sidebarCollapsed, setSidebarCollapsed] = useState<boolean>(() => {
|
const [sidebarCollapsed, setSidebarCollapsed] = useState<boolean>(() => {
|
||||||
// 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
|
||||||
@@ -60,12 +63,34 @@ export default function Layout({ children }: LayoutProps) {
|
|||||||
enabled: !!user,
|
enabled: !!user,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Effet pour marquer l'initialisation comme terminée
|
||||||
|
useEffect(() => {
|
||||||
|
if (user && stores.length > 0) {
|
||||||
|
// Pour les admins, vérifier que selectedStoreId est cohérent avec les stores disponibles
|
||||||
|
if (user.role === 'admin' && selectedStoreId) {
|
||||||
|
const storeExists = stores.find(store => store.id === selectedStoreId);
|
||||||
|
if (!storeExists) {
|
||||||
|
console.log('🏪 Selected store not found in available stores, clearing selection');
|
||||||
|
setSelectedStoreId(null);
|
||||||
|
localStorage.removeItem('selectedStoreId');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🏪 Store initialization complete:', {
|
||||||
|
user: user.role,
|
||||||
|
selectedStoreId,
|
||||||
|
storesCount: stores.length
|
||||||
|
});
|
||||||
|
setStoreInitialized(true);
|
||||||
|
}
|
||||||
|
}, [user, stores, selectedStoreId]);
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
window.location.href = "/api/logout";
|
window.location.href = "/api/logout";
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StoreContext.Provider value={{ selectedStoreId, setSelectedStoreId, stores, sidebarCollapsed, setSidebarCollapsed, mobileMenuOpen, setMobileMenuOpen }}>
|
<StoreContext.Provider value={{ selectedStoreId, setSelectedStoreId, stores, sidebarCollapsed, setSidebarCollapsed, mobileMenuOpen, setMobileMenuOpen, storeInitialized }}>
|
||||||
<div className="layout-container flex bg-gray-50">
|
<div className="layout-container flex bg-gray-50">
|
||||||
{/* Mobile overlay */}
|
{/* Mobile overlay */}
|
||||||
{isMobile && mobileMenuOpen && (
|
{isMobile && mobileMenuOpen && (
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ type TaskWithRelations = Task & {
|
|||||||
|
|
||||||
export default function Tasks() {
|
export default function Tasks() {
|
||||||
const { user } = useAuthUnified();
|
const { user } = useAuthUnified();
|
||||||
const { selectedStoreId } = useStore();
|
const { selectedStoreId, storeInitialized } = useStore();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
@@ -57,14 +57,20 @@ export default function Tasks() {
|
|||||||
const [selectedTask, setSelectedTask] = useState<TaskWithRelations | null>(null);
|
const [selectedTask, setSelectedTask] = useState<TaskWithRelations | null>(null);
|
||||||
const [taskToDelete, setTaskToDelete] = useState<TaskWithRelations | null>(null);
|
const [taskToDelete, setTaskToDelete] = useState<TaskWithRelations | null>(null);
|
||||||
|
|
||||||
// Fetch tasks
|
// Fetch tasks - attendre que l'initialisation des stores soit terminée pour les admins
|
||||||
const { data: tasks = [], isLoading } = useQuery({
|
const { data: tasks = [], isLoading } = useQuery({
|
||||||
queryKey: ["/api/tasks", selectedStoreId],
|
queryKey: ["/api/tasks", selectedStoreId],
|
||||||
queryFn: () => {
|
queryFn: () => {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
if (selectedStoreId) {
|
if (selectedStoreId && user?.role === 'admin') {
|
||||||
params.append('storeId', selectedStoreId.toString());
|
params.append('storeId', selectedStoreId.toString());
|
||||||
}
|
}
|
||||||
|
console.log('📋 TASKS QUERY - Fetching with params:', {
|
||||||
|
selectedStoreId,
|
||||||
|
userRole: user?.role,
|
||||||
|
storeInitialized,
|
||||||
|
url: `/api/tasks?${params.toString()}`
|
||||||
|
});
|
||||||
return fetch(`/api/tasks?${params.toString()}`, {
|
return fetch(`/api/tasks?${params.toString()}`, {
|
||||||
credentials: 'include'
|
credentials: 'include'
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
@@ -74,7 +80,7 @@ export default function Tasks() {
|
|||||||
return res.json();
|
return res.json();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
enabled: !!user,
|
enabled: !!user && (user.role !== 'admin' || storeInitialized),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch users for task assignment - seulement pour admin/manager/directeur
|
// Fetch users for task assignment - seulement pour admin/manager/directeur
|
||||||
|
|||||||
+10
-2
@@ -1265,11 +1265,19 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
userRole: user.role,
|
userRole: user.role,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
requestedStoreId: storeId,
|
requestedStoreId: storeId,
|
||||||
userGroups: user.role !== 'admin' ? user.userGroups.map(ug => ug.groupId) : 'all'
|
userGroups: user.role !== 'admin' ? user.userGroups.map(ug => ug.groupId) : 'all',
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
});
|
});
|
||||||
|
|
||||||
const tasks = await storage.getTasks(groupIds);
|
const tasks = await storage.getTasks(groupIds);
|
||||||
console.log('📋 Tasks returned:', tasks.length, 'items for user:', user.id);
|
console.log('📋 Tasks returned:', {
|
||||||
|
count: tasks.length,
|
||||||
|
userId: user.id,
|
||||||
|
userRole: user.role,
|
||||||
|
requestedStoreId: storeId,
|
||||||
|
groupIds,
|
||||||
|
taskGroups: tasks.map(t => ({ id: t.id, title: t.title, groupId: t.groupId })).slice(0, 3)
|
||||||
|
});
|
||||||
res.json(tasks);
|
res.json(tasks);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching tasks:", error);
|
console.error("Error fetching tasks:", error);
|
||||||
|
|||||||
Reference in new issue
Block a user