Changes
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
import { CheckCircle, XCircle, Clock, MessageSquare } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Textarea } from '@/components/ui/textarea';
|
||||
import { useModelStore, type ChecklistItem } from '@/stores/useModelStore';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
function ChecklistRow({ item }: { item: ChecklistItem }) {
|
||||
const { setChecklistItemStatus, setChecklistItemNote } = useModelStore();
|
||||
const [showNote, setShowNote] = useState(item.status === 'rejected');
|
||||
|
||||
const handleApprove = () => {
|
||||
setChecklistItemStatus(item.id, 'approved');
|
||||
setShowNote(false);
|
||||
toast.success(`"${item.label}" aprovado`);
|
||||
};
|
||||
|
||||
const handleReject = () => {
|
||||
setChecklistItemStatus(item.id, 'rejected');
|
||||
setShowNote(true);
|
||||
toast.error(`"${item.label}" reprovado — adicione uma anotação`);
|
||||
};
|
||||
|
||||
const statusColor =
|
||||
item.status === 'approved' ? 'text-success' :
|
||||
item.status === 'rejected' ? 'text-destructive' :
|
||||
'text-muted-foreground';
|
||||
|
||||
const StatusIcon =
|
||||
item.status === 'approved' ? CheckCircle :
|
||||
item.status === 'rejected' ? XCircle :
|
||||
Clock;
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border bg-muted/30 p-3 space-y-2">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-2 min-w-0">
|
||||
<StatusIcon className={`h-4 w-4 shrink-0 ${statusColor}`} />
|
||||
<span className="font-mono text-xs text-foreground truncate">{item.label}</span>
|
||||
</div>
|
||||
<div className="flex gap-1 shrink-0">
|
||||
<Button
|
||||
variant={item.status === 'approved' ? 'default' : 'ghost'}
|
||||
size="icon"
|
||||
className="h-7 w-7"
|
||||
onClick={handleApprove}
|
||||
title="Aprovar"
|
||||
>
|
||||
<CheckCircle className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
<Button
|
||||
variant={item.status === 'rejected' ? 'destructive' : 'ghost'}
|
||||
size="icon"
|
||||
className="h-7 w-7"
|
||||
onClick={handleReject}
|
||||
title="Reprovar"
|
||||
>
|
||||
<XCircle className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{(showNote || item.status === 'rejected') && (
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-1">
|
||||
<MessageSquare className="h-3 w-3 text-muted-foreground" />
|
||||
<span className="font-mono text-[10px] text-muted-foreground">Anotação</span>
|
||||
</div>
|
||||
<Textarea
|
||||
className="h-16 font-mono text-xs resize-none bg-background"
|
||||
placeholder="Descreva o problema encontrado…"
|
||||
value={item.note}
|
||||
onChange={(e) => setChecklistItemNote(item.id, e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function InspectionChecklist() {
|
||||
const { checklist, resetChecklist } = useModelStore();
|
||||
|
||||
const approved = checklist.filter(i => i.status === 'approved').length;
|
||||
const rejected = checklist.filter(i => i.status === 'rejected').length;
|
||||
const total = checklist.length;
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="font-mono text-xs font-semibold uppercase tracking-widest text-muted-foreground">
|
||||
Checklist de Inspeção
|
||||
</h3>
|
||||
<Button variant="ghost" size="sm" className="h-6 text-[10px]" onClick={resetChecklist}>
|
||||
Resetar
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Progress summary */}
|
||||
<div className="flex items-center gap-3 rounded-lg border bg-muted/30 px-3 py-2">
|
||||
<div className="flex-1">
|
||||
<div className="h-1.5 rounded-full bg-muted overflow-hidden">
|
||||
<div
|
||||
className="h-full rounded-full bg-primary transition-all"
|
||||
style={{ width: `${((approved + rejected) / total) * 100}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span className="font-mono text-[10px] text-muted-foreground shrink-0">
|
||||
{approved + rejected}/{total}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Status badges */}
|
||||
<div className="flex gap-2">
|
||||
{approved > 0 && (
|
||||
<span className="font-mono text-[10px] text-success flex items-center gap-1">
|
||||
<CheckCircle className="h-3 w-3" /> {approved}
|
||||
</span>
|
||||
)}
|
||||
{rejected > 0 && (
|
||||
<span className="font-mono text-[10px] text-destructive flex items-center gap-1">
|
||||
<XCircle className="h-3 w-3" /> {rejected}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Items */}
|
||||
<div className="space-y-2">
|
||||
{checklist.map(item => (
|
||||
<ChecklistRow key={item.id} item={item} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user