import { type Component, createEffect, createSignal, For } from "solid-js"; import { Sheet, SheetContent } from "@/components/ui/sheet"; import { type Task, removeTask, restoreTask, updateTask, saveTaskAsTemplate, shareTask, revokeShare, splitTask } from "@/store"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { ArrowUpCircle, Clock, Calendar, Type, Trash2, X, Copy, MoreHorizontal, Gauge, Share2, UserMinus, GitBranch, Tag, Settings } from "lucide-solid"; import { calculateDateFromUrgency, calculateUrgencyFromDate } from "@/store"; import { Button } from "./ui/button"; import { TagPicker } from "./TagPicker"; import { Badge } from "./ui/badge"; import { PRIORITY_OPTIONS, URGENCY_OPTIONS, SIZE_OPTIONS } from "@/lib/constants"; import { store } from "@/store"; import { cn } from "@/lib/utils"; import { toast } from "solid-sonner"; import { lazy, Suspense } from "solid-js"; import { useTheme } from "./ThemeProvider"; import { getThemeAdjustedColor } from "@/lib/colors"; import { pb } from "@/lib/pocketbase"; const TaskEditor = lazy(() => import("./TaskEditor").then(m => ({ default: m.TaskEditor }))); interface TaskDetailProps { task: Task; isOpen: boolean; onClose: () => void; } export const TaskDetail: Component = (props) => { const { resolvedTheme } = useTheme(); // Local state for immediate feedback, synced with props const [title, setTitle] = createSignal(props.task.title); const [editorInstance, setEditorInstance] = createSignal(null); // Sync input string for datetime-local const [dateString, setDateString] = createSignal(""); createEffect(() => { setTitle(props.task.title); // Format for datetime-local: yyyy-MM-ddThh:mm (local time) const dateObj = new Date(props.task.dueDate); const localIso = new Date(dateObj.getTime() - (dateObj.getTimezoneOffset() * 60000)).toISOString().slice(0, 16); setDateString(localIso); }); let debounceTimer: number | undefined; let pendingContent: string | null = null; const updateTaskContent = (html: string) => { pendingContent = html; clearTimeout(debounceTimer); debounceTimer = setTimeout(() => { if (pendingContent !== null) { updateTask(props.task.id, { content: pendingContent }); pendingContent = null; } }, 1000); }; // Removed onCleanup to avoid lockup const updateTitle = (val: string) => { setTitle(val); updateTask(props.task.id, { title: val }); }; const updatePriority = (val: any) => { const value = typeof val === 'object' ? val.value : val; const p = parseInt(value); if (!isNaN(p)) { updateTask(props.task.id, { priority: p }); } }; const updateUrgency = (val: any) => { const value = typeof val === 'object' ? val.value : val; const u = parseInt(value); if (!isNaN(u)) { const newDate = calculateDateFromUrgency(u); updateTask(props.task.id, { dueDate: newDate }); } }; const updateTags = (tags: string[]) => { updateTask(props.task.id, { tags }); }; const onDateInputChange = (e: Event) => { const val = (e.currentTarget as HTMLInputElement).value; if (val) { const iso = new Date(val).toISOString(); updateTask(props.task.id, { dueDate: iso }); } }; // Calculate current urgency level for display const currentUrgency = () => calculateUrgencyFromDate(props.task.dueDate).toString(); return ( { if (!open) { // Flash save before closing to avoid lockup if (pendingContent !== null) { updateTask(props.task.id, { content: pendingContent }); pendingContent = null; } props.onClose(); } }}> { // Prevent auto-focus on mobile to avoid keyboard popup if (window.innerWidth < 768) { e.preventDefault(); } }} class="w-full sm:max-w-2xl px-0 sm:px-0 flex flex-col h-full bg-background border-l border-border shadow-2xl" > {/* Header Area */}