Refactor task management, UI interactions, and theme support
- Added task editing functionality with `EditForm` and integrated it with `TodoItemTouch`. - Switched `dueDate` fields to `due_date` for consistency with API. - Updated `useTasks` to handle dynamic task updates, deletions, and periodic refresh. - Enhanced `useApi` with a dedicated delete method. - Improved UI responsiveness and styling with multi-theme support in DaisyUI. - Simplified modal handling for task interactions (`EditForm`, `CreateForm`). - Improved `useSettings` with a `theme` field to support theme switching. - Extended task commands for tagging, text, and due date updates. - Optimized `parser` for extended edit command parsing. - Updated helpers and actions to use `luxon` for date manipulations. - Streamlined task and view logic for improved usability and extensibility.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { Task } from '../types.ts'
|
||||
import type { Command } from './parser.ts'
|
||||
import { DateTime } from 'luxon'
|
||||
import { TaskStatus } from '../types.ts'
|
||||
import { parseDueDate, stopWorkLogging } from './helpers.ts'
|
||||
|
||||
@@ -14,8 +15,7 @@ export function beginCommand(tasks: Task[], ids: Task['id_'][]) {
|
||||
return tasks.filter(t => ids.includes(t.id_) && t.status !== TaskStatus.WIP).map((t) => {
|
||||
t.status = TaskStatus.WIP
|
||||
t.logs = (t.logs || []).concat({
|
||||
start: Date.now(),
|
||||
end: 0,
|
||||
start: DateTime.now().toUTC().toString(),
|
||||
})
|
||||
return t
|
||||
})
|
||||
@@ -37,10 +37,7 @@ export function deleteCommand(ids: Task['id_'][], cmd: Command, tasks: Task[]) {
|
||||
// Delete by tag
|
||||
const tag = (cmd?.id?.match(/^(@.*)/) || []).pop()
|
||||
if (tag) {
|
||||
return tasks.filter(t => t.tag === tag).map(t => ({
|
||||
...t,
|
||||
status: TaskStatus.NONE,
|
||||
} as Task))
|
||||
return tasks.filter(t => t.tag === tag)
|
||||
}
|
||||
// Delete by status
|
||||
const status = (
|
||||
@@ -70,20 +67,14 @@ export function deleteCommand(ids: Task['id_'][], cmd: Command, tasks: Task[]) {
|
||||
break
|
||||
}
|
||||
if (taskStatus) {
|
||||
return tasks.filter(t => t.status === taskStatus && !t.archived).map(t => ({
|
||||
...t,
|
||||
status: TaskStatus.NONE,
|
||||
} as Task))
|
||||
return tasks.filter(t => t.status === taskStatus)
|
||||
}
|
||||
}
|
||||
return []
|
||||
}
|
||||
else {
|
||||
// Delete by id
|
||||
return tasks.filter(t => ids.includes(t.id_)).map(t => ({
|
||||
...t,
|
||||
status: TaskStatus.NONE,
|
||||
} as Task))
|
||||
return tasks.filter(t => ids.includes(t.id_))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,19 +163,19 @@ export function insertTaskCommand(cmd: Command) {
|
||||
return {
|
||||
tag,
|
||||
title: task,
|
||||
dueDate: null,
|
||||
} as Pick<Task, 'title' | 'dueDate' | 'tag'>
|
||||
due_date: null,
|
||||
} as Pick<Task, 'title' | 'due_date' | 'tag'>
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function editTaskCommand(ids: Task['id_'][], cmd: Command, tasks: Task[]) {
|
||||
const id = ids[0]
|
||||
const task = cmd?.text
|
||||
if (task && task.length) {
|
||||
return tasks.filter(t => t.id === id).map(t => ({
|
||||
if (cmd) {
|
||||
return tasks.filter(t => t.id_ === id).map(t => ({
|
||||
...t,
|
||||
title: task,
|
||||
title: cmd.text?.length ? cmd.text : t.title,
|
||||
tag: cmd.tag ?? t.tag,
|
||||
} as Task))
|
||||
}
|
||||
|
||||
@@ -197,10 +188,10 @@ export function dueCommand(ids: Task['id_'][], cmd: Command, tasks: Task[]) {
|
||||
if (id) {
|
||||
return tasks.filter(t => t.id_ === id).map((t: Task) => {
|
||||
if (/^(?:clear|none|remove)$/i.test(text)) {
|
||||
t.dueDate = null
|
||||
t.due_date = null
|
||||
}
|
||||
else if (text && text.length) {
|
||||
t.dueDate = parseDueDate(text)
|
||||
t.due_date = parseDueDate(text)
|
||||
}
|
||||
return t
|
||||
})
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
import type { Task } from '../types.ts'
|
||||
import { DateTime } from 'luxon'
|
||||
import Sherlock from 'sherlockjs'
|
||||
|
||||
export function parseDueDate(text: string): number | null {
|
||||
export function parseDueDate(text: string): Task['due_date'] {
|
||||
try {
|
||||
const parsed = Sherlock.parse(text)
|
||||
if (parsed && parsed.startDate) {
|
||||
return parsed.startDate.getTime()
|
||||
return DateTime.fromMillis(parsed.startDate.getTime()).toUTC().toString()
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
const ts = Date.parse(text)
|
||||
return Number.isNaN(ts) ? null : ts
|
||||
const millis = Number.isNaN(ts) ? null : ts
|
||||
return millis ? DateTime.fromMillis(millis).toUTC().toString() : null
|
||||
}
|
||||
|
||||
export function stopWorkLogging(t: Task) {
|
||||
if (t.logs && t.logs.length) {
|
||||
const lastLog = t.logs[t.logs.length - 1]
|
||||
if (lastLog.start && !lastLog.end) {
|
||||
lastLog.end = Date.now()
|
||||
lastLog.end = DateTime.now().toUTC().toString()
|
||||
}
|
||||
}
|
||||
else {
|
||||
t.logs = []
|
||||
t.logs = null
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ function parseTaskCommand(str: string) {
|
||||
return str.match(/^(t(?:ask)?)\s(@\S*[0-9a-z'-])?([\s\S]*)/i)
|
||||
}
|
||||
function parseEditCommand(str: string) {
|
||||
return str.match(/^(e(?:dit)?)\s(\d+)([\s\S]*)/i)
|
||||
return str.match(/^(e(?:dit)?)\s(\d+)\s(@\S*[0-9a-z'-])?([\s\S]*)/i)
|
||||
}
|
||||
const parseDueCommand = (str: string) => str.match(/^(due)\s(\d+)([\s\S]*)/i)
|
||||
function parseMoveCommand(str: string) {
|
||||
@@ -72,7 +72,8 @@ function compileEditCommand(input: string) {
|
||||
return {
|
||||
command: matchEdit[1],
|
||||
id: matchEdit[2],
|
||||
text: matchEdit[3].trim(),
|
||||
tag: matchEdit[3],
|
||||
text: matchEdit[4].trim(),
|
||||
} as Command
|
||||
}
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user