Simplify cutting page workflow views
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m44s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m44s
This commit is contained in:
@@ -16,6 +16,7 @@ type SaveStatus = 'idle' | 'saving' | 'saved' | 'error';
|
||||
type CutProductIssue = Exclude<CutIssue, 'missing_yield_rule'>;
|
||||
type CorrectionIssueFilter = CutProductIssue | 'all';
|
||||
type SettingsSection = 'rules' | 'corrections';
|
||||
type CuttingView = 'plan' | 'families' | 'issues';
|
||||
|
||||
const SETTINGS_STORAGE_KEY = 'nexstar_cutting_settings';
|
||||
const coverageTargetOptions = [7, 15, 30, 60];
|
||||
@@ -144,6 +145,7 @@ const Cutting = () => {
|
||||
const [itemsPerPage, setItemsPerPage] = useState(10);
|
||||
const [isGeneratingOrders, setIsGeneratingOrders] = useState(false);
|
||||
const [isOrderPreviewOpen, setIsOrderPreviewOpen] = useState(false);
|
||||
const [activeCuttingView, setActiveCuttingView] = useState<CuttingView>('plan');
|
||||
const [generationMessage, setGenerationMessage] = useState('');
|
||||
const cutConfigSection = searchParams.get('config');
|
||||
const targetCorrectionSku = (searchParams.get('sku') || '').trim();
|
||||
@@ -979,7 +981,59 @@ const Cutting = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!!issueSummaries.length && (
|
||||
<div className="rounded-2xl border border-dark-border bg-dark-card p-2 shadow-sm">
|
||||
<div className="grid grid-cols-1 gap-2 md:grid-cols-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActiveCuttingView('plan')}
|
||||
aria-pressed={activeCuttingView === 'plan'}
|
||||
className={`flex items-center justify-between gap-3 rounded-xl border px-4 py-3 text-left transition-colors cursor-pointer ${activeCuttingView === 'plan' ? 'border-brand-primary/40 bg-brand-primary/15 text-brand-primary' : 'border-transparent text-dark-muted hover:bg-dark-input hover:text-dark-text'}`}
|
||||
>
|
||||
<span className="flex items-center gap-3">
|
||||
<Scissors className="h-4 w-4" />
|
||||
<span>
|
||||
<span className="block text-sm font-bold">Plano</span>
|
||||
<span className="block text-xs font-semibold opacity-80">SKUs para cortar</span>
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm font-bold">{formatNumber(rowsAvailableForOrder.length)}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActiveCuttingView('families')}
|
||||
aria-pressed={activeCuttingView === 'families'}
|
||||
className={`flex items-center justify-between gap-3 rounded-xl border px-4 py-3 text-left transition-colors cursor-pointer ${activeCuttingView === 'families' ? 'border-brand-primary/40 bg-brand-primary/15 text-brand-primary' : 'border-transparent text-dark-muted hover:bg-dark-input hover:text-dark-text'}`}
|
||||
>
|
||||
<span className="flex items-center gap-3">
|
||||
<Layers3 className="h-4 w-4" />
|
||||
<span>
|
||||
<span className="block text-sm font-bold">Famílias</span>
|
||||
<span className="block text-xs font-semibold opacity-80">Resumo de corte</span>
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm font-bold">{formatNumber(cutPlan.familySummaries.length)}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setActiveCuttingView('issues')}
|
||||
aria-pressed={activeCuttingView === 'issues'}
|
||||
className={`flex items-center justify-between gap-3 rounded-xl border px-4 py-3 text-left transition-colors cursor-pointer ${activeCuttingView === 'issues' ? 'border-amber-400/40 bg-amber-400/10 text-amber-300' : 'border-transparent text-dark-muted hover:bg-dark-input hover:text-dark-text'}`}
|
||||
>
|
||||
<span className="flex items-center gap-3">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
<span>
|
||||
<span className="block text-sm font-bold">Pendências</span>
|
||||
<span className="block text-xs font-semibold opacity-80">Dados a revisar</span>
|
||||
</span>
|
||||
</span>
|
||||
<span className="text-sm font-bold">{formatNumber(cutPlan.summary.rowsWithIssues)}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{activeCuttingView === 'issues' && (
|
||||
<div className="rounded-2xl border border-dark-border bg-dark-card p-4 shadow-sm">
|
||||
<div className="mb-3 flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
@@ -1002,8 +1056,21 @@ const Cutting = () => {
|
||||
<Settings2 className="h-4 w-4 text-brand-primary" />
|
||||
Corrigir
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setCutFilter('issues');
|
||||
setCurrentPage(1);
|
||||
setActiveCuttingView('plan');
|
||||
}}
|
||||
className="inline-flex items-center justify-center gap-2 rounded-xl border border-dark-border bg-dark-input px-3 py-2 text-xs font-bold text-dark-text transition-colors hover:border-brand-primary cursor-pointer"
|
||||
>
|
||||
<Search className="h-4 w-4 text-brand-primary" />
|
||||
Ver SKUs
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{issueSummaries.length ? (
|
||||
<div className="grid grid-cols-1 gap-3 md:grid-cols-4">
|
||||
{issueSummaries.map(summary => (
|
||||
<div
|
||||
@@ -1018,10 +1085,16 @@ const Cutting = () => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded-xl border border-dark-border bg-dark-input/60 px-4 py-8 text-center">
|
||||
<p className="text-sm font-bold text-dark-text">Nenhuma pendência no plano atual.</p>
|
||||
<p className="mt-1 text-xs font-semibold text-dark-muted">Os SKUs com necessidade já têm os dados mínimos para o cálculo.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!!cutPlan.familySummaries.length && (
|
||||
{activeCuttingView === 'families' && (
|
||||
<div className="rounded-2xl border border-dark-border bg-dark-card p-4 shadow-sm">
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div>
|
||||
@@ -1030,6 +1103,7 @@ const Cutting = () => {
|
||||
</div>
|
||||
<Scissors className="h-5 w-5 text-dark-muted" />
|
||||
</div>
|
||||
{cutPlan.familySummaries.length ? (
|
||||
<div className="grid grid-cols-1 gap-3 md:grid-cols-2 2xl:grid-cols-5">
|
||||
{cutPlan.familySummaries.map(summary => (
|
||||
<div
|
||||
@@ -1052,9 +1126,17 @@ const Cutting = () => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded-xl border border-dark-border bg-dark-input/60 px-4 py-8 text-center">
|
||||
<p className="text-sm font-bold text-dark-text">Nenhuma família com necessidade no período.</p>
|
||||
<p className="mt-1 text-xs font-semibold text-dark-muted">Ajuste o período ou a cobertura alvo para revisar outro cenário.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeCuttingView === 'plan' && (
|
||||
<>
|
||||
<div className="grid grid-cols-1 gap-3 rounded-2xl border border-dark-border bg-dark-card p-4 shadow-sm xl:grid-cols-[1fr_170px_170px_170px_190px]">
|
||||
<div className="relative">
|
||||
<Search className="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-zinc-400 dark:text-dark-muted" />
|
||||
@@ -1251,6 +1333,8 @@ const Cutting = () => {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user