Documentação Evento Rápido

Documentação técnica completa do app — banco de dados, regras, componentes, fluxos e mais.

# 📋 DOCUMENTAÇÃO COMPLETA — EVENTO RÁPIDO

> Plataforma SaaS multi-tenant para organizadores de eventos, igrejas e produtores.
> Modo COMPLETO (todas funcionalidades) e Modo EVENTO_PIX (simplificado para igrejas).
> URL pública: https://eventorapido.base44.app

---

## 📑 ÍNDICE

1. Visão Geral
2. Stack Tecnológico
3. Autenticação & Multi-Tenancy
4. Banco de Dados — Coleções (Entities)
5. Row-Level Security (RLS)
6. Funções Backend
7. Integrações
8. Páginas (Rotas)
9. Componentes
10. Bibliotecas Utilitárias (src/lib)
11. Regras de Negócio
12. Fluxo de Pagamento PIX
13. Sistema de Numeração de Ingressos
14. Controle de Estoque
15. Sistema de Lotes
16. Check-in / Portaria
17. Secrets & Credenciais
18. Problemas Conhecidos
19. Decisões de Produto
20. Preferências do Usuário

---

## 1. VISÃO GERAL

Nome do App: Evento Rápido
Missão: SaaS multi-tenant para organizadores de eventos, igrejas e produtores com controle de acesso granular (RLS) e modo "Evento PIX" ultra-simplificado.

Dois modos de operação:
- COMPLETO — Todas as funcionalidades (PDV, numeração, mapa de assentos, consignação, promoters, lotes, marketing, financeiro, analytics).
- EVENTO_PIX — Interface simplificada para igrejas: checkout de página única, sem multi-step, foco em PIX manual e confirmação manual.

Publicação: iOS, Android e Web a partir do mesmo código (React + Vite).

---

## 2. STACK TECNOLÓGICO

Frontend: React 18 + Vite + Tailwind CSS
UI Kit: shadcn/ui (Radix UI)
Ícones: lucide-react
Roteamento: react-router-dom v6
Estado/Dados: @tanstack/react-query v5
Formulários: react-hook-form + zod
Gráficos: recharts
Mapas: react-leaflet
Drag & Drop: @hello-pangea/dnd
3D: three.js
QR Code: html5-qrcode (scanner) + api.qrserver.com (geração)
PDF/Print: jspdf + html2canvas
Animações: framer-motion
Markdown: react-markdown
Editor rich text: react-quill
Backend: Base44 BaaS (auth, DB, integrações, hosting)
SDK: @base44/sdk

Pacotes instalados (package.json):
@base44/sdk, @base44/vite-plugin, @hello-pangea/dnd, @hookform/resolvers, @radix-ui/* (25+ pacotes), @tanstack/react-query, canvas-confetti, class-variance-authority, clsx, cmdk, date-fns, embla-carousel-react, framer-motion, html2canvas, html2canvas, html5-qrcode, input-otp, jspdf, lodash, lucide-react, moment, next-themes, react, react-day-picker, react-dom, react-hook-form, react-hot-toast, react-leaflet, react-markdown, react-quill, react-resizable-panels, react-router-dom, recharts, sonner, tailwind-merge, tailwindcss-animate, three, vaul, zod.

---

## 3. AUTENTICAÇÃO & MULTI-TENANCY

### 3.1 Auth (plataforma Base44)
A plataforma gerencia auth (tokens, sessões, verificação de e-mail). O app NÃO implementa lógica de auth backend.

Fluxo (src/lib/AuthContext.jsx):
1. checkAppState() — busca public-settings do app (com token se disponível).
2. Se token existe → checkUserAuth() → base44.auth.me().
3. Se usuário não é admin → loadOrganizer(email) — busca entidade Organizer pelo email.
4. Deriva modoPlano (COMPLETO ou EVENTO_PIX) e isOrganizerSuspended (status INATIVO).

Métodos SDK disponíveis:
- base44.auth.me() — usuário atual
- base44.auth.isAuthenticated() — Promise<boolean>
- base44.auth.logout(redirectUrl?) — logout + redirect
- base44.auth.redirectToLogin(nextUrl?) — redirect para login
- base44.auth.updateMe(data) — persiste dados extra no usuário
- base44.users.inviteUser(email, role) — convida usuário (role: "user" | "admin")

### 3.2 Multi-Tenancy
Isolamento por Organizer (src/lib/tenantUtils.js):
- Cada organizador tem um registro Organizer vinculado ao User via email.
- Organizer.modo_plano define COMPLETO ou EVENTO_PIX.
- Organizer.status = ATIVO/INATIVO (INATIVO = suspenso, bloqueia acesso).
- Admin (SuperAdmin) pode alternar entre visão "Global" (vê tudo) e "Organizador" (vê só seus eventos).
- getEventFilterForUser(user, globalView):
  - Admin + globalView=true → null (vê todos os eventos)
  - Organizador ou admin em visão organizador → { created_by_id: user.id }

Papéis:
- SuperAdmin (role=admin) — acesso total, gerencia organizers, ativa/suspende, gera credenciais temporárias.
- Organizador (role=user) — vê e gerencia apenas seus eventos e dados.
- Co-organizador — usuário autenticado via email vinculado em Event.co_organizer_email.

### 3.3 Layout & Navegação (src/Layout.jsx)
- Nav base: Eventos (Dashboard), Portaria (CheckIn), Vitrine (PublicEvents).
- Modo COMPLETO adiciona: PDV.
- Admin adiciona: Organizers.
- Páginas públicas (sem layout): SalesPage, Ticket, PublicEvents.
- Desktop: top nav sticky. Mobile: bottom tab bar.
- Botão "Global/Organizador" (apenas admin) alterna visão.
- Botão excluir conta (UserX) + logout.

---

## 4. BANCO DE DADOS — COLEÇÕES (ENTITIES)

18 entidades. Atributos built-in em TODAS: id, created_date, updated_date, created_by_id.

### 4.1 Event
Entidade central. Define um evento com todas as configurações.

Campos:
- title (string, req) — Título do evento
- slogan (string) — Slogan/frase de impacto
- description (string) — Descrição
- category (enum: show, palestra, workshop, curso, networking, outro; default: outro) — Categoria
- date (date) — Data do evento
- time (string) — Horário
- location (string) — Local
- price (number, req) — Valor base do ingresso (0 = gratuito)
- is_free (boolean, default: false) — Evento gratuito
- free_event_type (enum: inscricao, ingresso; default: inscricao) — Tipo gratuito
- inscricao_requires_names (boolean, default: true) — Inscrição exige nome individual
- simple_checkout (boolean, default: false) — Checkout página única (EVENTO_PIX)
- enable_checkin (boolean, default: true) — Controla check-in
- coupon_code (string) — Cupom de desconto
- coupon_price (number) — Valor com cupom
- promotion_end_date (date-time) — Fim da promoção
- pix_key (string) — Chave PIX manual
- pix_name (string) — Nome titular PIX
- cover_image (string) — URL capa principal
- cover_images (string[]) — Galeria de capas
- status (enum: active, paused, finished; default: active) — Status
- is_public (boolean, default: false) — Aparece na vitrine pública
- max_participants (number) — Máx. participantes
- testimonials (array<{name, text, avatar}>) — Depoimentos
- is_recurring (boolean, default: false) — Evento recorrente
- recurrence_pattern (enum: daily, weekly, monthly) — Padrão recorrência
- recurrence_end_date (date) — Fim da recorrência
- parent_event_id (string) — ID evento pai (recorrente)
- organizer_id (string) — ID Organizer vinculado (multi-tenant)
- co_organizer_email (string) — Email co-organizador (acesso via login)
- co_organizer_whatsapp (string) — WhatsApp co-organizador
- budget (number) — Orçamento total
- allow_multiple_tickets (boolean, default: false) — Permite vários ingressos
- max_tickets_per_purchase (number) — Limite por compra
- half_ticket_capacity (number) — Capacidade meia-entrada
- half_ticket_price (number) — Preço meia-entrada
- has_sessions (boolean, default: false) — Múltiplas sessões
- contact_email (string) — Email contato organizador
- contact_whatsapp (string) — WhatsApp organizador
- stripe_publishable_key (string) — [DESCONTINUADO] Migrado para PaymentGateway
- stripe_secret_key (string) — [DESCONTINUADO]
- enable_credit_card (boolean) — [DESCONTINUADO]
- payment_provider (string) — Provedor pagamento (pix_manual, mercado_pago, pagbank, asaas, pagarme, stripe)
- enable_pix_manual (boolean, default: false) — PIX manual (comprovante + confirmação manual)
- enable_physical_sales (boolean, default: true) — Vendas físicas PDV
- ticket_mode (enum: general, numbered, numbered_seat; default: general) — Modo ingresso
- numbering_config (object: start, end, prefix, digits, courtesy_start, courtesy_end, repeat_per_session) — Numeração sequencial
- seat_map_config (object: sectors[], stage) — Mapa de assentos (Modo B)
- sale_start_date (date-time) — Abertura vendas
- sale_end_date (date-time) — Encerramento vendas
- organizer_name (string) — Nome organizador
- logo_url (string) — URL logo
- duration_minutes (number) — Duração estimada
- age_rating (enum: livre, 10, 12, 14, 16, 18) — Classificação etária
- rules (string) — Regras/políticas

RLS:
- create: criador OU admin
- read: público (is_public=true) OU criador OU co_organizer_email==user.email OU admin
- update: criador OU co_organizer_email==user.email OU admin
- delete: criador OU admin

---

### 4.2 Registration
Inscrição/ingresso de um participante em um evento.

Campos:
- event_id (string, req) — ID do evento
- session_id (string) — ID da sessão
- ticket_type_id (string) — ID do tipo de ingresso
- ticket_type_name (string) — Nome do tipo
- full_name (string, req) — Nome completo participante
- responsible_name (string) — Nome responsável (eventos gratuitos)
- birth_date (date) — Data nascimento
- email (string) — Email
- whatsapp (string, req) — WhatsApp
- co_organizer_email (string) — Denormalizado do evento (RLS)
- payment_status (enum: pending, aguardando_confirmacao, confirmed, rejected, cancelled, refunded, expired, failed; default: pending) — Status pagamento
- used_coupon (boolean) — Usou cupom
- coupon_code (string) — Cupom usado
- paid_price (number) — Valor pago
- qr_code (string) — Código QR único
- short_code (string) — Código curto 6 dígitos
- ticket_number (string) — Número sequencial por sessão
- ticket_status (enum: disponivel, emitido, consignado, vendido, devolvido, perdido, cancelado, reservado, cortesia, utilizado; default: disponivel) — Status ingresso físico
- seat_sector (string) — Setor (Modo B)
- seat_row (string) — Fila (Modo B)
- seat_number (string) — Número assento (Modo B)
- emission_type (enum: digital, printed_pdv, printed_batch; default: digital) — Tipo emissão
- sale_channel (enum: online, pdv; default: online) — Canal venda
- promoter_id (string) — ID promoter (consignação)
- consignment_status (enum: em_posse, vendido, devolvido, acertado) — Status consignação
- pdv_payment_method (enum: dinheiro, pix, cartao) — Pagamento PDV
- payment_proof_url (string) — URL comprovante
- payment_proof_date (date-time) — Data envio comprovante
- payment_confirmed_date (date-time) — Data confirmação
- rejection_reason (string) — Motivo rejeição
- checked_in (boolean, default: false) — Fez check-in
- checked_in_date (string) — Data/hora check-in
- printed_count (number, default: 0) — Vezes impresso
- last_printed_date (date-time) — Última impressão

RLS:
- create: null (qualquer um pode criar — checkout público)
- read: email==user.email OU criador OU co_organizer_email==user.email OU admin
- update: email==user.email OU criador OU co_organizer_email==user.email OU admin
- delete: email==user.email OU criador OU admin

---

### 4.3 TicketType
Tipos de ingresso de um evento.

Campos:
- event_id (string, req) — ID evento
- session_id (string) — Sessão (null = todas)
- name (string, req) — Nome
- description (string) — Descrição
- price (number, req) — Preço
- capacity (number, req) — Capacidade máx
- available (number) — Disponível
- order (number) — Ordem exibição
- active (boolean, default: true) — Ativo para venda
- is_courtesy (boolean, default: false) — Cortesia (oculto na venda)
- is_half (boolean, default: false) — Meia-entrada
- benefits (string[]) — Benefícios inclusos
- type_category (enum: ingresso, inscricao; default: ingresso) — Ingresso (plateia) ou Inscrição (participante)

RLS: create/update/delete: criador OU admin. read: null (público).

---

### 4.4 BatchTicket
Lotes de ingressos com desconto progressivo.

Campos:
- event_id (string, req) — ID evento
- session_id (string) — Sessão
- order (number, req) — Ordem do lote (1,2,3)
- name (string) — Nome (Lote 1, Promocional)
- discount_percent (number, req) — % desconto sobre preço normal
- capacity (number, req) — Qtd ingressos no lote
- start_date (date-time) — Início do lote
- end_date (date-time, req) — Fim do lote
- active (boolean, default: true) — Lote ativo

RLS: create/update/delete: criador OU admin. read: {} (público).

---

### 4.5 Session
Sessões de eventos com múltiplas datas/horários.

Campos:
- event_id (string, req) — ID evento
- date (date, req) — Data da sessão
- time (string, req) — Horário
- label (string) — Nome/descrição (Turma A, Manhã)
- capacity (number) — Capacidade
- active (boolean, default: true) — Ativa

RLS: create/update/delete: criador OU admin. read: null (público).

---

### 4.6 Order
Pedidos de compra (carrinho → checkout).

Campos:
- event_id (string, req) — ID evento
- customer_name (string, req) — Nome cliente
- customer_email (string, req) — Email cliente
- customer_whatsapp (string, req) — WhatsApp cliente
- items (array<{ticket_type_id, ticket_type_name, quantity, unit_price, subtotal}>, req) — Itens
- subtotal (number) — Subtotal
- discount_amount (number) — Desconto
- total (number, req) — Total
- coupon_code (string) — Cupom usado
- payment_method (enum: pix, credit_card; default: pix) — Método
- payment_status (enum: pending, confirmed, rejected; default: pending) — Status
- stripe_payment_intent_id (string) — ID PaymentIntent Stripe
- registration_ids (string[]) — IDs inscrições geradas
- payment_proof_url (string) — URL comprovante PIX

RLS: create: null (público). read/update/delete: customer_email==user.email OU criador OU admin.

---

### 4.7 Organizer
Organizadores/igrejas do SaaS (multi-tenant).

Campos:
- nome (string, req) — Nome organizador/igreja
- email (string, req) — Email login (vínculo User)
- whatsapp (string) — WhatsApp contato/reset senha
- status (enum: ATIVO, INATIVO; default: ATIVO) — Status acesso
- tipo_cobranca (enum: PAGO, GRATUITO; default: GRATUITO) — Modelo cobrança
- modo_plano (enum: COMPLETO, EVENTO_PIX; default: COMPLETO) — Modo interface
- user_id (string) — ID User vinculado
- temp_password (string) — Senha temporária primeiro acesso
- password_reset_token (string) — Token reset senha via WhatsApp
- password_reset_expires (date-time) — Expiração token
- notes (string) — Observações internas SuperAdmin

RLS: create/update/delete: admin apenas. read: email==user.email OU admin.

---

### 4.8 CoOrganizerLink
Links de acesso de co-organizadores (legacy — agora usa co_organizer_email no Event).

Campos: token, event_id, co_organizer_name, co_organizer_whatsapp, event_title, event_date, event_time, event_location, pix_key, pix_name, active.

RLS: create/update/delete: criador OU admin. read: null (público — acesso via token).

---

### 4.9 Promoter
Promoters/comissionários para consignação de ingressos.

Campos: name, whatsapp, pix_key, commission_type (percent/fixed), commission_value, event_id, type (aluno/integrante/comissionario/ponto_venda), active.

RLS: create/read/update/delete: criador OU admin.

---

### 4.10 TicketConsignment
Blocos de ingressos consignados a promoters.

Campos: event_id, session_id, promoter_id, promoter_name, start_number, end_number, quantity, withdrawal_date, settlement_deadline, status (em_posse/parcialmente_vendido/acertado/devolvido), sold_count, returned_count, settled_amount, settlement_date, notes.

RLS: create/read/update/delete: criador OU admin.

---

### 4.11 TicketHistory
Auditoria de todas as ações em ingressos.

Campos: event_id, registration_id, ticket_number, session_id, action (created/sold_online/sold_pdv/consigned/returned/cancelled/refunded/reopened/reprinted/checked_in/printed_batch/courtesy_assigned), previous_status, new_status, actor_name, actor_id, reason, notes.

RLS: create: criador OU admin. read: criador OU admin. update/delete: admin apenas.

---

### 4.12 PaymentGateway
Configuração de gateways de pagamento por evento ou organização.

Campos: event_id, organization_level, provider, provider_label, mode (sandbox/production), is_active, is_primary, payment_methods[], credentials_ref, fees {pix_percent, card_percent, card_fixed, payout_days}, webhook_url, webhook_secret_ref, activated_at, deactivated_at, notes.

RLS: create/read/update/delete: criador OU admin.

---

### 4.13 FinancialEntry
Lançamentos financeiros (receita/despesa) do evento.

Campos: event_id, description, type (receita/despesa), amount, status (pendente/pago/recebido/cancelado), due_date, category, notes.

RLS: create/read/update/delete: criador OU admin.

---

### 4.14 Expense
Despesas específicas do evento.

Campos: event_id, description, category (local/equipamento/marketing/equipe/alimentacao/transporte/outros), amount, paid, payment_date, notes.

RLS: create/read/update/delete: criador OU admin.

---

### 4.15 Subscription
Planos/assinaturas dos organizadores.

Campos: user_email, plan (free/premium), event_limit, commission_rate, status (active/suspended/pending_payment), total_sales, commission_owed, commission_paid, last_payment_date.

RLS: create/read/update/delete: user_email==user.email OU admin.

---

### 4.16 CommissionPayment
Pagamentos de comissão devidos ao sistema.

Campos: user_email, amount, status (pending/paid/overdue), payment_proof_url, payment_date, pix_key, reference_period, tickets_count.

RLS: create/read/update/delete: user_email==user.email OU admin.

---

### 4.17 EmailTemplate & EmailAutomation
EmailTemplate: name, subject, body (suporta {{nome}}, {{evento}}, {{data}}), type (confirmation/reminder/followup/custom).
EmailAutomation: event_id, name, trigger (registration_confirmed/payment_confirmed/event_finished/event_reminder_1day/event_reminder_1week), template_id, segment_filter, active, last_run.

RLS ambas: create/read/update/delete: criador OU admin.

---

### 4.18 Feedback & EventTask
Feedback: event_id, registration_id, rating (1-5), comment, would_recommend, favorite_aspect. create: null. read: null. update/delete: criador OU admin.
EventTask: event_id, title, description, due_date, completed, priority (low/medium/high), reminder_sent. CRUD: criador OU admin.

---

### 4.19 User (built-in)
Entidade de usuário (não criável via SDK). Usuários entram via convite.

Campos built-in: id, created_date, full_name, email, role (admin/user).
Segurança built-in: apenas admins listam/atualizam/deletam outros usuários.

---

## 5. ROW-LEVEL SECURITY (RLS)

Padrões de RLS por entidade:

Event: create=criador/admin | read=público+criador+coorg+admin | update=criador+coorg+admin | delete=criador+admin
Registration: create=null | read=email+criador+coorg+admin | update=email+criador+coorg+admin | delete=email+criador+admin
TicketType: create=criador/admin | read=null | update=criador/admin | delete=criador/admin
BatchTicket: create=criador/admin | read={} | update=criador/admin | delete=criador/admin
Session: create=criador/admin | read=null | update=criador/admin | delete=criador/admin
Order: create=null | read=email+criador+admin | update=email+criador+admin | delete=email+criador+admin
Organizer: create=admin | read=email+admin | update=admin | delete=admin
CoOrganizerLink: create=criador/admin | read=null | update=criador/admin | delete=criador/admin
Promoter: create=criador/admin | read=criador/admin | update=criador/admin | delete=criador/admin
TicketConsignment: create=criador/admin | read=criador/admin | update=criador/admin | delete=criador/admin
TicketHistory: create=criador/admin | read=criador/admin | update=admin | delete=admin
PaymentGateway: create=criador/admin | read=criador/admin | update=criador/admin | delete=criador/admin
FinancialEntry: create=criador/admin | read=criador/admin | update=criador/admin | delete=criador/admin
Expense: create=criador/admin | read=criador/admin | update=criador/admin | delete=criador/admin
Subscription: create=email+admin | read=email+admin | update=email+admin | delete=email+admin
CommissionPayment: create=email+admin | read=email+admin | update=email+admin | delete=email+admin
EmailTemplate: create=criador/admin | read=criador/admin | update=criador/admin | delete=criador/admin
EmailAutomation: create=criador/admin | read=criador/admin | update=criador/admin | delete=criador/admin
Feedback: create=null | read=null | update=criador/admin | delete=criador/admin
EventTask: create=criador/admin | read=criador/admin | update=criador/admin | delete=criador/admin

Variáveis de template RLS:
- {{user.id}} — ID do usuário atual
- {{user.email}} — Email do usuário atual
- user_condition.role == "admin" — Condição de role

Operadores suportados: $or, $and, $eq (implícito), $ne, $gt, $gte, $lt, $lte, $in, $nin, $exists.

---

## 6. FUNÇÕES BACKEND

### 6.1 sendEmail (base44/functions/sendEmail/entry.ts)
Status: ⚠️ Existe mas INACESSÍVEL no plano atual (requer upgrade).

Função: Envia email via SMTP Zoho.
- Transport: smtp.zoho.com:465 (SSL)
- Remetente: "Corpus Escola de Dança" <financeiro@corpusescoladedanca.com.br>
- Secret: ZOHO_SMTP_PASSWORD
- Auth: Requer usuário autenticado (base44.auth.me()).
- Parâmetros: to, subject, body (HTML).

⚠️ Plano atual não inclui backend functions. Para modificar ou criar novas funções, é necessário upgrade.

---

## 7. INTEGRAÇÕES

### 7.1 Core (built-in, sempre disponível)

InvokeLLM — Gera resposta de LLM. Modelos: automatic, gpt_5_mini, gemini_3_flash, gpt_5_4, gpt_5_6_sol, gpt_5_6_luna, gemini_3_1_pro, claude_sonnet_4_6, claude_opus_4_6/4_7/4_8, claude-sonnet-5. add_context_from_internet apenas com gemini_3_flash/gemini_3_1_pro. Suporta response_json_schema, file_urls.
UploadFile — Upload arquivo público → {file_url}.
UploadPrivateFile — Upload arquivo privado → {file_uri}.
CreateFileSignedUrl — URL assinada para download de arquivo privado.
ExtractDataFromUploadedFile — Extrai dados estruturados de CSV/XLSX/JSON/HTML/PNG/JPG/PDF.
SendEmail — Envia email. Usuários registrados sempre. Não-registrados requer plano pago + domínio custom.
SendPushNotification — Push mobile (apenas app nativo iOS/Android). Server-side via asServiceRole.
GenerateImage — Gera imagem via IA.
GenerateSpeech — TTS → MP3. Vozes: river, honey, sunny, storm, spark. 1 crédito/50 chars.
GenerateVideo — Gera vídeo via Google Veo 3.x. 5 créditos/segundo.
TranscribeAudio — Transcrição áudio→texto (Whisper).

### 7.2 Analytics
base44.analytics.track({ eventName, properties }) — tracking de eventos custom.

### 7.3 Conectores OAuth (não autorizados ainda)
Disponíveis mas não conectados: Google Calendar, Gmail, Google Sheets, Slack, Notion, Salesforce, HubSpot, GitHub, Stripe, etc. (60+ conectores).

### 7.4 Secrets configurados
- ZOHO_SMTP_PASSWORD — Senha SMTP Zoho (sendEmail)
- RESEND_API_KEY — API key Resend (não utilizado ativamente)

---

## 8. PÁGINAS (ROTAS)

Config: src/pages.config.js (mainPage: "Dashboard")

/ → Dashboard — Lista de eventos, criação, métricas, AI assistant
/Analytics → Analytics — Analytics globais do organizador
/Billing → Billing — Faturamento/comissões
/CheckIn → CheckIn — Portaria — check-in via QR code (online/offline)
/EmailAutomations → EmailAutomations — Automações de email
/EventDetails → EventDetails — Detalhes públicos do evento
/EventManage → EventManage — Gerenciamento completo do evento (tabs)
/PaymentApproval → PaymentApproval — Aprovação manual de pagamentos
/PublicEvents → PublicEvents — Vitrine pública de eventos
/Registrations → Registrations — Lista de inscrições
/SalesPage → SalesPage — Página de venda/checkout (público)
/Ticket → Ticket — Visualização do ingresso com QR
/Organizers → Organizers — Gestão de organizadores (admin)
/PDV → PDV — Ponto de venda físico (modo COMPLETO)

Layout: src/Layout.jsx envolve todas as páginas exceto: SalesPage, Ticket, PublicEvents (públicas, sem nav).

---

## 9. COMPONENTES

### 9.1 Event Manage (src/components/event-manage/)
PixConferenceTab — Aprovação manual de PIX, agrupamento por cliente, envio de recibo WhatsApp
PixPresenceTab — Lista de presença PIX com edit/delete
PixFinancialTab — Financeiro do modo PIX
EventRegistrationsTab — Gestão completa de inscrições (filtro, sort, CSV, email, bulk)
EventPaymentsTab — Pagamentos
EventFinancialTab — Financeiro completo (DRE)
EventMarketingTab — Marketing/automações
EventAnalyticsTab — Analytics do evento
FeedbackViewsTab — Feedbacks/avaliações
CoOrganizerManager — Convite e gestão de co-organizadores
EditRegistrationDialog — Editar inscrição
ParticipantListDialog — Lista de participantes
SendTicketsDialog — Envio de ingressos

### 9.2 Events (src/components/events/)
EventFormDialog — Formulário wizard 3 passos (O que/Onde → Quando → Quanto)
SimpleEventForm — Formulário simples (modo EVENTO_PIX)
EventCard — Card de evento na dashboard
EventFilters — Filtros de eventos
TasksCalendar — Calendário de tarefas
ExpensesManager — Gestor de despesas

### 9.3 Sales (src/components/sales/)
SimplePixCheckout — Checkout PIX página única
RegistrationForm — Formulário de inscrição
FreeRegistrationForm — Inscrição gratuita
PixPaymentBox — Box de pagamento PIX (BR Code)
PaymentProofUpload — Upload de comprovante
PaymentMethodSelector — Seletor de método
MultiTicketSelector — Seletor múltiplos ingressos
TicketTypeSelector — Seletor de tipo
OrderSummary — Resumo do pedido
OrderSuccessView — Sucesso do pedido
OrderPendingView — Pendente
StripeCheckout — Checkout Stripe
CountdownTimer — Timer regressivo
Testimonials — Depoimentos
AutoEmailSender — Envio automático email

### 9.4 Tickets (src/components/tickets/)
TicketTypeManager — Gestão de tipos
NumberingConfigManager — Config de numeração
SeatMapEditor — Editor de mapa de assentos
BatchManager — Gestão de lotes
SessionManager — Gestão de sessões
PrintTicketDialog — Impressão de ingresso
BatchPrintDialog — Impressão em lote
CourtesyRegistrationDialog — Cortesias
TicketQRCode — Exibição do QR code

### 9.5 Promoters (src/components/promoters/)
PromoterManager — Gestão de promoters
PromoterSettlement — Acerto financeiro

### 9.6 Payments (src/components/payments/)
PaymentGatewayManager — Gestão de gateways

### 9.7 Organizers (src/components/organizers/)
OrganizerFormDialog — Formulário de organizador

### 9.8 Marketing (src/components/marketing/)
EmailTemplateForm, TemplateList, AutomationForm, AutomationList, DefaultTemplates

### 9.9 Communications (src/components/communications/)
EmailParticipantsDialog — Email em massa para participantes

### 9.10 Emails (src/components/emails/)
ConfirmationEmailSender — Envio de confirmação

### 9.11 Financeiro (src/components/financeiro/)
DREReport — Relatório DRE

### 9.12 Feedback (src/components/feedback/)
FeedbackFormDialog — Formulário de feedback

### 9.13 AI (src/components/ai/)
AIEventAssistant — Assistente IA para criação de eventos

### 9.14 Automation (src/components/automation/)
EventReminderScheduler — Scheduler de lembretes

### 9.15 UI (src/components/ui/) — shadcn/ui completo
accordion, alert, alert-dialog, aspect-ratio, avatar, badge, breadcrumb, button, calendar, card, carousel, chart, checkbox, collapsible, command, context-menu, dialog, drawer, dropdown-menu, form, hover-card, input, input-otp, label, menubar, mobile-header, navigation-menu, pagination, popover, progress, radio-group, resizable, scroll-area, select, separator, sheet, sidebar, skeleton, slider, sonner, switch, table, tabs, textarea, toast, toaster, toggle, toggle-group, tooltip, use-toast, whatsapp-input.

### 9.16 Outros
AuthLayout, ProtectedRoute, OrganizerSuspended, UserNotRegisteredError, OAuthConsent

---

## 10. BIBLIOTECAS UTILITÁRIAS (src/lib)

### 10.1 pixUtils.js — BR Code PIX
Gera BR Code (PIX Copia e Cola) no padrão EMV-QRCPS MPM do BACEN.
- generatePixBRCode({pixKey, pixName, city, amount, txid}) — Gera payload EMV com CRC16-CCITT.
- generateQRCodeUrl(data, size) — URL do QR code via api.qrserver.com.
- Sanitiza acentos/caracteres não-ASCII.
- Campos EMV: ID 26 (Merchant Account), ID 62 (TXID), CRC16 ID 63.

### 10.2 dateUtils.js — Timezone Brasília
- BR_TIMEZONE = "America/Sao_Paulo"
- parseLocalDate(dateStr) — Parseia "YYYY-MM-DD" como data local (evita bug UTC-midnight).
- formatBR(dateValue, formatStr) — Formata SEMPRE em Brasília (UTC-3) independente do browser.
- nowBR() — Momento atual em Brasília.

### 10.3 numberingUtils.js — Numeração de Ingressos
- formatTicketNumber(num, config) — Formata com prefixo e zeros (001, ING-001).
- generateNumberRange(config) — Gera faixa completa com cortesias.
- getSaleNumbers(config) / getCourtesyNumbers(config) — Filtra venda/cortesia.
- findNextAvailableNumber(config, usedNumbers, courtesyOnly) — Próximo disponível.
- findContiguousBlock(config, usedNumbers, quantity) — Bloco contíguo para consignação.
- parseTicketNumber(formatted, config) — Converte formatado→numérico.
- getNumberingSummary(config) — Resumo para exibição.
- DEFAULT_BUENOS_AIRES_CONFIG — Config específica (368 lugares, 353 venda, 15 cortesias 354-368).

### 10.4 stockUtils.js — Controle de Estoque
- getUsedNumbers(registrations, sessionId) — Números já alocados (exclui cancelado/devolvido).
- getAvailableNumbers(config, registrations, sessionId, courtesyOnly) — Disponíveis para venda.
- findNextAvailableForSession(...) — Próximo disponível na sessão.
- findContiguousBlockForSession(...) — Bloco contíguo para consignação.
- isNumberAvailable(...) — Verifica disponibilidade.
- getStockSummary(...) — Resumo {total, available, sold, consigned, courtesy, courtesyAvailable}.
- logTicketHistory(base44, params) — Cria registro de auditoria em TicketHistory.

### 10.5 batchUtils.js — Virada de Lotes
- computeActiveBatch(batches, soldCount, now) — Calcula lote vigente client-side.
  Retorna {activeBatch, nextBatch, remaining, hoursLeft, soldInThis, isLastUnits, batchIndex}.
  Lote expira por data OU por quantidade.
  isLastUnits = remaining <= 10% da capacidade (mín 5).
- formatHoursLeft(hours) — "encerra agora", "virada em Xmin/h/d".

### 10.6 ticketUtils.js — Templates de Ingresso
- generateQrCode() — EVT-{timestamp}-{random9}.
- generateShortCode() — 6 dígitos aleatórios.
- deriveShortCode(qrCode) — Hash determinístico para ingressos antigos.
- getShortCode(reg) — short_code ou derivado.
- buildTicketHTML(reg, event, layout, session) — HTML ingresso digital (A4 ou thermal 80mm).
- buildPhysicalTicketHTML(reg, event, session) — HTML ingresso físico A4 com canhoto destacável.
- buildBatchHTML(regs, event, layout, sessions) — Lote de ingressos para impressão.
- buildPhysicalBatchHTML(regs, event, sessions) — Lote físico A4.
- openPrintWindow(html, title) — Abre janela de impressão.

### 10.7 tenantUtils.js — Multi-Tenant
- isGlobalView() / setGlobalView(value) — localStorage "admin-global-view".
- getEventFilterForUser(user, globalView) — Filtro de eventos por papel.

### 10.8 AuthContext.jsx — Contexto de Auth
- Provider que gerencia user, organizer, isAuthenticated, modoPlano, isOrganizerSuspended.
- loadOrganizer(email) — busca Organizer pelo email.
- checkAppState() / checkUserAuth() — fluxo de inicialização.

### 10.9 Outros libs
- offlineCheckin.js — Check-in offline com cache local e sync.
- app-params.js — Parâmetros do app (appId, token).
- query-client.js — Instância do QueryClient (TanStack).
- NavigationTracker.jsx — Tracker de navegação.
- PageNotFound.jsx — Página 404.
- utils.js — cn() (clsx + tailwind-merge).

### 10.10 Hooks
- useAdminView.jsx — Hook para visão admin.
- use-mobile.jsx — Detecção mobile.

---

## 11. REGRAS DE NEGÓCIO

### 11.1 Modos de Operação
- COMPLETO: Todas funcionalidades (PDV, numeração, consignação, promoters, lotes, marketing, financeiro, analytics).
- EVENTO_PIX: Simplificado — checkout página única, sem multi-step, foco PIX manual.

### 11.2 Tipos de Evento
- Inscrição (free_event_type=inscricao): confirmar presença. Pode ser individual (1 por compra, exige nome) ou múltiplo.
- Ingresso (free_event_type=ingresso): garantir entrada. Permite multi-ticket.
- inscricao_requires_names: true = individual (1 por compra), false = múltiplos sem nome.

### 11.3 Modos de Ingresso (ticket_mode)
- general: Entrada geral, sem numeração. Controlado por capacidade total.
- numbered: Numerado sequencial (001, 002...) sem assento marcado.
- numbered_seat: Mapa de assentos (numerado com assento marcado). Requer seat_map_config.

### 11.4 Pagamentos
- PIX Manual (enable_pix_manual): comprovante + confirmação manual pelo organizador.
- Gateways: mercado_pago, pagbank, asaas, pagarme, stripe (via PaymentGateway).
- Cartão: via Stripe (requer chaves Stripe no PaymentGateway).
- PDV físico: dinheiro, pix, cartao (enable_physical_sales).

### 11.5 Confirmação de Pagamento
- Automática: apenas status confirmed (PAGO) dispara entrega de ingresso.
- Manual: organizador aprova na PixConferenceTab → pode enviar recibo WhatsApp.
- Status: pending → aguardando_confirmacao → confirmed/rejected.

### 11.6 Comunicações
- WhatsApp exclusivo para todas as comunicações automatizadas e manuais (evita consumo de créditos de email).
- NÃO dispara WhatsApp automático após inscrição no modo EVENTO_PIX.
- Centralização no painel manual do organizador.
- Mascaramento WhatsApp: (xx)xxxxx-xxxx.
- Templates incluem: nome completo + quantidade + tipo (Inscrição/Ingresso) + valor.

### 11.7 Co-organizador
- Acesso via email autenticado (co_organizer_email no Event).
- Comparação case-insensitive.
- Login obrigatório (sem acesso público via link — risco de segurança).
- Pode gerenciar evento (EventManage) e checkout simples.
- Co-organizador sem email: autentica via WhatsApp (auto-generated login).

### 11.8 Check-in
- Restrito a QR code ou lista física pelo organizador.
- Funciona online e offline (cache local + sync).
- Valida: inscrição existe, pagamento confirmed, sessão compatível.

### 11.9 Identificação de Participantes
- Nome e WhatsApp são campos obrigatórios e primários.
- Email NUNCA é identificador único.
- Display: full_name como primário, responsible_name como fallback.
- Destaque com ícone de usuário em listas PIX.

### 11.10 SuperAdmin
- Ativa/suspende organizadores (Organizer.status).
- Gera credenciais temporárias (temp_password).
- Visão global (vê todos os eventos) ou visão organizador (só seus).
- Gerencia organizers, subscriptions, commission payments.

### 11.11 Multi-Ticket
- Permitido por default (allow_multiple_tickets).
- Restrito apenas por capacidade do ticket.
- max_tickets_per_purchase: limite por compra (null = ilimitado).

### 11.12 PIX Checkout
- BR Code (EMV-QRCPS MPM) padrão BACEN para todos os displays.
- Auto-copia para clipboard imediatamente.
- Modo EVENTO_PIX: single-page, sem redirecionamentos, sem multi-step.

### 11.13 Conferência PIX
- Agrupamento por cliente (WhatsApp) para aprovação em lote.
- Aprovação individual ou em lote.
- Botão "Enviar Recibo" separado com WhatsApp pré-preenchido.
- Mensagem: "Olá {nome}! Seu pagamento para '{evento}' foi CONFIRMADO ✓ Quantidade: {qty} {tipo}(s) Valor total: R$ {total} Deus abençoe sempre, até lá."

---

## 12. FLUXO DE PAGAMENTO PIX

1. Cliente acessa SalesPage (público)
2. Seleciona ticket type / quantidade
3. Preenche Nome + WhatsApp (+ email opcional)
4. Cria Registration (payment_status=pending) + Order
5. Gera BR Code (pixUtils.generatePixBRCode)
6. Display PIX Copia e Cola + QR Code
7. Auto-copia para clipboard
8. Cliente paga PIX → envia comprovante (PaymentProofUpload)
9. Registration → payment_status=aguardando_confirmacao
10. Organizador aprova na PixConferenceTab
11. Registration → payment_status=confirmed
12. Organador envia recibo WhatsApp (manual)
13. Ingresso disponível na página /Ticket (com QR)

---

## 13. SISTEMA DE NUMERAÇÃO DE INGRESSOS

Configuração (Event.numbering_config):
{
  start: 1,           // número inicial
  end: 368,           // número final
  prefix: "",         // prefixo opcional (ex: "ING")
  digits: 3,          // qtd dígitos (001)
  courtesy_start: 354, // início faixa cortesia
  courtesy_end: 368,   // fim faixa cortesia
  repeat_per_session: true // numeração reinicia por sessão
}

Modos:
- Modo A (numbered): Numeração sequencial sem assento.
- Modo B (numbered_seat): Mapa de assentos com setores, blocos, filas e assentos.

Algoritmo:
1. generateNumberRange(config) gera todos os números.
2. Cortesias separadas por courtesy_start/end.
3. findNextAvailableNumber busca próximo livre (exclui usados).
4. findContiguousBlock encontra bloco contíguo para consignação.
5. Numeração pode repetir por sessão (repeat_per_session).

---

## 14. CONTROLE DE ESTOQUE

Estoque único sincronizado (online + PDV + consignação):

getStockSummary(config, registrations, sessionId) → {
  total: 368,          // total de números
  available: 300,      // disponíveis para venda
  sold: 50,            // vendidos/utilizados
  consigned: 15,       // consignados a promoters
  courtesy: 3,         // cortesias emitidas
  courtesyAvailable: 12, // cortesias disponíveis
  totalSale: 353,      // total para venda
  totalCourtesy: 15    // total cortesias
}

Regras:
- Número cancelado/devolvido retorna ao estoque.
- Número consignado não está disponível para venda online.
- Cortesias têm pool separado.
- Auditoria: toda ação gera TicketHistory.

---

## 15. SISTEMA DE LOTES

Virada automática (batchUtils.computeActiveBatch):
- Lote ativo = primeiro lote não expirado (por data OU por quantidade).
- soldCount acumulado determina posição nos lotes.
- isLastUnits = remaining <= 10% capacidade (mín 5) → gatilho de urgência.
- hoursLeft → countdown timer.

Estrutura:
Lote 1 (Promocional): 100 ingressos, -20%, até 01/09
Lote 2 (Normal): 150 ingressos, -10%, até 15/09
Lote 3 (Última hora): 50 ingressos, 0%, até 20/09

---

## 16. CHECK-IN / PORTARIA

CheckIn (src/pages/CheckIn.jsx):
- Online: scanner QR via html5-qrcode + validação server.
- Offline: cache local (offlineCheckin.js) + sync quando volta conexão.
- Manual: digitação do short_code (6 dígitos).
- Valida: inscrição existe, pagamento confirmed, sessão compatível.
- Registra checked_in=true, checked_in_date.
- Cria TicketHistory action=checked_in.

---

## 17. SECRETS & CREDENCIAIS

ZOHO_SMTP_PASSWORD — Senha SMTP Zoho — sendEmail backend function
RESEND_API_KEY — API key Resend — Não utilizado ativamente

API keys armazenadas como secrets, nunca hardcoded.
PaymentGateway.credentials_ref referencia o secret (nunca o valor).

---

## 18. PROBLEMAS CONHECIDOS

1. EventFormDialog screen 3 — fecha prematuramente durante transição do wizard.
2. sendEmail — sem restrição admin-only (limite do plano atual). Backend functions inacessíveis sem upgrade.
3. full_name em registros legados — pode não renderizar em EventRegistrationsTab (PixPresenceTab tem fallback).
4. Signup page — referenciada em publicPages mas não existe como rota explícita.

---

## 19. DECISÕES DE PRODUTO

1. Event como vitrine pública com flag is_public.
2. FinancialEntry + Expense para dados financeiros.
3. Inscrições restritas a entradas individual/intransferível.
4. Ingressos permitem multi-ticket.
5. WhatsApp exclusivo para notificações (evita créditos de email).
6. RLS granular em todas as entidades core.
7. Co-organizador via co_organizer_email em RLS + routing EventManage.
8. Dashboard unificado agrega eventos onde user é criador OU co-organizador.
9. EventManage + checkout simples para co-organizadores autenticados.
10. SimpleEventForm com descrição, cover_image, IA.
11. co_organizer_whatsapp para contato/instruções.
12. Tab "2º Organizador" no EventManage para convite/instruções.
13. Co-organizador sem email autentica via WhatsApp.
14. BR Code EMV-QRCPS MPM padrão BACEN para todos os PIX.
15. Nome + WhatsApp como identificador primário (não email).
16. Edit/Delete em inscrições no modo EVENTO_PIX via PixPresenceTab.
17. full_name primário, responsible_name fallback.
18. Destaque full_name com ícone em PixPresenceTab/PixConferenceTab.
19. Recibo padronizado com nome completo + quantidade + tipo.

---

## 20. PREFERÊNCIAS DO USUÁRIO

1. API keys como secrets, nunca hardcoded.
2. Entrega automática de ingresso apenas status confirmed (PAGO).
3. Detecção de tipo (Inscrição vs Ingresso) em todos os templates.
4. WhatsApp exclusivo para todas as comunicações (evita créditos email).
5. Horário de Brasília (UTC-3) para toda lógica de data/timezone.
6. formatBR centralizado para toda formatação de data/hora.
7. SuperAdmin exclusivo para ativar/suspender organizers e gerar credenciais.
8. Multi-ticket permitido por default (exceto se restrito por capacidade).
9. Auto-copia clipboard para códigos PIX.
10. EVENTO_PIX = checkout single-page, sem redirecionamentos.
11. NÃO disparar WhatsApp automático pós-inscrição no EVENTO_PIX.
12. Centralização no painel manual do organizador.
13. Mascaramento WhatsApp: (xx)xxxxx-xxxx.
14. Aprovação em lote na Conference tab agrupando por cliente.
15. Login obrigatório para co-organizadores (sem acesso público).
16. Lookups por email case-insensitive.
17. Nome + WhatsApp obrigatórios (email nunca único).
18. Check-in restrito a QR code ou lista física.
19. Nome como identificador primário em listas.
20. Botões dedicados para envio de recibo WhatsApp pré-preenchidos.

---

## 📐 TAMANHOS DE IMAGEM RECOMENDADOS

Capa Desktop (vitrine/página): 1200 × 400 px — 3:1 (paisagem larga)
Capa Mobile (celular): 800 × 600 px — 4:3
Imagem no ingresso (QR Code): 600 × 400 px — 3:2

Dica: envie imagem maior (1200px+). O sistema ajusta o corte automaticamente via CSS object-cover.

---

## 📁 ESTRUTURA DE ARQUIVOS

evento-rapido/
├── base44/
│   ├── config.jsonc
│   ├── entities/              # 18 schemas JSON
│   ├── functions/
│   │   └── sendEmail/entry.ts  # (inacessível sem upgrade)
│   ├── agents/                 # (vazio)
│   └── workflows/              # (vazio)
├── src/
│   ├── App.jsx                 # Router + AuthProvider
│   ├── Layout.jsx              # Nav + layout
│   ├── main.jsx                # Entry
│   ├── index.css               # Tailwind + design tokens
│   ├── pages.config.js         # Config de rotas
│   ├── api/
│   │   └── base44Client.js     # SDK pré-inicializado
│   ├── pages/                  # 12 páginas + PDV + Organizers
│   ├── components/
│   │   ├── ui/                 # shadcn/ui (50+ componentes)
│   │   ├── event-manage/       # Tabs do EventManage
│   │   ├── events/             # Formulários e cards
│   │   ├── sales/              # Checkout e pagamento
│   │   ├── tickets/            # Tipos, numeração, impressão
│   │   ├── promoters/          # Promoters e acerto
│   │   ├── payments/           # Gateways
│   │   ├── organizers/         # Form organizer
│   │   ├── marketing/          # Templates e automações
│   │   ├── communications/     # Email participantes
│   │   ├── emails/             # Confirmation sender
│   │   ├── financeiro/         # DRE
│   │   ├── feedback/           # Feedback form
│   │   ├── ai/                 # AI assistant
│   │   └── automation/        # Reminder scheduler
│   ├── lib/
│   │   ├── AuthContext.jsx     # Contexto de auth
│   │   ├── tenantUtils.js      # Multi-tenant
│   │   ├── pixUtils.js         # BR Code PIX
│   │   ├── dateUtils.js        # Timezone Brasília
│   │   ├── numberingUtils.js   # Numeração ingressos
│   │   ├── stockUtils.js       # Controle estoque
│   │   ├── batchUtils.js       # Virada de lotes
│   │   ├── ticketUtils.js      # Templates ingresso
│   │   ├── offlineCheckin.js   # Check-in offline
│   │   ├── app-params.js       # Params app
│   │   ├── query-client.js     # QueryClient
│   │   ├── NavigationTracker.jsx
│   │   ├── PageNotFound.jsx
│   │   └── utils.js            # cn()
│   ├── hooks/
│   │   ├── useAdminView.jsx
│   │   └── use-mobile.jsx
│   └── utils/
│       └── index.ts            # createPageUrl
├── tailwind.config.js
├── postcss.config.js
├── vite.config.js
├── package.json
├── index.html
└── README.md

---

## 🚀 COMANDOS

npm install      # Instalar dependências
npm run dev      # Desenvolvimento
npm run build    # Build produção (./dist)

---

Documentação gerada em: 01/09/2026
Versão do App: Evento Rápido (SaaS multi-tenant)
Plano atual: Sem backend functions (requer upgrade para modificar sendEmail)
URL pública: https://eventorapido.base44.app

Fim da documentação completa.