feat: adicionar exibição da fase da OF no histórico de apontamentos

This commit is contained in:
2026-10-20 13:34:22 -03:00
parent 264c41cc80
commit f3eff4b805
4 changed files with 57 additions and 7 deletions
@@ -12,12 +12,15 @@ import { ptBR } from 'date-fns/locale';
export const ApontamentosList = () => {
const { apontamentos, loading } = useApontamentosProducao();
const [filtroOF, setFiltroOF] = useState('');
const [filtroFase, setFiltroFase] = useState('');
const [filtroProcesso, setFiltroProcesso] = useState('');
const [filtroData, setFiltroData] = useState('');
const [filtroPecaComponente, setFiltroPecaComponente] = useState('');
const apontamentosFiltrados = apontamentos.filter(apt => {
const matchOF = !filtroOF || apt.of_number.toLowerCase().includes(filtroOF.toLowerCase());
const faseStr = apt.peca?.etapa_fase || (apt.componente as any)?.peca?.etapa_fase || '';
const matchFase = !filtroFase || faseStr.toLowerCase().includes(filtroFase.toLowerCase());
const matchProcesso = !filtroProcesso || apt.processo?.nome.toLowerCase().includes(filtroProcesso.toLowerCase());
const matchData = !filtroData || apt.data_apontamento.includes(filtroData);
@@ -25,7 +28,7 @@ export const ApontamentosList = () => {
const matchPecaComponente = !filtroPecaComponente ||
getMarcaExibida(apt).toLowerCase().includes(filtroPecaComponente.toLowerCase());
return matchOF && matchProcesso && matchData && matchPecaComponente;
return matchOF && matchFase && matchProcesso && matchData && matchPecaComponente;
});
// Função para determinar a marca exibida baseada no tipo de apontamento
@@ -90,7 +93,7 @@ export const ApontamentosList = () => {
</CardTitle>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-5 gap-3">
<div className="grid grid-cols-1 md:grid-cols-6 gap-3">
<div>
<label className="text-sm font-medium mb-2 block">OF</label>
<Input
@@ -100,6 +103,15 @@ export const ApontamentosList = () => {
className="h-8"
/>
</div>
<div>
<label className="text-sm font-medium mb-2 block">Fase</label>
<Input
placeholder="Filtrar por fase..."
value={filtroFase}
onChange={(e) => setFiltroFase(e.target.value)}
className="h-8"
/>
</div>
<div>
<label className="text-sm font-medium mb-2 block">Processo</label>
<Input
@@ -163,6 +175,7 @@ export const ApontamentosList = () => {
<TableHeader>
<TableRow>
<TableHead>OF</TableHead>
<TableHead>Fase</TableHead>
<TableHead>Peça/Componente</TableHead>
<TableHead>Tipo</TableHead>
<TableHead>Processo</TableHead>
@@ -184,6 +197,17 @@ export const ApontamentosList = () => {
<TableCell className="font-medium py-1">
{apontamento.of_number}
</TableCell>
<TableCell className="py-1">
{apontamento.peca?.etapa_fase ? (
<Badge variant="outline" className="text-xs">
{apontamento.peca.etapa_fase.toLowerCase().startsWith('fase') || apontamento.peca.etapa_fase.toLowerCase().startsWith('etapa')
? apontamento.peca.etapa_fase
: `Fase ${apontamento.peca.etapa_fase}`}
</Badge>
) : (
<span className="text-xs text-muted-foreground">-</span>
)}
</TableCell>
<TableCell className="py-1">
<div className="font-medium">
{getMarcaExibida(apontamento)}
@@ -95,7 +95,9 @@ export const ApontamentosFilters: React.FC<ApontamentosFiltersProps> = ({
<SelectContent>
<SelectItem value="all">Todas as fases</SelectItem>
{uniqueFases.map((fase) => (
<SelectItem key={fase} value={fase}>{fase}</SelectItem>
<SelectItem key={fase} value={fase}>
{fase.toLowerCase().startsWith('fase') || fase.toLowerCase().startsWith('etapa') ? fase : `Fase ${fase}`}
</SelectItem>
))}
</SelectContent>
</Select>
@@ -35,6 +35,15 @@ export const ApontamentosListItem: React.FC<ApontamentosListItemProps> = ({
}
};
const getFaseItem = (apontamento: ApontamentoProducao) => {
const rawFase = apontamento.peca?.etapa_fase || (apontamento.componente as any)?.peca?.etapa_fase;
if (!rawFase || !String(rawFase).trim()) return null;
const str = String(rawFase).trim();
return str.toLowerCase().startsWith('fase') || str.toLowerCase().startsWith('etapa')
? str
: `Fase ${str}`;
};
return (
<div className="flex items-center justify-between p-3 border rounded-lg hover:bg-muted/50 transition-colors">
<div className="flex items-center gap-3">
@@ -52,6 +61,21 @@ export const ApontamentosListItem: React.FC<ApontamentosListItemProps> = ({
<Badge variant="outline">
{apontamento.of_number || 'N/A'}
</Badge>
{getFaseItem(apontamento) ? (
<Badge
variant="secondary"
className="bg-sky-50 text-sky-700 border-sky-200 dark:bg-sky-950/60 dark:text-sky-300 dark:border-sky-800 text-xs font-semibold"
>
{getFaseItem(apontamento)}
</Badge>
) : (
<Badge
variant="outline"
className="text-muted-foreground border-dashed text-xs"
>
Fase -
</Badge>
)}
{apontamento.is_forcado && (
<span className={`text-[10px] font-black px-2 py-0.5 rounded-full border ${
apontamento.status_confirmacao === 'pendente_confirmacao'
@@ -100,7 +124,7 @@ export const ApontamentosListItem: React.FC<ApontamentosListItemProps> = ({
Tem certeza de que deseja reverter este apontamento?
Esta ação não pode ser desfeita e irá remover permanentemente o registro de:
<br />
<strong>{getMarcaItem(apontamento)}</strong> - {apontamento.quantidade_produzida} unidades
<strong>{getMarcaItem(apontamento)}</strong> (OF: {apontamento.of_number || 'N/A'}{getFaseItem(apontamento) ? ` • ${getFaseItem(apontamento)}` : ''}) - {apontamento.quantidade_produzida} unidades
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
@@ -89,12 +89,12 @@ export const useApontamentosFilters = (apontamentos: ApontamentoProducao[]) => {
: apontamentos;
const fases = apontamentosFiltrados
.map(apt => apt.peca?.etapa_fase)
.map(apt => apt.peca?.etapa_fase || (apt.componente as any)?.peca?.etapa_fase)
.filter((fase): fase is string => {
return typeof fase === 'string' && fase.trim() !== '';
})
.filter((fase, index, array) => array.indexOf(fase) === index)
.sort();
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }));
console.log(`📋 Fases únicas encontradas para OF "${filterOF}": ${fases.length}`, fases);
return fases;
@@ -166,7 +166,7 @@ export const useApontamentosFilters = (apontamentos: ApontamentoProducao[]) => {
// Aplicar filtro por Fase APENAS se selecionado
if (filterFase && filterFase !== '' && filterFase !== 'all') {
const beforeFase = resultado.length;
resultado = resultado.filter(apt => apt.peca?.etapa_fase === filterFase);
resultado = resultado.filter(apt => (apt.peca?.etapa_fase || (apt.componente as any)?.peca?.etapa_fase) === filterFase);
console.log(`📋 Filtro Fase "${filterFase}": ${beforeFase} → ${resultado.length} registros`);
}