From 72475a552a70df702d12548cf358819aa21a4224 Mon Sep 17 00:00:00 2001 From: Tristan Michael Date: Wed, 1 Apr 2026 01:04:01 -0700 Subject: [PATCH] fix: use has_time flag for due date time tracking Replace the hours==0 && minutes==0 heuristic with an explicit has_time bool field on Task. Existing files without the field deserialize as false (date-only), preserving current behavior. Frontend components pass and receive has_time through DateTimePicker's onchange callback. --- apps/tauri/src/lib/components/DateTimePicker.svelte | 11 ++++++----- apps/tauri/src/lib/components/NewTaskInput.svelte | 12 ++++++++---- apps/tauri/src/lib/components/TaskDetailView.svelte | 7 ++++--- apps/tauri/src/lib/types.ts | 1 + crates/onyx-core/src/models.rs | 3 +++ crates/onyx-core/src/storage.rs | 5 +++++ 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/apps/tauri/src/lib/components/DateTimePicker.svelte b/apps/tauri/src/lib/components/DateTimePicker.svelte index 40cafce..df7d969 100644 --- a/apps/tauri/src/lib/components/DateTimePicker.svelte +++ b/apps/tauri/src/lib/components/DateTimePicker.svelte @@ -1,7 +1,8 @@ diff --git a/apps/tauri/src/lib/components/NewTaskInput.svelte b/apps/tauri/src/lib/components/NewTaskInput.svelte index 189566a..9b0180e 100644 --- a/apps/tauri/src/lib/components/NewTaskInput.svelte +++ b/apps/tauri/src/lib/components/NewTaskInput.svelte @@ -10,6 +10,7 @@ let title = $state(""); let description = $state(""); let dueDate = $state(null); + let dueDateHasTime = $state(false); let inputEl = $state(null); let showDatePicker = $state(false); @@ -17,11 +18,12 @@ if (!title.trim()) return; const created = await app.createTask(title.trim(), description.trim() || undefined); if (dueDate && created) { - await app.updateTask({ ...created, due_date: dueDate, updated_at: new Date().toISOString() }); + await app.updateTask({ ...created, due_date: dueDate, has_time: dueDateHasTime, updated_at: new Date().toISOString() }); } title = ""; description = ""; dueDate = null; + dueDateHasTime = false; newTaskState.open = false; } @@ -30,11 +32,13 @@ title = ""; description = ""; dueDate = null; + dueDateHasTime = false; showDatePicker = false; } - function handleDateChange(iso: string | null) { + function handleDateChange(iso: string | null, hasTime: boolean = false) { dueDate = iso; + dueDateHasTime = hasTime; } function formatDateChip(iso: string): string { @@ -43,8 +47,7 @@ const dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; const day = dayNames[d.getDay()]; const pad = (n: number) => String(n).padStart(2, "0"); - const hasTime = d.getHours() !== 0 || d.getMinutes() !== 0; - const timePart = hasTime ? `, ${pad(d.getHours())}:${pad(d.getMinutes())}` : ""; + const timePart = dueDateHasTime ? `, ${pad(d.getHours())}:${pad(d.getMinutes())}` : ""; if (d.toDateString() === today.toDateString()) return `Today${timePart}`; return `${day}, ${pad(d.getDate())}/${pad(d.getMonth() + 1)}${timePart}`; } @@ -137,6 +140,7 @@ {#if showDatePicker} (showDatePicker = false)} /> diff --git a/apps/tauri/src/lib/components/TaskDetailView.svelte b/apps/tauri/src/lib/components/TaskDetailView.svelte index 478dd35..506c8e6 100644 --- a/apps/tauri/src/lib/components/TaskDetailView.svelte +++ b/apps/tauri/src/lib/components/TaskDetailView.svelte @@ -42,8 +42,8 @@ debouncedSave({ description }); } - function handleDateChange(iso: string | null) { - app.updateTask({ ...task, due_date: iso, updated_at: new Date().toISOString() }); + function handleDateChange(iso: string | null, hasTime: boolean = false) { + app.updateTask({ ...task, due_date: iso, has_time: hasTime, updated_at: new Date().toISOString() }); } async function handleToggle() { @@ -79,7 +79,7 @@ const dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; const day = dayNames[d.getDay()]; const pad = (n: number) => String(n).padStart(2, "0"); - const hasTime = d.getHours() !== 0 || d.getMinutes() !== 0; + const hasTime = task.has_time; const timePart = hasTime ? `, ${pad(d.getHours())}:${pad(d.getMinutes())}` : ""; if (d.toDateString() === today.toDateString()) return `Today${timePart}`; return `${day}, ${pad(d.getDate())}/${pad(d.getMonth() + 1)}${timePart}`; @@ -223,6 +223,7 @@ {#if showDatePicker} (showDatePicker = false)} /> diff --git a/apps/tauri/src/lib/types.ts b/apps/tauri/src/lib/types.ts index 16d3af4..40187e7 100644 --- a/apps/tauri/src/lib/types.ts +++ b/apps/tauri/src/lib/types.ts @@ -4,6 +4,7 @@ export interface Task { description: string; status: "backlog" | "completed"; due_date: string | null; + has_time: boolean; created_at: string; updated_at: string; parent_id: string | null; diff --git a/crates/onyx-core/src/models.rs b/crates/onyx-core/src/models.rs index b614af6..17db348 100644 --- a/crates/onyx-core/src/models.rs +++ b/crates/onyx-core/src/models.rs @@ -17,6 +17,8 @@ pub struct Task { pub status: TaskStatus, #[serde(skip_serializing_if = "Option::is_none")] pub due_date: Option>, + #[serde(default)] + pub has_time: bool, pub created_at: DateTime, pub updated_at: DateTime, #[serde(skip_serializing_if = "Option::is_none")] @@ -32,6 +34,7 @@ impl Task { description: String::new(), status: TaskStatus::Backlog, due_date: None, + has_time: false, created_at: now, updated_at: now, parent_id: None, diff --git a/crates/onyx-core/src/storage.rs b/crates/onyx-core/src/storage.rs index 2fda73a..62bb4a2 100644 --- a/crates/onyx-core/src/storage.rs +++ b/crates/onyx-core/src/storage.rs @@ -56,6 +56,8 @@ pub struct TaskFrontmatter { pub status: TaskStatus, #[serde(skip_serializing_if = "Option::is_none")] pub due: Option>, + #[serde(default)] + pub has_time: bool, pub created: DateTime, pub updated: DateTime, #[serde(skip_serializing_if = "Option::is_none")] @@ -68,6 +70,7 @@ impl From<&Task> for TaskFrontmatter { id: task.id, status: task.status, due: task.due_date, + has_time: task.has_time, created: task.created_at, updated: task.updated_at, parent: task.parent_id, @@ -256,6 +259,7 @@ impl Storage for FileSystemStorage { description, status: frontmatter.status, due_date: frontmatter.due, + has_time: frontmatter.has_time, created_at: frontmatter.created, updated_at: frontmatter.updated, parent_id: frontmatter.parent, @@ -344,6 +348,7 @@ impl Storage for FileSystemStorage { description, status: frontmatter.status, due_date: frontmatter.due, + has_time: frontmatter.has_time, created_at: frontmatter.created, updated_at: frontmatter.updated, parent_id: frontmatter.parent,