From b04854a4882034e40d6a82826f423294dfe03057 Mon Sep 17 00:00:00 2001 From: Kyle Pope Date: Tue, 3 Mar 2026 17:08:55 +0800 Subject: [PATCH] Default date/time fields to today/now on create forms Todo, reminder, project, and task forms now pre-fill date/time fields with today's date and current time when creating new items. Edit mode still uses stored values. DOB fields excluded. Co-Authored-By: Claude Opus 4.6 --- frontend/src/components/projects/ProjectForm.tsx | 8 +++++++- .../src/components/projects/TaskDetailPanel.tsx | 8 +++++++- frontend/src/components/projects/TaskForm.tsx | 8 +++++++- .../components/reminders/ReminderDetailPanel.tsx | 8 +++++++- .../src/components/reminders/ReminderForm.tsx | 8 +++++++- .../src/components/todos/TodoDetailPanel.tsx | 16 ++++++++++++++-- frontend/src/components/todos/TodoForm.tsx | 16 ++++++++++++++-- 7 files changed, 63 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/projects/ProjectForm.tsx b/frontend/src/components/projects/ProjectForm.tsx index 3c3329d..7148a10 100644 --- a/frontend/src/components/projects/ProjectForm.tsx +++ b/frontend/src/components/projects/ProjectForm.tsx @@ -18,6 +18,12 @@ import { Select } from '@/components/ui/select'; import { Label } from '@/components/ui/label'; import { Button } from '@/components/ui/button'; +function todayLocal(): string { + const d = new Date(); + const pad = (n: number) => n.toString().padStart(2, '0'); + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; +} + interface ProjectFormProps { project: Project | null; onClose: () => void; @@ -29,7 +35,7 @@ export default function ProjectForm({ project, onClose }: ProjectFormProps) { name: project?.name || '', description: project?.description || '', status: project?.status || 'not_started', - due_date: project?.due_date ? project.due_date.slice(0, 10) : '', + due_date: project?.due_date ? project.due_date.slice(0, 10) : todayLocal(), }); const mutation = useMutation({ diff --git a/frontend/src/components/projects/TaskDetailPanel.tsx b/frontend/src/components/projects/TaskDetailPanel.tsx index d18ca84..2f7c144 100644 --- a/frontend/src/components/projects/TaskDetailPanel.tsx +++ b/frontend/src/components/projects/TaskDetailPanel.tsx @@ -60,6 +60,12 @@ interface EditState { description: string; } +function todayLocal(): string { + const d = new Date(); + const pad = (n: number) => n.toString().padStart(2, '0'); + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; +} + function buildEditState(task: ProjectTask): EditState { return { title: task.title, @@ -84,7 +90,7 @@ export default function TaskDetailPanel({ const [commentText, setCommentText] = useState(''); const [isEditing, setIsEditing] = useState(false); const [editState, setEditState] = useState(() => - task ? buildEditState(task) : { title: '', status: 'pending', priority: 'none', due_date: '', person_id: '', description: '' } + task ? buildEditState(task) : { title: '', status: 'pending', priority: 'none', due_date: todayLocal(), person_id: '', description: '' } ); const { data: people = [] } = useQuery({ diff --git a/frontend/src/components/projects/TaskForm.tsx b/frontend/src/components/projects/TaskForm.tsx index 8809e32..9cf4385 100644 --- a/frontend/src/components/projects/TaskForm.tsx +++ b/frontend/src/components/projects/TaskForm.tsx @@ -18,6 +18,12 @@ import { Select } from '@/components/ui/select'; import { Label } from '@/components/ui/label'; import { Button } from '@/components/ui/button'; +function todayLocal(): string { + const d = new Date(); + const pad = (n: number) => n.toString().padStart(2, '0'); + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; +} + interface TaskFormProps { projectId: number; task: ProjectTask | null; @@ -33,7 +39,7 @@ export default function TaskForm({ projectId, task, parentTaskId, defaultDueDate description: task?.description || '', status: task?.status || 'pending', priority: task?.priority || 'medium', - due_date: task?.due_date ? task.due_date.slice(0, 10) : (!task && defaultDueDate ? defaultDueDate.slice(0, 10) : ''), + due_date: task?.due_date ? task.due_date.slice(0, 10) : (!task && defaultDueDate ? defaultDueDate.slice(0, 10) : todayLocal()), person_id: task?.person_id?.toString() || '', }); diff --git a/frontend/src/components/reminders/ReminderDetailPanel.tsx b/frontend/src/components/reminders/ReminderDetailPanel.tsx index 3cfff13..e6dfe6a 100644 --- a/frontend/src/components/reminders/ReminderDetailPanel.tsx +++ b/frontend/src/components/reminders/ReminderDetailPanel.tsx @@ -40,6 +40,12 @@ const recurrenceLabels: Record = { monthly: 'Monthly', }; +function nowLocal(): string { + const d = new Date(); + const pad = (n: number) => n.toString().padStart(2, '0'); + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; +} + const QUERY_KEYS = [['reminders'], ['dashboard'], ['upcoming']] as const; function buildEditState(reminder: Reminder): EditState { @@ -55,7 +61,7 @@ function buildCreateState(): EditState { return { title: '', description: '', - remind_at: '', + remind_at: nowLocal(), recurrence_rule: '', }; } diff --git a/frontend/src/components/reminders/ReminderForm.tsx b/frontend/src/components/reminders/ReminderForm.tsx index 193ce94..a95e560 100644 --- a/frontend/src/components/reminders/ReminderForm.tsx +++ b/frontend/src/components/reminders/ReminderForm.tsx @@ -18,6 +18,12 @@ import { Select } from '@/components/ui/select'; import { Label } from '@/components/ui/label'; import { Button } from '@/components/ui/button'; +function nowLocal(): string { + const d = new Date(); + const pad = (n: number) => n.toString().padStart(2, '0'); + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`; +} + interface ReminderFormProps { reminder: Reminder | null; onClose: () => void; @@ -28,7 +34,7 @@ export default function ReminderForm({ reminder, onClose }: ReminderFormProps) { const [formData, setFormData] = useState({ title: reminder?.title || '', description: reminder?.description || '', - remind_at: reminder?.remind_at ? reminder.remind_at.slice(0, 16) : '', + remind_at: reminder?.remind_at ? reminder.remind_at.slice(0, 16) : nowLocal(), recurrence_rule: reminder?.recurrence_rule || '', }); diff --git a/frontend/src/components/todos/TodoDetailPanel.tsx b/frontend/src/components/todos/TodoDetailPanel.tsx index a7893ec..8b6a503 100644 --- a/frontend/src/components/todos/TodoDetailPanel.tsx +++ b/frontend/src/components/todos/TodoDetailPanel.tsx @@ -58,6 +58,18 @@ const recurrenceLabels: Record = { monthly: 'Monthly', }; +function todayLocal(): string { + const d = new Date(); + const pad = (n: number) => n.toString().padStart(2, '0'); + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; +} + +function nowTimeLocal(): string { + const d = new Date(); + const pad = (n: number) => n.toString().padStart(2, '0'); + return `${pad(d.getHours())}:${pad(d.getMinutes())}`; +} + const QUERY_KEYS = [['todos'], ['dashboard'], ['upcoming']] as const; function buildEditState(todo: Todo): EditState { @@ -77,8 +89,8 @@ function buildCreateState(defaults?: TodoCreateDefaults | null): EditState { title: '', description: '', priority: 'medium', - due_date: '', - due_time: '', + due_date: todayLocal(), + due_time: nowTimeLocal(), category: defaults?.category || '', recurrence_rule: '', }; diff --git a/frontend/src/components/todos/TodoForm.tsx b/frontend/src/components/todos/TodoForm.tsx index 6a56032..39744f9 100644 --- a/frontend/src/components/todos/TodoForm.tsx +++ b/frontend/src/components/todos/TodoForm.tsx @@ -18,6 +18,18 @@ import { Select } from '@/components/ui/select'; import { Label } from '@/components/ui/label'; import { Button } from '@/components/ui/button'; +function todayLocal(): string { + const d = new Date(); + const pad = (n: number) => n.toString().padStart(2, '0'); + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; +} + +function nowTimeLocal(): string { + const d = new Date(); + const pad = (n: number) => n.toString().padStart(2, '0'); + return `${pad(d.getHours())}:${pad(d.getMinutes())}`; +} + interface TodoFormProps { todo: Todo | null; onClose: () => void; @@ -29,8 +41,8 @@ export default function TodoForm({ todo, onClose }: TodoFormProps) { title: todo?.title || '', description: todo?.description || '', priority: todo?.priority || 'medium', - due_date: todo?.due_date || '', - due_time: todo?.due_time ? todo.due_time.slice(0, 5) : '', + due_date: todo?.due_date || todayLocal(), + due_time: todo?.due_time ? todo.due_time.slice(0, 5) : nowTimeLocal(), category: todo?.category || '', recurrence_rule: todo?.recurrence_rule || '', });