forked from mosaicstack/stack
Co-authored-by: Jason Woltje <[email protected]> Co-committed-by: Jason Woltje <[email protected]>
100 lines
2.3 KiB
TypeScript
100 lines
2.3 KiB
TypeScript
'use client';
|
|
|
|
import { cn } from '@/lib/cn';
|
|
import type { Task, TaskStatus } from '@/lib/types';
|
|
|
|
interface TaskStatusSummaryProps {
|
|
tasks: Task[];
|
|
activeFilter: TaskStatus | 'all';
|
|
onFilterChange: (filter: TaskStatus | 'all') => void;
|
|
}
|
|
|
|
const statusConfig: {
|
|
id: TaskStatus | 'all';
|
|
label: string;
|
|
color: string;
|
|
activeColor: string;
|
|
}[] = [
|
|
{
|
|
id: 'all',
|
|
label: 'All',
|
|
color: 'text-text-muted',
|
|
activeColor: 'bg-surface-elevated text-text-primary',
|
|
},
|
|
{
|
|
id: 'not-started',
|
|
label: 'Not Started',
|
|
color: 'text-gray-400',
|
|
activeColor: 'bg-gray-600/20 text-gray-300',
|
|
},
|
|
{
|
|
id: 'in-progress',
|
|
label: 'In Progress',
|
|
color: 'text-blue-400',
|
|
activeColor: 'bg-blue-600/20 text-blue-400',
|
|
},
|
|
{
|
|
id: 'blocked',
|
|
label: 'Blocked',
|
|
color: 'text-error',
|
|
activeColor: 'bg-error/20 text-error',
|
|
},
|
|
{
|
|
id: 'done',
|
|
label: 'Done',
|
|
color: 'text-success',
|
|
activeColor: 'bg-success/20 text-success',
|
|
},
|
|
];
|
|
|
|
export function TaskStatusSummary({
|
|
tasks,
|
|
activeFilter,
|
|
onFilterChange,
|
|
}: TaskStatusSummaryProps): React.ReactElement {
|
|
const counts: Record<TaskStatus | 'all', number> = {
|
|
all: tasks.length,
|
|
'not-started': 0,
|
|
'in-progress': 0,
|
|
blocked: 0,
|
|
done: 0,
|
|
cancelled: 0,
|
|
};
|
|
|
|
for (const task of tasks) {
|
|
counts[task.status] = (counts[task.status] ?? 0) + 1;
|
|
}
|
|
|
|
return (
|
|
<div className="flex flex-wrap gap-2">
|
|
{statusConfig.map((config) => {
|
|
const count = counts[config.id];
|
|
const isActive = activeFilter === config.id;
|
|
return (
|
|
<button
|
|
key={config.id}
|
|
type="button"
|
|
onClick={() => onFilterChange(config.id)}
|
|
className={cn(
|
|
'flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs transition-colors',
|
|
isActive
|
|
? cn('border-transparent', config.activeColor)
|
|
: 'border-surface-border text-text-muted hover:border-gray-500',
|
|
)}
|
|
>
|
|
<span>{config.label}</span>
|
|
<span
|
|
className={cn(
|
|
'rounded-full px-1.5 py-0.5 text-xs font-medium',
|
|
isActive ? 'bg-black/20' : 'bg-surface-elevated',
|
|
)}
|
|
>
|
|
{count}
|
|
</span>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|