import { motion, AnimatePresence } from 'framer-motion'; import { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { Building2, Users, Phone, Plus, Search, Filter, MapPin, Calendar, User, Mail, MoreVertical, Eye, Edit3, Trash2, Settings, Wrench } from 'lucide-react'; import { ThemeToggle } from '../components/ThemeToggle'; import { supabase } from '../lib/supabase'; interface Obra { id: string; nome: string; endereco: string; cliente: string; responsavel: string; data_inicio: string; data_previsao: string; status: 'planejamento' | 'em_andamento' | 'pausada' | 'concluida'; progresso: number; orcamento: number; } interface Usuario { id: string; nome: string; email: string; telefone: string; funcao: string; empresa: string; status: 'ativo' | 'inativo'; data_cadastro: string; ultimo_acesso: string; } interface Equipamento { id: string; nome: string; tipo: string; modelo: string; fabricante: string; ano_fabricacao: number; numero_serie: string; status: 'disponivel' | 'em_uso' | 'manutencao' | 'inativo'; obra_atual?: string; proximo_manutencao: string; } type TabType = 'obras' | 'usuarios' | 'equipamentos'; const statusConfig = { obras: { planejamento: { label: 'Planejamento', color: 'bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300' }, em_andamento: { label: 'Em Andamento', color: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300' }, pausada: { label: 'Pausada', color: 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-300' }, concluida: { label: 'Concluída', color: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300' } }, usuarios: { ativo: { label: 'Ativo', color: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300' }, inativo: { label: 'Inativo', color: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300' } }, equipamentos: { disponivel: { label: 'Disponível', color: 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300' }, em_uso: { label: 'Em Uso', color: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-300' }, manutencao: { label: 'Manutenção', color: 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-300' }, inativo: { label: 'Inativo', color: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300' } } }; export default function Cadastros() { const [activeTab, setActiveTab] = useState('obras'); const [searchTerm, setSearchTerm] = useState(''); const [showFilters, setShowFilters] = useState(false); const [selectedItem, setSelectedItem] = useState(null); const [obras, setObras] = useState([]); const [usuarios, setUsuarios] = useState([]); const [equipamentos, setEquipamentos] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { fetchData(); }, []); const fetchData = async () => { setIsLoading(true); try { // Fetch Obras const { data: obrasData, error: obrasError } = await (supabase .from('obras') as any) .select(` *, responsavel:usuarios(nome) `) .order('created_at', { ascending: false }); if (obrasError) console.error('Erro ao buscar obras:', obrasError); else { const mappedObras: Obra[] = obrasData?.map(o => ({ id: o.id, nome: o.nome, endereco: o.endereco || '', cliente: o.cliente || '', responsavel: o.responsavel?.nome || 'Não definido', data_inicio: o.data_inicio || '', data_previsao: o.data_prevista_fim || '', status: (o.status as any) || 'planejamento', progresso: Number(o.progresso_geral) || 0, orcamento: Number(o.valor_contrato) || 0 })) || []; setObras(mappedObras); } // Fetch Usuarios const { data: usuariosData, error: usuariosError } = await (supabase .from('usuarios') as any) .select('*') .order('created_at', { ascending: false }); if (usuariosError) console.error('Erro ao buscar usuários:', usuariosError); else { const mappedUsuarios: Usuario[] = usuariosData?.map(u => ({ id: u.id, nome: u.nome, email: u.email, telefone: u.telefone || '', funcao: u.cargo || 'Usuário', empresa: 'Baldon Engemetal', // Default since it is linked to org status: u.ativo ? 'ativo' : 'inativo', data_cadastro: u.created_at, ultimo_acesso: u.updated_at // Proxy })) || []; setUsuarios(mappedUsuarios); } // Fetch Equipamentos (Inventário) const { data: equipData, error: equipError } = await supabase .from('inventario_equipamentos' as any) .select(` *, obra_atual:obras(nome) `) .order('created_at', { ascending: false }); if (equipError) { console.warn('Erro ao buscar equipamentos:', equipError); } else { const mappedEquip: Equipamento[] = equipData?.map((e: any) => ({ id: e.id, nome: e.nome, tipo: e.tipo || '', modelo: e.modelo || '', fabricante: e.fabricante || '', ano_fabricacao: e.ano_fabricacao || 0, numero_serie: e.numero_serie || '', status: e.status || 'disponivel', obra_atual: e.obra_atual?.nome, proximo_manutencao: e.proxima_manutencao || '' })) || []; setEquipamentos(mappedEquip); } } catch (error) { console.error('Erro geral ao buscar dados:', error); } finally { setIsLoading(false); } }; const tabs = [ { id: 'obras' as TabType, label: 'Obras', icon: Building2, count: obras.length }, { id: 'usuarios' as TabType, label: 'Usuários', icon: Users, count: usuarios.length }, { id: 'equipamentos' as TabType, label: 'Equipamentos', icon: Wrench, count: equipamentos.length } ]; const formatCurrency = (value: number) => { return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(value); }; const formatDate = (dateString: string) => { if (!dateString) return '-'; return new Date(dateString).toLocaleDateString('pt-BR'); }; const ObraCard = ({ obra }: { obra: Obra }) => (

{obra.nome}

{obra.endereco}
{obra.cliente}
{formatDate(obra.data_inicio)} - {formatDate(obra.data_previsao)}
{selectedItem === obra.id && (
Visualizar
)}
{statusConfig.obras[obra.status]?.label || obra.status} {formatCurrency(obra.orcamento)}
Progresso {obra.progresso}%
Responsável: {obra.responsavel}
); const UsuarioCard = ({ usuario }: { usuario: Usuario }) => (
{usuario.nome.split(' ').map(n => n[0]).join('').toUpperCase().substring(0, 2)}

{usuario.nome}

{usuario.funcao}

{selectedItem === usuario.id && (
)}
{usuario.email}
{usuario.telefone}
{usuario.empresa}
{statusConfig.usuarios[usuario.status]?.label || usuario.status} Último acesso: {formatDate(usuario.ultimo_acesso)}
Cadastrado em: {formatDate(usuario.data_cadastro)}
); const EquipamentoCard = ({ equipamento }: { equipamento: Equipamento }) => (

{equipamento.nome}

Tipo: {equipamento.tipo}

Modelo: {equipamento.modelo}

Fabricante: {equipamento.fabricante}

{selectedItem === equipamento.id && (
)}
{statusConfig.equipamentos[equipamento.status]?.label || equipamento.status} {equipamento.ano_fabricacao}
{equipamento.obra_atual && (

Obra atual: {equipamento.obra_atual}

)}

Série: {equipamento.numero_serie}

Próxima manutenção: {formatDate(equipamento.proximo_manutencao)}

); const renderContent = () => { if (isLoading) { return (
); } switch (activeTab) { case 'obras': return (
{obras.length > 0 ? ( obras.map((obra) => ( )) ) : (
Nenhuma obra encontrada.
)}
); case 'usuarios': return (
{usuarios.length > 0 ? ( usuarios.map((usuario) => ( )) ) : (
Nenhum usuário encontrado.
)}
); case 'equipamentos': return (
{equipamentos.length > 0 ? ( equipamentos.map((equipamento) => ( )) ) : (
Nenhum equipamento encontrado.
)}
); default: return null; } }; return (
{/* Header */}

Cadastros

Gerencie obras, usuários e equipamentos

Novo {activeTab === 'obras' ? 'Obra' : activeTab === 'usuarios' ? 'Usuário' : 'Equipamento'}
{/* Tabs */}
{tabs.map((tab) => { const Icon = tab.icon; return ( ); })}
{/* Search and Filters */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-3 bg-white/50 dark:bg-gray-700/50 border border-gray-300 dark:border-gray-600 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all" />
{/* Content */}
{renderContent()}
); }