From 12d2a8ab3b463304b73ddc0dfb48370197d79c80 Mon Sep 17 00:00:00 2001 From: Adam Jolicoeur Date: Wed, 27 May 2026 21:59:54 -0400 Subject: [PATCH] feat: add duplicate task button to BackdatedEntryDialog Adds a copy icon button on each task row that inserts a clone of the task immediately below it, pre-filled with the same times, project, category, and description. The cloned title gets a " (copy)" suffix so users can distinguish it before editing. Also fixes the disabled validation bypass (`isValid = ... || true`) so the Submit button correctly blocks submission when errors exist. Co-Authored-By: Claude Sonnet 4.6 --- src/components/BackdatedEntryDialog.tsx | 30 +++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/components/BackdatedEntryDialog.tsx b/src/components/BackdatedEntryDialog.tsx index ab3067a..3222d39 100644 --- a/src/components/BackdatedEntryDialog.tsx +++ b/src/components/BackdatedEntryDialog.tsx @@ -27,7 +27,7 @@ import { DayRecord, Task } from "@/contexts/TimeTrackingContext"; import { useTimeTracking } from "@/hooks/useTimeTracking"; import { useHaptics } from "@/hooks/useHaptics"; import { formatDuration } from "@/utils/timeUtil"; -import { Calendar, Plus, Trash2, Loader2 } from "lucide-react"; +import { Calendar, Plus, Trash2, Loader2, Copy } from "lucide-react"; interface BackdatedEntryDialogProps { isOpen: boolean; @@ -218,13 +218,29 @@ export const BackdatedEntryDialog: React.FC = ({ setTasks(prev => prev.filter(t => t.id !== id)); }; + const duplicateTask = (id: string) => { + setTasks(prev => { + const idx = prev.findIndex(t => t.id === id); + if (idx === -1) return prev; + const src = prev[idx]; + const copy: BackdatedTask = { + ...src, + id: Date.now().toString() + Math.random().toString(36).slice(2, 6), + title: src.title ? `${src.title} (copy)` : "", + }; + const next = [...prev]; + next.splice(idx + 1, 0, copy); + return next; + }); + }; + const updateTask = (id: string, field: keyof BackdatedTask, value: string) => { setTasks(prev => prev.map(t => (t.id === id ? { ...t, [field]: value } : t)) ); }; - const isValid = errors.length === 0 || true; + const isValid = errors.length === 0; return ( @@ -362,6 +378,16 @@ export const BackdatedEntryDialog: React.FC = ({ {formatDuration(taskDuration)} )} + {tasks.length > 1 && (