"use client"; import { CATEGORIES, STATUSES } from "@/lib/constants"; import { ChecklistItem, Task, TaskCategory, TaskStatus } from "@/types"; import { AnimatePresence, motion } from "framer-motion"; import { useCallback, useEffect, useRef, useState } from "react"; interface TaskDetailModalProps { task: Task; onClose: () => void; onUpdate: (task: Task) => void; onDelete: (taskId: number) => void; onComplete: (taskId: number) => void; } export default function TaskDetailModal({ task, onClose, onUpdate, onDelete, onComplete, }: TaskDetailModalProps) { const [title, setTitle] = useState(task.text); const [description, setDescription] = useState(task.description || ""); const [checklist, setChecklist] = useState( task.checklist || [] ); const [newItemText, setNewItemText] = useState(""); const [isEditingTitle, setIsEditingTitle] = useState(false); const [isEditingDescription, setIsEditingDescription] = useState(false); const [saving, setSaving] = useState(false); const titleInputRef = useRef(null); const descriptionRef = useRef(null); const saveTimeoutRef = useRef(null); const cat = CATEGORIES.find((c) => c.key === task.category); const autoSave = useCallback( async (updates: Partial) => { if (saveTimeoutRef.current) { clearTimeout(saveTimeoutRef.current); } saveTimeoutRef.current = setTimeout(async () => { setSaving(true); try { const response = await fetch("/api/tasks", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id: task.id, ...updates }), }); if (response.ok) { const updatedTask = await response.json(); onUpdate(updatedTask); } } catch (error) { console.error("Error saving:", error); } finally { setSaving(false); } }, 500); }, [task.id, onUpdate] ); const handleTitleChange = (newTitle: string) => { setTitle(newTitle); if (newTitle.trim()) { autoSave({ text: newTitle }); } }; const handleDescriptionChange = (newDescription: string) => { setDescription(newDescription); autoSave({ description: newDescription }); }; const addChecklistItem = () => { if (!newItemText.trim()) return; const newItem: ChecklistItem = { id: Date.now().toString(), text: newItemText, checked: false, }; const newChecklist = [...checklist, newItem]; setChecklist(newChecklist); setNewItemText(""); autoSave({ checklist: newChecklist }); }; const toggleChecklistItem = (itemId: string) => { const newChecklist = checklist.map((item) => item.id === itemId ? { ...item, checked: !item.checked } : item ); setChecklist(newChecklist); autoSave({ checklist: newChecklist }); }; const deleteChecklistItem = (itemId: string) => { const newChecklist = checklist.filter((item) => item.id !== itemId); setChecklist(newChecklist); autoSave({ checklist: newChecklist }); }; const updateChecklistItemText = (itemId: string, newText: string) => { const newChecklist = checklist.map((item) => item.id === itemId ? { ...item, text: newText } : item ); setChecklist(newChecklist); autoSave({ checklist: newChecklist }); }; const handleCategoryChange = async (newCategory: TaskCategory) => { try { const response = await fetch("/api/tasks", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id: task.id, category: newCategory }), }); if (response.ok) { const updatedTask = await response.json(); onUpdate(updatedTask); } } catch (error) { console.error("Error updating category:", error); } }; const handleStatusChange = async (newStatus: TaskStatus) => { try { const response = await fetch("/api/tasks", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id: task.id, status: newStatus }), }); if (response.ok) { const updatedTask = await response.json(); onUpdate(updatedTask); } } catch (error) { console.error("Error updating status:", error); } }; useEffect(() => { if (isEditingTitle && titleInputRef.current) { titleInputRef.current.focus(); titleInputRef.current.select(); } }, [isEditingTitle]); useEffect(() => { if (isEditingDescription && descriptionRef.current) { descriptionRef.current.focus(); } }, [isEditingDescription]); useEffect(() => { return () => { if (saveTimeoutRef.current) { clearTimeout(saveTimeoutRef.current); } }; }, []); const completedCount = checklist.filter((item) => item.checked).length; const progressPercent = checklist.length > 0 ? (completedCount / checklist.length) * 100 : 0; return ( e.stopPropagation()} className="bg-gray-800 rounded-2xl w-full max-w-2xl my-8 overflow-hidden" >
{isEditingTitle ? ( handleTitleChange(e.target.value) } onBlur={() => setIsEditingTitle(false)} onKeyDown={(e) => { if (e.key === "Enter") setIsEditingTitle(false); if (e.key === "Escape") { setTitle(task.text); setIsEditingTitle(false); } }} className="w-full bg-white/20 text-white text-xl font-bold px-3 py-2 rounded-lg outline-none" /> ) : (

setIsEditingTitle(true)} className="text-xl font-bold text-white cursor-pointer hover:bg-white/10 px-3 py-2 rounded-lg transition" > {title}

)}

dans {cat?.label} • {task.added}

{saving && (
{" "} Enregistrement...
)}

Statut

{STATUSES.map((status) => ( ))}

Catégorie

{CATEGORIES.map((category) => ( ))}

📝 Description

{isEditingDescription ? (