fix: seletor de OFs no Mapa Termico de Kits

This commit is contained in:
2026-10-20 15:37:40 -03:00
parent fcb3fc08fd
commit 9ade5d0d5a
@@ -20,7 +20,7 @@ import {
Scissors
} from 'lucide-react';
import { useKitsProducao, PecaKitInfo } from '@/hooks/useKitsProducao';
import { useOFs } from '@/hooks/useOFs';
import { useOFsAtivas, OFAtiva } from '@/hooks/useOFsAtivas';
interface MapaTermicoKitsViewProps {
initialOF?: string;
@@ -35,8 +35,8 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
readOnlyOF = false,
onSelectPecaParaApontar,
}) => {
const { ofs, loading: loadingOFs } = useOFs();
const [selectedOF, setSelectedOF] = useState<string>(initialOF || (ofs[0]?.of_number || ''));
const { ofsAtivas, isLoading: loadingOFs } = useOFsAtivas();
const [selectedOF, setSelectedOF] = useState<string>(initialOF || '');
const [selectedFase, setSelectedFase] = useState<string>(initialFase);
const [busca, setBusca] = useState<string>('');
const [filtroStatus, setFiltroStatus] = useState<'todos' | 'liberados' | 'parciais' | 'travados'>('todos');
@@ -44,18 +44,20 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
// Atualizar OF padrão se carregar depois
React.useEffect(() => {
if (!selectedOF && ofs.length > 0) {
setSelectedOF(ofs[0].of_number);
if (initialOF) {
setSelectedOF(initialOF);
} else if (!selectedOF && ofsAtivas.length > 0) {
setSelectedOF(ofsAtivas[0].of_number);
}
}, [ofs, selectedOF]);
}, [initialOF, ofsAtivas, selectedOF]);
const { listaKits, resumoKits, loading, refetch } = useKitsProducao(selectedOF, selectedFase);
const { listaKits, resumoKits, loading, refetch } = useKitsProducao(selectedOF);
// Extrair fases únicas da lista de kits carregada
// Extrair fases únicas da lista de kits carregada de toda a OF
const fasesDisponiveis = useMemo(() => {
const s = new Set<string>();
listaKits.forEach((k) => {
if (k.etapa_fase) s.add(k.etapa_fase);
if (k.etapa_fase && k.etapa_fase.trim()) s.add(k.etapa_fase.trim());
});
return Array.from(s).sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }));
}, [listaKits]);
@@ -81,9 +83,14 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
setPecasExpandidas(new Set());
};
// Filtragem
// Filtragem combinada (Fase + Status + Busca textual)
const pecasFiltradas = useMemo(() => {
return listaKits.filter((item) => {
// Filtro de fase
if (selectedFase && selectedFase !== 'all' && selectedFase !== 'todas') {
if (item.etapa_fase !== selectedFase) return false;
}
// Filtro de status
if (filtroStatus === 'liberados') {
if (item.kits_completos_cortados <= 0) return false;
@@ -111,7 +118,41 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
return true;
});
}, [listaKits, filtroStatus, busca]);
}, [listaKits, selectedFase, filtroStatus, busca]);
// KPIs calculados com base nas peças filtradas
const resumoExibido = useMemo(() => {
let total100 = 0;
let totalParciais = 0;
let totalTravados = 0;
let pesoTot = 0;
let pesoCort = 0;
let unTot = 0;
let unLib = 0;
pecasFiltradas.forEach((item) => {
unTot += item.quantidade_total;
unLib += item.kits_completos_cortados;
pesoTot += item.peso_total_componentes;
pesoCort += item.peso_cortado_componentes;
if (item.status_termico === 'verde') total100++;
else if (item.status_termico === 'verde_parcial' || item.status_termico === 'amarelo') totalParciais++;
else totalTravados++;
});
return {
totalPecas: pecasFiltradas.length,
totalKits100Porcento: total100,
totalKitsParciais: totalParciais,
totalKitsNaoIniciados: totalTravados,
pesoTotalOFKg: pesoTot,
pesoCortadoTotalKg: pesoCort,
percentualGeralOF: pesoTot > 0 ? Math.min(100, Math.round((pesoCort / pesoTot) * 100)) : 0,
totalUnidadesTotal: unTot,
totalUnidadesLiberadasSolda: unLib,
};
}, [pecasFiltradas]);
return (
<div className="space-y-4 w-full">
@@ -159,14 +200,23 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
OF {selectedOF}
</div>
) : (
<Select value={selectedOF} onValueChange={setSelectedOF} disabled={loadingOFs}>
<Select
value={selectedOF}
onValueChange={(val) => {
setSelectedOF(val);
setSelectedFase('all');
}}
disabled={loadingOFs}
>
<SelectTrigger className="h-9 text-xs font-semibold">
<SelectValue placeholder="Selecione uma OF..." />
<SelectValue placeholder={loadingOFs ? "Carregando OFs..." : "Selecione uma OF..."}>
{selectedOF ? `OF ${selectedOF}` : undefined}
</SelectValue>
</SelectTrigger>
<SelectContent>
{ofs.map((o) => (
<SelectItem key={o.id} value={o.of_number}>
OF {o.of_number} {o.cliente ? `• ${o.cliente}` : ''}
<SelectContent className="max-h-72">
{ofsAtivas.map((o) => (
<SelectItem key={o.of_number} value={o.of_number}>
OF {o.of_number} {o.cliente ? `• ${o.cliente}` : o.descricao_resumida ? `• ${o.descricao_resumida}` : ''}
</SelectItem>
))}
</SelectContent>
@@ -214,7 +264,7 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
</Card>
{/* ──────────────── Cards de KPIs do Mapa Térmico ──────────────── */}
{resumoKits && (
{resumoExibido && (
<div className="grid grid-cols-2 md:grid-cols-4 gap-2.5 sm:gap-3">
{/* KPI 1: 100% Liberadas */}
<div className="p-3.5 rounded-2xl bg-emerald-50/80 dark:bg-emerald-950/40 border border-emerald-200 dark:border-emerald-800 shadow-sm flex items-center justify-between">
@@ -223,7 +273,7 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
100% Liberadas
</div>
<div className="text-2xl font-black text-emerald-900 dark:text-emerald-100 mt-0.5">
{resumoKits.totalKits100Porcento}
{resumoExibido.totalKits100Porcento}
</div>
<div className="text-[10px] text-emerald-700/80 dark:text-emerald-400/80 font-medium">
peças com todos os kits cortados
@@ -241,7 +291,7 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
Unidades Liberadas
</div>
<div className="text-2xl font-black text-blue-900 dark:text-blue-100 mt-0.5">
{resumoKits.totalUnidadesLiberadasSolda} <span className="text-xs text-blue-600 font-bold">/ {resumoKits.totalUnidadesTotal} un</span>
{resumoExibido.totalUnidadesLiberadasSolda} <span className="text-xs text-blue-600 font-bold">/ {resumoExibido.totalUnidadesTotal} un</span>
</div>
<div className="text-[10px] text-blue-700/80 dark:text-blue-400/80 font-medium">
kits prontos na bancada de solda
@@ -259,7 +309,7 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
Corte em Andamento
</div>
<div className="text-2xl font-black text-amber-900 dark:text-amber-100 mt-0.5">
{resumoKits.totalKitsParciais}
{resumoExibido.totalKitsParciais}
</div>
<div className="text-[10px] text-amber-700/80 dark:text-amber-400/80 font-medium">
kits parciais (prioridade de corte)
@@ -277,7 +327,7 @@ export const MapaTermicoKitsView: React.FC<MapaTermicoKitsViewProps> = ({
Não Iniciados
</div>
<div className="text-2xl font-black text-rose-900 dark:text-rose-100 mt-0.5">
{resumoKits.totalKitsNaoIniciados}
{resumoExibido.totalKitsNaoIniciados}
</div>
<div className="text-[10px] text-rose-700/80 dark:text-rose-400/80 font-medium">
sem nenhum componente cortado