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 { 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({

View File

@ -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<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({

View File

@ -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() || '',
});

View File

@ -40,6 +40,12 @@ const recurrenceLabels: Record<string, string> = {
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: '',
};
}

View File

@ -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 || '',
});

View File

@ -58,6 +58,18 @@ const recurrenceLabels: Record<string, string> = {
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: '',
};

View File

@ -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 || '',
});