Expand production order status inline
This commit is contained in:
@@ -196,7 +196,6 @@ const ProductionOrders = () => {
|
||||
const finishedCount = summary.counts.finished || 0;
|
||||
const totalQuantity = summary.orders.reduce((total, order) => total + order.quantity, 0);
|
||||
const selectedOrder = summary.orders.find(order => order.id === selectedOrderId) || null;
|
||||
const statusEditorOrder = summary.orders.find(order => order.id === statusEditorOrderId) || null;
|
||||
|
||||
const handleManualRefresh = () => {
|
||||
void loadProductionOrders({ force: true });
|
||||
@@ -282,11 +281,13 @@ const ProductionOrders = () => {
|
||||
|
||||
<div className="grid grid-cols-2 gap-3 md:grid-cols-4">
|
||||
<div className="rounded-xl border border-dark-border bg-dark-card p-3"><p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Quantidade</p><p className="mt-1 text-lg font-bold text-dark-text">{formatQuantity(order.quantity)} <span className="text-xs text-dark-muted">{order.unit}</span></p></div>
|
||||
<div className="rounded-xl border border-dark-border bg-dark-card p-3"><p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Status</p><button type="button" onClick={() => setStatusEditorOrderId(order.id)} className={`mt-2 inline-flex items-center gap-2 rounded-lg border px-2.5 py-1 text-xs font-bold ${getStatusStyle(order.status, order.statusLabel).className}`}><span className={`h-2 w-2 rounded-full ${getStatusStyle(order.status, order.statusLabel).dotClass}`} />{getStatusStyle(order.status, order.statusLabel).label}</button></div>
|
||||
<div className="rounded-xl border border-dark-border bg-dark-card p-3"><p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Status</p><button type="button" onClick={() => setStatusEditorOrderId(current => current === order.id ? null : order.id)} aria-expanded={statusEditorOrderId === order.id} className={`mt-2 inline-flex cursor-pointer items-center gap-2 rounded-lg border px-2.5 py-1 text-xs font-bold ${getStatusStyle(order.status, order.statusLabel).className}`}><span className={`h-2 w-2 rounded-full ${getStatusStyle(order.status, order.statusLabel).dotClass}`} />{getStatusStyle(order.status, order.statusLabel).label}{statusEditorOrderId === order.id ? <ChevronUp className="h-3.5 w-3.5" /> : <ChevronDown className="h-3.5 w-3.5" />}</button></div>
|
||||
<div className="rounded-xl border border-dark-border bg-dark-card p-3"><p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Emissão</p><p className="mt-1 text-sm font-bold text-dark-text">{formatDate(order.issueDate)}</p></div>
|
||||
<div className="rounded-xl border border-dark-border bg-dark-card p-3"><p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Previsão</p><p className="mt-1 text-sm font-bold text-dark-text">{formatDate(order.expectedDate)}</p></div>
|
||||
</div>
|
||||
|
||||
{statusEditorOrderId === order.id && <section className="rounded-xl border border-dark-border bg-dark-card p-4"><p className="text-xs font-bold uppercase tracking-widest text-dark-muted">Alterar status</p><div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2">{editableStatusOptions.map(option => { const style = getStatusStyle(option.value, option.label); const isCurrent = order.status === option.value; const Icon = option.value === 'finished' ? CheckCircle2 : option.value === 'canceled' ? XCircle : option.value === 'in_progress' ? PlayCircle : Clock3; return <button key={option.value} type="button" disabled={isCurrent || busyStatusOrderId === order.id} onClick={() => void handleStatusChange(order, option.value)} className={`flex cursor-pointer items-center gap-3 rounded-xl border p-3 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-60 ${isCurrent ? style.className : 'border-dark-border bg-dark-input/45 hover:border-brand-primary/60'}`}><span className={`flex h-8 w-8 shrink-0 items-center justify-center rounded-lg border ${isCurrent ? style.className : 'border-dark-border bg-dark-card text-dark-muted'}`}><Icon className="h-4 w-4" /></span><span><span className="block text-xs font-bold text-dark-text">{option.label}{isCurrent && ' · Atual'}</span><span className="mt-0.5 block text-[10px] font-semibold text-dark-muted">{option.description}</span></span></button>; })}</div></section>}
|
||||
|
||||
<section>
|
||||
<h3 className="text-xs font-bold uppercase tracking-widest text-dark-muted">Produto e marcadores</h3>
|
||||
<div className="mt-3 rounded-xl border border-dark-border bg-dark-card p-4">
|
||||
@@ -517,11 +518,16 @@ const ProductionOrders = () => {
|
||||
<button
|
||||
type="button"
|
||||
disabled={busyStatusOrderId === order.id}
|
||||
onClick={() => setStatusEditorOrderId(order.id)}
|
||||
className={`inline-flex min-h-9 items-center gap-2 rounded-lg border px-3 text-xs font-bold transition-colors hover:brightness-125 disabled:cursor-not-allowed disabled:opacity-50 ${statusStyle.className}`}
|
||||
onClick={() => {
|
||||
setSelectedOrderId(order.id);
|
||||
setStatusEditorOrderId(current => current === order.id ? null : order.id);
|
||||
}}
|
||||
aria-expanded={statusEditorOrderId === order.id}
|
||||
className={`inline-flex min-h-9 cursor-pointer items-center gap-2 rounded-lg border px-3 text-xs font-bold transition-colors hover:brightness-125 disabled:cursor-not-allowed disabled:opacity-50 ${statusStyle.className}`}
|
||||
>
|
||||
<span className={`h-2 w-2 rounded-full ${statusStyle.dotClass}`} />
|
||||
{statusStyle.label}
|
||||
{statusEditorOrderId === order.id ? <ChevronUp className="h-3.5 w-3.5" /> : <ChevronDown className="h-3.5 w-3.5" />}
|
||||
</button>
|
||||
</td>
|
||||
<td className="px-6 py-3 text-right">
|
||||
@@ -583,16 +589,6 @@ const ProductionOrders = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{statusEditorOrder && (
|
||||
<div className="fixed inset-0 z-[60] flex items-center justify-center bg-black/70 p-4 backdrop-blur-sm" role="dialog" aria-modal="true" aria-labelledby="production-status-title">
|
||||
<button type="button" aria-label="Fechar alteração de status" onClick={() => setStatusEditorOrderId(null)} className="absolute inset-0 cursor-default" />
|
||||
<div className="relative w-full max-w-lg rounded-2xl border border-dark-border bg-dark-card shadow-2xl">
|
||||
<div className="flex items-start justify-between gap-4 border-b border-dark-border px-5 py-4"><div><h2 id="production-status-title" className="text-lg font-bold text-dark-text">Status da OP</h2><p className="mt-1 text-sm font-semibold text-dark-muted">{statusEditorOrder.number || `OP #${statusEditorOrder.id}`} · {statusEditorOrder.productDescription}</p></div><button type="button" onClick={() => setStatusEditorOrderId(null)} aria-label="Fechar alteração de status" className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-dark-border bg-dark-input text-dark-muted transition-colors hover:border-brand-primary hover:text-brand-primary"><X className="h-4 w-4" /></button></div>
|
||||
<div className="space-y-2 p-5">{editableStatusOptions.map(option => { const style = getStatusStyle(option.value, option.label); const isCurrent = statusEditorOrder.status === option.value; const Icon = option.value === 'finished' ? CheckCircle2 : option.value === 'canceled' ? XCircle : option.value === 'in_progress' ? PlayCircle : Clock3; return <button key={option.value} type="button" disabled={isCurrent || busyStatusOrderId === statusEditorOrder.id} onClick={() => void handleStatusChange(statusEditorOrder, option.value)} className={`flex w-full items-center gap-4 rounded-xl border p-4 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-60 ${isCurrent ? style.className : 'border-dark-border bg-dark-input/45 hover:border-brand-primary/60'}`}><span className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border ${isCurrent ? style.className : 'border-dark-border bg-dark-card text-dark-muted'}`}><Icon className="h-5 w-5" /></span><span><span className="block text-sm font-bold text-dark-text">{option.label}{isCurrent && ' · Atual'}</span><span className="mt-1 block text-xs font-semibold text-dark-muted">{option.description}</span></span></button>; })}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user