Compare commits

...

2 Commits

Author SHA1 Message Date
Cauê Faleiros
5d697f8f8a Consolidate production flow under supplies
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m43s
2026-08-27 14:16:45 -03:00
Cauê Faleiros
ed750ac4ce Organize quality under supplies 2026-08-27 13:43:17 -03:00
3 changed files with 12 additions and 12 deletions

View File

@@ -1,6 +1,6 @@
import { useState, useEffect } from 'react';
import { Outlet, Link, useLocation } from 'react-router-dom';
import { LayoutDashboard, Users, BarChart3, ChevronLeft, ChevronRight, Package, LogOut, Megaphone, Grid3X3, Shield, ShieldCheck, Moon, Sun, Tags, Boxes, ClipboardList, Menu, X, BriefcaseBusiness, Radio } from 'lucide-react';
import { LayoutDashboard, Users, BarChart3, ChevronLeft, ChevronRight, Package, LogOut, Megaphone, Grid3X3, Shield, Moon, Sun, Tags, Boxes, ClipboardList, Menu, X, BriefcaseBusiness, Radio } from 'lucide-react';
import type { DateRange, OrderData } from '../types';
import { isSuperAdmin, logout } from '../dataService';
import { rangeForLastDays } from '../dateRanges';
@@ -81,9 +81,6 @@ const Layout = () => {
{ name: 'Dados Pendentes', href: '/planning-issues', icon: ClipboardList },
{ name: 'Cadastros', href: '/registrations', icon: Tags },
{ name: 'Suprimentos', href: '/supplies', icon: Boxes },
{ name: 'Planos de Produção', href: '/production-plans', icon: ClipboardList },
{ name: 'Ordens de Produção', href: '/production-orders', icon: Package },
{ name: 'Qualidade', href: '/production-quality', icon: ShieldCheck },
],
},
{

View File

@@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { Link, useOutletContext, useSearchParams } from 'react-router-dom';
import { AlertTriangle, ArrowLeft, ArrowRight, Check, ChevronDown, ClipboardList, Download, Eye, Layers3, Pencil, RotateCcw, Ruler, Save as SaveIcon, Scissors, Search, Settings2, UserRound, X } from 'lucide-react';
import DateRangePicker from '../components/DateRangePicker';
@@ -394,10 +394,10 @@ const Cutting = () => {
};
}, [cutPlan.needRows, materialReadinessByProductId]);
const getPreviewQuantity = (row: CutPlanSkuRow) => {
const getPreviewQuantity = useCallback((row: CutPlanSkuRow) => {
const override = Number((previewQuantityOverrides[row.id] || '').replace(',', '.'));
return Number.isFinite(override) && override > 0 ? Math.round(override) : row.suggestedCutQuantity;
};
}, [previewQuantityOverrides]);
const selectedPreviewRows = useMemo(() => {
const selectedIds = new Set(selectedPreviewRowIds);
@@ -405,7 +405,7 @@ const Cutting = () => {
}, [rowsAvailableForOrder, selectedPreviewRowIds]);
const orderPreviewTotalUnits = useMemo(() => (
selectedPreviewRows.reduce((total, row) => total + getPreviewQuantity(row), 0)
), [previewQuantityOverrides, selectedPreviewRows]);
), [getPreviewQuantity, selectedPreviewRows]);
const selectedResponsibleUser = useMemo(() => (
operationalUsers.find((user) => user.id === productionPlanForm.responsibleUserId && user.name === productionPlanForm.responsibleName) || null
), [operationalUsers, productionPlanForm.responsibleName, productionPlanForm.responsibleUserId]);
@@ -434,7 +434,7 @@ const Cutting = () => {
});
});
return Array.from(requirements.values()).sort((a, b) => a.label.localeCompare(b.label, 'pt-BR'));
}, [compositionsByProductId, previewQuantityOverrides, selectedPreviewRows]);
}, [compositionsByProductId, getPreviewQuantity, selectedPreviewRows]);
const selectedLotReservations = useMemo(() => (
selectedMaterialRequirements.flatMap(requirement => {

View File

@@ -22,6 +22,7 @@ import {
Save,
Search,
Scissors,
ShieldCheck,
Truck,
Trash2,
Warehouse,
@@ -400,10 +401,11 @@ const SuppliesHub = () => {
<h2 className="text-base font-bold text-dark-text">Fluxo operacional</h2>
<p className="mt-1 text-sm font-semibold text-dark-muted">Da necessidade de material até a produção acompanhada.</p>
</div>
<div className="grid grid-cols-1 gap-4 xl:grid-cols-3">
<div className="grid grid-cols-1 gap-4 xl:grid-cols-4">
<FlowStepCard title="Garantir materiais" description="Confira saldo disponível, recebimentos e a compra sugerida." icon={BarChart3} to={materialPurchaseNeeds.length > 0 ? '/supplies/purchase-needs?tab=materials&filter=to_buy' : '/supplies/purchase-needs?tab=materials&filter=all'} tone={materialPurchaseNeeds.length > 0 ? 'attention' : 'ready'} meta={materialPurchaseNeeds.length > 0 ? `${formatNumber(materialPurchaseNeeds.length, 0)} materiais para comprar` : 'Materiais cobertos'} />
<FlowStepCard title="Definir corte" description="Priorize SKUs, cores e tamanhos com necessidade e material disponível." icon={Scissors} to="/cutting" tone="default" meta="Abrir plano de corte" />
<FlowStepCard title="Acompanhar produção" description="Gerencie as OPs criadas a partir do corte até sua finalização." icon={ClipboardList} to="/production-orders" tone={activeProductionCount > 0 ? 'ready' : 'default'} meta={activeProductionCount > 0 ? `${formatNumber(productionCounts.open, 0)} abertas · ${formatNumber(productionCounts.inProgress, 0)} em andamento` : 'Nenhuma OP em execução'} />
<FlowStepCard title="Planejar corte" description="Priorize SKUs, cores e tamanhos com necessidade e material disponível." icon={Scissors} to="/cutting" tone="default" meta="Abrir plano de corte" />
<FlowStepCard title="Planos de produção" description="Organize os cortes em planos, defina o responsável e acompanhe a liberação." icon={ClipboardCheck} to="/production-plans" tone="default" meta="Abrir planos de produção" />
<FlowStepCard title="Ordens de produção" description="Acompanhe as OPs criadas a partir do plano até sua finalização." icon={ClipboardList} to="/production-orders" tone={activeProductionCount > 0 ? 'ready' : 'default'} meta={activeProductionCount > 0 ? `${formatNumber(productionCounts.open, 0)} abertas · ${formatNumber(productionCounts.inProgress, 0)} em andamento` : 'Nenhuma OP em execução'} />
</div>
</section>
<section className="border-t border-dark-border pt-6">
@@ -416,6 +418,7 @@ const SuppliesHub = () => {
<ModuleCard title="Ordens de compra" description="Formalize pedidos de materiais, fornecedor, prazo e valor antes do recebimento." icon={ClipboardList} to="/supplies/purchase-orders" meta="Criar e acompanhar OCs" />
<ModuleCard title="Planejamento de malha" description="Organize a fila de matéria-prima para abastecer compras e corte." icon={Ruler} to="/supplies/fabric-planning" />
<ModuleCard title="Transformações e perdas" description="Planeje tecelagem, tinturaria, cores e perda esperada sem alterar o estoque físico." icon={Factory} to="/supplies/material-transformations" />
<ModuleCard title="Qualidade da malha" description="Acompanhe furos, perdas e origem dos defeitos por lote, posto e OP." icon={ShieldCheck} to="/production-quality" />
<ModuleCard title="Prioridades de estoque" description="Analise reposição, cobertura e itens que precisam de revisão de cadastro." icon={PackageSearch} to="/supplies/current-planning" />
</div>
</section>