wedding-management-system

Mapa de Assentos (Seating Chart)

A partir da v0.3.0 o sistema tem uma tela visual para distribuir convidados em mesas. Acesse em /dashboard/wedding-day/seating.

Acesso na UI: item “Mapa de assentos” no menu lateral (grupo Casamento, logo abaixo de “Dia D”) e card de atalho no topo da página /dashboard/wedding-day.

Modelo de dados

O campo legado Guest.tableNumber (string) continua existindo mas não é mais usado para alocação. Considere migrar entrada por entrada e remover em versão futura.

Fluxo

  1. Criar mesa — botão “Nova mesa”, informa nome, capacidade e formato. A mesa nasce sem convidados.
  2. Alocar convidado — o pool lateral lista convidados com rsvpStatus = CONFIRMED e tableId = null, ordenados por nome. Arraste o chip para uma mesa.
  3. Capacidade — considera +1 confirmados. Convidado com plusOnesConfirmed = 2 ocupa 3 assentos. Drop em mesa cheia falha silenciosamente com toast.
  4. Reordenar mesas — cada card tem uma alça (ícone GripVertical no cabeçalho). Arraste pela alça para mudar a ordem das mesas no grid; a nova ordem é persistida em sortOrder. Só a alça inicia o arrasto da mesa, então os chips de convidado dentro do card continuam clicáveis/arrastáveis.
  5. Desalocar — solte o chip de volta no pool. O tableId volta a ser null.
  6. Excluir mesa — soft delete. Convidados que estavam nela são desalocados em transação.

Server actions (src/app/actions/seatingTableActions.ts)

Todas exigem permissão de edição (denyIfNoEdit) e gravam AuditLog (entity SeatingTable ou Guest, action CREATE / UPDATE / DELETE / REORDER / ASSIGN_TABLE / UNASSIGN_TABLE).

A ordenação inicial em page.tsx é orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }] — mesas antigas (todas com sortOrder = 0) caem no desempate por data de criação.

Dependência

Coexistência de dois arrastos no mesmo DndContext

Cada card de mesa é, ao mesmo tempo, um item sortable (reordenável) e um droppable que recebe convidados. Para o over nunca ficar ambíguo, o DndContext usa uma collisionDetection customizada (seatingCollision em seating-client.tsx) que filtra os candidatos pelo tipo do item ativo:

Limitações conhecidas