Files
GPI/src/client/components/forms/PaintingInspectionForm.tsx

226 lines
12 KiB
TypeScript

import React from 'react';
import { AdhesionGradeSelect } from '../AdhesionGradeSelect';
import { Input } from '../Input';
import { Select } from '../Select';
import { Droplets, Thermometer, Sun } from 'lucide-react';
interface PaintingFormData {
epsPoints: string[];
adhesionTest: string;
batch?: string;
treatmentExecutor?: string;
stockItemId?: string;
temperature?: string;
relativeHumidity?: string;
period?: string;
partTemperature?: string;
treatmentType?: string;
roughnessReadings?: string[];
}
interface PaintingInspectionFormProps {
formData: PaintingFormData;
handleChange: (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => void;
handleEpsChange: (index: number, value: string) => void;
numericPoints: number[];
stockItems?: any[]; // Using any because StockItem might need to be imported or loosely typed here
handleRoughnessChange: (index: number, value: string) => void;
}
export const PaintingInspectionForm: React.FC<PaintingInspectionFormProps> = ({
formData,
handleChange,
handleEpsChange,
numericPoints,
stockItems = [],
handleRoughnessChange
}) => {
const minEps = numericPoints.length > 0 ? Math.min(...numericPoints) : 0;
const maxEps = numericPoints.length > 0 ? Math.max(...numericPoints) : 0;
const avgEps = numericPoints.length > 0 ? numericPoints.reduce((a, b) => a + b, 0) / numericPoints.length : 0;
return (
<div className="space-y-6 animate-in fade-in slide-in-from-left-4 duration-500">
{/* Batch and Executor Section */}
<div className="space-y-4">
<div className="space-y-1">
<label className="text-[10px] font-bold text-text-muted uppercase tracking-wider ml-1">Tinta Utilizada</label>
<select
name="stockItemId"
value={formData.stockItemId || ''}
onChange={handleChange}
className="w-full p-3 bg-surface border border-border/40 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary outline-none transition-all font-medium appearance-none"
>
<option value="">Selecione a tinta...</option>
{stockItems.map((item: any) => (
<option key={item.id || item._id} value={item.id || item._id}>
{item.dataSheetId?.name || 'Item sem nome'} - Lote: {item.batchNumber}
</option>
))}
</select>
</div>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="space-y-1">
<label className="text-[10px] font-bold text-text-muted uppercase tracking-wider ml-1">Lote / Referência</label>
<input
type="text"
name="batch"
value={formData.batch || ''}
onChange={handleChange}
className="w-full p-3 bg-surface border border-border/40 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary outline-none transition-all font-medium"
placeholder="Ex: Lote 123"
/>
</div>
<div className="space-y-1">
<label className="text-[10px] font-bold text-text-muted uppercase tracking-wider ml-1">Executante</label>
<input
type="text"
name="treatmentExecutor"
value={formData.treatmentExecutor || ''}
onChange={handleChange}
className="w-full p-3 bg-surface border border-border/40 rounded-xl focus:ring-2 focus:ring-primary/20 focus:border-primary outline-none transition-all font-medium"
placeholder="Nome do pintor/equipe"
/>
</div>
</div>
<div className="border border-border/30 rounded-2xl p-4 bg-amber-50/40 shadow-sm relative overflow-hidden group">
<div className="absolute top-0 left-0 w-1 h-full bg-primary opacity-60"></div>
<label className="text-[10px] font-black text-primary uppercase tracking-[0.2em] block mb-4">Medições de EPS (µm) Mínimo 10</label>
<div className="grid grid-cols-4 sm:grid-cols-5 gap-2">
{formData.epsPoints.map((point: string, index: number) => (
<div key={index} className="flex flex-col">
<span className="text-[10px] text-text-muted mb-0.5 ml-1">{index + 1}</span>
<input
type="number"
step="1"
className="w-full p-1.5 text-xs rounded border border-border bg-[var(--input-bg)] text-[var(--input-text)] focus:ring-1 focus:ring-primary outline-none transition-all"
value={point}
onChange={(e) => handleEpsChange(index, e.target.value)}
placeholder="µm"
/>
</div>
))}
</div>
<div className="mt-6 grid grid-cols-3 gap-3 pt-4 border-t border-amber-200/20">
<div className="flex flex-col bg-white p-3 rounded-xl border border-amber-100 shadow-sm transition-transform hover:scale-[1.02]">
<span className="text-[9px] uppercase font-black text-primary tracking-widest">Mínimo</span>
<span className="text-base font-black text-stone-900">{minEps.toFixed(0)} <small className="text-[10px] text-stone-400 font-medium">µm</small></span>
</div>
<div className="flex flex-col bg-white p-3 rounded-xl border border-amber-100 shadow-sm transition-transform hover:scale-[1.02]">
<span className="text-[9px] uppercase font-black text-primary tracking-widest">Máximo</span>
<span className="text-base font-black text-stone-900">{maxEps.toFixed(0)} <small className="text-[10px] text-stone-400 font-medium">µm</small></span>
</div>
<div className="flex flex-col bg-white p-3 rounded-xl border border-primary/30 shadow-sm transition-transform hover:scale-[1.02] bg-gradient-to-br from-white to-amber-50/50">
<span className="text-[9px] uppercase font-black text-primary tracking-widest">Média Geral</span>
<span className="text-base font-black text-primary">{avgEps.toFixed(1)} <small className="text-[10px] opacity-70 font-medium">µm</small></span>
</div>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 border-t border-border/10 pt-4">
<Select
name="treatmentType"
label="Tipo de Tratamento / Jato"
value={formData.treatmentType || ''}
onChange={handleChange}
options={[
{ label: '-- Selecione --', value: '' },
{ label: 'Jateamento Abrasivo Seco', value: 'dry_abrasive_blasting' },
{ label: 'Hidrojateamento', value: 'water_jetting' },
{ label: 'Limpeza Mecânica (St2/St3)', value: 'mechanical_cleaning' },
{ label: 'Outro', value: 'other' }
]}
/>
<div className="space-y-1">
<label className="text-[10px] font-bold text-text-muted uppercase tracking-wider ml-1">Rugosidade Média (Opcional)</label>
<div className="flex gap-2">
{[0, 1, 2].map((i) => (
<input
key={i}
type="number"
className="w-full p-2 text-xs border border-border/40 rounded-lg bg-surface text-center font-bold"
placeholder={`R${i + 1}`}
value={formData.roughnessReadings?.[i] || ''}
onChange={(e) => handleRoughnessChange(i, e.target.value)}
/>
))}
</div>
</div>
</div>
{/* Environmental Conditions */}
<div className="bg-surface-soft border border-border/40 rounded-xl p-4">
<span className="text-[10px] font-bold text-primary uppercase tracking-[0.15em] block mb-3">Condições Ambientais</span>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="relative">
<Thermometer className="absolute left-3 top-1/2 -translate-y-1/2 text-text-muted w-4 h-4" />
<Input
name="temperature"
label="Temperatura (°C)"
type="number"
value={formData.temperature || ''}
onChange={handleChange}
className="pl-10"
/>
</div>
<div className="relative">
<Droplets className="absolute left-3 top-1/2 -translate-y-1/2 text-text-muted w-4 h-4" />
<Input
name="relativeHumidity"
label="Umidade Relativa (%)"
type="number"
value={formData.relativeHumidity || ''}
onChange={handleChange}
className="pl-10"
/>
</div>
<div className="relative">
<Sun className="absolute left-3 top-1/2 -translate-y-1/2 text-text-muted w-4 h-4" />
<Select
name="period"
label="Período"
value={formData.period || ''}
onChange={handleChange}
options={[
{ label: 'Manhã', value: 'morning' },
{ label: 'Tarde', value: 'afternoon' },
{ label: 'Noite', value: 'night' }
]}
className="pl-10"
/>
</div>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 border-t border-border/10 pt-4">
<div className="relative">
<Thermometer className="absolute left-3 top-1/2 -translate-y-1/2 text-primary/60 w-4 h-4" />
<Input
name="partTemperature"
label="Temperatura das Peças (°C)"
type="number"
value={formData.partTemperature || ''}
onChange={handleChange}
className="pl-10 border-primary/20 bg-primary/5 focus:border-primary"
placeholder="Ex: 25.5"
/>
</div>
<AdhesionGradeSelect
name="adhesionTest"
label="Teste de Aderência"
value={formData.adhesionTest || ''}
onChange={handleChange}
/>
</div>
{numericPoints.length < 10 && numericPoints.length > 0 && (
<p className="text-[10px] text-error text-right italic font-medium">Preencha ao menos 10 medições para registrar.</p>
)}
</div>
);
};