From 7704b61c414dd341c1bcbc92fe53e8771892f4d2 Mon Sep 17 00:00:00 2001 From: Anirban Biswas <139000437+Rustix69@users.noreply.github.com> Date: Sat, 15 Nov 2025 17:09:11 +0530 Subject: [PATCH 1/2] feat: make start field editable Added start date field editing functionality to tasks --- backend/controllers/edit_task.go | 8 +- backend/models/request_body.go | 1 + backend/utils/tw/edit_task.go | 31 +- backend/utils/tw/taskwarrior_test.go | 8 +- .../components/HomeComponents/Tasks/Tasks.tsx | 284 +++++++++++++++--- .../components/HomeComponents/Tasks/hooks.ts | 55 ++++ 6 files changed, 323 insertions(+), 64 deletions(-) diff --git a/backend/controllers/edit_task.go b/backend/controllers/edit_task.go index 6402bbe2..30cdb266 100644 --- a/backend/controllers/edit_task.go +++ b/backend/controllers/edit_task.go @@ -46,23 +46,19 @@ func EditTaskHandler(w http.ResponseWriter, r *http.Request) { description := requestBody.Description tags := requestBody.Tags project := requestBody.Project + start := requestBody.Start if taskID == "" { http.Error(w, "taskID is required", http.StatusBadRequest) return } - // if err := tw.EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID); err != nil { - // http.Error(w, err.Error(), http.StatusInternalServerError) - // return - // } - logStore := models.GetLogStore() job := Job{ Name: "Edit Task", Execute: func() error { logStore.AddLog("INFO", fmt.Sprintf("Editing task ID: %s", taskID), uuid, "Edit Task") - err := tw.EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID, tags, project) + err := tw.EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID, tags, project, start) if err != nil { logStore.AddLog("ERROR", fmt.Sprintf("Failed to edit task ID %s: %v", taskID, err), uuid, "Edit Task") return err diff --git a/backend/models/request_body.go b/backend/models/request_body.go index 725a6075..e2d87a0c 100644 --- a/backend/models/request_body.go +++ b/backend/models/request_body.go @@ -31,6 +31,7 @@ type EditTaskRequestBody struct { Description string `json:"description"` Tags []string `json:"tags"` Project string `json:"project"` + Start string `json:"start"` } type CompleteTaskRequestBody struct { Email string `json:"email"` diff --git a/backend/utils/tw/edit_task.go b/backend/utils/tw/edit_task.go index a9b8faf4..ed5dbc68 100644 --- a/backend/utils/tw/edit_task.go +++ b/backend/utils/tw/edit_task.go @@ -7,10 +7,7 @@ import ( "strings" ) -func EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID string, tags []string, project string) error { - if err := utils.ExecCommand("rm", "-rf", "/root/.task"); err != nil { - return fmt.Errorf("error deleting Taskwarrior data: %v", err) - } +func EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID string, tags []string, project string, start string) error { tempDir, err := os.MkdirTemp("", "taskwarrior-"+email) if err != nil { return fmt.Errorf("failed to create temporary directory: %v", err) @@ -27,14 +24,16 @@ func EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID st } // Escape the double quotes in the description and format it - if err := utils.ExecCommand("task", taskID, "modify", description); err != nil { - fmt.Println("task " + taskID + " modify " + description) - return fmt.Errorf("failed to edit task: %v", err) + if description != "" { + escapedDescription := fmt.Sprintf(`description:"%s"`, strings.ReplaceAll(description, `"`, `\"`)) + if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", escapedDescription, "rc.confirmation=off"); err != nil { + return fmt.Errorf("failed to edit task: %v", err) + } } // Handle project if project != "" { - if err := utils.ExecCommand("task", taskID, "modify", "project:"+project); err != nil { + if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "project:"+project, "rc.confirmation=off"); err != nil { return fmt.Errorf("failed to set project %s: %v", project, err) } } @@ -43,27 +42,29 @@ func EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID st if len(tags) > 0 { for _, tag := range tags { if strings.HasPrefix(tag, "+") { - // Add tag tagValue := strings.TrimPrefix(tag, "+") - if err := utils.ExecCommand("task", taskID, "modify", "+"+tagValue); err != nil { + if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "+"+tagValue, "rc.confirmation=off"); err != nil { return fmt.Errorf("failed to add tag %s: %v", tagValue, err) } } else if strings.HasPrefix(tag, "-") { - // Remove tag tagValue := strings.TrimPrefix(tag, "-") - if err := utils.ExecCommand("task", taskID, "modify", "-"+tagValue); err != nil { + if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "-"+tagValue, "rc.confirmation=off"); err != nil { return fmt.Errorf("failed to remove tag %s: %v", tagValue, err) } } else { - // Add tag without prefix - if err := utils.ExecCommand("task", taskID, "modify", "+"+tag); err != nil { + if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "+"+tag, "rc.confirmation=off"); err != nil { return fmt.Errorf("failed to add tag %s: %v", tag, err) } } } } - // Sync Taskwarrior again + if start != "" { + if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "start:"+start, "rc.confirmation=off"); err != nil { + return fmt.Errorf("failed to set start date %s: %v", start, err) + } + } + if err := SyncTaskwarrior(tempDir); err != nil { return err } diff --git a/backend/utils/tw/taskwarrior_test.go b/backend/utils/tw/taskwarrior_test.go index 04ab28ad..4df0ced7 100644 --- a/backend/utils/tw/taskwarrior_test.go +++ b/backend/utils/tw/taskwarrior_test.go @@ -23,7 +23,7 @@ func TestSyncTaskwarrior(t *testing.T) { } func TestEditTaskInATaskwarrior(t *testing.T) { - err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", nil, "project") + err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", nil, "project", "2025-03-03") if err != nil { t.Errorf("EditTaskInTaskwarrior() failed: %v", err) } else { @@ -68,7 +68,7 @@ func TestAddTaskWithTags(t *testing.T) { } func TestEditTaskWithTagAddition(t *testing.T) { - err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"+urgent", "+important"}, "project") + err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"+urgent", "+important"}, "project", "") if err != nil { t.Errorf("EditTaskInTaskwarrior with tag addition failed: %v", err) } else { @@ -77,7 +77,7 @@ func TestEditTaskWithTagAddition(t *testing.T) { } func TestEditTaskWithTagRemoval(t *testing.T) { - err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"-work", "-lowpriority"}, "project") + err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"-work", "-lowpriority"}, "project", "") if err != nil { t.Errorf("EditTaskInTaskwarrior with tag removal failed: %v", err) } else { @@ -86,7 +86,7 @@ func TestEditTaskWithTagRemoval(t *testing.T) { } func TestEditTaskWithMixedTagOperations(t *testing.T) { - err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"+urgent", "-work", "normal"}, "project") + err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"+urgent", "-work", "normal"}, "project", "") if err != nil { t.Errorf("EditTaskInTaskwarrior with mixed tag operations failed: %v", err) } else { diff --git a/frontend/src/components/HomeComponents/Tasks/Tasks.tsx b/frontend/src/components/HomeComponents/Tasks/Tasks.tsx index b1d547f5..c341cbe7 100644 --- a/frontend/src/components/HomeComponents/Tasks/Tasks.tsx +++ b/frontend/src/components/HomeComponents/Tasks/Tasks.tsx @@ -35,6 +35,13 @@ import { } from 'lucide-react'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; import CopyToClipboard from 'react-copy-to-clipboard'; import { formattedDate, @@ -56,10 +63,13 @@ import BottomBar from '../BottomBar/BottomBar'; import { addTaskToBackend, editTaskOnBackend, + modifyTaskOnBackend, fetchTaskwarriorTasks, TasksDatabase, } from './hooks'; import { debounce } from '@/components/utils/utils'; +import { DatePicker } from '@/components/ui/date-picker'; +import { format, parseISO } from 'date-fns'; const db = new TasksDatabase(); export let syncTasksWithTwAndDb: () => any; @@ -101,10 +111,14 @@ export const Tasks = ( _selectedTask?.tags || [] ); const [isEditingTags, setIsEditingTags] = useState(false); + const [isEditingPriority, setIsEditingPriority] = useState(false); + const [editedPriority, setEditedPriority] = useState('NONE'); const [isEditingProject, setIsEditingProject] = useState(false); const [editedProject, setEditedProject] = useState( _selectedTask?.project || '' ); + const [isEditingStart, setIsEditingStart] = useState(false); + const [editedStart, setEditedStart] = useState(undefined); const [searchTerm, setSearchTerm] = useState(''); const [lastSyncTime, setLastSyncTime] = useState(null); @@ -303,7 +317,8 @@ export const Tasks = ( description: string, tags: string[], taskID: string, - project: string + project: string, + start?: string ) { try { await editTaskOnBackend({ @@ -315,6 +330,7 @@ export const Tasks = ( taskID, backendURL: url.backendURL, project, + start, }); console.log('Task edited successfully!'); @@ -385,9 +401,14 @@ export const Tasks = ( if (!_isDialogOpen) { setIsEditing(false); setEditedDescription(''); + setIsEditingTags(false); + setEditedTags([]); + setIsEditingPriority(false); + setEditedPriority('NONE'); } else { setSelectedTask(task); setEditedDescription(task?.description || ''); + setEditedPriority(task?.priority || 'NONE'); } }; @@ -463,7 +484,83 @@ export const Tasks = ( const handleCancelTags = () => { setIsEditingTags(false); - setEditedTags([]); // Reset tags + setEditedTags([]); + }; + + const handleEditStartClick = (start: string) => { + if (start && start.trim() !== '') { + try { + const parsedDate = parseISO(start); + setEditedStart(isNaN(parsedDate.getTime()) ? undefined : parsedDate); + } catch { + setEditedStart(undefined); + } + } else { + setEditedStart(undefined); + } + setIsEditingStart(true); + }; + + const handleSaveStart = async (task: Task) => { + const startDate = editedStart ? format(editedStart, 'yyyy-MM-dd') : ''; + await handleEditTaskOnBackend( + props.email, + props.encryptionSecret, + props.UUID, + task.description, + task.tags || [], + task.uuid, + task.project, + startDate + ); + setIsEditingStart(false); + await syncTasksWithTwAndDb(); + }; + + const handleCancelStart = () => { + setIsEditingStart(false); + setEditedStart(undefined); + }; + + const handleEditPriorityClick = (task: Task) => { + // Convert empty priority to "NONE" for the select component + setEditedPriority(task.priority || 'NONE'); + setIsEditingPriority(true); + }; + + const handleSavePriority = async (task: Task) => { + try { + // Convert "NONE" to empty string for backend + const priorityValue = editedPriority === 'NONE' ? '' : editedPriority; + + await modifyTaskOnBackend({ + email: props.email, + encryptionSecret: props.encryptionSecret, + UUID: props.UUID, + taskID: task.id.toString(), + description: task.description, + project: task.project || '', + priority: priorityValue, + status: task.status, + due: task.due || '', + tags: task.tags || [], + backendURL: url.backendURL, + }); + + console.log('Priority updated successfully!'); + toast.success('Priority updated successfully!'); + setIsEditingPriority(false); + } catch (error) { + console.error('Failed to update priority:', error); + toast.error('Failed to update priority. Please try again.'); + } + }; + + const handleCancelPriority = () => { + setIsEditingPriority(false); + if (_selectedTask) { + setEditedPriority(_selectedTask.priority || 'NONE'); + } }; return ( @@ -654,26 +751,27 @@ export const Tasks = ( />
-
-
diff --git a/frontend/src/components/HomeComponents/Tasks/hooks.ts b/frontend/src/components/HomeComponents/Tasks/hooks.ts index 6bf42b88..3102a533 100644 --- a/frontend/src/components/HomeComponents/Tasks/hooks.ts +++ b/frontend/src/components/HomeComponents/Tasks/hooks.ts @@ -89,6 +89,7 @@ export const editTaskOnBackend = async ({ taskID, backendURL, project, + start, }: { email: string; encryptionSecret: string; @@ -98,6 +99,7 @@ export const editTaskOnBackend = async ({ taskID: string; backendURL: string; project: string; + start?: string; }) => { const response = await fetch(`${backendURL}edit-task`, { method: 'POST', @@ -109,6 +111,7 @@ export const editTaskOnBackend = async ({ description, tags, project, + start, }), headers: { 'Content-Type': 'application/json', @@ -123,6 +126,58 @@ export const editTaskOnBackend = async ({ return response; }; +export const modifyTaskOnBackend = async ({ + email, + encryptionSecret, + UUID, + taskID, + description, + project, + priority, + status, + due, + tags, + backendURL, +}: { + email: string; + encryptionSecret: string; + UUID: string; + taskID: string; + description: string; + project: string; + priority: string; + status: string; + due: string; + tags: string[]; + backendURL: string; +}) => { + const response = await fetch(`${backendURL}modify-task`, { + method: 'POST', + body: JSON.stringify({ + email, + encryptionSecret, + UUID, + taskid: taskID, + description, + project, + priority, + status, + due, + tags, + }), + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error(errorText || 'Failed to modify task'); + } + + return response; +}; + export class TasksDatabase extends Dexie { tasks: Dexie.Table; From e476e229ea4d9ed4a5586f73730c426f058f37eb Mon Sep 17 00:00:00 2001 From: Rajat yadav Date: Sun, 16 Nov 2025 17:15:06 +0530 Subject: [PATCH 2/2] feat: make start field editable Added start date field editing functionality to tasks --- backend/utils/tw/edit_task.go | 26 ++- backend/utils/tw/taskwarrior_test.go | 8 +- .../components/HomeComponents/Tasks/Tasks.tsx | 199 ++++++++++-------- .../components/HomeComponents/Tasks/hooks.ts | 2 +- 4 files changed, 135 insertions(+), 100 deletions(-) diff --git a/backend/utils/tw/edit_task.go b/backend/utils/tw/edit_task.go index ed5dbc68..4d467e88 100644 --- a/backend/utils/tw/edit_task.go +++ b/backend/utils/tw/edit_task.go @@ -8,6 +8,9 @@ import ( ) func EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID string, tags []string, project string, start string) error { + if err := utils.ExecCommand("rm", "-rf", "/root/.task"); err != nil { + return fmt.Errorf("error deleting Taskwarrior data: %v", err) + } tempDir, err := os.MkdirTemp("", "taskwarrior-"+email) if err != nil { return fmt.Errorf("failed to create temporary directory: %v", err) @@ -24,16 +27,14 @@ func EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID st } // Escape the double quotes in the description and format it - if description != "" { - escapedDescription := fmt.Sprintf(`description:"%s"`, strings.ReplaceAll(description, `"`, `\"`)) - if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", escapedDescription, "rc.confirmation=off"); err != nil { - return fmt.Errorf("failed to edit task: %v", err) - } + if err := utils.ExecCommand("task", taskID, "modify", description); err != nil { + fmt.Println("task " + taskID + " modify " + description) + return fmt.Errorf("failed to edit task: %v", err) } // Handle project if project != "" { - if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "project:"+project, "rc.confirmation=off"); err != nil { + if err := utils.ExecCommand("task", taskID, "modify", "project:"+project); err != nil { return fmt.Errorf("failed to set project %s: %v", project, err) } } @@ -42,29 +43,34 @@ func EditTaskInTaskwarrior(uuid, description, email, encryptionSecret, taskID st if len(tags) > 0 { for _, tag := range tags { if strings.HasPrefix(tag, "+") { + // Add tag tagValue := strings.TrimPrefix(tag, "+") - if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "+"+tagValue, "rc.confirmation=off"); err != nil { + if err := utils.ExecCommand("task", taskID, "modify", "+"+tagValue); err != nil { return fmt.Errorf("failed to add tag %s: %v", tagValue, err) } } else if strings.HasPrefix(tag, "-") { + // Remove tag tagValue := strings.TrimPrefix(tag, "-") - if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "-"+tagValue, "rc.confirmation=off"); err != nil { + if err := utils.ExecCommand("task", taskID, "modify", "-"+tagValue); err != nil { return fmt.Errorf("failed to remove tag %s: %v", tagValue, err) } } else { - if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "+"+tag, "rc.confirmation=off"); err != nil { + // Add tag without prefix + if err := utils.ExecCommand("task", taskID, "modify", "+"+tag); err != nil { return fmt.Errorf("failed to add tag %s: %v", tag, err) } } } } + // Handle start date if start != "" { - if err := utils.ExecCommandInDir(tempDir, "task", taskID, "modify", "start:"+start, "rc.confirmation=off"); err != nil { + if err := utils.ExecCommand("task", taskID, "modify", "start:"+start); err != nil { return fmt.Errorf("failed to set start date %s: %v", start, err) } } + // Sync Taskwarrior again if err := SyncTaskwarrior(tempDir); err != nil { return err } diff --git a/backend/utils/tw/taskwarrior_test.go b/backend/utils/tw/taskwarrior_test.go index 4df0ced7..e858f9cf 100644 --- a/backend/utils/tw/taskwarrior_test.go +++ b/backend/utils/tw/taskwarrior_test.go @@ -23,7 +23,7 @@ func TestSyncTaskwarrior(t *testing.T) { } func TestEditTaskInATaskwarrior(t *testing.T) { - err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", nil, "project", "2025-03-03") + err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", nil, "project", "2025-11-29T18:30:00.000Z") if err != nil { t.Errorf("EditTaskInTaskwarrior() failed: %v", err) } else { @@ -68,7 +68,7 @@ func TestAddTaskWithTags(t *testing.T) { } func TestEditTaskWithTagAddition(t *testing.T) { - err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"+urgent", "+important"}, "project", "") + err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"+urgent", "+important"}, "project", "2025-11-29T18:30:00.000Z") if err != nil { t.Errorf("EditTaskInTaskwarrior with tag addition failed: %v", err) } else { @@ -77,7 +77,7 @@ func TestEditTaskWithTagAddition(t *testing.T) { } func TestEditTaskWithTagRemoval(t *testing.T) { - err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"-work", "-lowpriority"}, "project", "") + err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"-work", "-lowpriority"}, "project", "2025-11-29T18:30:00.000Z") if err != nil { t.Errorf("EditTaskInTaskwarrior with tag removal failed: %v", err) } else { @@ -86,7 +86,7 @@ func TestEditTaskWithTagRemoval(t *testing.T) { } func TestEditTaskWithMixedTagOperations(t *testing.T) { - err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"+urgent", "-work", "normal"}, "project", "") + err := EditTaskInTaskwarrior("uuid", "description", "email", "encryptionSecret", "taskuuid", []string{"+urgent", "-work", "normal"}, "project", "2025-11-29T18:30:00.000Z") if err != nil { t.Errorf("EditTaskInTaskwarrior with mixed tag operations failed: %v", err) } else { diff --git a/frontend/src/components/HomeComponents/Tasks/Tasks.tsx b/frontend/src/components/HomeComponents/Tasks/Tasks.tsx index a7f836b5..737d6fc0 100644 --- a/frontend/src/components/HomeComponents/Tasks/Tasks.tsx +++ b/frontend/src/components/HomeComponents/Tasks/Tasks.tsx @@ -118,8 +118,8 @@ export const Tasks = ( const [editedProject, setEditedProject] = useState( _selectedTask?.project || '' ); - const [isEditingStart, setIsEditingStart] = useState(false); - const [editedStart, setEditedStart] = useState(undefined); + const [isEditingStartDate, setIsEditingStartDate] = useState(false); + const [editedStartDate, setEditedStartDate] = useState(''); const [searchTerm, setSearchTerm] = useState(''); const [lastSyncTime, setLastSyncTime] = useState(null); @@ -321,7 +321,7 @@ export const Tasks = ( tags: string[], taskID: string, project: string, - start?: string + start: string ) { try { await editTaskOnBackend({ @@ -376,7 +376,8 @@ export const Tasks = ( task.description, task.tags, task.id.toString(), - task.project + task.project, + task.start ); setIsEditing(false); }; @@ -390,11 +391,29 @@ export const Tasks = ( task.description, task.tags, task.id.toString(), - task.project + task.project, + task.start ); setIsEditingProject(false); }; + const handleStartDateSaveClick = (task: Task) => { + task.start = editedStartDate; + + handleEditTaskOnBackend( + props.email, + props.encryptionSecret, + props.UUID, + task.description, + task.tags, + task.id.toString(), + task.project, + task.start + ); + + setIsEditingStartDate(false); + }; + const handleCancelClick = () => { setIsEditing(false); }; @@ -479,7 +498,8 @@ export const Tasks = ( task.description, finalTags, task.id.toString(), - task.project + task.project, + task.start ); setIsEditingTags(false); // Exit editing mode @@ -489,42 +509,6 @@ export const Tasks = ( setIsEditingTags(false); setEditedTags([]); }; - - const handleEditStartClick = (start: string) => { - if (start && start.trim() !== '') { - try { - const parsedDate = parseISO(start); - setEditedStart(isNaN(parsedDate.getTime()) ? undefined : parsedDate); - } catch { - setEditedStart(undefined); - } - } else { - setEditedStart(undefined); - } - setIsEditingStart(true); - }; - - const handleSaveStart = async (task: Task) => { - const startDate = editedStart ? format(editedStart, 'yyyy-MM-dd') : ''; - await handleEditTaskOnBackend( - props.email, - props.encryptionSecret, - props.UUID, - task.description, - task.tags || [], - task.uuid, - task.project, - startDate - ); - setIsEditingStart(false); - await syncTasksWithTwAndDb(); - }; - - const handleCancelStart = () => { - setIsEditingStart(false); - setEditedStart(undefined); - }; - const handleEditPriorityClick = (task: Task) => { // Convert empty priority to "NONE" for the select component setEditedPriority(task.priority || 'NONE'); @@ -566,48 +550,6 @@ export const Tasks = ( } }; - const handleEditPriorityClick = (task: Task) => { - // Convert empty priority to "NONE" for the select component - setEditedPriority(task.priority || 'NONE'); - setIsEditingPriority(true); - }; - - const handleSavePriority = async (task: Task) => { - try { - // Convert "NONE" to empty string for backend - const priorityValue = editedPriority === 'NONE' ? '' : editedPriority; - - await modifyTaskOnBackend({ - email: props.email, - encryptionSecret: props.encryptionSecret, - UUID: props.UUID, - taskID: task.id.toString(), - description: task.description, - project: task.project || '', - priority: priorityValue, - status: task.status, - due: task.due || '', - tags: task.tags || [], - backendURL: url.backendURL, - }); - - console.log('Priority updated successfully!'); - toast.success('Priority updated successfully!'); - setIsEditingPriority(false); - } catch (error) { - console.error('Failed to update priority:', error); - toast.error('Failed to update priority. Please try again.'); - } - }; - - const handleCancelPriority = () => { - setIsEditingPriority(false); - // Reset to the task's original priority - if (_selectedTask) { - setEditedPriority(_selectedTask.priority || 'NONE'); - } - }; - return (
Start: - {formattedDate(task.start)} + {isEditingStartDate ? ( +
+ { + try { + // Handle YYYY-MM-DD format + const dateStr = + editedStartDate.includes( + 'T' + ) + ? editedStartDate.split( + 'T' + )[0] + : editedStartDate; + const parsed = + new Date( + dateStr + + 'T00:00:00' + ); + return isNaN( + parsed.getTime() + ) + ? undefined + : parsed; + } catch { + return undefined; + } + })() + : undefined + } + onDateChange={(date) => + setEditedStartDate( + date + ? format( + date, + 'yyyy-MM-dd' + ) + : '' + ) + } + /> + + + + +
+ ) : ( + <> + + {formattedDate(task.start)} + + + + )}
diff --git a/frontend/src/components/HomeComponents/Tasks/hooks.ts b/frontend/src/components/HomeComponents/Tasks/hooks.ts index 3102a533..f905fdbb 100644 --- a/frontend/src/components/HomeComponents/Tasks/hooks.ts +++ b/frontend/src/components/HomeComponents/Tasks/hooks.ts @@ -99,7 +99,7 @@ export const editTaskOnBackend = async ({ taskID: string; backendURL: string; project: string; - start?: string; + start: string; }) => { const response = await fetch(`${backendURL}edit-task`, { method: 'POST',