Delete the src/app tree, next.config.ts, next-env.d.ts, and the Next-only guard/header components. Port AppShell/Sidebar/Topbar to react-router and mount them as a DashboardLayout route over all authenticated routes. Strip 'use client' directives, move globals.css up from the deleted app/ tree, rewrite tsconfig for Vite/Bundler resolution, drop the next dependency. Test fixes the port surfaced: jsdom v29 has no window.matchMedia (sidebar breakpoint) so setup.ts stubs it; the router-boundary specs render inside ThemeProvider because the chrome's ThemeToggle requires the context.
66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
import { cn } from '@/lib/cn';
|
|
import type { Task } from '@/lib/types';
|
|
|
|
interface TaskListViewProps {
|
|
tasks: Task[];
|
|
onTaskClick: (task: Task) => void;
|
|
}
|
|
|
|
const priorityColors: Record<string, string> = {
|
|
critical: 'text-error',
|
|
high: 'text-warning',
|
|
medium: 'text-blue-400',
|
|
low: 'text-text-muted',
|
|
};
|
|
|
|
const statusColors: Record<string, string> = {
|
|
'not-started': 'text-gray-400',
|
|
'in-progress': 'text-blue-400',
|
|
blocked: 'text-error',
|
|
done: 'text-success',
|
|
cancelled: 'text-gray-500',
|
|
};
|
|
|
|
export function TaskListView({ tasks, onTaskClick }: TaskListViewProps): React.ReactElement {
|
|
if (tasks.length === 0) {
|
|
return <p className="py-8 text-center text-sm text-text-muted">No tasks found</p>;
|
|
}
|
|
|
|
return (
|
|
<div className="overflow-hidden rounded-lg border border-surface-border">
|
|
<table className="w-full">
|
|
<thead>
|
|
<tr className="border-b border-surface-border bg-surface-elevated text-left text-xs text-text-muted">
|
|
<th className="px-4 py-2 font-medium">Title</th>
|
|
<th className="px-4 py-2 font-medium">Status</th>
|
|
<th className="px-4 py-2 font-medium">Priority</th>
|
|
<th className="hidden px-4 py-2 font-medium md:table-cell">Due</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{tasks.map((task) => (
|
|
<tr
|
|
key={task.id}
|
|
onClick={() => onTaskClick(task)}
|
|
className="cursor-pointer border-b border-surface-border transition-colors last:border-b-0 hover:bg-surface-elevated"
|
|
>
|
|
<td className="px-4 py-3 text-sm text-text-primary">{task.title}</td>
|
|
<td className="px-4 py-3">
|
|
<span className={cn('text-xs', statusColors[task.status])}>{task.status}</span>
|
|
</td>
|
|
<td className="px-4 py-3">
|
|
<span className={cn('text-xs', priorityColors[task.priority])}>
|
|
{task.priority}
|
|
</span>
|
|
</td>
|
|
<td className="hidden px-4 py-3 text-xs text-text-muted md:table-cell">
|
|
{task.dueDate ? new Date(task.dueDate).toLocaleDateString() : '—'}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
}
|