diff --git a/frontend/src/components/TaskList/TaskList.tsx b/frontend/src/components/TaskList/TaskList.tsx deleted file mode 100644 index 81394f0..0000000 --- a/frontend/src/components/TaskList/TaskList.tsx +++ /dev/null @@ -1,223 +0,0 @@ -import React, { useRef } from 'react'; -import { Task, TaskFilter, TaskStatus } from '../../types'; -import TaskCard from './TaskCard'; -import TaskRow from './TaskRow'; -import './TaskList.css'; - -export interface FilterCounts { - my: number; - all: number; - blocked: number; -} - -interface TaskListProps { - tasks: Task[]; - totalTaskCount: number; - counts: FilterCounts; - currentFilter: TaskFilter; - pendingTaskId: number | null; - onFilterChange: (filter: TaskFilter) => void; - onCreateTask: () => void; - onEditTask: (task: Task) => void; - onDeleteTask: (task: Task) => void; - onStatusChange: (task: Task, status: TaskStatus) => void; -} - -const FILTERS: { value: TaskFilter; label: string }[] = [ - { value: 'my', label: 'My Tasks' }, - { value: 'all', label: 'All Tasks' }, - { value: 'blocked', label: 'Blocked' }, -]; - -const COLUMNS = ['Priority', 'Task Name', 'Assignee', 'Status', 'Due Date', 'Actions']; - -const EMPTY_STATES: Record = { - my: { - icon: '\u2705', - heading: 'Nothing assigned to you', - body: 'When a teammate assigns you a task it shows up here.', - }, - all: { - icon: '\u{1F4CB}', - heading: 'No tasks yet', - body: 'Get started by creating your first task.', - }, - blocked: { - icon: '\u{1F6AB}', - heading: 'No blocked tasks', - body: 'Your team has no blocked work right now.', - }, -}; - -const TaskList: React.FC = ({ - tasks, - totalTaskCount, - counts, - currentFilter, - pendingTaskId, - onFilterChange, - onCreateTask, - onEditTask, - onDeleteTask, - onStatusChange, -}) => { - const tabsRef = useRef(null); - - // Left/Right arrows move between filter tabs, as expected of an ARIA tablist. - const handleTabKeyDown = (event: React.KeyboardEvent): void => { - if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') { - return; - } - event.preventDefault(); - - const currentIndex = FILTERS.findIndex((filter) => filter.value === currentFilter); - const step = event.key === 'ArrowRight' ? 1 : -1; - const next = FILTERS[(currentIndex + step + FILTERS.length) % FILTERS.length]; - - onFilterChange(next.value); - tabsRef.current?.querySelector(`#filter-tab-${next.value}`)?.focus(); - }; - - const emptyState = EMPTY_STATES[totalTaskCount === 0 ? 'all' : currentFilter]; - - return ( -
-
-
- {FILTERS.map((filter) => ( - - ))} -
- - {/* aria-label keeps the name stable when the label is hidden in the mobile FAB. */} - -
- -
- {currentFilter === 'blocked' && tasks.length > 0 && ( -
- -
-

These tasks are blocked

-

- Blocked work cannot move forward yet, usually because it depends on another - unfinished task or is waiting on access. Open a task to review the details, then - reach out to the assignee. -

-
-
- )} - - {tasks.length === 0 ? ( -
-
- -

{emptyState.heading}

-

{emptyState.body}

- {totalTaskCount === 0 && ( - - )} -
-
- ) : ( -
- {/* Both views are rendered; CSS media queries decide which one is shown, - so only one reaches the accessibility tree at any width. */} -
-
- {COLUMNS.map((column) => ( -
- {/* The mockup leaves the priority heading blank. Hiding the - text (not the cell) keeps the grid columns aligned. */} - {column} -
- ))} -
-
- {tasks.map((task) => ( - - ))} -
-
- -
- {tasks.map((task) => ( - - ))} -
-
- )} -
-
- ); -}; - -export default TaskList;