Componentes React
📋 Visão Geral
O Portal FindUP utiliza uma arquitetura de componentes baseada no padrão Atomic Design, com componentes reutilizáveis e bem estruturados. A base é o sistema de design do shadcn/ui, customizado para as necessidades específicas do projeto.
🎨 Sistema de Design
Arquitetura de Componentes
Componentes Base (shadcn/ui)
Localizados em src/components/ui/:
Básicos
- Button - Botões em várias variantes
- Input - Campos de entrada de texto
- Label - Rótulos para formulários
- Card - Containers para conteúdo
- Badge - Badges e tags
- Avatar - Avatares de usuários
Navegação
- Sidebar - Barra lateral do sistema
- Navigation Menu - Menus de navegação
- Breadcrumb - Navegação estrutural
- Tabs - Abas para organização
Formulários
- Form - Sistema de formulários com validação
- Select - Seletores dropdown
- Checkbox - Caixas de seleção
- Radio Group - Grupos de radio buttons
- Switch - Interruptores toggle
- Calendar - Seletor de datas
Feedback
- Alert - Alertas e notificações
- Toast - Notificações temporárias
- Dialog - Modais e diálogos
- Progress - Barras de progresso
- Skeleton - Loading placeholders
Dados
- Table - Tabelas de dados
- Chart - Gráficos e visualizações
- Pagination - Paginação de listas
🏗️ Componentes de Layout
DashboardLayout
Localização: src/components/layout/DashboardLayout.tsx
Layout principal do sistema com sidebar e header.
interface DashboardLayoutProps {
children: React.ReactNode;
}
export const DashboardLayout = ({ children }: DashboardLayoutProps) => {
return (
<SidebarProvider>
<div className="min-h-screen flex w-full">
<AppSidebar />
<SidebarInset>
<Header />
<main className="flex-1 p-4">{children}</main>
</SidebarInset>
</div>
</SidebarProvider>
);
};
Header
Localização: src/components/layout/Header.tsx
Cabeçalho com navegação e informações do usuário.
PageLayout
Localização: src/components/layout/PageLayout.tsx
Layout padrão para páginas internas.
🔐 Componentes de Autenticação
RoleGuard
Localização: src/components/auth/RoleGuard.tsx
Componente para controle de acesso baseado em roles.
interface RoleGuardProps {
children: React.ReactNode;
allowedRoles: string[];
fallbackPath?: string;
}
export const RoleGuard = ({
children,
allowedRoles,
fallbackPath = "/",
}: RoleGuardProps) => {
// Verificação de role e renderização condicional
};
Uso:
<RoleGuard allowedRoles={["admin", "super_admin"]}>
<AdminPanel />
</RoleGuard>
📊 Componentes do Dashboard
StatsCards
Localização: src/components/dashboard/StatsCards.tsx
Cards com métricas principais do dashboard.
interface StatsCardsProps {
totalSales: number;
pendingCommissions: number;
activeProposals: number;
monthlyGoal: number;
}
RecentActivity
Localização: src/components/dashboard/RecentActivity.tsx
Timeline das atividades recentes do usuário.
QuickActions
Localização: src/components/dashboard/QuickActions.tsx
Ações rápidas baseadas no role do usuário.
🛒 Componentes de Vendas
ProductCatalog
Localização: src/components/sales/ProductCatalog.tsx
Catálogo de produtos com funcionalidades de busca e filtro.
interface ProductCatalogProps {
technicianId?: string;
}
export const ProductCatalog = ({ technicianId }: ProductCatalogProps) => {
// Listagem e gestão de produtos
};
ProposalForm
Localização: src/components/sales/ProposalForm.tsx
Formulário para criação de propostas.
interface ProposalFormProps {
customerId: string;
productId: string;
onSuccess: () => void;
onCancel: () => void;
}
ProposalManagement
Localização: src/components/sales/ProposalManagement.tsx
Gestão completa de propostas com listagem, filtros e ações.
CustomerForm
Localização: src/components/sales/CustomerForm.tsx
Formulário para cadastro e edição de clientes.
CustomerManagement
Localização: src/components/sales/CustomerManagement.tsx
Gestão de clientes com listagem e operações CRUD.
SalesDashboard
Localização: src/components/sales/SalesDashboard.tsx
Dashboard específico para vendas e métricas.
📦 Componentes de Produtos
ProductForm
Localização: src/components/products/ProductForm.tsx
Formulário para criação e edição de produtos.
interface ProductFormProps {
onSuccess?: () => void;
onCancel?: () => void;
initialData?: Product;
isEditing?: boolean;
}
Características:
- Validação com Zod
- Upload de imagens
- Gestão de features
- Cálculo de comissões
👥 Componentes de Usuários
UserForm
Localização: src/components/users/UserForm.tsx
Formulário para criação e edição de usuários.
UserProfile
Localização: src/components/profile/UserProfile.tsx
Perfil do usuário com edição de dados pessoais.
🔧 Componentes de Admin
SystemSettings
Localização: src/components/admin/SystemSettings.tsx
Configurações gerais do sistema.
PasswordResetDialog
Localização: src/components/admin/PasswordResetDialog.tsx
Dialog para reset de senhas pelos administradores.
📚 Componentes de Wiki
WikiContentManager
Localização: src/components/wiki/WikiContentManager.tsx
Gestão de conteúdo da wiki interna.
🎨 Componentes Customizados
FindupLogo
Localização: src/components/ui/findup-logo.tsx
Logo SVG da FindUP.
AppSidebar
Localização: src/components/app-sidebar.tsx
Barra lateral principal com navegação baseada em roles.
export function AppSidebar() {
const [userRole, setUserRole] = useState<string | null>(null);
// Navegação dinâmica baseada no role
const getNavigationItems = () => {
switch (userRole) {
case "super_admin":
return [...adminItems, ...superAdminItems];
case "admin":
return adminItems;
case "technician":
return technicianItems;
default:
return userItems;
}
};
}
🪝 Hooks Customizados
useCep
Localização: src/hooks/use-cep.ts
Hook para busca de endereços via CEP.
export const useCep = () => {
const searchCep = async (cep: string) => {
const cleanCep = cep.replace(/\D/g, "");
const response = await fetch(`https://viacep.com.br/ws/${cleanCep}/json/`);
return response.json();
};
return { searchCep };
};
useToast
Localização: src/hooks/use-toast.ts
Hook para sistema de notificações.
useMobile
Localização: src/hooks/use-mobile.tsx
Hook para detecção de dispositivos móveis.
🎯 Padrões de Desenvolvimento
Estrutura de Componente
interface ComponentProps {
// Props tipadas
}
export const Component = ({ prop1, prop2 }: ComponentProps) => {
// Estado local
const [state, setState] = useState();
// Efeitos
useEffect(() => {
// Side effects
}, []);
// Handlers
const handleAction = () => {
// Logic
};
// Render
return <div>{/* JSX */}</div>;
};
Validação com Zod
const schema = z.object({
name: z.string().min(1, "Nome é obrigatório"),
email: z.string().email("Email inválido"),
});
type FormData = z.infer<typeof schema>;
Estilização com Tailwind
const variants = {
primary: "bg-primary text-primary-foreground",
secondary: "bg-secondary text-secondary-foreground",
};
export const Button = ({ variant = "primary", ...props }) => {
return (
<button
className={cn(
"px-4 py-2 rounded-md transition-colors",
variants[variant]
)}
{...props}
/>
);
};
Loading States
export const Component = () => {
const [loading, setLoading] = useState(true);
if (loading) {
return <Skeleton className="h-32 w-full" />;
}
return <div>Content</div>;
};
Error Boundaries
export const ErrorBoundary = ({ children }) => {
const [hasError, setHasError] = useState(false);
if (hasError) {
return <ErrorFallback />;
}
return children;
};
📱 Responsividade
Breakpoints
/* Tailwind CSS breakpoints */
sm: 640px
md: 768px
lg: 1024px
xl: 1280px
2xl: 1536px
Componentes Responsivos
export const ResponsiveComponent = () => {
return (
<div
className="
grid grid-cols-1
md:grid-cols-2
lg:grid-cols-3
gap-4
"
>
{/* Content */}
</div>
);
};
🧪 Testes
Testes de Componente
import { render, screen } from "@testing-library/react";
import { Component } from "./Component";
test("renders component correctly", () => {
render(<Component />);
expect(screen.getByText("Content")).toBeInTheDocument();
});
Testes de Interação
import userEvent from "@testing-library/user-event";
test("handles user interaction", async () => {
const user = userEvent.setup();
render(<Button onClick={mockFn} />);
await user.click(screen.getByRole("button"));
expect(mockFn).toHaveBeenCalled();
});
🚀 Performance
Otimizações
- React.memo para componentes puros
- useMemo para cálculos custosos
- useCallback para funções estáveis
- Lazy loading para componentes grandes
Code Splitting
const LazyComponent = lazy(() => import("./LazyComponent"));
export const App = () => {
return (
<Suspense fallback={<Loading />}>
<LazyComponent />
</Suspense>
);
};