forked from cardosofelipe/pragma-stack
- Fix IssueStatus: remove 'done', keep 'closed' - Add IssuePriority 'critical' level - Add IssueType enum (epic, story, task, bug) - Update constants, hooks, and mocks to match - Fix StatusWorkflow component icons
86 lines
2.3 KiB
TypeScript
86 lines
2.3 KiB
TypeScript
'use client';
|
|
|
|
/**
|
|
* StatusWorkflow Component
|
|
*
|
|
* Interactive status selector with workflow transitions.
|
|
*
|
|
* @module features/issues/components/StatusWorkflow
|
|
*/
|
|
|
|
import {
|
|
CircleDot,
|
|
PlayCircle,
|
|
Clock,
|
|
AlertCircle,
|
|
CheckCircle2,
|
|
XCircle,
|
|
} from 'lucide-react';
|
|
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
|
|
import { cn } from '@/lib/utils';
|
|
import type { IssueStatus } from '../types';
|
|
import { STATUS_ORDER, STATUS_CONFIG } from '../constants';
|
|
|
|
const STATUS_ICONS = {
|
|
open: CircleDot,
|
|
in_progress: PlayCircle,
|
|
in_review: Clock,
|
|
blocked: AlertCircle,
|
|
closed: XCircle,
|
|
} as const;
|
|
|
|
interface StatusWorkflowProps {
|
|
currentStatus: IssueStatus;
|
|
onStatusChange: (status: IssueStatus) => void;
|
|
disabled?: boolean;
|
|
className?: string;
|
|
}
|
|
|
|
export function StatusWorkflow({
|
|
currentStatus,
|
|
onStatusChange,
|
|
disabled = false,
|
|
className,
|
|
}: StatusWorkflowProps) {
|
|
return (
|
|
<Card className={className}>
|
|
<CardHeader>
|
|
<CardTitle className="text-lg">Status Workflow</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-2" role="radiogroup" aria-label="Issue status">
|
|
{STATUS_ORDER.map((status) => {
|
|
const config = STATUS_CONFIG[status];
|
|
const Icon = STATUS_ICONS[status];
|
|
const isActive = currentStatus === status;
|
|
|
|
return (
|
|
<button
|
|
key={status}
|
|
type="button"
|
|
role="radio"
|
|
aria-checked={isActive}
|
|
disabled={disabled}
|
|
className={cn(
|
|
'flex w-full items-center gap-2 rounded-lg p-2 text-left transition-colors',
|
|
isActive
|
|
? 'bg-primary/10 text-primary'
|
|
: 'hover:bg-muted',
|
|
disabled && 'cursor-not-allowed opacity-50'
|
|
)}
|
|
onClick={() => !disabled && onStatusChange(status)}
|
|
>
|
|
<Icon className={cn('h-4 w-4', config.color)} aria-hidden="true" />
|
|
<span className="text-sm">{config.label}</span>
|
|
{isActive && (
|
|
<CheckCircle2 className="ml-auto h-4 w-4" aria-hidden="true" />
|
|
)}
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|