import React, { useEffect, useState, useMemo } from 'react'; import { useStatus } from '../hooks/useStatus'; import { useVehicles } from '../hooks/useVehicles'; import { useDrivers } from '../hooks/useDrivers'; import { useFleetLists } from '../hooks/useFleetLists'; import AutocompleteInput from '../components/AutocompleteInput'; import ExcelTable from '../components/ExcelTable'; import { Plus, Search } from 'lucide-react'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog"; // Reusing styled components locally const DarkInput = ({ label, ...props }) => (
{label && }
); const DarkSelect = ({ label, options, value, onChange }) => (
{label && }
); const DarkButton = ({ children, variant = 'primary', className = '', ...props }) => { const baseClass = "px-4 py-2 rounded-lg font-bold text-sm transition-all shadow-lg active:scale-95 flex items-center justify-center gap-2"; const variants = { primary: "bg-orange-600 hover:bg-orange-500 text-white shadow-orange-500/10", secondary: "bg-slate-100 dark:bg-[#2a2a2a] hover:bg-slate-200 dark:hover:bg-[#333] text-slate-700 dark:text-slate-200 border border-slate-200 dark:border-[#333]", ghost: "bg-transparent hover:bg-slate-100 dark:hover:bg-[#2a2a2a] text-slate-500 dark:text-slate-400 hover:text-slate-700 dark:hover:text-white" }; return ( ); }; // --- Inline Status Editor --- const StatusCell = ({ currentStatus, id, options, onUpdate }) => { const [isEditing, setIsEditing] = useState(false); const [tempValue, setTempValue] = useState(currentStatus); useEffect(() => { setTempValue(currentStatus); }, [currentStatus]); const handleBlur = () => { setIsEditing(false); if (tempValue !== currentStatus) { onUpdate(id, tempValue); } }; const handleChange = (e) => { setTempValue(e.target.value); }; if (isEditing) { return ( ); } return (
{ e.stopPropagation(); setIsEditing(true); }} className={`inline-flex items-center px-2 py-0.5 rounded text-[9px] font-bold uppercase tracking-wider border cursor-pointer hover:opacity-80 transition-opacity ${ currentStatus === 'Disponível' ? 'bg-orange-500/10 text-orange-500 border-orange-500/20' : currentStatus === 'Em Manutenção' ? 'bg-amber-500/10 text-amber-500 border-amber-500/20' : 'bg-slate-500/10 text-slate-500 border-slate-500/20' }`} > {currentStatus || 'N/A'}
); }; export default function StatusView() { const { statusList, loading, fetchStatus, createStatus, updateStatus, updateStatusInline, updateStatusBatch, deleteStatus } = useStatus(); const { fetchListsConfig, statusFrotaOptions } = useFleetLists(); const [searchTerm, setSearchTerm] = useState(''); const [isModalOpen, setIsModalOpen] = useState(false); const [editingItem, setEditingItem] = useState(null); const initialFormState = { atuacao: '', base: '', categoria: '', id_rota: '', idstatus_frota: '', manutencao: '', modelo: '', motorista: '', obs: '', placa: '', placa_reserva: '', proprietario: '', status_frota: 'Disponível', tipo_placa: '', uf: '', vecfleet: '' }; const [formData, setFormData] = useState(initialFormState); const { vehicles, fetchVehicles } = useVehicles(); const { drivers, fetchDrivers } = useDrivers(); useEffect(() => { fetchStatus(); fetchVehicles(); fetchDrivers(); fetchListsConfig(); }, []); const handleVehicleSelect = (vehicle) => { if (!vehicle) return; setFormData(prev => ({ ...prev, placa: vehicle.placa || prev.placa, placa_reserva: vehicle.placa_reserva || prev.placa_reserva, modelo: vehicle.modelo || vehicle.mod_veiculo || prev.modelo, categoria: vehicle.categoria || vehicle.cat_veiculo || prev.categoria, tipo_placa: vehicle.tipo_placa || prev.tipo_placa, base: vehicle.base || prev.base, uf: vehicle.uf || prev.uf, proprietario: vehicle.proprietario || prev.proprietario, atuacao: vehicle.atuacao || prev.atuacao, vecfleet: vehicle.vecfleet || prev.vecfleet, })); }; const handleOpenModal = (item = null) => { if (item) { setEditingItem(item); setFormData({ ...initialFormState, ...item }); } else { setEditingItem(null); setFormData(initialFormState); } setIsModalOpen(true); }; const handleSubmit = async (e) => { e.preventDefault(); let success; if (editingItem) { success = await updateStatus(editingItem.idstatus_frota, formData); } else { success = await createStatus(formData); } if (success) setIsModalOpen(false); }; const [selectedIds, setSelectedIds] = useState([]); // ... (effects) const handleStatusUpdate = async (id, newStatus) => { // Verificação robusta com conversão para String para evitar incompatibilidade de tipos const isSelected = selectedIds.some(sid => String(sid) === String(id)); if (isSelected && selectedIds.length > 1) { // Confirmação simples para evitar acidentes apenas se houver mais de um item selecionado const confirmUpdate = window.confirm(`Você selecionou ${selectedIds.length} itens. Deseja atualizar o status de TODOS eles para "${newStatus}"?`); if (confirmUpdate) { const success = await updateStatusBatch(selectedIds, newStatus); if (success) { setSelectedIds([]); // Limpa a seleção após atualizar com sucesso } } } else { // Agora o Single Update também utiliza o endpoint em lote await updateStatusBatch([id], newStatus); } }; const filteredData = useMemo(() => Array.isArray(statusList) ? statusList.filter(item => item.placa?.toLowerCase().includes(searchTerm.toLowerCase()) || item.motorista?.toLowerCase().includes(searchTerm.toLowerCase()) ) : [], [statusList, searchTerm]); return (
{/* ... Header ... */}

Status da Frota

Histórico de movimentação e estados dos veículos.

{/* ... Search ... */}
setSearchTerm(e.target.value)} />
handleOpenModal()}> Nova Alteração Status
( )}, { header: 'MOTORISTA', field: 'motorista', width: '150px' }, { header: 'PLACA RESERVA', field: 'placa_reserva', width: '110px' }, { header: 'MODELO', field: 'modelo', width: '120px' }, { header: 'CATEGORIA', field: 'categoria', width: '100px' }, { header: 'TIPO PLACA', field: 'tipo_placa', width: '100px' }, { header: 'BASE', field: 'base', width: '100px' }, { header: 'UF', field: 'uf', width: '60px' }, { header: 'PROPRIETÁRIO', field: 'proprietario', width: '140px' }, { header: 'ATUAÇÃO', field: 'atuacao', width: '140px' }, { header: 'MANUTENÇÃO', field: 'manutencao', width: '150px' }, { header: 'ID ROTA', field: 'id_rota', width: '100px' }, { header: 'VECFLEET', field: 'vecfleet', width: '100px' }, { header: 'OBS', field: 'obs', width: '200px' }, ]} filterDefs={[ { field: 'placa', label: 'Placa', type: 'text', placeholder: 'Buscar placa...' }, { field: 'base', label: 'Base', type: 'select' }, { field: 'status_frota', label: 'Status', type: 'select' }, ]} onEdit={handleOpenModal} onDelete={(item) => deleteStatus(item.idstatus_frota)} />
{editingItem ? 'Editar Registro de Status' : 'Nova Alteração de Status'} Atualize o estado atual do veículo na frota.
setFormData({...formData, placa: v})} options={vehicles} displayKey="placa" valueKey="placa" searchKeys={['placa']} onSelect={handleVehicleSelect} required /> setFormData({...formData, placa_reserva: e.target.value})} /> setFormData({...formData, status_frota: v})} />
setFormData({...formData, motorista: v})} options={drivers} displayKey="NOME_FAVORECIDO" valueKey="NOME_FAVORECIDO" placeholder="Buscar motorista..." /> setFormData({...formData, base: e.target.value})} /> setFormData({...formData, id_rota: e.target.value})} />
setFormData({...formData, tipo_placa: e.target.value})} /> setFormData({...formData, categoria: e.target.value})} /> setFormData({...formData, modelo: e.target.value})} /> setFormData({...formData, uf: e.target.value})} />
setFormData({...formData, proprietario: e.target.value})} /> setFormData({...formData, atuacao: e.target.value})} /> setFormData({...formData, vecfleet: e.target.value})} />
setFormData({...formData, manutencao: e.target.value})} />