From 51f0f9a9147abe618eeab76f979a40f946dd88ff Mon Sep 17 00:00:00 2001 From: Marcos Reifonas Date: Thu, 10 Sep 2026 12:51:53 +0000 Subject: [PATCH] feat: ordenacao por marca no kanban e regra de quadradinhos de contagem no pdf --- .../KanbanPrioridadesFabricacao.tsx | 87 ++++++++++- .../prioridades/PrioridadesPDFTemplate.tsx | 143 +++++++++++------- src/pages/PrioridadesFabricacao.tsx | 94 ++++++++---- 3 files changed, 241 insertions(+), 83 deletions(-) diff --git a/src/components/prioridades/KanbanPrioridadesFabricacao.tsx b/src/components/prioridades/KanbanPrioridadesFabricacao.tsx index d8dfe39..2bfdd0c 100644 --- a/src/components/prioridades/KanbanPrioridadesFabricacao.tsx +++ b/src/components/prioridades/KanbanPrioridadesFabricacao.tsx @@ -8,7 +8,7 @@ import { Badge } from '@/components/ui/badge'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@/components/ui/alert-dialog'; import { ItemPrioridade } from '@/hooks/useItensPrioridadeFabricacao'; import { usePrioridades } from '@/hooks/usePrioridades'; -import { Edit, Trash2, GripVertical, X, Search } from 'lucide-react'; +import { Edit, Trash2, GripVertical, X, Search, ArrowUpDown } from 'lucide-react'; import { toast } from 'sonner'; interface KanbanPrioridadesFabricacaoProps { @@ -32,6 +32,8 @@ export const KanbanPrioridadesFabricacao: React.FC(null); const [editQuantity, setEditQuantity] = useState(1); const [showDeleteAllDialog, setShowDeleteAllDialog] = useState(null); + const [showSortDialog, setShowSortDialog] = useState(null); + const [isSorting, setIsSorting] = useState(false); const [filtrosPecas, setFiltrosPecas] = useState<{ [key: string]: string }>({ P1: '', P2: '', @@ -202,6 +204,45 @@ export const KanbanPrioridadesFabricacao: React.FC { + const itens = itensPorPrioridade[codigo] || []; + if (itens.length <= 1) { + setShowSortDialog(null); + return; + } + + try { + setIsSorting(true); + // Ordenação sequencial natural por Marca (tag) + const itensOrdenadosPorMarca = [...itens].sort((a, b) => { + const marcaA = a.peca?.marca || ''; + const marcaB = b.peca?.marca || ''; + return marcaA.localeCompare(marcaB, undefined, { numeric: true, sensitivity: 'base' }); + }); + + const itensOrdenados = itensOrdenadosPorMarca.map((item, index) => ({ + id: item.id, + ordem_fabricacao: index + 1 + })); + + const primeiroItem = itens[0]; + if (primeiroItem?.prioridade_fabricacao_id) { + const sucesso = await onReorderItems(primeiroItem.prioridade_fabricacao_id, itensOrdenados); + if (sucesso) { + toast.success(`Peças da prioridade ${codigo} ordenadas sequencialmente por marca!`); + } else { + toast.error(`Não foi possível salvar a nova ordenação da prioridade ${codigo}`); + } + } + } catch (error) { + console.error('Erro ao ordenar peças por marca:', error); + toast.error('Ocorreu um erro ao tentar ordenar as peças'); + } finally { + setIsSorting(false); + setShowSortDialog(null); + } + }; + return ( <> @@ -243,9 +284,9 @@ export const KanbanPrioridadesFabricacao: React.FC - {/* Campo de filtro */} -
-
+ {/* Campo de filtro e botão de ordenação por marca */} +
+
+
{/* Área de drop dos itens */} @@ -377,6 +429,7 @@ export const KanbanPrioridadesFabricacao: React.FC {/* Dialog de confirmação para excluir todas as peças */} + {/* Dialog de confirmação para exclusão de todas as peças */} @@ -407,6 +460,32 @@ export const KanbanPrioridadesFabricacao: React.FC + + {/* Dialog de confirmação para ordenação por Marca */} + setShowSortDialog(null)}> + + + Confirmar Ordenação por Marca + + Atenção: A ordem manual atual das peças da prioridade {showSortDialog} será perdida e substituída pela sequência ordenada de Marca (Tag). +

+ Tem certeza que deseja aplicar esta ordenação? +
+
+ + setShowSortDialog(null)} disabled={isSorting}> + Cancelar + + showSortDialog && handleOrdenarPorMarca(showSortDialog)} + disabled={isSorting} + className="bg-primary hover:bg-primary/90" + > + {isSorting ? 'Ordenando...' : 'Ordenar por Marca'} + + +
+
); }; diff --git a/src/components/prioridades/PrioridadesPDFTemplate.tsx b/src/components/prioridades/PrioridadesPDFTemplate.tsx index 37c1e24..6857b60 100644 --- a/src/components/prioridades/PrioridadesPDFTemplate.tsx +++ b/src/components/prioridades/PrioridadesPDFTemplate.tsx @@ -48,59 +48,98 @@ export const PrioridadesPDFTemplate: React.FC = ({ }; const generateTickBoxes = (quantity: number) => { - const boxes = []; - - if (quantity > 10) { - const numBigBoxes = Math.floor(quantity / 5); - const numSmallBoxes = quantity % 5; - - // Quadrados com "5" - for (let i = 0; i < numBigBoxes; i++) { - boxes.push( - - - 5 - - ); - } - - // Quadrados unitários restantes - for (let i = 0; i < numSmallBoxes; i++) { - boxes.push( - - - - ); - } + if (!quantity || quantity <= 0) return null; + + let qtd50 = 0; + let qtd10 = 0; + let qtd5 = 0; + let qtd1 = 0; + + if (quantity <= 10) { + qtd1 = quantity; + } else if (quantity <= 50) { + qtd5 = Math.floor(quantity / 5); + qtd1 = quantity % 5; + } else if (quantity <= 100) { + qtd10 = Math.floor(quantity / 10); + const resto10 = quantity % 10; + qtd5 = Math.floor(resto10 / 5); + qtd1 = resto10 % 5; } else { - // Apenas quadrados unitários - for (let i = 0; i < quantity; i++) { - boxes.push( - - - - ); - } + // Acima de 100 unidades + qtd50 = Math.floor(quantity / 50); + const resto50 = quantity % 50; + qtd10 = Math.floor(resto50 / 10); + const resto10 = resto50 % 10; + qtd5 = Math.floor(resto10 / 5); + qtd1 = resto10 % 5; } - + + const boxes: React.ReactNode[] = []; + + // Quadrados de peso 50 + for (let i = 0; i < qtd50; i++) { + boxes.push( + + + 50 + + ); + } + + // Quadrados de peso 10 + for (let i = 0; i < qtd10; i++) { + boxes.push( + + + 10 + + ); + } + + // Quadrados de peso 5 + for (let i = 0; i < qtd5; i++) { + boxes.push( + + + 5 + + ); + } + + // Quadrados unitários (vazios) + for (let i = 0; i < qtd1; i++) { + boxes.push( + + + + ); + } + return {boxes}; }; @@ -221,7 +260,7 @@ export const PrioridadesPDFTemplate: React.FC = ({ > - indicam o controle de peças fabricadas. + indicam o controle de peças (quadrados com número = lotes de 50, 10 ou 5 unidades; vazios = 1 unidade).
{/* Itens por Prioridade */} diff --git a/src/pages/PrioridadesFabricacao.tsx b/src/pages/PrioridadesFabricacao.tsx index d62b053..a4e002f 100644 --- a/src/pages/PrioridadesFabricacao.tsx +++ b/src/pages/PrioridadesFabricacao.tsx @@ -54,34 +54,74 @@ const PrioridadesFabricacao = () => { }; const generateTickBoxesHTML = (quantity: number): string => { - let boxesHtml = ''; - if (quantity > 10) { - const numBigBoxes = Math.floor(quantity / 5); - const numSmallBoxes = quantity % 5; - for (let i = 0; i < numBigBoxes; i++) { - boxesHtml += ` - - - 5 - - `; - } - for (let i = 0; i < numSmallBoxes; i++) { - boxesHtml += ` - - - - `; - } + if (!quantity || quantity <= 0) return ''; + + let qtd50 = 0; + let qtd10 = 0; + let qtd5 = 0; + let qtd1 = 0; + + if (quantity <= 10) { + qtd1 = quantity; + } else if (quantity <= 50) { + qtd5 = Math.floor(quantity / 5); + qtd1 = quantity % 5; + } else if (quantity <= 100) { + qtd10 = Math.floor(quantity / 10); + const resto10 = quantity % 10; + qtd5 = Math.floor(resto10 / 5); + qtd1 = resto10 % 5; } else { - for (let i = 0; i < quantity; i++) { - boxesHtml += ` - - - - `; - } + // Acima de 100 unidades + qtd50 = Math.floor(quantity / 50); + const resto50 = quantity % 50; + qtd10 = Math.floor(resto50 / 10); + const resto10 = resto50 % 10; + qtd5 = Math.floor(resto10 / 5); + qtd1 = resto10 % 5; } + + let boxesHtml = ''; + + // Quadrados com "50" + for (let i = 0; i < qtd50; i++) { + boxesHtml += ` + + + 50 + + `; + } + + // Quadrados com "10" + for (let i = 0; i < qtd10; i++) { + boxesHtml += ` + + + 10 + + `; + } + + // Quadrados com "5" + for (let i = 0; i < qtd5; i++) { + boxesHtml += ` + + + 5 + + `; + } + + // Quadrados unitários (vazios) + for (let i = 0; i < qtd1; i++) { + boxesHtml += ` + + + + `; + } + return `${boxesHtml}`; }; @@ -309,7 +349,7 @@ const PrioridadesFabricacao = () => { - indicam o controle de peças fabricadas. + indicam o controle de peças (quadrados com número = lotes de 50, 10 ou 5 unidades; vazios = 1 unidade).