feat: modo claro em tons pasteis com sincronizacao de tema no modo smart

This commit is contained in:
2026-09-22 02:00:37 +00:00
parent 78f14672f8
commit 2fa1f4b1a3
8 changed files with 398 additions and 364 deletions
+1 -1
View File
@@ -125,7 +125,7 @@ export const ModoSmart: React.FC = () => {
const headerInfo = getHeaderInfo();
return (
<div className="min-h-screen bg-slate-950 text-slate-100 flex flex-col font-sans select-none antialiased">
<div className="min-h-screen bg-slate-100/90 text-slate-800 dark:bg-slate-950 dark:text-slate-100 flex flex-col font-sans select-none antialiased transition-colors duration-200">
{/* Cabeçalho Fixo do Modo Smart */}
<SmartHeader
titulo={headerInfo.titulo}
@@ -344,12 +344,12 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
// Badge da etapa
const getBadgeEtapa = (concluido: number, total: number) => {
if (concluido >= total && total > 0) {
return { icon: <CheckCircle2 className="h-4 w-4 text-emerald-400" />, cor: 'text-emerald-400', label: `${concluido}` };
return { icon: <CheckCircle2 className="h-4 w-4 text-emerald-600 dark:text-emerald-400" />, cor: 'text-emerald-700 dark:text-emerald-400', label: `${concluido}` };
}
if (concluido > 0) {
return { icon: <Clock className="h-4 w-4 text-amber-400" />, cor: 'text-amber-400', label: `${concluido}/${total}` };
return { icon: <Clock className="h-4 w-4 text-amber-600 dark:text-amber-400" />, cor: 'text-amber-700 dark:text-amber-400', label: `${concluido}/${total}` };
}
return { icon: <Circle className="h-4 w-4 text-slate-600" />, cor: 'text-slate-500', label: '0' };
return { icon: <Circle className="h-4 w-4 text-slate-300 dark:text-slate-600" />, cor: 'text-slate-400 dark:text-slate-500', label: '0' };
};
// ─────────────────────────────────────────────────────────────
@@ -623,7 +623,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
return (
<div className="flex flex-col flex-1 p-3.5 max-w-xl mx-auto w-full">
{/* Navegação entre Abas: Consulta Rápida vs Relatórios */}
<div className="grid grid-cols-2 gap-2 mb-3 bg-slate-800 p-1 rounded-2xl border border-slate-700">
<div className="grid grid-cols-2 gap-2 mb-3 bg-slate-200/80 dark:bg-slate-800 p-1 rounded-2xl border border-slate-300 dark:border-slate-700">
<button
type="button"
onClick={() => {
@@ -632,8 +632,8 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
}}
className={`h-11 rounded-xl font-bold text-xs sm:text-sm flex items-center justify-center gap-1.5 transition-all ${
abaAtiva === 'consulta'
? 'bg-amber-500 text-slate-950 shadow-md font-black'
: 'text-slate-300 hover:text-white'
? 'bg-amber-500 text-slate-950 shadow-sm font-black'
: 'text-slate-600 hover:text-slate-900 dark:text-slate-300 dark:hover:text-white'
}`}
>
<Search className="h-4 w-4" />
@@ -648,8 +648,8 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
}}
className={`h-11 rounded-xl font-bold text-xs sm:text-sm flex items-center justify-center gap-1.5 transition-all ${
abaAtiva === 'relatorios'
? 'bg-amber-500 text-slate-950 shadow-md font-black'
: 'text-slate-300 hover:text-white'
? 'bg-amber-500 text-slate-950 shadow-sm font-black'
: 'text-slate-600 hover:text-slate-900 dark:text-slate-300 dark:hover:text-white'
}`}
>
<FileText className="h-4 w-4" />
@@ -665,20 +665,20 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
{/* Campo de Busca Rápida */}
<div className="relative mb-2">
<div className="absolute inset-y-0 left-0 pl-3.5 flex items-center pointer-events-none text-slate-400">
<Search className="h-5 w-5 text-amber-400" />
<Search className="h-5 w-5 text-amber-600 dark:text-amber-400" />
</div>
<Input
type="text"
value={busca}
onChange={(e) => setBusca(e.target.value)}
placeholder="Buscar por Marca, Perfil (W, L...), Descrição..."
className="h-13 pl-11 pr-11 bg-slate-800/90 border-slate-700 text-slate-100 text-sm sm:text-base font-medium rounded-2xl placeholder:text-slate-500"
className="h-13 pl-11 pr-11 bg-white dark:bg-slate-800/90 border-slate-300 dark:border-slate-700 text-slate-800 dark:text-slate-100 text-sm sm:text-base font-medium rounded-2xl placeholder:text-slate-400 dark:placeholder:text-slate-500 shadow-sm"
/>
{busca && (
<button
type="button"
onClick={() => setBusca('')}
className="absolute inset-y-0 right-0 pr-3.5 flex items-center text-slate-400 hover:text-slate-200"
className="absolute inset-y-0 right-0 pr-3.5 flex items-center text-slate-400 hover:text-slate-600 dark:hover:text-slate-200"
>
<X className="h-5 w-5" />
</button>
@@ -687,7 +687,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
{/* FILTRO 1: Pílulas Rápidas de Perfis Abreviações (W/HP, L, CH, U, RED, TUB) */}
<div className="flex items-center gap-1.5 overflow-x-auto pb-1.5 mb-1.5 no-scrollbar">
<span className="text-[10px] font-black uppercase text-amber-400 px-1 shrink-0">
<span className="text-[10px] font-black uppercase text-amber-700 dark:text-amber-400 px-1 shrink-0">
PERFIL:
</span>
{[
@@ -710,7 +710,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
className={`h-8 px-3 rounded-lg text-xs font-black whitespace-nowrap shrink-0 transition-all border ${
ativo
? 'bg-amber-500 text-slate-950 border-amber-400 shadow-sm'
: 'bg-slate-800 text-slate-300 border-slate-700 hover:border-slate-600'
: 'bg-white text-slate-700 border-slate-300 hover:border-slate-400 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-700 dark:hover:border-slate-600 shadow-sm'
}`}
>
{p.label}
@@ -721,7 +721,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
{/* FILTRO 2: Fases da Obra (Com botão 'Todas' travado/fixo) */}
<div className="flex items-center gap-1.5 pb-1.5 mb-1.5">
<span className="text-[10px] font-black uppercase text-blue-400 px-1 shrink-0">
<span className="text-[10px] font-black uppercase text-blue-700 dark:text-blue-400 px-1 shrink-0">
FASE:
</span>
<button
@@ -732,14 +732,14 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
}}
className={`h-8 px-3 rounded-lg text-xs font-bold whitespace-nowrap shrink-0 transition-all border ${
filtroFase === 'todas'
? 'bg-blue-600 text-white border-blue-400 font-black shadow-sm'
: 'bg-slate-800 text-slate-300 border-slate-700'
? 'bg-blue-600 text-white border-blue-500 font-black shadow-sm'
: 'bg-white text-slate-700 border-slate-300 hover:border-slate-400 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-700 shadow-sm'
}`}
>
Todas
</button>
{fasesUnicas.length > 0 && <div className="h-4 w-px bg-slate-700 shrink-0" />}
{fasesUnicas.length > 0 && <div className="h-4 w-px bg-slate-300 dark:bg-slate-700 shrink-0" />}
{/* Demais fases rolando horizontalmente */}
<div className="flex items-center gap-1.5 overflow-x-auto no-scrollbar flex-1 py-0.5">
@@ -753,8 +753,8 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
}}
className={`h-8 px-3 rounded-lg text-xs font-bold whitespace-nowrap shrink-0 transition-all border ${
filtroFase === fase
? 'bg-blue-600 text-white border-blue-400 font-black shadow-sm'
: 'bg-slate-800 text-slate-300 border-slate-700'
? 'bg-blue-600 text-white border-blue-500 font-black shadow-sm'
: 'bg-white text-slate-700 border-slate-300 hover:border-slate-400 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-700 shadow-sm'
}`}
>
Fase {fase}
@@ -764,7 +764,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
</div>
{/* FILTRO 3: Status Fabril (Com botão 'Todos' travado/fixo sem scroll) e Botão Limpar */}
<div className="flex items-center gap-1.5 pb-2 mb-2 border-b border-slate-800">
<div className="flex items-center gap-1.5 pb-2 mb-2 border-b border-slate-200 dark:border-slate-800">
{/* Botão "Todos" fixo/travado à esquerda */}
<button
type="button"
@@ -774,15 +774,15 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
}}
className={`h-7 px-3 rounded-md text-[11px] font-bold whitespace-nowrap shrink-0 transition-all ${
filtroStatus === 'todos'
? 'bg-slate-200 text-slate-900 font-black ring-1 ring-white/60 shadow-sm'
: 'bg-slate-800 text-slate-400 hover:text-slate-200 border border-slate-700'
? 'bg-slate-800 text-white font-black dark:bg-slate-200 dark:text-slate-900 shadow-sm'
: 'bg-white text-slate-600 hover:text-slate-900 border border-slate-300 dark:bg-slate-800 dark:text-slate-400 dark:hover:text-slate-200 dark:border-slate-700 shadow-sm'
}`}
>
Todos
</button>
{/* Divisor vertical */}
<div className="h-4 w-px bg-slate-700 shrink-0" />
<div className="h-4 w-px bg-slate-300 dark:bg-slate-700 shrink-0" />
{/* Demais botões roláveis horizontalmente */}
<div className="flex items-center gap-1.5 overflow-x-auto no-scrollbar flex-1 py-0.5">
@@ -801,8 +801,8 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
}}
className={`h-7 px-2.5 rounded-md text-[11px] font-bold whitespace-nowrap shrink-0 transition-all ${
filtroStatus === f.id
? 'bg-slate-200 text-slate-900 font-black shadow-sm'
: 'bg-slate-800/80 text-slate-400 hover:text-slate-200 border border-slate-700/60'
? 'bg-slate-800 text-white font-black dark:bg-slate-200 dark:text-slate-900 shadow-sm'
: 'bg-white text-slate-600 hover:text-slate-900 border border-slate-200 dark:bg-slate-800/80 dark:text-slate-400 dark:hover:text-slate-200 dark:border-slate-700/60 shadow-sm'
}`}
>
{f.label}
@@ -815,7 +815,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
<button
type="button"
onClick={handleLimparFiltros}
className="h-7 px-2.5 rounded-lg bg-red-950/50 hover:bg-red-900/60 border border-red-800/60 text-red-300 text-[11px] font-bold flex items-center gap-1 shrink-0 active:scale-95 ml-auto"
className="h-7 px-2.5 rounded-lg bg-rose-50 hover:bg-rose-100 border border-rose-200 text-rose-700 dark:bg-red-950/50 dark:hover:bg-red-900/60 dark:border-red-800/60 dark:text-red-300 text-[11px] font-bold flex items-center gap-1 shrink-0 active:scale-95 ml-auto shadow-sm"
title="Limpar todos os filtros aplicados"
>
<RotateCcw className="h-3 w-3" />
@@ -825,9 +825,9 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
</div>
{/* Contador de Peças Encontradas */}
<div className="flex items-center justify-between text-xs text-slate-400 px-1 mb-2">
<div className="flex items-center justify-between text-xs text-slate-500 dark:text-slate-400 px-1 mb-2">
<span>
Exibindo <b className="text-amber-400">{pecasFiltradas.length}</b> de{' '}
Exibindo <b className="text-amber-700 dark:text-amber-400 font-bold">{pecasFiltradas.length}</b> de{' '}
{pecasStatus.length} marcas
</span>
<span className="text-[11px] font-semibold text-slate-500">
@@ -838,22 +838,22 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
{/* Lista de Peças Ordenadas com Timeline Completa */}
<div className="flex-1 overflow-y-auto space-y-2.5 pb-4">
{loading ? (
<div className="py-12 flex flex-col items-center justify-center text-slate-400 gap-2">
<div className="py-12 flex flex-col items-center justify-center text-slate-500 dark:text-slate-400 gap-2">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-amber-500 border-t-transparent" />
<span>Carregando peças e apontamentos...</span>
</div>
) : pecasFiltradas.length === 0 ? (
<div className="p-8 text-center bg-slate-800/40 rounded-2xl border border-slate-800">
<AlertCircle className="h-10 w-10 text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-200">Nenhuma peça encontrada</h3>
<p className="text-xs text-slate-400 mt-1 mb-3">
<div className="p-8 text-center bg-white dark:bg-slate-800/40 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm">
<AlertCircle className="h-10 w-10 text-slate-400 dark:text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-800 dark:text-slate-200">Nenhuma peça encontrada</h3>
<p className="text-xs text-slate-500 dark:text-slate-400 mt-1 mb-3">
Tente ajustar a busca, a fase ou clique em limpar filtros
</p>
<Button
type="button"
variant="outline"
onClick={handleLimparFiltros}
className="h-10 px-4 bg-slate-800 border-slate-700 text-amber-400 font-bold text-xs rounded-xl"
className="h-10 px-4 bg-white dark:bg-slate-800 border-slate-300 dark:border-slate-700 text-amber-700 dark:text-amber-400 font-bold text-xs rounded-xl shadow-sm"
>
<RotateCcw className="h-3.5 w-3.5 mr-1.5" />
Limpar Filtros
@@ -863,55 +863,55 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
pecasFiltradas.map((peca) => (
<div
key={peca.id}
className="p-3.5 rounded-2xl bg-slate-800/95 border border-slate-700 shadow-sm"
className="p-3.5 rounded-2xl bg-white dark:bg-slate-800/95 border border-slate-200 dark:border-slate-700 shadow-sm"
>
{/* Linha Superior: Marca, Perfil, Fase e Quantidade */}
<div className="flex items-start justify-between gap-2">
<div className="min-w-0">
<div className="flex items-center gap-2 flex-wrap">
<span className="text-xl font-black text-amber-400 tracking-wider">
<span className="text-xl font-black text-amber-700 dark:text-amber-400 tracking-wider">
{peca.marca}
</span>
{peca.tem_componentes === false && (
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-950/80 text-purple-300 font-bold border border-purple-800/50">
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-100 text-purple-800 font-bold border border-purple-300 dark:bg-purple-950/80 dark:text-purple-300 dark:border-purple-800/50">
S/M
</span>
)}
{peca.perfil_principal && (
<span className="text-xs px-2 py-0.5 rounded-md bg-amber-500/15 text-amber-300 font-black border border-amber-500/30">
<span className="text-xs px-2 py-0.5 rounded-md bg-amber-50 text-amber-800 font-black border border-amber-300 dark:bg-amber-500/15 dark:text-amber-300 dark:border-amber-500/30">
{peca.perfil_principal}
</span>
)}
<span className="text-[11px] px-1.5 py-0.5 rounded bg-blue-500/15 text-blue-300 font-bold border border-blue-500/30">
<span className="text-[11px] px-1.5 py-0.5 rounded bg-blue-50 text-blue-800 font-bold border border-blue-200 dark:bg-blue-500/15 dark:text-blue-300 dark:border-blue-500/30">
Fase {peca.etapa_fase}
</span>
{peca.material && (
<span className="text-[10px] px-1.5 py-0.5 rounded bg-slate-700 text-slate-300 font-semibold">
<span className="text-[10px] px-1.5 py-0.5 rounded bg-slate-100 text-slate-700 dark:bg-slate-700 dark:text-slate-300 font-semibold border border-slate-200 dark:border-transparent">
{peca.material}
</span>
)}
</div>
<div className="text-xs text-slate-300 mt-1 line-clamp-1">
<div className="text-xs text-slate-600 dark:text-slate-300 mt-1 line-clamp-1">
{peca.descricao || 'Peça Estrutural'}
</div>
</div>
<div className="text-right shrink-0">
<span className="text-xs text-slate-400 block font-medium">Total</span>
<span className="text-base font-black text-white">
<span className="text-xs text-slate-500 dark:text-slate-400 block font-medium">Total</span>
<span className="text-base font-black text-slate-900 dark:text-white">
{peca.quantidade}{' '}
<span className="text-xs font-normal text-slate-400">un</span>
<span className="text-xs font-normal text-slate-500 dark:text-slate-400">un</span>
</span>
</div>
</div>
{/* Linha do Tempo Visual com TODAS as Etapas Fabris */}
<div className="grid grid-cols-7 gap-1 mt-3 pt-2.5 border-t border-slate-700/80 text-center">
<div className="grid grid-cols-7 gap-1 mt-3 pt-2.5 border-t border-slate-100 dark:border-slate-700/80 text-center">
{[
{ nome: 'Det.', valor: peca.detalhamento, isPula: false },
{ nome: 'Corte', valor: peca.corte, isPula: false },
@@ -923,14 +923,14 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
].map((etapa, idx) => {
if (etapa.isPula) {
return (
<div key={idx} className="flex flex-col items-center opacity-60">
<div className="text-[9px] font-bold text-slate-400 mb-0.5 uppercase">
<div key={idx} className="flex flex-col items-center opacity-70">
<div className="text-[9px] font-bold text-slate-500 dark:text-slate-400 mb-0.5 uppercase">
{etapa.nome}
</div>
<div className="h-5 px-1 rounded-md bg-slate-900 border border-purple-800/40 mb-0.5 flex items-center justify-center">
<span className="text-[9px] font-bold text-purple-400">S/M</span>
<div className="h-5 px-1 rounded-md bg-purple-50 dark:bg-slate-900 border border-purple-200 dark:border-purple-800/40 mb-0.5 flex items-center justify-center">
<span className="text-[9px] font-bold text-purple-700 dark:text-purple-400">S/M</span>
</div>
<span className="text-[10px] font-bold text-slate-500">
<span className="text-[10px] font-bold text-slate-400 dark:text-slate-500">
N/A
</span>
</div>
@@ -940,10 +940,10 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
const badge = getBadgeEtapa(etapa.valor, peca.quantidade);
return (
<div key={idx} className="flex flex-col items-center">
<div className="text-[9px] font-bold text-slate-400 mb-0.5 uppercase">
<div className="text-[9px] font-bold text-slate-500 dark:text-slate-400 mb-0.5 uppercase">
{etapa.nome}
</div>
<div className="p-0.5 rounded-md bg-slate-900 border border-slate-700/60 mb-0.5">
<div className="p-0.5 rounded-md bg-slate-50 dark:bg-slate-900 border border-slate-200 dark:border-slate-700/60 mb-0.5">
{badge.icon}
</div>
<span className={`text-[10px] font-black ${badge.cor}`}>
@@ -966,29 +966,29 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
{abaAtiva === 'relatorios' && (
<div className="flex flex-col flex-1 overflow-y-auto space-y-4 pb-4">
<div className="text-center mb-1">
<h3 className="text-base font-black text-slate-100 uppercase">
<h3 className="text-base font-black text-slate-800 dark:text-slate-100 uppercase">
Selecione o Relatório Desejado
</h3>
<p className="text-xs text-slate-400">
<p className="text-xs text-slate-500 dark:text-slate-400">
Gere documentos oficiais para download ou envio imediato
</p>
</div>
{/* CARD 1: RELATÓRIO DO MEU TURNO */}
<div className="p-4 rounded-2xl bg-gradient-to-br from-amber-500/15 via-slate-800 to-slate-800 border border-amber-500/30 shadow-md">
<div className="p-4 rounded-2xl bg-gradient-to-br from-amber-500/10 via-amber-500/5 to-white dark:from-amber-500/15 dark:via-slate-800 dark:to-slate-800 border border-amber-300 dark:border-amber-500/30 shadow-sm">
<div className="flex items-start justify-between gap-2 mb-3">
<div>
<span className="text-xs font-black uppercase text-amber-400 tracking-wider">
<span className="text-xs font-black uppercase text-amber-700 dark:text-amber-400 tracking-wider">
Opção 1
</span>
<h4 className="text-base font-black text-slate-100">
<h4 className="text-base font-black text-slate-800 dark:text-slate-100">
Relatório do Meu Turno (Hoje)
</h4>
<p className="text-xs text-slate-300 mt-0.5">
<p className="text-xs text-slate-600 dark:text-slate-300 mt-0.5">
Lista todas as peças apontadas por você no turno de hoje
</p>
</div>
<div className="p-2.5 rounded-xl bg-amber-500/20 text-amber-400">
<div className="p-2.5 rounded-xl bg-amber-100 text-amber-800 dark:bg-amber-500/20 dark:text-amber-400">
<FileText className="h-6 w-6" />
</div>
</div>
@@ -998,7 +998,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
type="button"
disabled={gerandoPDF}
onClick={() => gerarRelatorioTurnoPDF('download')}
className="h-12 bg-amber-500 hover:bg-amber-400 text-slate-950 font-black text-xs rounded-xl gap-1.5 active:scale-95"
className="h-12 bg-amber-500 hover:bg-amber-400 text-slate-950 font-black text-xs rounded-xl gap-1.5 active:scale-95 shadow-sm"
>
<Download className="h-4 w-4" />
<span>Baixar PDF</span>
@@ -1008,7 +1008,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
type="button"
disabled={gerandoPDF}
onClick={() => gerarRelatorioTurnoPDF('whatsapp')}
className="h-12 bg-emerald-600 hover:bg-emerald-500 text-white font-black text-xs rounded-xl gap-1.5 active:scale-95"
className="h-12 bg-emerald-600 hover:bg-emerald-500 text-white font-black text-xs rounded-xl gap-1.5 active:scale-95 shadow-sm"
>
<MessageCircle className="h-4 w-4" />
<span>WhatsApp</span>
@@ -1018,7 +1018,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
type="button"
disabled={gerandoPDF}
onClick={() => gerarRelatorioTurnoPDF('email')}
className="h-12 bg-slate-700 hover:bg-slate-650 text-white font-black text-xs rounded-xl gap-1.5 active:scale-95"
className="h-12 bg-slate-700 hover:bg-slate-600 text-white font-black text-xs rounded-xl gap-1.5 active:scale-95 shadow-sm"
>
<Mail className="h-4 w-4" />
<span>E-mail</span>
@@ -1027,20 +1027,20 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
</div>
{/* CARD 2: RELATÓRIO GERAL DA OBRA */}
<div className="p-4 rounded-2xl bg-slate-800 border border-slate-700 shadow-md">
<div className="p-4 rounded-2xl bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 shadow-sm">
<div className="flex items-start justify-between gap-2 mb-3">
<div>
<span className="text-xs font-black uppercase text-blue-400 tracking-wider">
<span className="text-xs font-black uppercase text-blue-700 dark:text-blue-400 tracking-wider">
Opção 2
</span>
<h4 className="text-base font-black text-slate-100">
<h4 className="text-base font-black text-slate-800 dark:text-slate-100">
Relatório de Produção Geral da Obra
</h4>
<p className="text-xs text-slate-300 mt-0.5">
<p className="text-xs text-slate-600 dark:text-slate-300 mt-0.5">
Quadro completo de todas as marcas com avanço por etapa
</p>
</div>
<div className="p-2.5 rounded-xl bg-blue-500/20 text-blue-400">
<div className="p-2.5 rounded-xl bg-blue-100 text-blue-800 dark:bg-blue-500/20 dark:text-blue-400">
<FileText className="h-6 w-6" />
</div>
</div>
@@ -1049,7 +1049,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
type="button"
disabled={gerandoPDF}
onClick={gerarRelatorioGeralObraPDF}
className="w-full h-12 bg-blue-600 hover:bg-blue-500 text-white font-black text-xs rounded-xl gap-2 active:scale-95"
className="w-full h-12 bg-blue-600 hover:bg-blue-500 text-white font-black text-xs rounded-xl gap-2 active:scale-95 shadow-sm"
>
<Download className="h-4 w-4" />
<span>Gerar e Baixar PDF Geral</span>
@@ -1066,7 +1066,7 @@ export const SmartConsultaRelatoriosFlow: React.FC<SmartConsultaRelatoriosFlowPr
smartAudio.playClick();
onVoltarHub();
}}
className="w-full h-13 bg-slate-800 border-slate-700 text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98"
className="w-full h-13 bg-white dark:bg-slate-800 border-slate-300 dark:border-slate-700 text-slate-700 dark:text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98 shadow-sm"
>
⬅️ Voltar ao Menu Principal
</Button>
+126 -123
View File
@@ -649,22 +649,22 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
smartAudio.playClick();
setSubTela('selecionar_romaneio');
}}
className="w-full min-h-[90px] p-5 rounded-3xl bg-slate-800 hover:bg-slate-750 active:scale-[0.98] text-slate-100 border-2 border-slate-700 hover:border-blue-500/60 flex items-center justify-between text-left shadow-md transition-all group"
className="w-full min-h-[90px] p-5 rounded-3xl bg-white hover:bg-slate-50 dark:bg-slate-800 dark:hover:bg-slate-750 active:scale-[0.98] text-slate-800 dark:text-slate-100 border-2 border-slate-200 hover:border-blue-500/60 dark:border-slate-700 flex items-center justify-between text-left shadow-sm transition-all group"
>
<div className="flex items-center gap-3.5">
<div className="p-3 rounded-2xl bg-slate-700 text-blue-400">
<div className="p-3 rounded-2xl bg-blue-100 text-blue-700 dark:bg-slate-700 dark:text-blue-400">
<ListChecks className="h-7 w-7" />
</div>
<div>
<div className="text-lg font-black tracking-tight">
<div className="text-lg font-black tracking-tight text-slate-900 dark:text-slate-100">
Romaneios da Obra & Conferência
</div>
<div className="text-xs text-slate-400 font-medium">
<div className="text-xs text-slate-500 dark:text-slate-400 font-medium">
{romaneios.length} romaneio(s) ativo(s) — carregar peças ou abrir PDF
</div>
</div>
</div>
<ChevronRight className="h-6 w-6 text-slate-400 group-hover:text-blue-400 group-hover:translate-x-1 transition-all" />
<ChevronRight className="h-6 w-6 text-slate-400 group-hover:text-blue-600 dark:text-slate-400 dark:group-hover:text-blue-400 group-hover:translate-x-1 transition-all" />
</button>
</div>
@@ -675,7 +675,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
smartAudio.playClick();
onVoltarHub();
}}
className="w-full h-14 bg-slate-800 border-slate-700 text-slate-200 text-sm font-bold rounded-2xl mt-4 active:scale-98"
className="w-full h-14 bg-white hover:bg-slate-100 text-slate-800 border-slate-300 dark:bg-slate-800 dark:hover:bg-slate-750 dark:border-slate-700 dark:text-slate-200 text-sm font-bold rounded-2xl mt-4 active:scale-98 transition-colors"
>
Voltar ao Menu Principal
</Button>
@@ -690,37 +690,40 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
return (
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
<div className="mb-4 text-center">
<span className="text-xs font-black uppercase text-blue-400 tracking-wider">
NOVO CARREGAMENTO
<span className="text-xs font-black uppercase text-blue-700 dark:text-blue-400 tracking-wider">
NOVO ROMANEIO
</span>
<h2 className="text-xl font-black text-slate-100 uppercase mt-0.5">
Dados do Veículo & Frete
<h2 className="text-xl font-black text-slate-900 dark:text-slate-100 uppercase mt-0.5">
Iniciar Carga de Embarque
</h2>
<p className="text-xs text-slate-500 dark:text-slate-400">
Identifique o veículo para abrir a conferência de saída
</p>
</div>
<div className="flex-1 overflow-y-auto space-y-4 pb-4">
{/* Nome / Placa do Motorista */}
<div>
<label className="text-xs font-black uppercase text-slate-300 tracking-wider block mb-1.5">
<label className="text-xs font-black uppercase text-slate-700 dark:text-slate-300 tracking-wider block mb-1.5">
Motorista ou Identificação do Veículo
</label>
<div className="relative">
<div className="absolute inset-y-0 left-0 pl-3.5 flex items-center pointer-events-none text-slate-400">
<User className="h-5 w-5 text-blue-400" />
<div className="absolute inset-y-0 left-0 pl-3.5 flex items-center pointer-events-none text-blue-600 dark:text-blue-400">
<User className="h-5 w-5" />
</div>
<Input
type="text"
value={nomeMotorista}
onChange={(e) => setNomeMotorista(e.target.value)}
placeholder="Ex: João Silva - Placa ABC-1234"
className="h-14 pl-11 bg-slate-800 border-slate-700 text-slate-100 text-base font-bold rounded-2xl"
className="h-14 pl-11 bg-white dark:bg-slate-800 border-slate-300 dark:border-slate-700 text-slate-900 dark:text-slate-100 placeholder:text-slate-400 dark:placeholder:text-slate-500 text-base font-bold rounded-2xl shadow-sm focus-visible:ring-blue-500"
/>
</div>
</div>
{/* Tipo de Veículo */}
<div>
<label className="text-xs font-black uppercase text-slate-300 tracking-wider block mb-1.5">
<label className="text-xs font-black uppercase text-slate-700 dark:text-slate-300 tracking-wider block mb-1.5">
Tipo de Transporte / Veículo
</label>
<div className="grid grid-cols-2 gap-2">
@@ -739,8 +742,8 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
}}
className={`h-12 rounded-xl text-xs font-bold border-2 transition-all flex items-center justify-center gap-1.5 ${
tipoTransporte === tipo.id
? 'bg-blue-600 text-white border-blue-400 font-black shadow-md'
: 'bg-slate-800 text-slate-300 border-slate-700 hover:border-slate-600'
? 'bg-blue-600 text-white border-blue-500 font-black shadow-md'
: 'bg-white hover:bg-slate-50 text-slate-700 border-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-700 dark:hover:border-slate-600'
}`}
>
<Truck className="h-4 w-4" />
@@ -752,7 +755,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
{/* Tipo de Frete */}
<div>
<label className="text-xs font-black uppercase text-slate-300 tracking-wider block mb-1.5">
<label className="text-xs font-black uppercase text-slate-700 dark:text-slate-300 tracking-wider block mb-1.5">
Tipo de Frete
</label>
<div className="grid grid-cols-2 gap-2">
@@ -764,8 +767,8 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
}}
className={`h-12 rounded-xl text-xs font-bold border-2 transition-all ${
freteTipo === 'proprio'
? 'bg-blue-600 text-white border-blue-400 font-black'
: 'bg-slate-800 text-slate-300 border-slate-700'
? 'bg-blue-600 text-white border-blue-500 font-black shadow-sm'
: 'bg-white hover:bg-slate-50 text-slate-700 border-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-700'
}`}
>
Frete Próprio
@@ -778,8 +781,8 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
}}
className={`h-12 rounded-xl text-xs font-bold border-2 transition-all ${
freteTipo === 'terceiros'
? 'bg-blue-600 text-white border-blue-400 font-black'
: 'bg-slate-800 text-slate-300 border-slate-700'
? 'bg-blue-600 text-white border-blue-500 font-black shadow-sm'
: 'bg-white hover:bg-slate-50 text-slate-700 border-slate-200 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-700'
}`}
>
Terceiros / Contratado
@@ -793,7 +796,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
type="button"
disabled={criandoRomaneio}
onClick={handleCriarRomaneio}
className="w-full h-15 bg-blue-600 hover:bg-blue-500 text-white text-base font-black rounded-2xl shadow-lg shadow-blue-950/50 uppercase active:scale-98"
className="w-full h-15 bg-blue-600 hover:bg-blue-500 text-white text-base font-black rounded-2xl shadow-lg shadow-blue-900/20 dark:shadow-blue-950/50 uppercase active:scale-98"
>
{criandoRomaneio ? 'Criando Romaneio...' : 'INICIAR CARGA DESTE CAMINHÃO 🚀'}
</Button>
@@ -821,28 +824,28 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
return (
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
<div className="mb-4 text-center">
<span className="text-xs font-black uppercase text-blue-400 tracking-wider">
<span className="text-xs font-black uppercase text-blue-600 dark:text-blue-400 tracking-wider">
EXPEDIÇÃO DA OBRA
</span>
<h2 className="text-xl font-black text-slate-100 uppercase mt-0.5">
<h2 className="text-xl font-black text-slate-800 dark:text-slate-100 uppercase mt-0.5">
Romaneios de Carga
</h2>
<p className="text-xs text-slate-400">
<p className="text-xs text-slate-500 dark:text-slate-400">
Selecione para carregar peças ou abrir conferência e PDF
</p>
</div>
<div className="flex-1 overflow-y-auto space-y-3 pb-4">
{loadingRomaneios ? (
<div className="py-12 flex flex-col items-center justify-center text-slate-400 gap-2">
<div className="py-12 flex flex-col items-center justify-center text-slate-500 dark:text-slate-400 gap-2">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-blue-500 border-t-transparent" />
<span>Buscando romaneios...</span>
</div>
) : romaneios.length === 0 ? (
<div className="p-8 text-center bg-slate-800/40 rounded-2xl border border-slate-800">
<AlertCircle className="h-10 w-10 text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-200">Nenhum romaneio aberto</h3>
<p className="text-xs text-slate-400 mt-1">
<div className="p-8 text-center bg-white dark:bg-slate-800/40 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm">
<AlertCircle className="h-10 w-10 text-slate-400 dark:text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-800 dark:text-slate-200">Nenhum romaneio aberto</h3>
<p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
Crie um novo romaneio para iniciar a expedição
</p>
</div>
@@ -850,28 +853,28 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
romaneios.map((r) => (
<div
key={r.id}
className="p-4 rounded-2xl bg-slate-800/90 border-2 border-slate-700 shadow-sm space-y-3"
className="p-4 rounded-2xl bg-white dark:bg-slate-800/90 border-2 border-slate-200 dark:border-slate-700 shadow-sm space-y-3"
>
<div className="flex items-start justify-between gap-2">
<div className="flex items-center gap-3">
<div className="h-12 w-12 rounded-xl bg-blue-500/20 text-blue-400 flex items-center justify-center shrink-0">
<div className="h-12 w-12 rounded-xl bg-blue-50 text-blue-600 dark:bg-blue-500/20 dark:text-blue-400 flex items-center justify-center shrink-0">
<Truck className="h-6 w-6" />
</div>
<div>
<div className="flex items-center gap-2">
<span className="text-base font-black text-blue-400">
<span className="text-base font-black text-blue-600 dark:text-blue-400">
{r.numero_romaneio}
</span>
<span className="text-[10px] px-2 py-0.5 rounded bg-slate-700 text-slate-300 font-bold uppercase">
<span className="text-[10px] px-2 py-0.5 rounded bg-slate-100 text-slate-700 dark:bg-slate-700 dark:text-slate-300 font-bold uppercase">
{r.status || 'Aberto'}
</span>
</div>
<div className="text-xs text-slate-200 font-semibold mt-0.5">
<div className="text-xs text-slate-800 dark:text-slate-200 font-semibold mt-0.5">
{r.nome_motorista || 'Motorista padrão'}
</div>
<div className="text-[11px] text-slate-400">
<div className="text-[11px] text-slate-500 dark:text-slate-400">
Veículo: {formatTransporte(r.tipo_transporte)} | Peso:{' '}
<b className="text-amber-400">
<b className="text-amber-700 dark:text-amber-400">
{(r.peso_total_romaneio || 0).toLocaleString('pt-BR')} kg
</b>
</div>
@@ -880,7 +883,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
</div>
{/* Botões de Ação Direta no Card */}
<div className="grid grid-cols-2 gap-2 pt-1 border-t border-slate-700/60">
<div className="grid grid-cols-2 gap-2 pt-1 border-t border-slate-100 dark:border-slate-700/60">
<button
type="button"
onClick={() => {
@@ -897,9 +900,9 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
<button
type="button"
onClick={() => handleAbrirConferencia(r)}
className="h-10 px-3 rounded-xl bg-slate-700 hover:bg-slate-600 text-slate-100 text-xs font-bold flex items-center justify-center gap-1.5 active:scale-95 border border-slate-600"
className="h-10 px-3 rounded-xl bg-slate-100 hover:bg-slate-200 text-slate-800 dark:bg-slate-700 dark:hover:bg-slate-600 dark:text-slate-100 text-xs font-bold flex items-center justify-center gap-1.5 active:scale-95 border border-slate-200 dark:border-slate-600 shadow-sm"
>
<Eye className="h-4 w-4 text-amber-400" />
<Eye className="h-4 w-4 text-amber-600 dark:text-amber-400" />
<span>Conferir & PDF</span>
</button>
</div>
@@ -915,7 +918,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
smartAudio.playClick();
setSubTela('menu');
}}
className="w-full h-14 bg-slate-800 border-slate-700 text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98"
className="w-full h-14 bg-white dark:bg-slate-800 border-slate-300 dark:border-slate-700 text-slate-700 dark:text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98 shadow-sm"
>
⬅️ Voltar ao Menu
</Button>
@@ -930,23 +933,23 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
return (
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
{/* Banner do Romaneio Ativo com Atalho para Conferência */}
<div className="p-3.5 rounded-2xl bg-blue-950/60 border border-blue-700/60 mb-3 shadow-md flex items-center justify-between gap-2">
<div className="p-3.5 rounded-2xl bg-blue-50/90 dark:bg-blue-950/60 border border-blue-200 dark:border-blue-700/60 mb-3 shadow-sm flex items-center justify-between gap-2">
<div>
<div className="flex items-center gap-2">
<span className="text-xs font-black uppercase text-blue-400 tracking-wider">
<span className="text-xs font-black uppercase text-blue-700 dark:text-blue-400 tracking-wider">
CAMINHÃO ATIVO
</span>
<span className="text-xs font-bold px-2 py-0.5 rounded bg-blue-500/20 text-blue-300">
<span className="text-xs font-bold px-2 py-0.5 rounded bg-blue-100 dark:bg-blue-500/20 text-blue-800 dark:text-blue-300">
{romaneioAtivo.numero_romaneio}
</span>
</div>
<div className="text-xs text-slate-300 mt-0.5">
Motorista: <span className="font-bold">{romaneioAtivo.nome_motorista}</span> | Peso:{' '}
<span className="font-bold text-amber-400">
<div className="text-xs text-slate-600 dark:text-slate-300 mt-0.5">
Motorista: <span className="font-bold text-slate-800 dark:text-white">{romaneioAtivo.nome_motorista}</span> | Peso:{' '}
<span className="font-bold text-amber-700 dark:text-amber-400">
{(romaneioAtivo.peso_total_romaneio || 0).toLocaleString('pt-BR')} kg
</span>
{itensRomaneio.length > 0 && (
<span className="text-blue-300 font-semibold ml-1.5">
<span className="text-blue-700 dark:text-blue-300 font-semibold ml-1.5">
({itensRomaneio.length} marcas na carga)
</span>
)}
@@ -960,7 +963,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
carregarItensDoRomaneio(romaneioAtivo.id);
setSubTela('conferencia_romaneio');
}}
className="h-8 px-2.5 rounded-lg bg-amber-500/20 hover:bg-amber-500/30 border border-amber-500/40 text-amber-300 text-xs font-black flex items-center gap-1 active:scale-95"
className="h-8 px-2.5 rounded-lg bg-amber-100 hover:bg-amber-200 border border-amber-300 text-amber-900 dark:bg-amber-500/20 dark:hover:bg-amber-500/30 dark:border-amber-500/40 dark:text-amber-300 text-xs font-black flex items-center gap-1 active:scale-95 shadow-sm"
title="Abrir conferência do que já foi colocado no romaneio"
>
<Eye className="h-3.5 w-3.5" />
@@ -973,7 +976,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
setRomaneioAtivo(null);
setSubTela('menu');
}}
className="text-xs font-bold text-slate-400 hover:text-slate-200 underline px-1 py-1"
className="text-xs font-bold text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200 underline px-1 py-1"
>
Trocar
</button>
@@ -982,26 +985,26 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
{/* Modal/Seção de Quantidade para o Item Selecionado */}
{pecaEmbarque ? (
<div className="p-4 rounded-2xl bg-slate-800 border-2 border-blue-500/80 mb-3 shadow-lg">
<div className="p-4 rounded-2xl bg-white dark:bg-slate-800 border-2 border-blue-500/80 mb-3 shadow-md">
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2">
<span className="text-xl font-black text-amber-400">
<span className="text-xl font-black text-amber-700 dark:text-amber-400">
{pecaEmbarque.marca}
</span>
{pecaEmbarque.tem_componentes === false && (
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-950/80 text-purple-300 font-bold border border-purple-800/50">
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-100 text-purple-800 font-bold border border-purple-300 dark:bg-purple-950/80 dark:text-purple-300 dark:border-purple-800/50">
S/M
</span>
)}
</div>
<span className="text-xs font-bold text-slate-400">
<span className="text-xs font-bold text-slate-500 dark:text-slate-400">
Saldo Disponível: {pecaEmbarque.saldoDisponivel} un
</span>
</div>
<div className="flex items-center justify-center gap-3 my-3">
<div className="h-16 px-6 rounded-2xl bg-slate-900 border border-slate-700 flex items-center justify-center">
<span className="text-3xl font-black text-blue-400">{qtdEmbarcar}</span>
<div className="h-16 px-6 rounded-2xl bg-slate-50 dark:bg-slate-900 border border-slate-200 dark:border-slate-700 flex items-center justify-center">
<span className="text-3xl font-black text-blue-600 dark:text-blue-400">{qtdEmbarcar}</span>
</div>
<div className="grid grid-cols-3 gap-2">
<button
@@ -1010,7 +1013,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
smartAudio.playClick();
setQtdEmbarcar((p) => Math.min(pecaEmbarque.saldoDisponivel, p + 1));
}}
className="h-12 px-3 rounded-xl bg-slate-700 font-bold text-white active:scale-95"
className="h-12 px-3 rounded-xl bg-slate-100 hover:bg-slate-200 text-slate-800 dark:bg-slate-700 dark:hover:bg-slate-600 dark:text-white font-bold active:scale-95 border border-slate-200 dark:border-transparent"
>
+1
</button>
@@ -1020,7 +1023,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
smartAudio.playClick();
setQtdEmbarcar((p) => Math.min(pecaEmbarque.saldoDisponivel, p + 2));
}}
className="h-12 px-3 rounded-xl bg-slate-700 font-bold text-white active:scale-95"
className="h-12 px-3 rounded-xl bg-slate-100 hover:bg-slate-200 text-slate-800 dark:bg-slate-700 dark:hover:bg-slate-600 dark:text-white font-bold active:scale-95 border border-slate-200 dark:border-transparent"
>
+2
</button>
@@ -1030,7 +1033,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
smartAudio.playClick();
setQtdEmbarcar(pecaEmbarque.saldoDisponivel);
}}
className="h-12 px-2.5 rounded-xl bg-blue-500/20 text-blue-300 font-black text-xs active:scale-95"
className="h-12 px-2.5 rounded-xl bg-blue-100 text-blue-800 hover:bg-blue-200 dark:bg-blue-500/20 dark:text-blue-300 font-black text-xs active:scale-95 border border-blue-200 dark:border-transparent"
>
TODAS
</button>
@@ -1042,7 +1045,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
type="button"
disabled={salvandoItem}
onClick={handleIncluirPeca}
className="h-13 bg-blue-600 hover:bg-blue-500 text-white font-black rounded-xl text-xs uppercase"
className="h-13 bg-blue-600 hover:bg-blue-500 text-white font-black rounded-xl text-xs uppercase shadow-sm"
>
{salvandoItem ? 'Gravando...' : 'INCLUIR NO CAMINHÃO'}
</Button>
@@ -1050,7 +1053,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
type="button"
variant="outline"
onClick={() => setPecaEmbarque(null)}
className="h-13 bg-slate-700 text-slate-300 text-xs font-bold rounded-xl"
className="h-13 bg-slate-100 hover:bg-slate-200 text-slate-700 dark:bg-slate-700 dark:text-slate-300 text-xs font-bold rounded-xl border border-slate-200 dark:border-transparent"
>
Cancelar
</Button>
@@ -1060,22 +1063,22 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
{/* Lista de Peças Prontas para Embarcar */}
<div className="flex-1 overflow-y-auto space-y-2.5 pb-4">
<div className="text-xs font-black uppercase text-slate-400 tracking-wider mb-1">
<div className="text-xs font-black uppercase text-slate-500 dark:text-slate-400 tracking-wider mb-1">
Peças com Saldo para Embarque
</div>
{loadingPecas ? (
<div className="py-12 flex flex-col items-center justify-center text-slate-400 gap-2">
<div className="py-12 flex flex-col items-center justify-center text-slate-500 dark:text-slate-400 gap-2">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-blue-500 border-t-transparent" />
<span>Carregando peças prontas...</span>
</div>
) : pecasProntas.filter((p) => p.saldoDisponivel > 0).length === 0 ? (
<div className="p-8 text-center bg-slate-800/40 rounded-2xl border border-slate-800">
<Package className="h-10 w-10 text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-200">
<div className="p-8 text-center bg-white dark:bg-slate-800/40 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm">
<Package className="h-10 w-10 text-slate-400 dark:text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-800 dark:text-slate-200">
Nenhuma peça com saldo de embarque
</h3>
<p className="text-xs text-slate-400 mt-1">
<p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
Todas as peças prontas já foram embarcadas em romaneios anteriores
</p>
</div>
@@ -1085,23 +1088,23 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
.map((p) => (
<div
key={p.id}
className="p-3.5 rounded-2xl bg-slate-800/95 border border-slate-700 flex items-center justify-between gap-2 shadow-sm"
className="p-3.5 rounded-2xl bg-white dark:bg-slate-800/95 border border-slate-200 dark:border-slate-700 flex items-center justify-between gap-2 shadow-sm"
>
<div>
<div className="flex items-center gap-2">
<span className="text-lg font-black text-amber-400">{p.marca}</span>
<span className="text-lg font-black text-amber-700 dark:text-amber-400">{p.marca}</span>
{p.tem_componentes === false && (
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-950/80 text-purple-300 font-bold border border-purple-800/50">
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-100 text-purple-800 font-bold border border-purple-300 dark:bg-purple-950/80 dark:text-purple-300 dark:border-purple-800/50">
S/M
</span>
)}
<span className="text-[11px] px-2 py-0.5 rounded bg-slate-700 text-slate-300 font-semibold">
<span className="text-[11px] px-2 py-0.5 rounded bg-slate-100 text-slate-700 dark:bg-slate-700 dark:text-slate-300 font-semibold border border-slate-200 dark:border-transparent">
{p.etapa_fase || 'Estrutural'}
</span>
</div>
<div className="text-xs text-slate-300 mt-0.5">
<div className="text-xs text-slate-600 dark:text-slate-300 mt-0.5">
Saldo p/ Embarque:{' '}
<span className="font-bold text-blue-400">{p.saldoDisponivel} un</span>
<span className="font-bold text-blue-600 dark:text-blue-400">{p.saldoDisponivel} un</span>
</div>
</div>
@@ -1113,7 +1116,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
setPecaEmbarque(p);
setQtdEmbarcar(1);
}}
className="h-11 px-3.5 bg-blue-600 hover:bg-blue-500 text-white font-bold rounded-xl active:scale-95 text-xs uppercase shrink-0"
className="h-11 px-3.5 bg-blue-600 hover:bg-blue-500 text-white font-bold rounded-xl active:scale-95 text-xs uppercase shrink-0 shadow-sm"
>
Embarcar
</Button>
@@ -1131,7 +1134,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
carregarItensDoRomaneio(romaneioAtivo.id);
setSubTela('conferencia_romaneio');
}}
className="w-full h-15 bg-emerald-600 hover:bg-emerald-500 text-white text-sm font-black rounded-2xl shadow-lg uppercase active:scale-98 gap-2"
className="w-full h-15 bg-emerald-600 hover:bg-emerald-500 text-white text-sm font-black rounded-2xl shadow-md uppercase active:scale-98 gap-2"
>
<FileCheck className="h-5 w-5" />
<span>CONFERIR & FINALIZAR ROMANEIO</span>
@@ -1144,7 +1147,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
smartAudio.playClick();
setSubTela('menu');
}}
className="w-full h-12 bg-slate-800 border-slate-700 text-slate-300 text-xs font-bold rounded-2xl"
className="w-full h-12 bg-white dark:bg-slate-800 border-slate-300 dark:border-slate-700 text-slate-700 dark:text-slate-300 text-xs font-bold rounded-2xl shadow-sm"
>
⬅️ Voltar ao Menu
</Button>
@@ -1170,17 +1173,17 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
{/* Cabeçalho da Conferência */}
<div className="mb-3 text-center">
<span className="text-xs font-black uppercase text-amber-400 tracking-wider">
<span className="text-xs font-black uppercase text-amber-600 dark:text-amber-400 tracking-wider">
CONFERÊNCIA DE EMBARQUE
</span>
<h2 className="text-xl font-black text-slate-100 uppercase mt-0.5">
<h2 className="text-xl font-black text-slate-800 dark:text-slate-100 uppercase mt-0.5">
{romaneioAtivo.numero_romaneio}
</h2>
<div className="flex items-center justify-center gap-2 mt-1">
<span className="text-xs text-slate-300 font-medium">
<span className="text-xs text-slate-600 dark:text-slate-300 font-medium">
OF {obra.of_number} — {obra.cliente || 'Industrial'}
</span>
<span className="text-[10px] px-2 py-0.5 rounded bg-emerald-500/20 text-emerald-300 font-bold uppercase">
<span className="text-[10px] px-2 py-0.5 rounded bg-emerald-100 text-emerald-800 dark:bg-emerald-500/20 dark:text-emerald-300 font-bold uppercase border border-emerald-200 dark:border-transparent">
{romaneioAtivo.status || 'Em conferência'}
</span>
</div>
@@ -1188,49 +1191,49 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
{/* KPIs em Grid Rápido */}
<div className="grid grid-cols-3 gap-2 mb-3">
<div className="p-3 rounded-2xl bg-slate-800 border border-slate-700 text-center">
<span className="text-[10px] font-black uppercase text-slate-400 block">
<div className="p-3 rounded-2xl bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 text-center shadow-sm">
<span className="text-[10px] font-black uppercase text-slate-500 dark:text-slate-400 block">
Marcas
</span>
<span className="text-xl font-black text-amber-400">
<span className="text-xl font-black text-amber-600 dark:text-amber-400">
{itensRomaneio.length}
</span>
</div>
<div className="p-3 rounded-2xl bg-slate-800 border border-slate-700 text-center">
<span className="text-[10px] font-black uppercase text-slate-400 block">
<div className="p-3 rounded-2xl bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 text-center shadow-sm">
<span className="text-[10px] font-black uppercase text-slate-500 dark:text-slate-400 block">
Peças
</span>
<span className="text-xl font-black text-blue-400">
<span className="text-xl font-black text-blue-600 dark:text-blue-400">
{totalPecasCarregadas} un
</span>
</div>
<div className="p-3 rounded-2xl bg-slate-800 border border-slate-700 text-center">
<span className="text-[10px] font-black uppercase text-slate-400 block">
<div className="p-3 rounded-2xl bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 text-center shadow-sm">
<span className="text-[10px] font-black uppercase text-slate-500 dark:text-slate-400 block">
Peso Carga
</span>
<span className="text-lg font-black text-emerald-400">
<span className="text-lg font-black text-emerald-600 dark:text-emerald-400">
{pesoTotalCarregado.toLocaleString('pt-BR', { maximumFractionDigits: 1 })} kg
</span>
</div>
</div>
{/* Card de Dados do Transporte */}
<div className="p-3 rounded-2xl bg-slate-800/80 border border-slate-700 mb-3 text-xs text-slate-300 space-y-1">
<div className="p-3 rounded-2xl bg-white/90 dark:bg-slate-800/80 border border-slate-200 dark:border-slate-700 mb-3 text-xs text-slate-700 dark:text-slate-300 space-y-1 shadow-sm">
<div className="flex items-center justify-between">
<span className="text-slate-400">Motorista:</span>
<span className="font-bold text-slate-200">
<span className="text-slate-500 dark:text-slate-400">Motorista:</span>
<span className="font-bold text-slate-800 dark:text-slate-200">
{romaneioAtivo.nome_motorista || 'Não informado'}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-slate-400">Veículo:</span>
<span className="font-bold text-slate-200">
<span className="text-slate-500 dark:text-slate-400">Veículo:</span>
<span className="font-bold text-slate-800 dark:text-slate-200">
{formatTransporte(romaneioAtivo.tipo_transporte)}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-slate-400">Tipo de Frete:</span>
<span className="font-bold text-slate-200">
<span className="text-slate-500 dark:text-slate-400">Tipo de Frete:</span>
<span className="font-bold text-slate-800 dark:text-slate-200">
{formatFrete(romaneioAtivo.frete_tipo)}
</span>
</div>
@@ -1238,29 +1241,29 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
{/* Lista de Peças Colocadas no Romaneio para Conferência */}
<div className="flex-1 overflow-y-auto space-y-2 pb-3">
<div className="flex items-center justify-between text-xs font-black uppercase text-slate-400 tracking-wider mb-1 px-1">
<div className="flex items-center justify-between text-xs font-black uppercase text-slate-500 dark:text-slate-400 tracking-wider mb-1 px-1">
<span>Peças Colocadas no Caminhão ({itensRomaneio.length})</span>
<span className="text-slate-500 font-normal">Toque na lixeira para estornar</span>
<span className="text-slate-400 dark:text-slate-500 font-normal">Toque na lixeira para estornar</span>
</div>
{loadingItensRomaneio ? (
<div className="py-12 flex flex-col items-center justify-center text-slate-400 gap-2">
<div className="py-12 flex flex-col items-center justify-center text-slate-500 dark:text-slate-400 gap-2">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-amber-500 border-t-transparent" />
<span>Carregando itens do romaneio...</span>
</div>
) : itensRomaneio.length === 0 ? (
<div className="p-8 text-center bg-slate-800/40 rounded-2xl border border-slate-800">
<Package className="h-10 w-10 text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-200">
<div className="p-8 text-center bg-white dark:bg-slate-800/40 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm">
<Package className="h-10 w-10 text-slate-400 dark:text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-800 dark:text-slate-200">
Nenhuma peça colocada neste romaneio ainda
</h3>
<p className="text-xs text-slate-400 mt-1 mb-3">
<p className="text-xs text-slate-500 dark:text-slate-400 mt-1 mb-3">
Adicione peças prontas no caminhão para gerar o romaneio
</p>
<Button
type="button"
onClick={() => setSubTela('carregando_pecas')}
className="h-11 px-4 bg-blue-600 hover:bg-blue-500 text-white font-black text-xs rounded-xl"
className="h-11 px-4 bg-blue-600 hover:bg-blue-500 text-white font-black text-xs rounded-xl shadow-sm"
>
+ Adicionar Peças ao Caminhão
</Button>
@@ -1269,43 +1272,43 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
itensRomaneio.map((item, idx) => (
<div
key={item.id}
className="p-3 rounded-2xl bg-slate-800/95 border border-slate-700/80 flex items-center justify-between gap-2 shadow-sm"
className="p-3 rounded-2xl bg-white dark:bg-slate-800/95 border border-slate-200 dark:border-slate-700/80 flex items-center justify-between gap-2 shadow-sm"
>
<div className="flex items-center gap-3">
<div className="h-7 w-7 rounded-lg bg-slate-700 flex items-center justify-center text-[11px] font-black text-slate-300 shrink-0">
<div className="h-7 w-7 rounded-lg bg-slate-100 dark:bg-slate-700 flex items-center justify-center text-[11px] font-black text-slate-600 dark:text-slate-300 shrink-0">
#{idx + 1}
</div>
<div>
<div className="flex items-center gap-2">
<span className="text-base font-black text-amber-400">
<span className="text-base font-black text-amber-700 dark:text-amber-400">
{item.marca}
</span>
{(item.tem_componentes === false || pecasProntas.some(p => p.id === item.peca_id && p.tem_componentes === false)) && (
<span className="text-[10px] px-2 py-0.5 rounded bg-purple-950/80 text-purple-300 font-bold border border-purple-800/40">
<span className="text-[10px] px-2 py-0.5 rounded bg-purple-100 text-purple-800 font-bold border border-purple-300 dark:bg-purple-950/80 dark:text-purple-300 dark:border-purple-800/40">
S/M
</span>
)}
<span className="text-[10px] px-2 py-0.5 rounded bg-blue-950/80 text-blue-300 font-bold border border-blue-800/40">
<span className="text-[10px] px-2 py-0.5 rounded bg-blue-100 text-blue-800 font-bold border border-blue-200 dark:bg-blue-950/80 dark:text-blue-300 dark:border-blue-800/40">
{item.fase || '1'}
</span>
</div>
{item.descricao && (
<div className="text-xs text-slate-300 line-clamp-1">
<div className="text-xs text-slate-600 dark:text-slate-300 line-clamp-1">
{item.descricao}
</div>
)}
<div className="text-[11px] text-slate-400 mt-0.5">
Peso Total: <b className="text-slate-200">{item.peso_total.toFixed(1)} kg</b> ({item.peso_unitario.toFixed(1)} kg/un)
<div className="text-[11px] text-slate-500 dark:text-slate-400 mt-0.5">
Peso Total: <b className="text-slate-800 dark:text-slate-200">{item.peso_total.toFixed(1)} kg</b> ({item.peso_unitario.toFixed(1)} kg/un)
</div>
</div>
</div>
<div className="flex items-center gap-2 shrink-0">
<div className="text-right">
<span className="text-lg font-black text-blue-400">
<span className="text-lg font-black text-blue-600 dark:text-blue-400">
{item.quantidade_expedida}
</span>
<span className="text-[10px] text-slate-400 block font-semibold">un</span>
<span className="text-[10px] text-slate-500 dark:text-slate-400 block font-semibold">un</span>
</div>
{/* Botão de Excluir / Estornar Item */}
@@ -1313,7 +1316,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
type="button"
disabled={removendoItemId === item.id}
onClick={() => handleRemoverItemRomaneio(item)}
className="h-9 w-9 rounded-xl bg-rose-950/40 hover:bg-rose-900/60 border border-rose-800/50 text-rose-400 flex items-center justify-center active:scale-95 transition-all"
className="h-9 w-9 rounded-xl bg-rose-50 hover:bg-rose-100 border border-rose-200 text-rose-600 dark:bg-rose-950/40 dark:hover:bg-rose-900/60 dark:border-rose-800/50 dark:text-rose-400 flex items-center justify-center active:scale-95 transition-all shadow-sm"
title="Remover peça deste romaneio"
>
<Trash2 className="h-4 w-4" />
@@ -1325,13 +1328,13 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
</div>
{/* Botões de Ação na Base: Imprimir PDF, Compartilhar e Concluir */}
<div className="space-y-2 pt-2 border-t border-slate-800">
<div className="space-y-2 pt-2 border-t border-slate-200 dark:border-slate-800">
{/* Botão Principal: Imprimir / Baixar PDF Oficial */}
<Button
type="button"
disabled={gerandoPDF || itensRomaneio.length === 0}
onClick={() => gerarRomaneioPDF('download')}
className="w-full h-14 bg-amber-500 hover:bg-amber-400 text-slate-950 text-sm font-black rounded-2xl shadow-lg shadow-amber-950/30 uppercase active:scale-98 gap-2"
className="w-full h-14 bg-amber-500 hover:bg-amber-400 text-slate-950 text-sm font-black rounded-2xl shadow-md uppercase active:scale-98 gap-2"
>
<Download className="h-5 w-5" />
<span>{gerandoPDF ? 'Gerando Romaneio...' : 'BAIXAR / IMPRIMIR PDF DO ROMANEIO'}</span>
@@ -1343,7 +1346,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
type="button"
disabled={itensRomaneio.length === 0}
onClick={() => gerarRomaneioPDF('whatsapp')}
className="h-12 px-3 rounded-xl bg-emerald-600 hover:bg-emerald-500 text-white text-xs font-black flex items-center justify-center gap-1.5 active:scale-95 transition-all disabled:opacity-50"
className="h-12 px-3 rounded-xl bg-emerald-600 hover:bg-emerald-500 text-white text-xs font-black flex items-center justify-center gap-1.5 active:scale-95 transition-all disabled:opacity-50 shadow-sm"
>
<Share2 className="h-4 w-4" />
<span>Enviar WhatsApp</span>
@@ -1355,9 +1358,9 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
smartAudio.playClick();
setSubTela('carregando_pecas');
}}
className="h-12 px-3 rounded-xl bg-slate-800 hover:bg-slate-700 border border-slate-700 text-slate-200 text-xs font-bold flex items-center justify-center gap-1.5 active:scale-95 transition-all"
className="h-12 px-3 rounded-xl bg-white hover:bg-slate-100 border border-slate-200 text-slate-800 dark:bg-slate-800 dark:hover:bg-slate-700 dark:border-slate-700 dark:text-slate-200 text-xs font-bold flex items-center justify-center gap-1.5 active:scale-95 transition-all shadow-sm"
>
<Plus className="h-4 w-4 text-blue-400" />
<Plus className="h-4 w-4 text-blue-600 dark:text-blue-400" />
<span>+ Adicionar Peças</span>
</button>
</div>
@@ -1366,7 +1369,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
<Button
type="button"
onClick={() => handleConcluirRomaneioOficial('Expedido')}
className="w-full h-12 bg-blue-600 hover:bg-blue-500 text-white text-xs font-black rounded-xl uppercase active:scale-98 gap-1.5"
className="w-full h-12 bg-blue-600 hover:bg-blue-500 text-white text-xs font-black rounded-xl uppercase active:scale-98 gap-1.5 shadow-sm"
>
<CheckCircle2 className="h-4 w-4" />
<span>CONCLUIR & MARCAR COMO EXPEDIDO</span>
@@ -1381,7 +1384,7 @@ export const SmartEmbarqueFlow: React.FC<SmartEmbarqueFlowProps> = ({ obra, onVo
setSubTela('menu');
setRomaneioAtivo(null);
}}
className="w-full h-10 text-slate-400 hover:text-slate-200 text-xs font-bold"
className="w-full h-10 text-slate-500 hover:text-slate-800 dark:text-slate-400 dark:hover:text-slate-200 text-xs font-bold"
>
⬅️ Voltar ao Menu Principal
</Button>
+44 -14
View File
@@ -1,7 +1,8 @@
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Building2, Volume2, VolumeX, LogOut, ArrowLeft } from 'lucide-react';
import { Building2, Volume2, VolumeX, LogOut, ArrowLeft, Sun, Moon } from 'lucide-react';
import { useAuth } from '@/hooks/useAuth';
import { useTheme } from '@/hooks/useTheme';
import { smartAudio } from '@/utils/smartAudio';
import { Button } from '@/components/ui/button';
@@ -20,13 +21,27 @@ export const SmartHeader: React.FC<SmartHeaderProps> = ({
}) => {
const navigate = useNavigate();
const { user, signOut } = useAuth();
const { theme, setTheme } = useTheme();
const [soundOn, setSoundOn] = useState<boolean>(() => smartAudio.isSoundEnabled());
// Detecta se está efetivamente em modo escuro
const isDark =
theme === 'dark' ||
(theme === 'system' &&
typeof window !== 'undefined' &&
window.matchMedia('(prefers-color-scheme: dark)').matches);
const handleToggleSound = () => {
const novoEstado = smartAudio.toggleSound();
setSoundOn(novoEstado);
};
const handleToggleTheme = () => {
smartAudio.playClick();
const novoTema = isDark ? 'light' : 'dark';
setTheme(novoTema);
};
const handleVoltarAoModoCompleto = () => {
smartAudio.playClick();
try {
@@ -46,7 +61,7 @@ export const SmartHeader: React.FC<SmartHeaderProps> = ({
};
return (
<header className="sticky top-0 z-50 w-full bg-slate-900 border-b border-slate-800 text-white shadow-md">
<header className="sticky top-0 z-50 w-full bg-white dark:bg-slate-900 border-b border-slate-200 dark:border-slate-800 text-slate-800 dark:text-white shadow-sm transition-colors duration-200">
<div className="max-w-4xl mx-auto px-2.5 sm:px-3 py-2 flex items-center justify-between gap-1.5 sm:gap-2">
{/* Lado Esquerdo: Botão Voltar ou Logo/Status */}
<div className="flex items-center gap-1.5 sm:gap-2 min-w-0 flex-1">
@@ -58,23 +73,23 @@ export const SmartHeader: React.FC<SmartHeaderProps> = ({
smartAudio.playClick();
onVoltar();
}}
className="h-10 px-2 sm:px-2.5 bg-slate-800/90 hover:bg-slate-700 text-slate-100 rounded-xl border border-slate-700 active:scale-95 text-xs sm:text-sm font-bold flex items-center gap-1 shrink-0"
className="h-10 px-2 sm:px-2.5 bg-slate-100 hover:bg-slate-200 dark:bg-slate-800/90 dark:hover:bg-slate-700 text-slate-800 dark:text-slate-100 rounded-xl border border-slate-300 dark:border-slate-700 active:scale-95 text-xs sm:text-sm font-bold flex items-center gap-1 shrink-0 transition-colors"
>
<ArrowLeft className="h-4 w-4 text-amber-400 shrink-0" />
<ArrowLeft className="h-4 w-4 text-amber-600 dark:text-amber-400 shrink-0" />
<span>Voltar</span>
</Button>
) : (
<div className="flex items-center gap-2">
<span className="flex h-3 w-3 relative">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-amber-500"></span>
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-500 dark:bg-amber-400 opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-amber-600 dark:bg-amber-500"></span>
</span>
<div className="leading-tight min-w-0 flex-1">
<h1 className="text-sm sm:text-base font-black tracking-wider text-amber-400 uppercase truncate">
<h1 className="text-sm sm:text-base font-black tracking-wider text-amber-700 dark:text-amber-400 uppercase truncate">
{titulo}
</h1>
{subtitulo && (
<p className="text-[11px] sm:text-xs text-slate-300 font-medium truncate">
<p className="text-[11px] sm:text-xs text-slate-600 dark:text-slate-300 font-medium truncate">
{subtitulo}
</p>
)}
@@ -84,11 +99,11 @@ export const SmartHeader: React.FC<SmartHeaderProps> = ({
{mostrarVoltar && (
<div className="leading-tight min-w-0 flex-1">
<h1 className="text-xs sm:text-sm font-black text-slate-100 uppercase truncate">
<h1 className="text-xs sm:text-sm font-black text-slate-900 dark:text-slate-100 uppercase truncate">
{titulo}
</h1>
{subtitulo && (
<p className="text-[11px] sm:text-xs text-amber-400 font-extrabold tracking-wide truncate">
<p className="text-[11px] sm:text-xs text-amber-700 dark:text-amber-400 font-extrabold tracking-wide truncate">
{subtitulo}
</p>
)}
@@ -98,14 +113,29 @@ export const SmartHeader: React.FC<SmartHeaderProps> = ({
{/* Lado Direito: Ações de Controle e Comutação */}
<div className="flex items-center gap-1 sm:gap-1.5 shrink-0">
{/* Alternador de Tema Claro / Escuro (Sincronizado) */}
<button
type="button"
onClick={handleToggleTheme}
className={`h-10 w-8 sm:w-9 rounded-xl flex items-center justify-center border transition-all active:scale-90 ${
isDark
? 'bg-slate-800/80 border-slate-700 text-amber-400 hover:bg-slate-750'
: 'bg-amber-50 border-amber-200 text-amber-700 hover:bg-amber-100'
}`}
title={isDark ? 'Mudar para Modo Claro (Tons Pastéis)' : 'Mudar para Modo Escuro'}
aria-label="Alternar tema visual"
>
{isDark ? <Sun className="h-4 w-4" /> : <Moon className="h-4 w-4" />}
</button>
{/* Controle de Som / Áudio */}
<button
type="button"
onClick={handleToggleSound}
className={`h-10 w-8 sm:w-9 rounded-xl flex items-center justify-center border transition-all active:scale-90 ${
soundOn
? 'bg-emerald-950/60 border-emerald-600/50 text-emerald-400'
: 'bg-slate-800/80 border-slate-700 text-slate-400'
? 'bg-emerald-100 border-emerald-300 text-emerald-800 dark:bg-emerald-950/60 dark:border-emerald-600/50 dark:text-emerald-400'
: 'bg-slate-100 border-slate-200 text-slate-500 dark:bg-slate-800/80 dark:border-slate-700 dark:text-slate-400'
}`}
title={soundOn ? 'Som ativo (BIP habilitado)' : 'Mudo'}
>
@@ -117,7 +147,7 @@ export const SmartHeader: React.FC<SmartHeaderProps> = ({
type="button"
variant="outline"
onClick={handleVoltarAoModoCompleto}
className="h-10 px-2 sm:px-2.5 gap-1 bg-blue-600 hover:bg-blue-500 text-white border-blue-500 hover:border-blue-400 font-bold text-xs rounded-xl shadow-sm active:scale-95 transition-all shrink-0"
className="h-10 px-2 sm:px-2.5 gap-1 bg-blue-600 hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-500 text-white border-blue-600 hover:border-blue-500 dark:border-blue-500 dark:hover:border-blue-400 font-bold text-xs rounded-xl shadow-sm active:scale-95 transition-all shrink-0"
title="Sair do Modo Smart e abrir o sistema completo (Dashboard / 3D / Cadastros)"
>
<Building2 className="h-3.5 w-3.5 sm:h-4 sm:w-4 shrink-0" />
@@ -128,7 +158,7 @@ export const SmartHeader: React.FC<SmartHeaderProps> = ({
<button
type="button"
onClick={handleLogout}
className="h-10 w-8 sm:w-9 rounded-xl flex items-center justify-center bg-slate-800 hover:bg-red-900/60 border border-slate-700 hover:border-red-600/50 text-slate-400 hover:text-red-300 transition-colors active:scale-90 shrink-0"
className="h-10 w-8 sm:w-9 rounded-xl flex items-center justify-center bg-slate-100 hover:bg-rose-100 border border-slate-200 hover:border-rose-300 text-slate-600 hover:text-rose-700 dark:bg-slate-800 dark:hover:bg-red-900/60 dark:border-slate-700 dark:hover:border-red-600/50 dark:text-slate-400 dark:hover:text-red-300 transition-colors active:scale-90 shrink-0"
title={`Sair do sistema (${user?.email || 'Operador'})`}
>
<LogOut className="h-4 w-4" />
+30 -30
View File
@@ -36,12 +36,12 @@ export const SmartHub: React.FC<SmartHubProps> = ({
return (
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
{/* Barra de Contexto da Obra */}
<div className="mb-4 p-3.5 rounded-2xl bg-slate-800/80 border border-slate-700/80 flex items-center justify-between gap-2 shadow-sm">
<div className="mb-4 p-3.5 rounded-2xl bg-white dark:bg-slate-800/80 border border-slate-200 dark:border-slate-700/80 flex items-center justify-between gap-2 shadow-sm">
<div className="min-w-0">
<span className="text-[11px] font-black uppercase text-amber-400 tracking-wider">
<span className="text-[11px] font-black uppercase text-amber-700 dark:text-amber-400 tracking-wider">
OBRA ATIVA
</span>
<div className="text-base font-black text-slate-100 truncate">
<div className="text-base font-black text-slate-900 dark:text-slate-100 truncate">
OF {obra.of_number} — {obra.cliente || 'Obra Industrial'}
</div>
</div>
@@ -52,9 +52,9 @@ export const SmartHub: React.FC<SmartHubProps> = ({
smartAudio.playClick();
onTrocarObra();
}}
className="h-10 px-3 border-slate-600 bg-slate-700/60 hover:bg-slate-650 text-slate-200 hover:text-white rounded-xl text-xs font-bold shrink-0 active:scale-95 gap-1.5"
className="h-10 px-3 border-slate-300 dark:border-slate-600 bg-slate-100 hover:bg-slate-200 dark:bg-slate-700/60 dark:hover:bg-slate-650 text-slate-800 dark:text-slate-200 rounded-xl text-xs font-bold shrink-0 active:scale-95 gap-1.5 transition-colors"
>
<ArrowLeftRight className="h-4 w-4 text-amber-400" />
<ArrowLeftRight className="h-4 w-4 text-amber-600 dark:text-amber-400" />
<span>Trocar</span>
</Button>
</div>
@@ -65,13 +65,13 @@ export const SmartHub: React.FC<SmartHubProps> = ({
<button
type="button"
onClick={() => handleAcao('producao')}
className="min-h-[110px] sm:min-h-[125px] p-4 rounded-3xl bg-gradient-to-br from-amber-600 to-amber-700 hover:from-amber-500 hover:to-amber-600 active:from-amber-700 active:to-amber-800 text-white shadow-lg shadow-amber-950/40 border-2 border-amber-400/40 flex flex-col justify-between text-left transition-all active:scale-[0.97] group"
className="min-h-[110px] sm:min-h-[125px] p-4 rounded-3xl bg-gradient-to-br from-amber-500 to-amber-600 dark:from-amber-600 dark:to-amber-700 hover:from-amber-400 hover:to-amber-500 text-white shadow-lg shadow-amber-900/20 dark:shadow-amber-950/40 border-2 border-amber-300/60 dark:border-amber-400/40 flex flex-col justify-between text-left transition-all active:scale-[0.97] group"
>
<div className="flex items-center justify-between w-full">
<div className="p-2.5 rounded-2xl bg-white/15 text-white backdrop-blur-sm">
<div className="p-2.5 rounded-2xl bg-white/20 dark:bg-white/15 text-white backdrop-blur-sm">
<Hammer className="h-7 w-7" />
</div>
<span className="text-[11px] font-black uppercase tracking-wider px-2 py-0.5 rounded-full bg-black/25 text-amber-100">
<span className="text-[11px] font-black uppercase tracking-wider px-2 py-0.5 rounded-full bg-black/20 dark:bg-black/25 text-amber-100">
Passo 1
</span>
</div>
@@ -89,13 +89,13 @@ export const SmartHub: React.FC<SmartHubProps> = ({
<button
type="button"
onClick={() => handleAcao('embarque')}
className="min-h-[110px] sm:min-h-[125px] p-4 rounded-3xl bg-gradient-to-br from-blue-600 to-blue-700 hover:from-blue-500 hover:to-blue-600 active:from-blue-700 active:to-blue-800 text-white shadow-lg shadow-blue-950/40 border-2 border-blue-400/40 flex flex-col justify-between text-left transition-all active:scale-[0.97] group"
className="min-h-[110px] sm:min-h-[125px] p-4 rounded-3xl bg-gradient-to-br from-blue-600 to-blue-700 hover:from-blue-500 hover:to-blue-600 active:from-blue-700 active:to-blue-800 text-white shadow-lg shadow-blue-900/20 dark:shadow-blue-950/40 border-2 border-blue-300/60 dark:border-blue-400/40 flex flex-col justify-between text-left transition-all active:scale-[0.97] group"
>
<div className="flex items-center justify-between w-full">
<div className="p-2.5 rounded-2xl bg-white/15 text-white backdrop-blur-sm">
<div className="p-2.5 rounded-2xl bg-white/20 dark:bg-white/15 text-white backdrop-blur-sm">
<Truck className="h-7 w-7" />
</div>
<span className="text-[11px] font-black uppercase tracking-wider px-2 py-0.5 rounded-full bg-black/25 text-blue-100">
<span className="text-[11px] font-black uppercase tracking-wider px-2 py-0.5 rounded-full bg-black/20 dark:bg-black/25 text-blue-100">
Passo 2
</span>
</div>
@@ -113,13 +113,13 @@ export const SmartHub: React.FC<SmartHubProps> = ({
<button
type="button"
onClick={() => handleAcao('montagem')}
className="min-h-[110px] sm:min-h-[125px] p-4 rounded-3xl bg-gradient-to-br from-emerald-600 to-emerald-700 hover:from-emerald-500 hover:to-emerald-600 active:from-emerald-700 active:to-emerald-800 text-white shadow-lg shadow-emerald-950/40 border-2 border-emerald-400/40 flex flex-col justify-between text-left transition-all active:scale-[0.97] group"
className="min-h-[110px] sm:min-h-[125px] p-4 rounded-3xl bg-gradient-to-br from-emerald-600 to-emerald-700 hover:from-emerald-500 hover:to-emerald-600 active:from-emerald-700 active:to-emerald-800 text-white shadow-lg shadow-emerald-900/20 dark:shadow-emerald-950/40 border-2 border-emerald-300/60 dark:border-emerald-400/40 flex flex-col justify-between text-left transition-all active:scale-[0.97] group"
>
<div className="flex items-center justify-between w-full">
<div className="p-2.5 rounded-2xl bg-white/15 text-white backdrop-blur-sm">
<div className="p-2.5 rounded-2xl bg-white/20 dark:bg-white/15 text-white backdrop-blur-sm">
<PackageCheck className="h-7 w-7" />
</div>
<span className="text-[11px] font-black uppercase tracking-wider px-2 py-0.5 rounded-full bg-black/25 text-emerald-100">
<span className="text-[11px] font-black uppercase tracking-wider px-2 py-0.5 rounded-full bg-black/20 dark:bg-black/25 text-emerald-100">
Passo 3
</span>
</div>
@@ -137,13 +137,13 @@ export const SmartHub: React.FC<SmartHubProps> = ({
<button
type="button"
onClick={() => handleAcao('consulta')}
className="min-h-[110px] sm:min-h-[125px] p-4 rounded-3xl bg-gradient-to-br from-purple-600 to-purple-700 hover:from-purple-500 hover:to-purple-600 active:from-purple-700 active:to-purple-800 text-white shadow-lg shadow-purple-950/40 border-2 border-purple-400/40 flex flex-col justify-between text-left transition-all active:scale-[0.97] group"
className="min-h-[110px] sm:min-h-[125px] p-4 rounded-3xl bg-gradient-to-br from-purple-600 to-purple-700 hover:from-purple-500 hover:to-purple-600 active:from-purple-700 active:to-purple-800 text-white shadow-lg shadow-purple-900/20 dark:shadow-purple-950/40 border-2 border-purple-300/60 dark:border-purple-400/40 flex flex-col justify-between text-left transition-all active:scale-[0.97] group"
>
<div className="flex items-center justify-between w-full">
<div className="p-2.5 rounded-2xl bg-white/15 text-white backdrop-blur-sm">
<div className="p-2.5 rounded-2xl bg-white/20 dark:bg-white/15 text-white backdrop-blur-sm">
<Search className="h-7 w-7" />
</div>
<span className="text-[11px] font-black uppercase tracking-wider px-2 py-0.5 rounded-full bg-black/25 text-purple-100">
<span className="text-[11px] font-black uppercase tracking-wider px-2 py-0.5 rounded-full bg-black/20 dark:bg-black/25 text-purple-100">
Info
</span>
</div>
@@ -159,33 +159,33 @@ export const SmartHub: React.FC<SmartHubProps> = ({
</div>
{/* Card Informativo de Produção do Operador Hoje */}
<div className="mt-4 p-4 rounded-2xl bg-slate-800/90 border border-slate-700/80 flex flex-col gap-3 shadow-sm">
<div className="mt-4 p-4 rounded-2xl bg-white dark:bg-slate-800/90 border border-slate-200 dark:border-slate-700/80 flex flex-col gap-3 shadow-sm">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2 text-slate-300">
<TrendingUp className="h-5 w-5 text-amber-400" />
<div className="flex items-center gap-2 text-slate-700 dark:text-slate-300">
<TrendingUp className="h-5 w-5 text-amber-600 dark:text-amber-400" />
<span className="text-xs font-black uppercase tracking-wider">
Minha Produção Hoje
</span>
</div>
<span className="inline-flex items-center gap-1 text-[11px] font-bold px-2 py-0.5 rounded-full bg-amber-500/15 text-amber-400 border border-amber-500/30">
<span className="inline-flex items-center gap-1 text-[11px] font-bold px-2 py-0.5 rounded-full bg-amber-100 dark:bg-amber-500/15 text-amber-800 dark:text-amber-400 border border-amber-300 dark:border-amber-500/30">
<Sparkles className="h-3 w-3" />
Turno Ativo
</span>
</div>
<div className="grid grid-cols-2 gap-2 bg-slate-900/60 p-3 rounded-xl border border-slate-800">
<div className="grid grid-cols-2 gap-2 bg-slate-50 dark:bg-slate-900/60 p-3 rounded-xl border border-slate-200 dark:border-slate-800">
<div>
<div className="text-2xl sm:text-3xl font-black text-amber-400 leading-tight">
<div className="text-2xl sm:text-3xl font-black text-amber-700 dark:text-amber-400 leading-tight">
{producaoHoje.totalPecas}
</div>
<div className="text-xs text-slate-400 font-medium">Peças Apontadas</div>
<div className="text-xs text-slate-500 dark:text-slate-400 font-medium">Peças Apontadas</div>
</div>
<div className="border-l border-slate-800 pl-3">
<div className="text-2xl sm:text-3xl font-black text-slate-100 leading-tight">
<div className="border-l border-slate-200 dark:border-slate-800 pl-3">
<div className="text-2xl sm:text-3xl font-black text-slate-900 dark:text-slate-100 leading-tight">
{producaoHoje.totalKg.toLocaleString('pt-BR', { maximumFractionDigits: 1 })}{' '}
<span className="text-sm text-slate-400">kg</span>
<span className="text-sm text-slate-500 dark:text-slate-400">kg</span>
</div>
<div className="text-xs text-slate-400 font-medium">Peso Total</div>
<div className="text-xs text-slate-500 dark:text-slate-400 font-medium">Peso Total</div>
</div>
</div>
@@ -195,9 +195,9 @@ export const SmartHub: React.FC<SmartHubProps> = ({
smartAudio.playClick();
onGerarRelatorioTurno();
}}
className="w-full h-12 bg-slate-700 hover:bg-slate-650 active:bg-slate-600 text-slate-100 font-bold rounded-xl gap-2 border border-slate-600 text-sm active:scale-98"
className="w-full h-12 bg-slate-100 hover:bg-slate-200 dark:bg-slate-700 dark:hover:bg-slate-650 active:bg-slate-300 dark:active:bg-slate-600 text-slate-800 dark:text-slate-100 font-bold rounded-xl gap-2 border border-slate-300 dark:border-slate-600 text-sm active:scale-98 transition-colors"
>
<FileText className="h-4 w-4 text-amber-400" />
<FileText className="h-4 w-4 text-amber-600 dark:text-amber-400" />
<span>Gerar Relatório do Meu Turno (PDF)</span>
</Button>
</div>
@@ -228,28 +228,28 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
return (
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
{/* Resumo da Peça */}
<div className="p-4 rounded-2xl bg-slate-800/90 border border-slate-700 mb-4 shadow-sm">
<div className="p-4 rounded-2xl bg-white dark:bg-slate-800/90 border border-slate-200 dark:border-slate-700 mb-4 shadow-sm">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<span className="text-2xl font-black text-amber-400">
<span className="text-2xl font-black text-amber-700 dark:text-amber-400">
{itemSelecionado.marca}
</span>
{itemSelecionado.tem_componentes === false && (
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-950/80 text-purple-300 font-bold border border-purple-800/50">
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-100 text-purple-800 font-bold border border-purple-300 dark:bg-purple-950/80 dark:text-purple-300 dark:border-purple-800/50">
S/M
</span>
)}
</div>
<span className="text-xs font-black px-2.5 py-1 rounded-lg bg-emerald-500/20 text-emerald-300 border border-emerald-500/30 uppercase">
<span className="text-xs font-black px-2.5 py-1 rounded-lg bg-emerald-100 text-emerald-800 border border-emerald-300 dark:bg-emerald-500/20 dark:text-emerald-300 dark:border-emerald-500/30 uppercase">
Montagem em Obra
</span>
</div>
<div className="text-sm font-semibold text-slate-200 mt-1">
<div className="text-sm font-semibold text-slate-800 dark:text-slate-200 mt-1">
{itemSelecionado.descricao || 'Peça Estrutural'}
</div>
<div className="flex items-center justify-between text-xs text-slate-400 mt-2 pt-2 border-t border-slate-700/80">
<div className="flex items-center justify-between text-xs text-slate-500 dark:text-slate-400 mt-2 pt-2 border-t border-slate-100 dark:border-slate-700/80">
<span>Recebidas no Canteiro: {itemSelecionado.quantidade_expedida} un</span>
<span className="text-emerald-400 font-bold">
<span className="text-emerald-700 dark:text-emerald-400 font-bold">
Disponíveis p/ Montar: {saldo} un
</span>
</div>
@@ -257,12 +257,12 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
{/* Display da Quantidade */}
<div className="my-auto py-3 text-center">
<span className="text-xs font-black uppercase text-slate-400 tracking-wider">
<span className="text-xs font-black uppercase text-slate-500 dark:text-slate-400 tracking-wider">
Quantidade Montada Agora
</span>
<div className="flex items-center justify-center gap-4 mt-2">
<div className="min-w-[120px] h-20 px-6 rounded-3xl bg-slate-900 border-2 border-emerald-500 flex items-center justify-center shadow-inner">
<span className="text-4xl sm:text-5xl font-black text-emerald-400 tracking-tight">
<div className="min-w-[120px] h-20 px-6 rounded-3xl bg-slate-50 dark:bg-slate-900 border-2 border-emerald-500 flex items-center justify-center shadow-inner">
<span className="text-4xl sm:text-5xl font-black text-emerald-600 dark:text-emerald-400 tracking-tight">
{qtdApontar}
</span>
</div>
@@ -272,7 +272,7 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
smartAudio.playClick();
setQtdApontar(1);
}}
className="h-14 px-4 rounded-2xl bg-slate-800 hover:bg-slate-700 active:bg-slate-650 border border-slate-700 text-slate-300 text-xs font-bold flex items-center gap-1.5 active:scale-95"
className="h-14 px-4 rounded-2xl bg-slate-100 hover:bg-slate-200 text-slate-700 dark:bg-slate-800 dark:hover:bg-slate-700 active:bg-slate-650 border border-slate-200 dark:border-slate-700 dark:text-slate-300 text-xs font-bold flex items-center gap-1.5 active:scale-95 shadow-sm"
>
<RotateCcw className="h-4 w-4" />
<span>Zerar</span>
@@ -288,7 +288,7 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
smartAudio.playClick();
setQtdApontar((p) => Math.min(saldo, p + 1));
}}
className="h-16 rounded-2xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border-2 border-slate-700 text-white text-xl font-black active:scale-95 shadow-sm"
className="h-16 rounded-2xl bg-slate-100 hover:bg-slate-200 text-slate-800 border-2 border-slate-200 dark:bg-slate-800 dark:hover:bg-slate-750 active:bg-slate-700 dark:border-slate-700 dark:text-white text-xl font-black active:scale-95 shadow-sm"
>
+1
</button>
@@ -298,7 +298,7 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
smartAudio.playClick();
setQtdApontar((p) => Math.min(saldo, p + 2));
}}
className="h-16 rounded-2xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border-2 border-slate-700 text-white text-xl font-black active:scale-95 shadow-sm"
className="h-16 rounded-2xl bg-slate-100 hover:bg-slate-200 text-slate-800 border-2 border-slate-200 dark:bg-slate-800 dark:hover:bg-slate-750 active:bg-slate-700 dark:border-slate-700 dark:text-white text-xl font-black active:scale-95 shadow-sm"
>
+2
</button>
@@ -308,7 +308,7 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
smartAudio.playClick();
setQtdApontar((p) => Math.min(saldo, p + 5));
}}
className="h-16 rounded-2xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border-2 border-slate-700 text-white text-xl font-black active:scale-95 shadow-sm"
className="h-16 rounded-2xl bg-slate-100 hover:bg-slate-200 text-slate-800 border-2 border-slate-200 dark:bg-slate-800 dark:hover:bg-slate-750 active:bg-slate-700 dark:border-slate-700 dark:text-white text-xl font-black active:scale-95 shadow-sm"
>
+5
</button>
@@ -318,7 +318,7 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
smartAudio.playClick();
setQtdApontar(saldo > 0 ? saldo : 1);
}}
className="h-16 rounded-2xl bg-emerald-500/20 hover:bg-emerald-500/30 border-2 border-emerald-500/60 text-emerald-400 text-sm font-black active:scale-95 flex flex-col items-center justify-center leading-tight"
className="h-16 rounded-2xl bg-emerald-100 hover:bg-emerald-200 border-2 border-emerald-300 text-emerald-800 dark:bg-emerald-500/20 dark:hover:bg-emerald-500/30 dark:border-emerald-500/60 dark:text-emerald-400 text-sm font-black active:scale-95 flex flex-col items-center justify-center leading-tight shadow-sm"
>
<span>TODAS</span>
<span className="text-[11px] opacity-80">({saldo})</span>
@@ -331,7 +331,7 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
type="button"
disabled={salvando || qtdApontar <= 0}
onClick={handleConfirmarMontagem}
className="w-full h-16 bg-emerald-600 hover:bg-emerald-500 text-white text-base font-black rounded-2xl shadow-lg uppercase tracking-wide active:scale-98 gap-2"
className="w-full h-16 bg-emerald-600 hover:bg-emerald-500 text-white text-base font-black rounded-2xl shadow-md uppercase tracking-wide active:scale-98 gap-2"
>
{salvando ? (
<>
@@ -353,7 +353,7 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
smartAudio.playClick();
setItemSelecionado(null);
}}
className="w-full h-13 bg-slate-800 border-slate-700 text-slate-300 text-sm font-bold rounded-2xl active:scale-98"
className="w-full h-13 bg-white hover:bg-slate-100 border border-slate-200 text-slate-700 dark:bg-slate-800 dark:border-slate-700 dark:text-slate-300 text-sm font-bold rounded-2xl active:scale-98 shadow-sm"
>
Cancelar
</Button>
@@ -368,28 +368,28 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
return (
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
<div className="mb-4 text-center">
<span className="text-xs font-black uppercase text-emerald-400 tracking-wider">
<span className="text-xs font-black uppercase text-emerald-700 dark:text-emerald-400 tracking-wider">
ETAPA 3 — CANTEIRO DE OBRAS
</span>
<h2 className="text-xl font-black text-slate-100 uppercase mt-0.5">
<h2 className="text-xl font-black text-slate-800 dark:text-slate-100 uppercase mt-0.5">
Apontar Peças Montadas
</h2>
<p className="text-xs text-slate-400">
<p className="text-xs text-slate-500 dark:text-slate-400">
Peças entregues no canteiro aguardando fixação/montagem
</p>
</div>
<div className="flex-1 overflow-y-auto space-y-3 pb-4">
{loading ? (
<div className="py-12 flex flex-col items-center justify-center text-slate-400 gap-2">
<div className="py-12 flex flex-col items-center justify-center text-slate-500 dark:text-slate-400 gap-2">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-emerald-500 border-t-transparent" />
<span>Consultando entregas no canteiro...</span>
</div>
) : itens.length === 0 ? (
<div className="p-8 text-center bg-slate-800/40 rounded-2xl border border-slate-800">
<AlertCircle className="h-10 w-10 text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-200">Nenhuma peça recebida na obra</h3>
<p className="text-xs text-slate-400 mt-1">
<div className="p-8 text-center bg-white dark:bg-slate-800/40 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm">
<AlertCircle className="h-10 w-10 text-slate-400 dark:text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-800 dark:text-slate-200">Nenhuma peça recebida na obra</h3>
<p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
É necessário gerar e enviar romaneios de fábrica antes de apontar montagem
</p>
</div>
@@ -401,37 +401,37 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
key={item.marca}
className={`p-4 rounded-2xl border-2 transition-all shadow-sm ${
concluida
? 'bg-slate-900/60 border-slate-800 opacity-75'
: 'bg-slate-800/95 border-slate-700/90 hover:border-emerald-500/80'
? 'bg-slate-50 dark:bg-slate-900/60 border-slate-200 dark:border-slate-800 opacity-75'
: 'bg-white dark:bg-slate-800/95 border-slate-200 dark:border-slate-700/90 hover:border-emerald-500/80'
}`}
>
<div className="flex items-start justify-between gap-2">
<div>
<div className="flex items-center gap-2">
<span className="text-xl font-black text-amber-400 tracking-wider">
<span className="text-xl font-black text-amber-700 dark:text-amber-400 tracking-wider">
{item.marca}
</span>
{item.tem_componentes === false && (
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-950/80 text-purple-300 font-bold border border-purple-800/50">
<span className="text-[10px] px-2 py-0.5 rounded-md bg-purple-100 text-purple-800 font-bold border border-purple-300 dark:bg-purple-950/80 dark:text-purple-300 dark:border-purple-800/50">
S/M
</span>
)}
</div>
<div className="text-xs text-slate-300 mt-0.5 line-clamp-1">
<div className="text-xs text-slate-600 dark:text-slate-300 mt-0.5 line-clamp-1">
{item.descricao || 'Peça Estrutural'}
</div>
</div>
<div className="text-right shrink-0">
<div className="text-xs font-semibold text-slate-400">
<div className="text-xs font-semibold text-slate-500 dark:text-slate-400">
Entregues: {item.quantidade_expedida}
</div>
{concluida ? (
<span className="inline-flex items-center gap-1 text-xs font-black text-emerald-400 px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-700">
<span className="inline-flex items-center gap-1 text-xs font-black text-emerald-800 bg-emerald-100 border border-emerald-300 dark:text-emerald-400 px-2 py-0.5 rounded-full dark:bg-emerald-950/80 dark:border-emerald-700">
<Check className="h-3 w-3" /> 100% Montada
</span>
) : (
<span className="inline-flex items-center gap-1 text-xs font-black text-emerald-300 px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-700">
<span className="inline-flex items-center gap-1 text-xs font-black text-emerald-800 bg-emerald-100 border border-emerald-300 dark:text-emerald-300 px-2 py-0.5 rounded-full dark:bg-emerald-950/80 dark:border-emerald-700">
Saldo: {item.saldo_disponivel}
</span>
)}
@@ -449,8 +449,8 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
}}
className={`w-full h-13 text-sm font-black rounded-xl uppercase tracking-wider transition-all active:scale-[0.98] ${
concluida
? 'bg-slate-800 text-slate-500 border border-slate-700'
: 'bg-emerald-600 hover:bg-emerald-500 text-white shadow-md shadow-emerald-950/30'
? 'bg-slate-100 text-slate-400 border border-slate-200 dark:bg-slate-800 dark:text-slate-500 dark:border-slate-700'
: 'bg-emerald-600 hover:bg-emerald-500 text-white shadow-md shadow-emerald-950/20'
}`}
>
{concluida ? 'Totalmente Montada' : `APONTAR MONTAGEM (${item.saldo_disponivel} PENDENTES)`}
@@ -469,7 +469,7 @@ export const SmartMontagemFlow: React.FC<SmartMontagemFlowProps> = ({
smartAudio.playClick();
onVoltarHub();
}}
className="w-full h-14 bg-slate-800 border-slate-700 text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98"
className="w-full h-14 bg-white dark:bg-slate-800 border-slate-300 dark:border-slate-700 text-slate-700 dark:text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98 shadow-sm"
>
⬅️ Voltar ao Menu Principal
</Button>
@@ -37,34 +37,34 @@ export const SmartObraSelector: React.FC<SmartObraSelectorProps> = ({ onSelectOb
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
{/* Título de Instrução Touch */}
<div className="mb-4 text-center">
<div className="inline-flex p-3 rounded-2xl bg-amber-500/10 text-amber-400 border border-amber-500/20 mb-2">
<div className="inline-flex p-3 rounded-2xl bg-amber-100 dark:bg-amber-500/10 text-amber-800 dark:text-amber-400 border border-amber-300 dark:border-amber-500/20 mb-2">
<HardHat className="h-8 w-8" />
</div>
<h2 className="text-xl font-black text-slate-100 uppercase tracking-wide">
<h2 className="text-xl font-black text-slate-900 dark:text-slate-100 uppercase tracking-wide">
Selecione a Obra / OF
</h2>
<p className="text-sm text-slate-400 font-medium">
<p className="text-sm text-slate-600 dark:text-slate-400 font-medium">
Escolha a obra em que você está operando hoje
</p>
</div>
{/* Campo de Busca Grande para Touch */}
<div className="relative mb-5">
<div className="absolute inset-y-0 left-0 pl-3.5 flex items-center pointer-events-none text-slate-400">
<Search className="h-5 w-5 text-amber-400" />
<div className="absolute inset-y-0 left-0 pl-3.5 flex items-center pointer-events-none text-amber-700 dark:text-amber-400">
<Search className="h-5 w-5" />
</div>
<Input
type="text"
value={busca}
onChange={(e) => setBusca(e.target.value)}
placeholder="Buscar por OF ou Cliente..."
className="h-14 pl-11 pr-11 bg-slate-800/90 border-slate-700 text-slate-100 placeholder:text-slate-500 text-base font-medium rounded-2xl focus-visible:ring-amber-500 focus-visible:border-amber-500"
className="h-14 pl-11 pr-11 bg-white dark:bg-slate-800/90 border-slate-300 dark:border-slate-700 text-slate-900 dark:text-slate-100 placeholder:text-slate-400 dark:placeholder:text-slate-500 text-base font-medium rounded-2xl focus-visible:ring-amber-500 focus-visible:border-amber-500 shadow-sm"
/>
{busca && (
<button
type="button"
onClick={() => setBusca('')}
className="absolute inset-y-0 right-0 pr-3.5 flex items-center text-slate-400 hover:text-slate-200"
className="absolute inset-y-0 right-0 pr-3.5 flex items-center text-slate-400 hover:text-slate-700 dark:hover:text-slate-200"
>
<X className="h-5 w-5" />
</button>
@@ -74,15 +74,15 @@ export const SmartObraSelector: React.FC<SmartObraSelectorProps> = ({ onSelectOb
{/* Lista de Obras em Cards Touch */}
<div className="flex-1 overflow-y-auto space-y-3 pb-8">
{isLoading ? (
<div className="py-12 flex flex-col items-center justify-center text-slate-400 gap-3">
<div className="py-12 flex flex-col items-center justify-center text-slate-500 dark:text-slate-400 gap-3">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-amber-500 border-t-transparent" />
<span className="text-sm font-semibold">Carregando obras ativas...</span>
</div>
) : filteredOFs.length === 0 ? (
<div className="p-8 text-center bg-slate-800/40 rounded-2xl border border-slate-800">
<AlertCircle className="h-10 w-10 text-amber-500/60 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-200">Nenhuma obra encontrada</h3>
<p className="text-xs text-slate-400 mt-1">
<div className="p-8 text-center bg-white dark:bg-slate-800/40 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm">
<AlertCircle className="h-10 w-10 text-amber-600 dark:text-amber-500/60 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-800 dark:text-slate-200">Nenhuma obra encontrada</h3>
<p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
{busca ? 'Tente buscar com outro termo' : 'Nenhuma ordem de fabricação ativa no momento'}
</p>
</div>
@@ -92,29 +92,29 @@ export const SmartObraSelector: React.FC<SmartObraSelectorProps> = ({ onSelectOb
key={of.of_number}
type="button"
onClick={() => handleSelect(of)}
className="w-full min-h-[72px] p-4 rounded-2xl bg-slate-800/90 hover:bg-slate-750 active:bg-slate-700 border-2 border-slate-700/80 hover:border-amber-500/60 transition-all flex items-center justify-between text-left gap-3 shadow-sm active:scale-[0.98] group"
className="w-full min-h-[72px] p-4 rounded-2xl bg-white hover:bg-amber-50/60 active:bg-amber-100/60 dark:bg-slate-800/90 dark:hover:bg-slate-750 dark:active:bg-slate-700 border-2 border-slate-200 hover:border-amber-400/80 dark:border-slate-700/80 dark:hover:border-amber-500/60 transition-all flex items-center justify-between text-left gap-3 shadow-sm active:scale-[0.98] group"
>
<div className="flex items-center gap-3.5 min-w-0">
<div className="h-12 w-12 rounded-xl bg-slate-700/80 flex items-center justify-center text-amber-400 group-hover:bg-amber-500 group-hover:text-slate-950 transition-colors shrink-0">
<div className="h-12 w-12 rounded-xl bg-amber-100 text-amber-800 dark:bg-slate-700/80 dark:text-amber-400 group-hover:bg-amber-500 group-hover:text-white dark:group-hover:text-slate-950 transition-colors shrink-0 flex items-center justify-center">
<Building className="h-6 w-6" />
</div>
<div className="min-w-0">
<div className="flex items-center gap-2">
<span className="text-base font-black text-amber-400 tracking-wider">
<span className="text-base font-black text-amber-700 dark:text-amber-400 tracking-wider">
OF {of.of_number}
</span>
</div>
<div className="text-sm font-bold text-slate-100 truncate">
<div className="text-sm font-bold text-slate-900 dark:text-slate-100 truncate">
{of.cliente || of.descricao_resumida || 'Cliente não especificado'}
</div>
{of.descricao_resumida && of.cliente && (
<div className="text-xs text-slate-400 truncate">
<div className="text-xs text-slate-500 dark:text-slate-400 truncate">
{of.descricao_resumida}
</div>
)}
</div>
</div>
<ChevronRight className="h-6 w-6 text-slate-500 group-hover:text-amber-400 transition-colors shrink-0" />
<ChevronRight className="h-6 w-6 text-slate-400 group-hover:text-amber-600 dark:text-slate-500 dark:group-hover:text-amber-400 transition-colors shrink-0" />
</button>
))
)}
@@ -354,20 +354,20 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
key={p.id}
type="button"
onClick={() => handleEscolherProcesso(p as ProcessoFabricacao)}
className="min-h-[72px] p-4 rounded-2xl bg-slate-800/90 hover:bg-slate-750 active:bg-slate-700 border-2 border-slate-700 hover:border-amber-500/80 flex items-center justify-between text-left transition-all active:scale-[0.98] group shadow-sm"
className="min-h-[72px] p-4 rounded-2xl bg-white hover:bg-amber-50/60 active:bg-amber-100/60 dark:bg-slate-800/90 dark:hover:bg-slate-750 dark:active:bg-slate-700 border-2 border-slate-200 hover:border-amber-400/80 dark:border-slate-700 dark:hover:border-amber-500/80 flex items-center justify-between text-left transition-all active:scale-[0.98] group shadow-sm"
>
<div className="flex items-center gap-3">
<div className="h-12 w-12 rounded-xl bg-amber-500/15 text-amber-400 flex items-center justify-center shrink-0">
<div className="h-12 w-12 rounded-xl bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-400 flex items-center justify-center shrink-0">
{getIconeProcesso(p.nome)}
</div>
<div>
<div className="text-base font-black text-slate-100 uppercase tracking-wide">
<div className="text-base font-black text-slate-900 dark:text-slate-100 uppercase tracking-wide">
{p.nome}
</div>
<div className="text-xs text-slate-400 font-medium">Toque para selecionar</div>
<div className="text-xs text-slate-500 dark:text-slate-400 font-medium">Toque para selecionar</div>
</div>
</div>
<ChevronRight className="h-6 w-6 text-slate-500 group-hover:text-amber-400" />
<ChevronRight className="h-6 w-6 text-slate-400 group-hover:text-amber-600 dark:text-slate-500 dark:group-hover:text-amber-400" />
</button>
))
) : (
@@ -376,20 +376,20 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
key={proc.id}
type="button"
onClick={() => handleEscolherProcesso(proc)}
className="min-h-[72px] p-4 rounded-2xl bg-slate-800/90 hover:bg-slate-750 active:bg-slate-700 border-2 border-slate-700 hover:border-amber-500/80 flex items-center justify-between text-left transition-all active:scale-[0.98] group shadow-sm"
className="min-h-[72px] p-4 rounded-2xl bg-white hover:bg-amber-50/60 active:bg-amber-100/60 dark:bg-slate-800/90 dark:hover:bg-slate-750 dark:active:bg-slate-700 border-2 border-slate-200 hover:border-amber-400/80 dark:border-slate-700 dark:hover:border-amber-500/80 flex items-center justify-between text-left transition-all active:scale-[0.98] group shadow-sm"
>
<div className="flex items-center gap-3">
<div className="h-12 w-12 rounded-xl bg-amber-500/15 text-amber-400 flex items-center justify-center shrink-0">
<div className="h-12 w-12 rounded-xl bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-400 flex items-center justify-center shrink-0">
{getIconeProcesso(proc.nome)}
</div>
<div>
<div className="text-base font-black text-slate-100 uppercase tracking-wide">
<div className="text-base font-black text-slate-900 dark:text-slate-100 uppercase tracking-wide">
{proc.nome}
</div>
<div className="text-xs text-slate-400 font-medium">Etapa #{proc.ordem}</div>
<div className="text-xs text-slate-500 dark:text-slate-400 font-medium">Etapa #{proc.ordem}</div>
</div>
</div>
<ChevronRight className="h-6 w-6 text-slate-500 group-hover:text-amber-400" />
<ChevronRight className="h-6 w-6 text-slate-400 group-hover:text-amber-600 dark:text-slate-500 dark:group-hover:text-amber-400" />
</button>
))
)}
@@ -402,7 +402,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
smartAudio.playClick();
onVoltarHub();
}}
className="w-full h-14 bg-slate-800 border-slate-700 text-slate-200 text-sm font-bold rounded-2xl mt-3 active:scale-98"
className="w-full h-14 bg-white hover:bg-slate-100 text-slate-800 border-slate-300 dark:bg-slate-800 dark:hover:bg-slate-750 dark:border-slate-700 dark:text-slate-200 text-sm font-bold rounded-2xl mt-3 active:scale-98 transition-colors"
>
Voltar ao Menu Principal
</Button>
@@ -417,10 +417,11 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
return (
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
{/* Breadcrumb de Processo */}
<div className="mb-4 flex items-center justify-between p-3 rounded-2xl bg-amber-500/15 border border-amber-500/30">
{/* Breadcrumb de Processo */}
<div className="mb-4 flex items-center justify-between p-3 rounded-2xl bg-amber-100 dark:bg-amber-500/15 border border-amber-300 dark:border-amber-500/30 shadow-sm">
<div className="flex items-center gap-2">
<span className="text-amber-400">{getIconeProcesso(processoSelecionado?.nome || '')}</span>
<span className="text-sm font-black text-amber-300 uppercase">
<span className="text-amber-800 dark:text-amber-400">{getIconeProcesso(processoSelecionado?.nome || '')}</span>
<span className="text-sm font-black text-amber-900 dark:text-amber-300 uppercase">
PROCESSO: {processoSelecionado?.nome}
</span>
</div>
@@ -430,17 +431,17 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
smartAudio.playClick();
setEtapaAtual('processo');
}}
className="text-xs font-bold text-amber-400 underline hover:text-amber-300 px-2 py-1"
className="text-xs font-bold text-amber-800 dark:text-amber-400 underline hover:text-amber-900 dark:hover:text-amber-300 px-2 py-1"
>
Trocar
</button>
</div>
<div className="mb-3 text-center">
<span className="text-xs font-black uppercase text-slate-400 tracking-wider">
<span className="text-xs font-black uppercase text-slate-500 dark:text-slate-400 tracking-wider">
ETAPA 1.2 — SUBCONJUNTO
</span>
<h2 className="text-xl font-black text-slate-100 uppercase mt-0.5">
<h2 className="text-xl font-black text-slate-900 dark:text-slate-100 uppercase mt-0.5">
Qual é a Fase das Peças?
</h2>
</div>
@@ -453,18 +454,18 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
key={fase}
type="button"
onClick={() => handleEscolherFase(fase)}
className="w-full min-h-[68px] p-4 rounded-2xl bg-slate-800/90 hover:bg-slate-750 active:bg-slate-700 border-2 border-slate-700 hover:border-amber-500/80 flex items-center justify-between text-left transition-all active:scale-[0.98] group shadow-sm"
className="w-full min-h-[68px] p-4 rounded-2xl bg-white hover:bg-amber-50/60 active:bg-amber-100/60 dark:bg-slate-800/90 dark:hover:bg-slate-750 dark:active:bg-slate-700 border-2 border-slate-200 hover:border-amber-400/80 dark:border-slate-700 dark:hover:border-amber-500/80 flex items-center justify-between text-left transition-all active:scale-[0.98] group shadow-sm"
>
<div className="flex items-center gap-3">
<div className="h-11 w-11 rounded-xl bg-slate-700 text-slate-200 flex items-center justify-center shrink-0">
<div className="h-11 w-11 rounded-xl bg-slate-100 text-slate-700 dark:bg-slate-700 dark:text-slate-200 flex items-center justify-center shrink-0">
<Layers className="h-5 w-5" />
</div>
<div>
<div className="text-base font-black text-slate-100 uppercase">{fase}</div>
<div className="text-xs text-slate-400">{countFase} peças cadastradas</div>
<div className="text-base font-black text-slate-900 dark:text-slate-100 uppercase">{fase}</div>
<div className="text-xs text-slate-500 dark:text-slate-400">{countFase} peças cadastradas</div>
</div>
</div>
<ChevronRight className="h-6 w-6 text-slate-500 group-hover:text-amber-400" />
<ChevronRight className="h-6 w-6 text-slate-400 group-hover:text-amber-600 dark:text-slate-500 dark:group-hover:text-amber-400" />
</button>
);
})}
@@ -477,7 +478,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
smartAudio.playClick();
setEtapaAtual('processo');
}}
className="w-full h-14 bg-slate-800 border-slate-700 text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98"
className="w-full h-14 bg-white hover:bg-slate-100 text-slate-800 border-slate-300 dark:bg-slate-800 dark:hover:bg-slate-750 dark:border-slate-700 dark:text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98 transition-colors"
>
⬅️ Voltar aos Processos
</Button>
@@ -492,7 +493,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
return (
<div className="flex flex-col flex-1 p-4 max-w-xl mx-auto w-full">
{/* Sticky Context: Breadcrumbs Interativos no Topo */}
<div className="mb-3 p-3 rounded-2xl bg-slate-800/95 border border-slate-700 flex items-center justify-between gap-2 shadow-md">
<div className="mb-3 p-3 rounded-2xl bg-white dark:bg-slate-800/95 border border-slate-200 dark:border-slate-700 flex items-center justify-between gap-2 shadow-sm">
<div className="flex items-center gap-2 min-w-0">
<button
type="button"
@@ -500,7 +501,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
smartAudio.playClick();
setEtapaAtual('processo');
}}
className="px-2.5 py-1 rounded-lg bg-amber-500/20 text-amber-300 font-bold text-xs flex items-center gap-1 border border-amber-500/30 hover:bg-amber-500/30 shrink-0"
className="px-2.5 py-1 rounded-lg bg-amber-100 text-amber-800 dark:bg-amber-500/20 dark:text-amber-300 font-bold text-xs flex items-center gap-1 border border-amber-300 dark:border-amber-500/30 hover:bg-amber-200 dark:hover:bg-amber-500/30 shrink-0 transition-colors"
title="Trocar Processo"
>
<span>⚡ {processoSelecionado?.nome}</span>
@@ -512,14 +513,14 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
smartAudio.playClick();
setEtapaAtual('fase');
}}
className="px-2.5 py-1 rounded-lg bg-blue-500/20 text-blue-300 font-bold text-xs flex items-center gap-1 border border-blue-500/30 hover:bg-blue-500/30 truncate"
className="px-2.5 py-1 rounded-lg bg-blue-100 text-blue-800 dark:bg-blue-500/20 dark:text-blue-300 font-bold text-xs flex items-center gap-1 border border-blue-200 dark:border-blue-500/30 hover:bg-blue-200 dark:hover:bg-blue-500/30 truncate transition-colors"
title="Trocar Fase"
>
<span>🏢 {faseSelecionada}</span>
</button>
</div>
<span className="text-[11px] font-bold text-slate-400 shrink-0">
<span className="text-[11px] font-bold text-slate-500 dark:text-slate-400 shrink-0">
{pecasComSaldo.length} itens
</span>
</div>
@@ -527,15 +528,15 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
{/* Lista de Peças */}
<div className="flex-1 overflow-y-auto space-y-3 pb-4">
{carregandoDados ? (
<div className="py-12 flex flex-col items-center justify-center text-slate-400 gap-2">
<div className="py-12 flex flex-col items-center justify-center text-slate-500 dark:text-slate-400 gap-2">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-amber-500 border-t-transparent" />
<span>Carregando peças...</span>
</div>
) : pecasComSaldo.length === 0 ? (
<div className="p-8 text-center bg-slate-800/40 rounded-2xl border border-slate-800">
<Filter className="h-10 w-10 text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-200">Nenhuma peça nesta fase</h3>
<p className="text-xs text-slate-400 mt-1">
<div className="p-8 text-center bg-white dark:bg-slate-800/40 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm">
<Filter className="h-10 w-10 text-slate-400 dark:text-slate-500 mx-auto mb-2" />
<h3 className="text-base font-bold text-slate-800 dark:text-slate-200">Nenhuma peça nesta fase</h3>
<p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
Selecione outra fase ou processo para apontar
</p>
</div>
@@ -547,53 +548,53 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
key={item.id}
className={`p-4 rounded-2xl border-2 transition-all shadow-sm ${
concluida
? 'bg-slate-900/60 border-slate-800 opacity-75'
: 'bg-slate-800/95 border-slate-700/90 hover:border-amber-500/80'
? 'bg-slate-50 dark:bg-slate-900/60 border-slate-200 dark:border-slate-800 opacity-75'
: 'bg-white dark:bg-slate-800/95 border-slate-200 dark:border-slate-700/90 hover:border-amber-400 dark:hover:border-amber-500/80'
}`}
>
<div className="flex items-start justify-between gap-2">
<div>
<div className="flex items-center gap-2">
<span className="text-xl font-black text-amber-400 tracking-wider">
<span className="text-xl font-black text-amber-700 dark:text-amber-400 tracking-wider">
{item.marca}
</span>
{item.tem_componentes === false && (
<span
className="text-[10px] px-2 py-0.5 rounded-md bg-purple-950/80 text-purple-300 font-bold border border-purple-800/50"
className="text-[10px] px-2 py-0.5 rounded-md bg-purple-100 text-purple-800 border border-purple-300 dark:bg-purple-950/80 dark:text-purple-300 dark:border-purple-800/50 font-black"
title="Peça Sem Montagem (Pula Solda e Montagem)"
>
S/M
</span>
)}
{item.perfil_principal && (
<span className="text-xs px-2 py-0.5 rounded-md bg-slate-700/80 text-slate-300 font-semibold">
<span className="text-xs px-2 py-0.5 rounded-md bg-slate-100 dark:bg-slate-700/80 text-slate-700 dark:text-slate-300 font-semibold border border-slate-200 dark:border-transparent">
{item.perfil_principal}
</span>
)}
</div>
<div className="text-xs text-slate-300 mt-0.5 line-clamp-1">
<div className="text-xs text-slate-600 dark:text-slate-300 mt-0.5 line-clamp-1">
{item.descricao || 'Peça Estrutural'}
</div>
{item.motivoBloqueio && item.saldo === 0 && !concluida && (
<div className="text-[11px] text-amber-400/90 font-medium mt-1 flex items-center gap-1">
<AlertTriangle className="h-3.5 w-3.5 shrink-0 text-amber-400" />
<div className="text-[11px] text-amber-700 dark:text-amber-400/90 font-medium mt-1 flex items-center gap-1">
<AlertTriangle className="h-3.5 w-3.5 shrink-0 text-amber-600 dark:text-amber-400" />
<span>{item.motivoBloqueio}</span>
</div>
)}
</div>
<div className="text-right shrink-0">
<div className="text-xs font-semibold text-slate-400">Total: {item.quantidade}</div>
<div className="text-xs font-semibold text-slate-500 dark:text-slate-400">Total: {item.quantidade}</div>
{concluida ? (
<span className="inline-flex items-center gap-1 text-xs font-black text-emerald-400 px-2 py-0.5 rounded-full bg-emerald-950/80 border border-emerald-700">
<span className="inline-flex items-center gap-1 text-xs font-black text-emerald-800 dark:text-emerald-400 px-2 py-0.5 rounded-full bg-emerald-100 dark:bg-emerald-950/80 border border-emerald-300 dark:border-emerald-700">
<Check className="h-3 w-3" /> 100% Pronto
</span>
) : item.saldo > 0 ? (
<span className="inline-flex items-center gap-1 text-xs font-black text-amber-300 px-2 py-0.5 rounded-full bg-amber-950/80 border border-amber-700">
<span className="inline-flex items-center gap-1 text-xs font-black text-amber-800 dark:text-amber-300 px-2 py-0.5 rounded-full bg-amber-100 dark:bg-amber-950/80 border border-amber-300 dark:border-amber-700">
Disponível: {item.saldo}
</span>
) : (
<span className="inline-flex items-center gap-1 text-[11px] font-bold text-slate-400 px-2 py-0.5 rounded-full bg-slate-800 border border-slate-700">
<span className="inline-flex items-center gap-1 text-[11px] font-bold text-slate-600 dark:text-slate-400 px-2 py-0.5 rounded-full bg-slate-100 dark:bg-slate-800 border border-slate-300 dark:border-slate-700">
Pendente ant.
</span>
)}
@@ -601,7 +602,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
</div>
{/* Barra de Progresso Visual da Peça */}
<div className="w-full bg-slate-700/60 h-2 rounded-full mt-3 overflow-hidden">
<div className="w-full bg-slate-200 dark:bg-slate-700/60 h-2 rounded-full mt-3 overflow-hidden">
<div
className={`h-full transition-all duration-300 ${
concluida ? 'bg-emerald-500' : 'bg-amber-500'
@@ -620,10 +621,10 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
onClick={() => handleIniciarApontamentoPeca(item, item.saldo)}
className={`sm:col-span-2 h-13 text-sm font-black rounded-xl uppercase tracking-wider transition-all active:scale-[0.98] ${
concluida
? 'bg-slate-800 text-slate-500 border border-slate-700'
? 'bg-slate-100 text-slate-400 border border-slate-200 dark:bg-slate-800 dark:text-slate-500 dark:border-slate-700'
: item.saldo <= 0
? 'bg-slate-800 text-slate-400 border border-slate-700 cursor-not-allowed'
: 'bg-amber-500 hover:bg-amber-400 active:bg-amber-600 text-slate-950 shadow-md shadow-amber-950/30'
? 'bg-slate-100 text-slate-400 border border-slate-200 dark:bg-slate-800 dark:text-slate-400 dark:border-slate-700 cursor-not-allowed'
: 'bg-amber-500 hover:bg-amber-400 active:bg-amber-600 text-slate-950 shadow-md shadow-amber-900/20 dark:shadow-amber-950/30'
}`}
>
{concluida
@@ -642,7 +643,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
setQtdApontar(item.saldo);
setEtapaAtual('quantidade');
}}
className="h-13 bg-slate-700 hover:bg-slate-650 active:bg-slate-600 text-amber-400 border border-slate-600 text-xs font-black rounded-xl uppercase active:scale-95"
className="h-13 bg-amber-50 hover:bg-amber-100 active:bg-amber-200 text-amber-800 border border-amber-300 dark:bg-slate-700 dark:hover:bg-slate-650 dark:active:bg-slate-600 dark:text-amber-400 dark:border-slate-600 text-xs font-black rounded-xl uppercase active:scale-95 transition-colors"
title="Apontar todo o saldo disponível de uma vez"
>
TODAS ({item.saldo})
@@ -662,7 +663,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
smartAudio.playClick();
setEtapaAtual('fase');
}}
className="w-full h-14 bg-slate-800 border-slate-700 text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98"
className="w-full h-14 bg-white hover:bg-slate-100 text-slate-800 border-slate-300 dark:bg-slate-800 dark:hover:bg-slate-750 dark:border-slate-700 dark:text-slate-200 text-sm font-bold rounded-2xl mt-2 active:scale-98 transition-colors"
>
⬅️ Voltar às Fases
</Button>
@@ -746,31 +747,31 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
return (
<div className="flex flex-col flex-1 p-3.5 max-w-md mx-auto w-full pb-6">
{/* Resumo da Peça no Topo */}
<div className="p-3.5 rounded-2xl bg-slate-800/90 border border-slate-700 mb-3 shadow-sm">
<div className="p-3.5 rounded-2xl bg-white dark:bg-slate-800/90 border border-slate-200 dark:border-slate-700 mb-3 shadow-sm">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<span className="text-xl font-black text-amber-400">
<span className="text-xl font-black text-amber-700 dark:text-amber-400">
{pecaSelecionada.marca}
</span>
{pecaSelecionada.tem_componentes === false && (
<span
className="text-[10px] px-2 py-0.5 rounded-md bg-purple-950/80 text-purple-300 font-bold border border-purple-800/50"
className="text-[10px] px-2 py-0.5 rounded-md bg-purple-100 text-purple-800 border border-purple-300 dark:bg-purple-950/80 dark:text-purple-300 dark:border-purple-800/50 font-black"
title="Peça Sem Montagem (Pula Solda e Montagem)"
>
S/M
</span>
)}
</div>
<span className="text-xs font-black px-2.5 py-0.5 rounded-lg bg-amber-500/20 text-amber-300 border border-amber-500/30 uppercase">
<span className="text-xs font-black px-2.5 py-0.5 rounded-lg bg-amber-100 dark:bg-amber-500/20 text-amber-800 dark:text-amber-300 border border-amber-300 dark:border-amber-500/30 uppercase">
{processoSelecionado.nome}
</span>
</div>
<div className="text-xs font-semibold text-slate-200 mt-0.5 truncate">
<div className="text-xs font-semibold text-slate-600 dark:text-slate-200 mt-0.5 truncate">
{pecaSelecionada.descricao || 'Peça Estrutural'}
</div>
<div className="flex items-center justify-between text-xs text-slate-400 mt-2 pt-2 border-t border-slate-700/80">
<div className="flex items-center justify-between text-xs text-slate-500 dark:text-slate-400 mt-2 pt-2 border-t border-slate-200 dark:border-slate-700/80">
<span>Total da Peça: {pecaSelecionada.quantidade} un</span>
<span className="text-amber-400 font-bold">
<span className="text-amber-700 dark:text-amber-400 font-bold">
Saldo Pendente: {saldoPendente} un
</span>
</div>
@@ -778,7 +779,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
{/* Visor / Input Central da Quantidade com botões finos -1 e +1 */}
<div className="mb-2 text-center">
<span className="text-[11px] font-black uppercase text-slate-400 tracking-wider">
<span className="text-[11px] font-black uppercase text-slate-500 dark:text-slate-400 tracking-wider">
Digite ou Escolha a Quantidade a Apontar
</span>
@@ -787,14 +788,14 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
type="button"
onClick={() => somarQtd(-1)}
disabled={qtdApontar <= 1}
className="h-16 w-14 rounded-2xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border-2 border-slate-700 disabled:opacity-40 text-white flex items-center justify-center font-black active:scale-95 shadow-sm"
className="h-16 w-14 rounded-2xl bg-white hover:bg-slate-100 active:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-750 dark:active:bg-slate-700 border-2 border-slate-200 dark:border-slate-700 disabled:opacity-40 text-slate-800 dark:text-white flex items-center justify-center font-black active:scale-95 shadow-sm transition-colors"
title="Diminuir 1"
>
<Minus className="h-6 w-6" />
</button>
{/* Input Numérico Editável Direto (Toque para digitar ou use o teclado da tela) */}
<div className="flex-1 max-w-[180px] h-16 rounded-2xl bg-slate-900 border-2 border-amber-500 flex items-center justify-center shadow-inner relative">
<div className="flex-1 max-w-[180px] h-16 rounded-2xl bg-slate-50 dark:bg-slate-900 border-2 border-amber-500 flex items-center justify-center shadow-inner relative">
<input
type="text"
inputMode="numeric"
@@ -802,7 +803,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
value={qtdApontar === 0 ? '' : qtdApontar}
placeholder="0"
onChange={handleInputChange}
className="w-full text-center bg-transparent border-none outline-none text-3xl sm:text-4xl font-black text-amber-400 tracking-tight placeholder:text-slate-700"
className="w-full text-center bg-transparent border-none outline-none text-3xl sm:text-4xl font-black text-amber-700 dark:text-amber-400 tracking-tight placeholder:text-slate-400 dark:placeholder:text-slate-700"
/>
</div>
@@ -810,7 +811,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
type="button"
onClick={() => somarQtd(1)}
disabled={saldoPendente > 0 && qtdApontar >= saldoPendente}
className="h-16 w-14 rounded-2xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border-2 border-slate-700 disabled:opacity-40 text-white flex items-center justify-center font-black active:scale-95 shadow-sm"
className="h-16 w-14 rounded-2xl bg-white hover:bg-slate-100 active:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-750 dark:active:bg-slate-700 border-2 border-slate-200 dark:border-slate-700 disabled:opacity-40 text-slate-800 dark:text-white flex items-center justify-center font-black active:scale-95 shadow-sm transition-colors"
title="Aumentar 1"
>
<Plus className="h-6 w-6" />
@@ -823,41 +824,41 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
<button
type="button"
onClick={() => somarQtd(5)}
className="h-11 rounded-xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border border-slate-700 text-slate-200 text-xs font-bold active:scale-95"
className="h-11 rounded-xl bg-white hover:bg-slate-100 active:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-750 dark:active:bg-slate-700 border border-slate-200 dark:border-slate-700 text-slate-800 dark:text-slate-200 text-xs font-bold active:scale-95 shadow-sm transition-colors"
>
+5
</button>
<button
type="button"
onClick={() => somarQtd(10)}
className="h-11 rounded-xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border border-slate-700 text-slate-200 text-xs font-bold active:scale-95"
className="h-11 rounded-xl bg-white hover:bg-slate-100 active:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-750 dark:active:bg-slate-700 border border-slate-200 dark:border-slate-700 text-slate-800 dark:text-slate-200 text-xs font-bold active:scale-95 shadow-sm transition-colors"
>
+10
</button>
<button
type="button"
onClick={() => somarQtd(25)}
className="h-11 rounded-xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border border-slate-700 text-slate-200 text-xs font-bold active:scale-95"
className="h-11 rounded-xl bg-white hover:bg-slate-100 active:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-750 dark:active:bg-slate-700 border border-slate-200 dark:border-slate-700 text-slate-800 dark:text-slate-200 text-xs font-bold active:scale-95 shadow-sm transition-colors"
>
+25
</button>
<button
type="button"
onClick={definirTodas}
className="h-11 rounded-xl bg-amber-500/20 hover:bg-amber-500/30 border border-amber-500/50 text-amber-300 text-xs font-black active:scale-95"
className="h-11 rounded-xl bg-amber-100 hover:bg-amber-200 active:bg-amber-300 border border-amber-300 text-amber-800 dark:bg-amber-500/20 dark:hover:bg-amber-500/30 dark:border-amber-500/50 dark:text-amber-300 text-xs font-black active:scale-95 transition-colors"
>
TODAS ({saldoPendente})
</button>
</div>
{/* Teclado Numérico Touch de Chão de Fábrica (0 a 9, C, ⌫) */}
<div className="grid grid-cols-3 gap-2 mb-3 bg-slate-900/80 p-2.5 rounded-2xl border border-slate-800 shadow-inner">
<div className="grid grid-cols-3 gap-2 mb-3 bg-slate-100 dark:bg-slate-900/80 p-2.5 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-inner">
{[1, 2, 3, 4, 5, 6, 7, 8, 9].map((num) => (
<button
key={num}
type="button"
onClick={() => handleDigitoTeclado(num)}
className="h-13 rounded-xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border border-slate-700/80 text-white text-xl font-black active:scale-95 shadow-sm transition-all"
className="h-13 rounded-xl bg-white hover:bg-slate-50 active:bg-slate-100 dark:bg-slate-800 dark:hover:bg-slate-750 dark:active:bg-slate-700 border border-slate-200 dark:border-slate-700/80 text-slate-900 dark:text-white text-xl font-black active:scale-95 shadow-sm transition-all"
>
{num}
</button>
@@ -865,7 +866,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
<button
type="button"
onClick={handleLimpar}
className="h-13 rounded-xl bg-red-950/40 hover:bg-red-900/60 active:bg-red-900 border border-red-800/50 text-red-300 text-sm font-black active:scale-95 uppercase tracking-wider"
className="h-13 rounded-xl bg-rose-100 hover:bg-rose-200 active:bg-rose-300 border border-rose-300 text-rose-800 dark:bg-red-950/40 dark:hover:bg-red-900/60 dark:active:bg-red-900 dark:border-red-800/50 dark:text-red-300 text-sm font-black active:scale-95 uppercase tracking-wider transition-colors"
title="Limpar valor"
>
Limpar
@@ -873,14 +874,14 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
<button
type="button"
onClick={() => handleDigitoTeclado(0)}
className="h-13 rounded-xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border border-slate-700/80 text-white text-xl font-black active:scale-95 shadow-sm"
className="h-13 rounded-xl bg-white hover:bg-slate-50 active:bg-slate-100 dark:bg-slate-800 dark:hover:bg-slate-750 dark:active:bg-slate-700 border border-slate-200 dark:border-slate-700/80 text-slate-900 dark:text-white text-xl font-black active:scale-95 shadow-sm transition-all"
>
0
</button>
<button
type="button"
onClick={handleBackspace}
className="h-13 rounded-xl bg-slate-800 hover:bg-slate-750 active:bg-slate-700 border border-slate-700/80 text-amber-400 flex items-center justify-center active:scale-95"
className="h-13 rounded-xl bg-amber-100 hover:bg-amber-200 active:bg-amber-300 border border-amber-300 text-amber-800 dark:bg-slate-800 dark:hover:bg-slate-750 dark:active:bg-slate-700 dark:border-slate-700/80 dark:text-amber-400 flex items-center justify-center active:scale-95 transition-colors"
title="Apagar último dígito"
>
<Delete className="h-5 w-5" />
@@ -893,7 +894,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
type="button"
disabled={salvando || qtdApontar <= 0}
onClick={handleConfirmarApontamento}
className="w-full h-15 bg-emerald-600 hover:bg-emerald-500 active:bg-emerald-700 text-white text-base font-black rounded-2xl shadow-lg shadow-emerald-950/40 uppercase tracking-wide active:scale-98 gap-2"
className="w-full h-15 bg-emerald-600 hover:bg-emerald-500 active:bg-emerald-700 text-white text-base font-black rounded-2xl shadow-lg shadow-emerald-950/20 dark:shadow-emerald-950/40 uppercase tracking-wide active:scale-98 gap-2"
>
{salvando ? (
<>
@@ -916,7 +917,7 @@ export const SmartProducaoFlow: React.FC<SmartProducaoFlowProps> = ({
smartAudio.playClick();
setEtapaAtual('pecas');
}}
className="w-full h-11 bg-slate-800 border-slate-700 text-slate-300 text-xs font-bold rounded-xl active:scale-98"
className="w-full h-11 bg-white hover:bg-slate-100 text-slate-700 border-slate-300 dark:bg-slate-800 dark:border-slate-700 dark:text-slate-300 text-xs font-bold rounded-xl active:scale-98 transition-colors"
>
Cancelar e Voltar à Lista
</Button>