# Componentes de Layout Padrão Este diretório contém componentes reutilizáveis para manter um design system consistente em todas as páginas de listagem do dashboard. ## Componentes Disponíveis ### 1. **PageHeader** Header padrão com título, descrição e botão de ação. ```tsx import PageHeader from '@/components/layout/PageHeader'; setModalOpen(true)} /> ``` ### 2. **SearchBar** Barra de busca padrão com ícone de lupa. ```tsx import SearchBar from '@/components/layout/SearchBar'; ``` ### 3. **StatusFilter** Dropdown de filtro de status com Headless UI. ```tsx import StatusFilter from '@/components/layout/StatusFilter'; const STATUS_OPTIONS = [ { id: 'all', name: 'Todos os Status' }, { id: 'active', name: 'Ativos' }, { id: 'inactive', name: 'Inativos' }, ]; ``` ### 4. **EmptyState** Estado vazio padrão com ícone, título e descrição. ```tsx import EmptyState from '@/components/layout/EmptyState'; import { BuildingOfficeIcon } from '@heroicons/react/24/outline'; } title="Nenhuma agência encontrada" description="Não encontramos resultados para os filtros selecionados." actionLabel="Limpar todos os filtros" onAction={clearFilters} /> ``` ### 5. **LoadingState** Estado de carregamento com spinner. ```tsx import LoadingState from '@/components/layout/LoadingState'; {loading && } ``` ### 6. **StatusBadge** Badge de status ativo/inativo com toggle opcional. ```tsx import StatusBadge from '@/components/layout/StatusBadge'; toggleStatus(item.id, item.is_active)} activeLabel="Ativo" inactiveLabel="Inativo" /> ``` ### 7. **Pagination** ⭐ NEW Paginação funcional com navegação e indicador de páginas. ```tsx import Pagination from '@/components/layout/Pagination'; const [currentPage, setCurrentPage] = useState(1); const itemsPerPage = 10; const totalItems = filteredItems.length; const totalPages = Math.ceil(totalItems / itemsPerPage); const paginatedItems = filteredItems.slice( (currentPage - 1) * itemsPerPage, currentPage * itemsPerPage ); ``` ### 8. **ConfirmDialog** ⭐ NEW Modal de confirmação profissional (substitui `confirm()`). ```tsx import { useState } from 'react'; import ConfirmDialog from '@/components/layout/ConfirmDialog'; const [confirmOpen, setConfirmOpen] = useState(false); const [itemToDelete, setItemToDelete] = useState(null); const handleDeleteClick = (id: string) => { setItemToDelete(id); setConfirmOpen(true); }; const handleConfirmDelete = () => { if (itemToDelete) { // Executar exclusão deleteItem(itemToDelete); } }; setConfirmOpen(false)} onConfirm={handleConfirmDelete} title="Excluir Item" message="Tem certeza que deseja excluir este item? Esta ação não pode ser desfeita." confirmText="Excluir" cancelText="Cancelar" variant="danger" /> ``` ### 9. **ToastContext & useToast** ⭐ NEW Sistema de notificações toast (substitui `alert()`). **Setup no layout:** ```tsx import { ToastProvider } from '@/components/layout/ToastContext'; {children} ``` **Uso nas páginas:** ```tsx import { useToast } from '@/components/layout/ToastContext'; const toast = useToast(); // Sucesso toast.success('Item criado!', 'O item foi criado com sucesso.'); // Erro toast.error('Erro ao excluir', 'Não foi possível excluir o item.'); // Info toast.info('Informação', 'Ação concluída.'); ``` ## Exemplo de Uso Completo ```tsx "use client"; import { useState, useEffect } from 'react'; import PageHeader from '@/components/layout/PageHeader'; import SearchBar from '@/components/layout/SearchBar'; import StatusFilter from '@/components/layout/StatusFilter'; import LoadingState from '@/components/layout/LoadingState'; import EmptyState from '@/components/layout/EmptyState'; import StatusBadge from '@/components/layout/StatusBadge'; import TableFooter from '@/components/layout/TableFooter'; import { BuildingOfficeIcon } from '@heroicons/react/24/outline'; const STATUS_OPTIONS = [ { id: 'all', name: 'Todos os Status' }, { id: 'active', name: 'Ativos' }, { id: 'inactive', name: 'Inativos' }, ]; export default function MyListPage() { const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(''); const [selectedStatus, setSelectedStatus] = useState(STATUS_OPTIONS[0]); const filteredItems = items.filter(item => { const matchesSearch = item.name.toLowerCase().includes(searchTerm.toLowerCase()); const matchesStatus = selectedStatus.id === 'all' ? true : selectedStatus.id === 'active' ? item.is_active : !item.is_active; return matchesSearch && matchesStatus; }); return (
{}} />
{loading ? ( ) : filteredItems.length === 0 ? ( } title="Nenhum item encontrado" description="Tente ajustar os filtros." /> ) : (
{/* Sua tabela aqui */}
)}
); } ``` ## Design System ### Cores ```css --gradient: linear-gradient(135deg, #ff3a05, #ff0080) --brand-color: #ff0080 ``` ### Classes Tailwind Padrão **Container principal:** ``` p-6 max-w-[1600px] mx-auto space-y-6 ``` **Tabela:** ``` bg-white dark:bg-zinc-900 rounded-xl border border-zinc-200 dark:border-zinc-800 ``` **Header da tabela:** ``` bg-zinc-50/50 dark:bg-zinc-800/50 border-b border-zinc-200 dark:border-zinc-800 ``` **Linha hover:** ``` hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors ``` ## Benefícios ✅ **Consistência visual** - Todas as páginas seguem o mesmo padrão ✅ **Manutenção fácil** - Altere um componente, atualiza em todas as páginas ✅ **Desenvolvimento rápido** - Reutilize componentes prontos ✅ **Design system** - Cores e estilos centralizados ✅ **Acessibilidade** - Componentes já otimizados