feat: sort tasks by due time
ci / gitleaks (push) Successful in 8s
ci / docker (push) Successful in 3m35s

This commit is contained in:
2026-09-10 18:16:13 +08:00
parent ab8c0a5138
commit addd49363d
8 changed files with 576 additions and 58 deletions
+25
View File
@@ -4,6 +4,7 @@ export type MinimalTask = {
description?: string
parent_id?: string | null
completed?: boolean
due_at?: string | null
list_name?: string
subtasks?: MinimalTask[]
}
@@ -92,6 +93,30 @@ export function groupTaskTree<T extends MinimalTask>(tasks: T[]) {
}))
}
export function classifyTaskForToday(
task: Pick<MinimalTask, 'completed' | 'due_at'>,
start: Date,
end: Date,
): 'overdue' | 'today' | 'outside' {
if (task.completed || !task.due_at) return 'outside'
const due = Date.parse(task.due_at)
if (!Number.isFinite(due)) return 'outside'
if (due < start.valueOf()) return 'overdue'
return due < end.valueOf() ? 'today' : 'outside'
}
export function isSameTaskSortTier(
source: Pick<MinimalTask, 'completed' | 'due_at'>,
target: Pick<MinimalTask, 'completed' | 'due_at'>,
) {
if (Boolean(source.completed) !== Boolean(target.completed)) return false
if (!source.due_at && !target.due_at) return true
if (!source.due_at || !target.due_at) return false
const sourceTime = Date.parse(source.due_at)
const targetTime = Date.parse(target.due_at)
return Number.isFinite(sourceTime) && Number.isFinite(targetTime) && sourceTime === targetTime
}
export function moveItemWithinScope<T extends { id: string; parent_id?: string | null }>(items: T[], sourceId: string, targetId: string, placement: 'before' | 'after') {
if (sourceId === targetId) return items
const source = items.find((item) => item.id === sourceId)