From d153cb839229a4d12cfd88d7eb847bec690eebe9 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Thu, 26 Feb 2026 22:40:39 -0500 Subject: [PATCH] fix: align frontend status types with API string enum serialization ASP.NET serializes C# enums as strings by default ("Pending", "Active"), but frontend types used numeric values (0, 1). Changed WorkTaskStatus and NoteType to string values matching API output. Co-Authored-By: Claude Opus 4.6 --- TaskTracker.Web/src/api/notes.ts | 2 +- TaskTracker.Web/src/components/KanbanBoard.tsx | 6 +++--- TaskTracker.Web/src/components/KanbanColumn.tsx | 6 +++--- TaskTracker.Web/src/components/NotesList.tsx | 2 +- TaskTracker.Web/src/components/SearchBar.tsx | 4 ++-- TaskTracker.Web/src/lib/constants.ts | 8 ++++---- TaskTracker.Web/src/types/index.ts | 16 ++++++++-------- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/TaskTracker.Web/src/api/notes.ts b/TaskTracker.Web/src/api/notes.ts index 1bc388e..6c2af2a 100644 --- a/TaskTracker.Web/src/api/notes.ts +++ b/TaskTracker.Web/src/api/notes.ts @@ -5,7 +5,7 @@ import type { TaskNote } from '../types' export function useCreateNote() { const qc = useQueryClient() return useMutation({ - mutationFn: ({ taskId, content, type }: { taskId: number; content: string; type: number }) => + mutationFn: ({ taskId, content, type }: { taskId: number; content: string; type: string }) => request({ method: 'POST', url: `/tasks/${taskId}/notes`, data: { content, type } }), onSuccess: () => qc.invalidateQueries({ queryKey: ['tasks'] }), }) diff --git a/TaskTracker.Web/src/components/KanbanBoard.tsx b/TaskTracker.Web/src/components/KanbanBoard.tsx index c261b16..add99ea 100644 --- a/TaskTracker.Web/src/components/KanbanBoard.tsx +++ b/TaskTracker.Web/src/components/KanbanBoard.tsx @@ -70,11 +70,11 @@ export default function KanbanBoard({ tasks, isLoading, onTaskClick }: KanbanBoa if (!task) return // Determine target status from the droppable column ID - let targetStatus: number | null = null + let targetStatus: string | null = null const overId = String(over.id) if (overId.startsWith('column-')) { - targetStatus = Number(overId.replace('column-', '')) + targetStatus = overId.replace('column-', '') } else { // Dropped over another card - find which column it belongs to const overTaskId = Number(over.id) @@ -136,7 +136,7 @@ export default function KanbanBoard({ tasks, isLoading, onTaskClick }: KanbanBoa color={col.color} tasks={col.tasks} onTaskClick={onTaskClick} - onAddTask={col.status === 0 ? () => {} : undefined} + onAddTask={col.status === WorkTaskStatus.Pending ? () => {} : undefined} /> ))} diff --git a/TaskTracker.Web/src/components/KanbanColumn.tsx b/TaskTracker.Web/src/components/KanbanColumn.tsx index da46bb3..fd0365d 100644 --- a/TaskTracker.Web/src/components/KanbanColumn.tsx +++ b/TaskTracker.Web/src/components/KanbanColumn.tsx @@ -2,12 +2,12 @@ import { useState } from 'react' import { useDroppable } from '@dnd-kit/core' import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable' import { Plus } from 'lucide-react' -import type { WorkTask } from '../types/index.ts' +import { WorkTaskStatus, type WorkTask } from '../types/index.ts' import TaskCard from './TaskCard.tsx' import CreateTaskForm from './CreateTaskForm.tsx' interface KanbanColumnProps { - status: number + status: string label: string color: string tasks: WorkTask[] @@ -65,7 +65,7 @@ export default function KanbanColumn({ {/* Add task form / button (Pending column only) */} - {status === 0 && ( + {status === WorkTaskStatus.Pending && (
{showForm ? ( setShowForm(false)} /> diff --git a/TaskTracker.Web/src/components/NotesList.tsx b/TaskTracker.Web/src/components/NotesList.tsx index 90fdd34..7dafdb4 100644 --- a/TaskTracker.Web/src/components/NotesList.tsx +++ b/TaskTracker.Web/src/components/NotesList.tsx @@ -9,7 +9,7 @@ interface NotesListProps { notes: TaskNote[] } -const NOTE_TYPE_CONFIG: Record = { +const NOTE_TYPE_CONFIG: Record = { [NoteType.PauseNote]: { label: 'Pause', color: '#f59e0b' }, [NoteType.ResumeNote]: { label: 'Resume', color: '#6366f1' }, [NoteType.General]: { label: 'General', color: '#64748b' }, diff --git a/TaskTracker.Web/src/components/SearchBar.tsx b/TaskTracker.Web/src/components/SearchBar.tsx index 461e3e5..f167f40 100644 --- a/TaskTracker.Web/src/components/SearchBar.tsx +++ b/TaskTracker.Web/src/components/SearchBar.tsx @@ -99,12 +99,12 @@ export default function SearchBar({ onSelect }: SearchBarProps) { [isOpen, results, selectedIndex, handleSelect] ) - const getStatusLabel = (status: number) => { + const getStatusLabel = (status: string) => { const col = COLUMN_CONFIG.find((c) => c.status === status) return col ? col.label : 'Unknown' } - const getStatusColor = (status: number) => { + const getStatusColor = (status: string) => { const col = COLUMN_CONFIG.find((c) => c.status === status) return col ? col.color : '#64748b' } diff --git a/TaskTracker.Web/src/lib/constants.ts b/TaskTracker.Web/src/lib/constants.ts index 366fb84..291eb95 100644 --- a/TaskTracker.Web/src/lib/constants.ts +++ b/TaskTracker.Web/src/lib/constants.ts @@ -1,8 +1,8 @@ export const COLUMN_CONFIG = [ - { status: 0, label: 'Pending', color: '#94a3b8' }, - { status: 1, label: 'Active', color: '#06b6d4' }, - { status: 2, label: 'Paused', color: '#f59e0b' }, - { status: 3, label: 'Completed', color: '#10b981' }, + { status: 'Pending' as const, label: 'Pending', color: '#94a3b8' }, + { status: 'Active' as const, label: 'Active', color: '#06b6d4' }, + { status: 'Paused' as const, label: 'Paused', color: '#f59e0b' }, + { status: 'Completed' as const, label: 'Completed', color: '#10b981' }, ] as const export const CATEGORY_COLORS: Record = { diff --git a/TaskTracker.Web/src/types/index.ts b/TaskTracker.Web/src/types/index.ts index b601efb..23985c8 100644 --- a/TaskTracker.Web/src/types/index.ts +++ b/TaskTracker.Web/src/types/index.ts @@ -1,16 +1,16 @@ export const WorkTaskStatus = { - Pending: 0, - Active: 1, - Paused: 2, - Completed: 3, - Abandoned: 4, + Pending: 'Pending', + Active: 'Active', + Paused: 'Paused', + Completed: 'Completed', + Abandoned: 'Abandoned', } as const export type WorkTaskStatus = (typeof WorkTaskStatus)[keyof typeof WorkTaskStatus] export const NoteType = { - PauseNote: 0, - ResumeNote: 1, - General: 2, + PauseNote: 'PauseNote', + ResumeNote: 'ResumeNote', + General: 'General', } as const export type NoteType = (typeof NoteType)[keyof typeof NoteType]