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 <noreply@anthropic.com>
This commit is contained in:
Kyle 2026-03-03 17:08:55 +08:00
parent 0c6ea1ccff
commit b04854a488
7 changed files with 63 additions and 9 deletions

View File

@ -18,6 +18,12 @@ import { Select } from '@/components/ui/select';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button'; 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 { interface ProjectFormProps {
project: Project | null; project: Project | null;
onClose: () => void; onClose: () => void;
@ -29,7 +35,7 @@ export default function ProjectForm({ project, onClose }: ProjectFormProps) {
name: project?.name || '', name: project?.name || '',
description: project?.description || '', description: project?.description || '',
status: project?.status || 'not_started', 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({ const mutation = useMutation({

View File

@ -60,6 +60,12 @@ interface EditState {
description: string; 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 { function buildEditState(task: ProjectTask): EditState {
return { return {
title: task.title, title: task.title,
@ -84,7 +90,7 @@ export default function TaskDetailPanel({
const [commentText, setCommentText] = useState(''); const [commentText, setCommentText] = useState('');
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
const [editState, setEditState] = useState<EditState>(() => const [editState, setEditState] = useState<EditState>(() =>
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({ const { data: people = [] } = useQuery({

View File

@ -18,6 +18,12 @@ import { Select } from '@/components/ui/select';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button'; 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 { interface TaskFormProps {
projectId: number; projectId: number;
task: ProjectTask | null; task: ProjectTask | null;
@ -33,7 +39,7 @@ export default function TaskForm({ projectId, task, parentTaskId, defaultDueDate
description: task?.description || '', description: task?.description || '',
status: task?.status || 'pending', status: task?.status || 'pending',
priority: task?.priority || 'medium', 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() || '', person_id: task?.person_id?.toString() || '',
}); });

View File

@ -40,6 +40,12 @@ const recurrenceLabels: Record<string, string> = {
monthly: 'Monthly', 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; const QUERY_KEYS = [['reminders'], ['dashboard'], ['upcoming']] as const;
function buildEditState(reminder: Reminder): EditState { function buildEditState(reminder: Reminder): EditState {
@ -55,7 +61,7 @@ function buildCreateState(): EditState {
return { return {
title: '', title: '',
description: '', description: '',
remind_at: '', remind_at: nowLocal(),
recurrence_rule: '', recurrence_rule: '',
}; };
} }

View File

@ -18,6 +18,12 @@ import { Select } from '@/components/ui/select';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button'; 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 { interface ReminderFormProps {
reminder: Reminder | null; reminder: Reminder | null;
onClose: () => void; onClose: () => void;
@ -28,7 +34,7 @@ export default function ReminderForm({ reminder, onClose }: ReminderFormProps) {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
title: reminder?.title || '', title: reminder?.title || '',
description: reminder?.description || '', 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 || '', recurrence_rule: reminder?.recurrence_rule || '',
}); });

View File

@ -58,6 +58,18 @@ const recurrenceLabels: Record<string, string> = {
monthly: 'Monthly', 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; const QUERY_KEYS = [['todos'], ['dashboard'], ['upcoming']] as const;
function buildEditState(todo: Todo): EditState { function buildEditState(todo: Todo): EditState {
@ -77,8 +89,8 @@ function buildCreateState(defaults?: TodoCreateDefaults | null): EditState {
title: '', title: '',
description: '', description: '',
priority: 'medium', priority: 'medium',
due_date: '', due_date: todayLocal(),
due_time: '', due_time: nowTimeLocal(),
category: defaults?.category || '', category: defaults?.category || '',
recurrence_rule: '', recurrence_rule: '',
}; };

View File

@ -18,6 +18,18 @@ import { Select } from '@/components/ui/select';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button'; 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 { interface TodoFormProps {
todo: Todo | null; todo: Todo | null;
onClose: () => void; onClose: () => void;
@ -29,8 +41,8 @@ export default function TodoForm({ todo, onClose }: TodoFormProps) {
title: todo?.title || '', title: todo?.title || '',
description: todo?.description || '', description: todo?.description || '',
priority: todo?.priority || 'medium', priority: todo?.priority || 'medium',
due_date: todo?.due_date || '', due_date: todo?.due_date || todayLocal(),
due_time: todo?.due_time ? todo.due_time.slice(0, 5) : '', due_time: todo?.due_time ? todo.due_time.slice(0, 5) : nowTimeLocal(),
category: todo?.category || '', category: todo?.category || '',
recurrence_rule: todo?.recurrence_rule || '', recurrence_rule: todo?.recurrence_rule || '',
}); });