diff --git a/src/components/ReportForm.tsx b/src/components/ReportForm.tsx index ba651b0..f0e2ba9 100644 --- a/src/components/ReportForm.tsx +++ b/src/components/ReportForm.tsx @@ -1,7 +1,7 @@ "use client"; import { useSession, signIn, signOut } from "next-auth/react"; -import { useState, useEffect } from "react"; +import { useState, useEffect, useRef } from "react"; import { Plus, Trash2, Send, Save, CheckCircle, Clock, Calendar, User as UserIcon, Link as LinkIcon, LogOut, ShieldCheck, ClipboardList } from "lucide-react"; import AdminDashboard from "./AdminDashboard"; @@ -14,6 +14,8 @@ export default function ReportForm() { const [completedTasks, setCompletedTasks] = useState([]); const [saving, setSaving] = useState(false); const [view, setView] = useState<"REPORT" | "ADMIN">("REPORT"); + const debounceTimers = useRef>>({}); + const pendingUpdates = useRef>({}); useEffect(() => { if (status === "authenticated") { @@ -89,21 +91,33 @@ export default function ReportForm() { } }; - const updateTask = async (id: string, updates: any) => { - try { + const updateTask = (id: string, updates: any) => { + // Update local state immediately so the UI stays responsive + if (updates.type === 'PLANNED') { + setPlannedTasks(prev => prev.map(t => t.id === id ? { ...t, ...updates } : t)); + } else { + setCompletedTasks(prev => prev.map(t => t.id === id ? { ...t, ...updates } : t)); + } + + // Accumulate all field changes for this task so a single request carries everything + pendingUpdates.current[id] = { ...pendingUpdates.current[id], ...updates }; + + // Reset the debounce timer — the API call fires 600 ms after the last keystroke + clearTimeout(debounceTimers.current[id]); + debounceTimers.current[id] = setTimeout(async () => { + const payload = pendingUpdates.current[id]; + delete pendingUpdates.current[id]; + delete debounceTimers.current[id]; + try { await fetch("/api/tasks", { method: "PATCH", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ id, ...updates }), + body: JSON.stringify({ id, ...payload }), }); - if (updates.type === 'PLANNED') { - setPlannedTasks(plannedTasks.map(t => t.id === id ? { ...t, ...updates } : t)); - } else { - setCompletedTasks(completedTasks.map(t => t.id === id ? { ...t, ...updates } : t)); - } } catch (error) { console.error("Failed to update task"); } + }, 600); }; const deleteTask = async (id: string, type: string) => {