mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-15 03:09:32 +02:00
Improve task management by handling date errors and ensuring data integrity
Implement robust error handling and data validation for task dates and properties in both frontend and backend to resolve production issues. Replit-Commit-Author: Agent Replit-Commit-Session-Id: cc2d271b-82f0-4d6a-9302-a0b067ffb429 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/cc2d271b-82f0-4d6a-9302-a0b067ffb429/0taewQN
This commit is contained in:
1 parent
aa1906a9bb
commit
0d863da97e
7 files changed
+765
-56
No files matched your search
+89
-48
@@ -59,27 +59,55 @@ export default function Tasks() {
|
||||
const [taskToDelete, setTaskToDelete] = useState<TaskWithRelations | null>(null);
|
||||
|
||||
// Fetch tasks - attendre que l'initialisation des stores soit terminée pour les admins
|
||||
const { data: tasks = [], isLoading } = useQuery({
|
||||
const { data: tasks = [], isLoading, error } = useQuery({
|
||||
queryKey: ["/api/tasks", selectedStoreId],
|
||||
queryFn: () => {
|
||||
const params = new URLSearchParams();
|
||||
if (selectedStoreId && user?.role === 'admin') {
|
||||
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()}`, {
|
||||
credentials: 'include'
|
||||
}).then(res => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP error! status: ${res.status}`);
|
||||
queryFn: async () => {
|
||||
try {
|
||||
const params = new URLSearchParams();
|
||||
if (selectedStoreId && user?.role === 'admin') {
|
||||
params.append('storeId', selectedStoreId.toString());
|
||||
}
|
||||
return res.json();
|
||||
});
|
||||
console.log('📋 TASKS QUERY - Fetching with params:', {
|
||||
selectedStoreId,
|
||||
userRole: user?.role,
|
||||
storeInitialized,
|
||||
url: `/api/tasks?${params.toString()}`
|
||||
});
|
||||
|
||||
const response = await fetch(`/api/tasks?${params.toString()}`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
console.log('📋 TASKS QUERY - Response received:', {
|
||||
dataType: typeof data,
|
||||
isArray: Array.isArray(data),
|
||||
length: data?.length,
|
||||
firstTask: data?.[0] ? {
|
||||
id: data[0].id,
|
||||
title: data[0].title,
|
||||
hasStartDate: !!data[0].startDate,
|
||||
hasGroup: !!data[0].group
|
||||
} : null
|
||||
});
|
||||
|
||||
// Valider et nettoyer les données reçues
|
||||
if (!Array.isArray(data)) {
|
||||
console.error('Tasks API returned non-array data:', data);
|
||||
return [];
|
||||
}
|
||||
|
||||
return data.filter(task => task && typeof task === 'object' && task.id);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching tasks:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
enabled: !!user && (user.role !== 'admin' || storeInitialized),
|
||||
});
|
||||
@@ -318,40 +346,53 @@ export default function Tasks() {
|
||||
const getStartDateStatus = (startDate: Date | string | null) => {
|
||||
if (!startDate) return null;
|
||||
|
||||
const start = new Date(startDate);
|
||||
const now = new Date();
|
||||
const daysDiff = differenceInDays(start, now);
|
||||
|
||||
if (isPast(start)) {
|
||||
return {
|
||||
type: 'started',
|
||||
color: 'default' as const,
|
||||
icon: CheckCircle,
|
||||
label: 'Démarrée',
|
||||
text: 'Active'
|
||||
};
|
||||
} else if (isToday(start)) {
|
||||
return {
|
||||
type: 'today',
|
||||
color: 'secondary' as const,
|
||||
icon: CalendarClock,
|
||||
label: "Démarre aujourd'hui",
|
||||
text: "Aujourd'hui"
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: 'future',
|
||||
color: 'outline' as const,
|
||||
icon: Clock,
|
||||
label: `Démarre dans ${daysDiff} jour${daysDiff > 1 ? 's' : ''}`,
|
||||
text: `+${daysDiff}j`
|
||||
};
|
||||
try {
|
||||
const start = new Date(startDate);
|
||||
if (isNaN(start.getTime())) return null;
|
||||
|
||||
const now = new Date();
|
||||
const daysDiff = differenceInDays(start, now);
|
||||
|
||||
if (isPast(start)) {
|
||||
return {
|
||||
type: 'started',
|
||||
color: 'default' as const,
|
||||
icon: CheckCircle,
|
||||
label: 'Démarrée',
|
||||
text: 'Active'
|
||||
};
|
||||
} else if (isToday(start)) {
|
||||
return {
|
||||
type: 'today',
|
||||
color: 'secondary' as const,
|
||||
icon: CalendarClock,
|
||||
label: "Démarre aujourd'hui",
|
||||
text: "Aujourd'hui"
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
type: 'future',
|
||||
color: 'outline' as const,
|
||||
icon: Clock,
|
||||
label: `Démarre dans ${daysDiff} jour${daysDiff > 1 ? 's' : ''}`,
|
||||
text: `+${daysDiff}j`
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error parsing start date:', error, startDate);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Fonction pour déterminer si une tâche est future (pas encore commencée)
|
||||
const isTaskFuture = (task: TaskWithRelations) => {
|
||||
return task.isFutureTask || (task.startDate && !isPast(new Date(task.startDate)));
|
||||
if (!task) return false;
|
||||
try {
|
||||
return task.isFutureTask || (task.startDate && !isPast(new Date(task.startDate)));
|
||||
} catch (error) {
|
||||
console.warn('Error checking if task is future:', error, task);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const canCreateTasks = user?.role === 'admin' || user?.role === 'manager' || user?.role === 'directeur';
|
||||
|
||||
Reference in new issue
Block a user