import { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useAuthUnified } from "@/hooks/useAuthUnified"; import { useStore } from "@/contexts/StoreContext"; import { useToast } from "@/hooks/use-toast"; import { apiRequest } from "@/lib/queryClient"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { ListTodo, Plus, Search, Circle, Clock, AlertTriangle, CheckCircle, Edit, Trash2 } from "lucide-react"; import { format } from "date-fns"; import { fr } from "date-fns/locale"; import { Task } from "@shared/schema"; type TaskWithRelations = Task & { creator: { id: string; username: string; name: string; }; group: { id: number; name: string; color: string; }; }; export default function TasksSimplified() { const { user } = useAuthUnified(); const { selectedStoreId } = useStore(); const { toast } = useToast(); const queryClient = useQueryClient(); // États locaux const [searchTerm, setSearchTerm] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); const [priorityFilter, setPriorityFilter] = useState("all"); // Modals et tâche sélectionnée const [showCreateModal, setShowCreateModal] = useState(false); const [showEditModal, setShowEditModal] = useState(false); const [selectedTask, setSelectedTask] = useState(null); // Récupération des tâches const { data: tasks = [], isLoading } = useQuery({ queryKey: ["/api/tasks", selectedStoreId], queryFn: () => { const params = new URLSearchParams(); if (selectedStoreId) { params.append('storeId', selectedStoreId.toString()); } return fetch(`/api/tasks?${params.toString()}`).then(res => res.json()); }, enabled: !!user, }); // Récupération des magasins const { data: stores = [] } = useQuery({ queryKey: ["/api/groups"], enabled: !!user, }); // Filtrer les tâches const filteredTasks = tasks.filter((task: TaskWithRelations) => { const matchesSearch = task.title.toLowerCase().includes(searchTerm.toLowerCase()) || task.description?.toLowerCase().includes(searchTerm.toLowerCase()) || task.assignedTo?.toLowerCase().includes(searchTerm.toLowerCase()); const matchesStatus = statusFilter === "all" || task.status === statusFilter; const matchesPriority = priorityFilter === "all" || task.priority === priorityFilter; return matchesSearch && matchesStatus && matchesPriority; }); // Création d'une tâche const handleCreateTask = async (taskData: any) => { try { const finalData = { ...taskData, groupId: selectedStoreId ? parseInt(selectedStoreId) : stores[0]?.id }; console.log('🔍 TasksSimplified - Creating task with data:', { selectedStoreId, storesLength: stores.length, finalGroupId: finalData.groupId, taskData: finalData }); await apiRequest('/api/tasks', 'POST', finalData); queryClient.invalidateQueries({ queryKey: ["/api/tasks"] }); setShowCreateModal(false); toast({ title: "Succès", description: "Tâche créée avec succès", }); } catch (error) { console.error('❌ TasksSimplified - Error creating task:', error); toast({ title: "Erreur", description: "Impossible de créer la tâche", variant: "destructive", }); } }; // Modification d'une tâche const handleUpdateTask = async (taskData: any) => { if (!selectedTask) return; try { await apiRequest(`/api/tasks/${selectedTask.id}`, 'PUT', taskData); queryClient.invalidateQueries({ queryKey: ["/api/tasks"] }); setShowEditModal(false); setSelectedTask(null); toast({ title: "Succès", description: "Tâche modifiée avec succès", }); } catch (error) { toast({ title: "Erreur", description: "Impossible de modifier la tâche", variant: "destructive", }); } }; // Complétion d'une tâche const handleCompleteTask = async (taskId: number) => { try { await apiRequest(`/api/tasks/${taskId}/complete`, 'POST'); queryClient.invalidateQueries({ queryKey: ["/api/tasks"] }); toast({ title: "Succès", description: "Tâche marquée comme terminée", }); } catch (error) { toast({ title: "Erreur", description: "Impossible de compléter la tâche", variant: "destructive", }); } }; // Suppression d'une tâche const handleDeleteTask = async (taskId: number) => { try { await apiRequest(`/api/tasks/${taskId}`, 'DELETE'); queryClient.invalidateQueries({ queryKey: ["/api/tasks"] }); toast({ title: "Succès", description: "Tâche supprimée avec succès", }); } catch (error) { toast({ title: "Erreur", description: "Impossible de supprimer la tâche", variant: "destructive", }); } }; const handleEditTask = (task: TaskWithRelations) => { setSelectedTask(task); setShowEditModal(true); }; const getStatusColor = (status: string) => { switch (status) { case "completed": return "bg-green-100 text-green-800"; case "pending": return "bg-yellow-100 text-yellow-800"; default: return "bg-gray-100 text-gray-800"; } }; const getPriorityColor = (priority: string) => { switch (priority) { case "high": return "bg-red-100 text-red-800"; case "medium": return "bg-blue-100 text-blue-800"; case "low": return "bg-green-100 text-green-800"; default: return "bg-gray-100 text-gray-800"; } }; if (isLoading) { return (
Chargement des tâches...
); } if (!user) { return (
Vous devez être connecté pour accéder aux tâches.
); } return (

Gestion des Tâches

Créer une nouvelle tâche
{/* Filtres */} Filtres
setSearchTerm(e.target.value)} className="pl-10" />
{/* Liste des tâches */}
{filteredTasks.length === 0 ? (

Aucune tâche trouvée

) : ( filteredTasks.map((task: TaskWithRelations) => (

{task.title}

{task.status === "completed" ? "Terminée" : "En attente"} {task.priority === "high" ? "Haute" : task.priority === "medium" ? "Moyenne" : "Basse"}
{task.description && (

{task.description}

)}
Assigné à: {task.assignedTo || "Non assigné"}
Magasin: {task.group.name}
Créé par: {task.creator.name || task.creator.username}
{task.dueDate && (
Échéance: {format(new Date(task.dueDate), 'dd/MM/yyyy HH:mm', { locale: fr })}
)}
{task.status !== "completed" && ( )}
)) )}
{/* Modal de modification */} Modifier la tâche {selectedTask && ( )}
); } // Composant de formulaire simplifié function TaskForm({ onSubmit, initialData, isEditing = false }: { onSubmit: (data: any) => void; initialData?: TaskWithRelations; isEditing?: boolean; }) { const [title, setTitle] = useState(initialData?.title || ""); const [description, setDescription] = useState(initialData?.description || ""); const [assignedTo, setAssignedTo] = useState(initialData?.assignedTo || ""); const [priority, setPriority] = useState(initialData?.priority || "medium"); const [dueDate, setDueDate] = useState( initialData?.dueDate ? format(new Date(initialData.dueDate), 'yyyy-MM-dd') : "" ); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!title.trim()) { return; } const taskData = { title: title.trim(), description: description.trim() || undefined, assignedTo: assignedTo?.trim() || "Non assigné", priority, startDate: null, // Toujours inclure startDate même si null dueDate: dueDate ? new Date(dueDate).toISOString() : null, }; onSubmit(taskData); }; return (
setTitle(e.target.value)} placeholder="Titre de la tâche" required />