wedding-management-system

🏗️ Arquitetura

Visão geral técnica do Wedding Finance Planner.

Stack

Camada Tecnologia Versão
Framework Next.js (App Router) 16.2
UI React 19.2
Estilos Tailwind CSS 4
Banco de dados SQLite via Prisma
ORM Prisma 6
Autenticação Auth.js (NextAuth v5 beta) 5.0.0-beta.31
2FA otplib (TOTP) 13
Validação Zod 4
Email Nodemailer 7
WhatsApp @whiskeysockets/baileys 7-rc11
Gráficos Recharts 3
Ícones Lucide React 1.x
Testes Vitest + Testing Library + happy-dom 4 / 16 / 20

Convenções Next.js 16

Convenções Tailwind 4

Fluxo de autenticação

┌─────────┐     ┌──────────────┐     ┌──────────────┐
│ /login  │ ──▶ │ authorize()  │ ──▶ │ JWT no cookie │
└─────────┘     │ (src/auth.ts)│     │ {role,mcp,oc} │
                └──────────────┘     └──────────────┘
                       │
                       ▼
                ┌────────────────────────────────┐
                │ authConfig.authorized()        │
                │ • mustChangePassword → /change │
                │ • !onboardingCompleted (ADMIN) │
                │                  → /onboarding │
                │ • Logado → /dashboard          │
                └────────────────────────────────┘

Onde:

Após cada login, o authorizeEventSettings.onboardingCompletedAt e inclui a flag no JWT. O authorized middleware bloqueia o dashboard até que ambos os pré-requisitos estejam satisfeitos.

Estrutura de diretórios

src/
├── app/
│   ├── (auth-pages)/        # login, forgot-password, reset-password
│   ├── dashboard/           # painel autenticado
│   │   ├── _components/     # nav, charts comuns
│   │   ├── onboarding/      # wizard de primeira config
│   │   ├── help/            # central de ajuda interna
│   │   ├── insights/        # análises financeiras
│   │   ├── vendors/         # fornecedores
│   │   ├── venues/          # locais
│   │   ├── tasks/           # tarefas
│   │   ├── payments/        # pagamentos
│   │   ├── income/          # receitas
│   │   ├── assets/          # caixa/poupança
│   │   ├── goals/           # metas
│   │   ├── guests/          # convidados
│   │   ├── gifts/           # presentes
│   │   ├── wedding-day/     # dia D
│   │   ├── honeymoon/       # lua de mel
│   │   ├── trousseau/       # enxoval
│   │   ├── settings/        # ajustes
│   │   ├── profile/         # troca de senha
│   │   ├── page.tsx         # dashboard inicial
│   │   └── layout.tsx
│   ├── api/                 # Route Handlers
│   │   ├── auth/[...nextauth]/
│   │   ├── calendar.ics/
│   │   ├── backup/
│   │   ├── cron/reminders/
│   │   └── files/[id]/
│   ├── actions/             # Server Actions
│   ├── rsvp/[token]/        # RSVP público
│   └── layout.tsx
├── components/              # componentes globais reutilizáveis
├── lib/                     # helpers e domínio
│   ├── prisma.ts
│   ├── event-config.ts
│   ├── notifications/       # email + whatsapp + templates
│   ├── totp.ts
│   ├── format.ts
│   ├── cashflow.ts
│   ├── task-templates.ts
│   ├── audit.ts
│   ├── permissions.ts
│   ├── rate-limit.ts
│   ├── timing-safe.ts
│   └── ics.ts
├── auth.ts                  # NextAuth handler (com Prisma)
├── auth.config.ts           # callbacks que rodam em edge
└── types.ts
prisma/
├── schema.prisma
├── seed.ts
└── dev.db                   # gerado, gitignored
docs/                        # esta pasta
public/                      # estáticos, manifest PWA, sw.js

Fluxo de dados

  1. Page (RSC) chama await prisma... e/ou await getEventConfig().
  2. Renderiza com dados; passa para um Client Component se precisar interatividade.
  3. Mutação vai via Server Action: valida sessão, valida Zod, escreve no Prisma, grava AuditLog, retorna ActionResult (success/error).
  4. revalidatePath invalida o cache; a página atualiza.

Helpers e regras de domínio:

Auditoria e logs

Internacionalização (i18n)

Desde a v0.5.0 o sistema suporta pt-BR, en e es via next-intl 4.x. O locale do usuário fica em User.locale e é propagado pelo JWT do Auth.js. Para detalhes (resolução do locale, padrões de chave, cobertura atual, como adicionar idioma), veja i18n.md.

PWA

Próximos passos