# Eventos e ingressos

**Para quem:** produtor, organizador, gerente  
**Última revisão:** 2026-07-13  
**Rotas relacionadas:** `/seller/events`, `/seller/new-event`, `/seller/events/[id]/edit`, `/seller/events/[id]`

---

## O que você consegue fazer

- Criar eventos com uma ou várias datas (sessões)
- Configurar lotes de ingressos com preços e quantidades
- Controlar vendas (abertas, pausadas, encerradas)
- Gerenciar fila de espera em tempo real
- Emitir cupons, cortesias e certificados de participação

---

## Pré-requisitos

- Organização criada e vinculada ao seu usuário
- **Stripe Connect ativo** com saques habilitados (`payoutsEnabled`) — sem isso, o botão **+ evento** em `/seller/events` não aparece
- Role com permissão para criar eventos (`organizer`, `manager` ou `admin`)

Detalhes de pagamentos: [Stripe e taxas](../pagamentos/stripe-e-taxas.md).

---

## Passo a passo — Criar evento

### 1. Abrir o formulário

Acesse `/seller/new-event` ou clique em **+ evento** em `/seller/events`.

### 2. Preencher informações básicas

| Campo | Obrigatório | Observação |
|-------|-------------|------------|
| Nome do evento | Sim | Mínimo 1 caractere |
| Endereço público (slug) | Sim | Link `/event/{slug}`; sugerido a partir do nome, editável; não pode repetir slug de outro evento, mesmo passado |
| Organização | Sim | Só na criação; evento fica vinculado ao dono da org |
| Descrição | Sim | Texto público do evento |
| Localização | Sim | Endereço + coordenadas via Google Places |
| Data principal | Sim | Deve ser hoje ou data futura |
| Horário início / término | Sim | Formato de hora |
| Capa | Não | Imagem opcional (comprimida) |
| Categoria (tag) | Não | theater, dance, music, exhibition, cinema, circus, party, class, gastronomy, fashion |

### 3. Datas adicionais (múltiplas sessões)

Use **+ adicionar outra data** para eventos com mais de um dia. Cada data vira uma **sessão** (`eventSessions`) com lotes próprios.

**Atenção:** confirme a **data principal** antes de salvar. Se você só adicionar datas extras sem editar a data principal (que vem preenchida com hoje por padrão), o formulário bloqueia o envio com a mensagem *"Confirme a data principal do evento"*.

### 4. Configurar lotes

Se o evento vende ingressos (opção **Não ofertar tickets** desmarcada):

- Cada data tem abas de lotes
- Por lote: **nome**, **preço (R$)**, **quantidade**, **info** opcional (ex.: elegibilidade para meia)
- Use **+ adicionar lote** para criar lotes extras (ilimitados)
- A soma de todas as quantidades deve ser **maior que zero**

### 5. Opções de venda

| Opção | Efeito |
|-------|--------|
| **Evento privado** | Não aparece na home nem na página da org; acesso só por link |
| **Começar com vendas abertas / pausadas** | `salesStatus: open` ou `paused` na criação |
| **Meia entrada disponível** | Habilita tipo meia na compra |
| **Certificado de participação** | Se ativo, título do certificado é obrigatório |
| **Não ofertar tickets** | Evento sem venda; lotes não são exigidos |

### 6. Publicar

Ao salvar, o sistema:

- Gera **slug** único a partir do nome (editável no formulário; não reutiliza slugs de eventos já criados)
- Gera **senha de validação** (12 caracteres) para check-in
- Cria sessões e lotes no Convex
- Redireciona para a página pública `/event/{slug}`

---

## Arquitetura de ingressos

```
events (evento pai)
  └── eventSessions (uma por data)
        └── ticketBatches (lotes ilimitados por sessão)
```

Cada lote tem: `name`, `price`, `totalTickets`, `soldTickets`, `isActive`, `salesStart`, `salesEnd`.

---

## Passo a passo — Gerenciar evento

Em `/seller/events`, expanda o card do evento. Para um guia visual completo do card (como chegar, expandir, cada botão e seção), veja [06 — Gestão de eventos no painel](06-gestao-de-eventos-no-painel.md).

Resumo das ações no card:

| Ação | Rota / componente |
|------|-------------------|
| Editar | `/seller/events/{id}/edit` |
| Dashboard de vendas | `/seller/events/{slug ou id}` |
| Validar tickets | `/seller/validate-ticket/{password}` |
| Status de vendas | Abrir / pausar / encerrar |
| Virar lote | Encerra lote atual (`isActive: false`) |
| Cupons | Gerar códigos de desconto |
| Cortesias | Links de convite gratuitos |
| Cancelar evento | Dispara fluxo de cancelamento e reembolsos |
| Bar digital | Ativar módulo de consumo no evento |

### Edição de ingressos

Ao editar em `/seller/events/[id]/edit`:

- Ingressos **já vendidos continuam válidos**
- Você pode **aumentar** a quantidade de um lote
- **Não reduza** abaixo do que já foi vendido

Eventos **curados** (`isCurated`) usam editor simplificado sem lotes/sessões dinâmicos.

---

## Fila de espera

Quando um lote esgota, compradores entram na fila.

### Fluxo de status

```
waiting → offered → purchased
                 ↘ expired
```

| Status | Significado |
|--------|-------------|
| `waiting` | Na fila, aguardando vaga |
| `offered` | Vaga liberada — 30 minutos para pagar |
| `purchased` | Pagamento concluído |
| `expired` | Oferta expirou; vaga volta para a fila |

### Regras importantes

- Oferta dura **30 minutos** (mínimo permitido pelo Stripe para expiração de checkout)
- Na fila de espera (sem vaga imediata), máximo **1 ingresso** por entrada
- Ingressos **gratuitos**: limite de **5 por pessoa** por evento
- Lotes especiais (`LoteTrans`, `LoteFlinta`) têm regras próprias na fila
- Cron a cada **10 minutos** limpa ofertas expiradas e reprocessa a fila

---

## Taxas em ingressos

Taxa da plataforma: **9%** em compras a partir de 03/07/2026 14:06 BRT (5% antes dessa data). Ver [Stripe e taxas](../pagamentos/stripe-e-taxas.md).

---

## O que acontece nos bastidores

- O `userId` do evento é o **dono da organização**, não necessariamente quem preencheu o formulário (colaborador).
- Eventos públicos com seguidores na org disparam notificação push na criação.
- Vendas podem encerrar automaticamente via cron (`autoCloseExpiredSales`, a cada 2 min) se configurado.
- Um evento só é considerado "passado" após a **última sessão** + horário de término.

---

## Problemas comuns

| Sintoma | Causa provável | O que fazer |
|---------|----------------|-------------|
| Não vejo "+ evento" | Stripe sem payouts habilitados | Complete onboarding em `/guides` |
| Erro ao salvar: data principal | Só usou datas adicionais | Edite/confirme o campo Data principal |
| Erro: lotes zerados | Quantidade total = 0 | Adicione quantidade em pelo menos um lote |
| Comprador perdeu a vaga | Oferta de 30 min expirou | Entrar na fila novamente |
| Não consigo reduzir ingressos | Já vendidos no lote | Só é possível aumentar a capacidade |
| Evento não aparece no mapa | Sem latitude/longitude ou fora das cidades ativas | Confirme localização (BH, Rio, SP) |

---

## Referências de código (time interno)

- `app/seller/new-event/page.tsx` — rota de criação
- `app/seller/events/page.tsx` — lista e gate Stripe
- `app/seller/events/[id]/edit/page.tsx` — edição
- `components/event/EventForm.tsx` — formulário principal
- `components/event/LoteFields.tsx` — UI de lotes
- `components/seller/SellerEventCard.tsx` — ações expandidas
- `convex/events.ts` — `create`, `updateEvent`, `joinWaitingList`, `virarLote`
- `convex/eventBatches.ts` — `getEventSessions`, `getEventBatches`
- `convex/waitingList.ts` — fila e expiração
- `convex/constants.ts` — `TICKET_OFFER` (30 min)
