> ## Documentation Index
> Fetch the complete documentation index at: https://docs.domsoftware.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Arquitetura do Frontend

> Visão técnica do frontend OmniDom — Next.js 16, feature-based architecture, autenticação e padrões de desenvolvimento.

## Stack tecnológica

| Camada             | Tecnologia                                     |
| ------------------ | ---------------------------------------------- |
| Framework          | Next.js 16.0.7 (App Router)                    |
| Linguagem          | TypeScript 5.x                                 |
| UI / Estilos       | Tailwind CSS v4.1, Radix UI, shadcn/ui pattern |
| Ícones             | Lucide React                                   |
| Animações          | Framer Motion, tw-animate-css                  |
| Gráficos           | Recharts                                       |
| Notificações       | Sonner (toast)                                 |
| Estado global      | Zustand v5                                     |
| Estado do servidor | TanStack Query v5 (React Query)                |
| HTTP Client        | Axios                                          |
| Formulários        | React Hook Form + Zod + @hookform/resolvers    |

***

## Estrutura de pastas

```
src/
├── app/                        # Roteamento Next.js (App Router)
│   ├── (public)/               # Rotas públicas (login, landing)
│   ├── (protected)/            # Rotas autenticadas
│   │   ├── layout.tsx          # Layout raiz protegido — auth guard + sidebar
│   │   ├── dashboard/
│   │   ├── products/
│   │   ├── inventory/
│   │   ├── orders/
│   │   ├── listings/
│   │   ├── integrations/
│   │   ├── imports/
│   │   └── ...                 # Demais módulos
│   ├── layout.tsx              # Root layout (providers globais)
│   └── globals.css
│
├── components/                 # Componentes compartilhados
│   ├── ui/                     # Design system (Button, Input, Dialog, etc.)
│   ├── layout/                 # Header, Sidebar, SidebarContext
│   ├── auth/                   # RefreshTokenOverlay
│   └── integrations/
│
├── features/                   # Lógica de negócio por domínio
│   ├── auth/
│   ├── catalog/
│   ├── inventory/
│   ├── listings/
│   ├── orders/
│   ├── imports/
│   ├── integrations/
│   ├── tenant/
│   └── ...                     # ~27 features no total
│
└── shared/                     # Utilitários transversais
    ├── lib/
    │   ├── axios.ts            # Instância Axios com interceptors
    │   └── utils.ts
    ├── providers/
    │   ├── auth-provider.tsx   # Silent refresh ao carregar a app
    │   └── query-provider.tsx  # QueryClient global
    ├── hooks/                  # (reservado para hooks globais futuros)
    └── types/                  # Tipos TypeScript globais
```

***

## Padrão de Feature

Cada domínio em `src/features/` segue a mesma estrutura interna:

```
src/features/<nome>/
├── components/     # Componentes exclusivos desta feature (formulários, tabelas, cards)
├── hooks/          # Custom hooks — chamam os services e expõem para componentes
├── services/       # Chamadas Axios à API (única camada que usa HTTP)
├── store/          # Zustand store (se o domínio tiver estado global)
├── types/          # Interfaces e tipos TypeScript do domínio
└── schemas.ts      # Schemas Zod de validação de formulários
```

**Regra de ouro:** componentes e hooks **nunca** chamam Axios. Só `services/` faz chamadas HTTP.

***

## Autenticação e Sessão

### Fluxo de tokens

```
Usuário faz login
      │
      ▼
POST /auth/login
      │
      ├── accessToken (JWT, memória — Zustand)
      └── refreshToken (HttpOnly cookie — automático)
```

O `accessToken` **nunca é salvo em localStorage**. Fica exclusivamente no Zustand (`useAuthStore`) em memória.

### Silent Refresh (ao recarregar a página)

Quando o usuário recarrega (F5), o Zustand é reiniciado e o `accessToken` é perdido. O `AuthProvider` e o `ProtectedLayout` detectam esse estado e automaticamente chamam `POST /auth/refresh` usando o cookie HttpOnly:

```
F5 / Recarregar
      │
      ▼
ProtectedLayout.initAuth()
      │
      ├── authApi.refresh()  →  POST /auth/refresh (cookie enviado automaticamente)
      │         │
      │         ├── Sucesso: login() no Zustand + loadTenant()
      │         └── Falha: logout() + redirect para /login?redirect=<pathname>
      │
      └── Mostra overlay de loading durante a hidratação
```

### Interceptor Axios (`src/shared/lib/axios.ts`)

Toda requisição passa pelo interceptor que:

1. Injeta `Authorization: Bearer <accessToken>` no header.
2. Injeta `x-tenant-id: <tenantId>` no header.
3. Se receber `401`, tenta renovar o token automaticamente via `/auth/refresh`.
4. Enquanto renova, coloca requisições paralelas em fila e as reexecuta após sucesso.
5. Se o refresh falhar, chama `logout()` e a fila de requisições é rejeitada.

### Proteção de rotas

Todas as rotas em `app/(protected)/**` requerem autenticação. O `ProtectedLayout` redireciona para `/login` se o usuário não estiver autenticado após a tentativa de silent refresh.

***

## Estado Global (Zustand)

| Store            | Localização                          | Responsabilidade                              |
| ---------------- | ------------------------------------ | --------------------------------------------- |
| `useAuthStore`   | `features/auth/store/auth-store`     | `user`, `accessToken`, `isRefreshing`, logout |
| `useTenantStore` | `features/tenant/store/tenant-store` | Dados do tenant ativo, `loadTenant()`         |

Os stores são inicializados **sem persistência em localStorage**. A persistência é feita via cookie do refresh token.

***

## Fetching de dados (TanStack Query)

O `QueryProvider` está no root layout. Toda busca de dados de servidor usa `useQuery` e mutações usam `useMutation`, sempre encapsulados em custom hooks dentro de `features/<nome>/hooks/`.

**Convenção:**

```ts theme={null}
// features/products/hooks/useProducts.ts
export function useProducts(filters: ProductFilters) {
  return useQuery({
    queryKey: ['products', filters],
    queryFn: () => productService.list(filters),
  })
}
```

**Paginação:** Todos os endpoints usam cursor-based pagination. Nunca implemente offset.

***

## Formulários e Validação

* **React Hook Form** gerencia o estado dos formulários.
* **Zod** valida os dados (schemas em `features/<nome>/schemas.ts`).
* A validação no frontend é limitada a UX e campos obrigatórios. Regras de negócio vêm do backend via resposta da API.

***

## Convenções de código

| O que                | Convenção                                                        |
| -------------------- | ---------------------------------------------------------------- |
| Diretórios           | `kebab-case`                                                     |
| Componentes          | `PascalCase.tsx`                                                 |
| Hooks / Services     | `camelCase.ts` (ex: `useProducts.ts`, `productService.ts`)       |
| Tipos                | `PascalCase` (ex: `Product`, `ProductResponse`)                  |
| `'use client'`       | Apenas em leaf components (formulários, tabelas, interatividade) |
| Axios direto         | ❌ Nunca em componentes ou hooks. Apenas em `services/`           |
| Estado global ad-hoc | ❌ Nunca use `window`, `localStorage`, ou singletons implícitos   |

***

## Módulos do frontend

Os 27 domínios em `src/features/` correspondem às seguintes áreas do sistema:

| Feature                        | Descrição                       |
| ------------------------------ | ------------------------------- |
| `auth`                         | Login, logout, sessão           |
| `catalog`                      | Catálogo de produtos            |
| `products`                     | Gestão de produtos              |
| `products-dashboard`           | Dashboard de produtos           |
| `inventory`                    | Controle de estoque             |
| `listings`                     | Anúncios dos marketplaces       |
| `integrations`                 | Conexões OAuth com marketplaces |
| `imports`                      | Importação de NF-e              |
| `orders`                       | Gestão de pedidos               |
| `orders-dashboard`             | Dashboard de pedidos            |
| `financial`                    | Módulo financeiro               |
| `fiscal`                       | Módulo fiscal                   |
| `logistics`                    | Logística                       |
| `dispatch`                     | Expedição                       |
| `returns`                      | Devoluções                      |
| `suppliers`                    | Fornecedores                    |
| `partners`                     | Parceiros                       |
| `brands`                       | Marcas                          |
| `registries`                   | Cadastros gerais                |
| `tenant`                       | Dados e configurações do tenant |
| `organization`                 | Organização / empresa           |
| `subscription`/`subscriptions` | Planos e assinaturas            |
| `plans`                        | Planos disponíveis              |
| `social-catalogs`              | Catálogos sociais               |
| `social-catalogs-dashboard`    | Dashboard de catálogos sociais  |

***

## Variáveis de ambiente

| Variável               | Obrigatória | Descrição                                               |
| ---------------------- | ----------- | ------------------------------------------------------- |
| `NEXT_PUBLIC_API_URL`  | ✅           | URL base da API backend (ex: `https://api.omnidom.com`) |
| `NEXT_PUBLIC_APP_NAME` |             | Nome exibido na interface (padrão: `Hub Marketplace`)   |

Configure em `.env.local` para desenvolvimento local. Em produção, configure no serviço de hospedagem (Vercel, etc.).
