/** * @file app/(app)/dashboard/modal/TaskModal.tsx * @description Client component orchestrating the task modal overlay, history sync, and action buttons. */ "use client"; import { useEffect } from "react"; import { Task } from "@/lib/types/task"; import { useRouter } from "next/navigation"; import { Pencil, Trash2 } from "lucide-react"; import TaskModalContent from "./TaskModalContent"; /** * Properties for the TaskModal component. * * @interface TaskModalProps * @property {Task | null} task - The selected task object to display, or null if hidden. * @property {() => void} onClose - Callback handler to close the modal dialog. * @property {(taskId: string) => void} [onDelete] - Optional callback function triggered when deleting the task. */ interface TaskModalProps { task: Task | null; onClose: () => void; onDelete?: (taskId: string) => void; } /** * Renders the task detail modal container with URL state synchronization, keyboard event handling, and action triggers. * * @param {TaskModalProps} props - The component props. * @returns {JSX.Element | null} The rendered modal overlay or null when no task is selected. */ export default function TaskModal({ task, onClose, onDelete }: TaskModalProps) { const router = useRouter(); useEffect(() => { /** * Handles keyboard events to close the modal when the Escape key is pressed. * * @param {KeyboardEvent} e - The keyboard event instance. */ const handleKeyDown = (e: KeyboardEvent) => { if (e.key === "Escape") handleClose(); }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, []); useEffect(() => { /** * Updates the URL search parameters to include `modal=task-detail` when a task is selected, * maintaining modal state in the browser history without triggering a full page re-render. */ if (task) { const params = new URLSearchParams(window.location.search); if (params.get("modal") !== "task-detail") { params.set("modal", "task-detail"); window.history.replaceState( {}, "", `${window.location.pathname}?${params.toString()}`, ); } } }, [task]); /** * Removes modal query parameters from browser history without triggering Next.js routing, then executes the onClose callback. */ const handleClose = () => { const params = new URLSearchParams(window.location.search); params.delete("modal"); const query = params.toString(); window.history.replaceState( {}, "", query ? `${window.location.pathname}?${query}` : window.location.pathname, ); onClose(); }; if (!task) return null; return (