docs: adiciona spec de design da Reserva Rede 1001
Novo app publico de reserva (Vite + React + Supabase) separado do Chatwoot, que reusa toda a tubulacao de PIX (CobService, PixCharge, webhook Inter, ConfirmationService) via um endpoint novo no Chatwoot. Cobre: arquitetura, paleta premium, modelo de dados reformado (corrige bug de preco nos domingos), contrato da API nova, fluxo do cliente, plano de entrega em 6 fases e riscos. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cdc5149866
commit
944cec7136
463
docs/superpowers/specs/2026-04-13-reserva-1001-design.md
Normal file
463
docs/superpowers/specs/2026-04-13-reserva-1001-design.md
Normal file
@ -0,0 +1,463 @@
|
||||
# Reserva Rede 1001 — Design
|
||||
|
||||
**Data:** 2026-04-13
|
||||
**Autor:** Rodrigo Borba Machado (com assistência do Claude)
|
||||
**Status:** Aprovado para planejamento
|
||||
|
||||
---
|
||||
|
||||
## 1. Contexto e objetivo
|
||||
|
||||
O Grupo Nova opera 4 marcas de hotéis/motéis em Brasília e Natal: **Hotel 1001 Noites**, **1001 Noites Prime**, **1001 Noites Express** e **Dolce Amore**. Hoje a reserva é feita pela atendente via WhatsApp, que gera um PIX usando a ferramenta `Captain::Tools::GeneratePix` dentro do Chatwoot fazer.ai. Essa ferramenta pode falhar (erro de API, mTLS, autenticação), e quando falha não há fallback automatizado.
|
||||
|
||||
**Objetivo:** criar uma página pública de reserva onde o próprio cliente:
|
||||
1. Escolhe marca → unidade → permanência → categoria de suíte → data/hora de check-in
|
||||
2. Vê fotos da categoria e o preço total
|
||||
3. Preenche dados pessoais (nome, telefone, CPF, e-mail)
|
||||
4. Paga 50% de entrada via PIX (QR code + copia-e-cola) direto na página
|
||||
5. Ao confirmar o pagamento, uma mensagem automática aparece na conversa do WhatsApp da atendente no Chatwoot
|
||||
|
||||
É fallback pro fluxo manual e também canal direto de auto-atendimento.
|
||||
|
||||
**Escopo EXCLUÍDO:**
|
||||
- Disponibilidade em tempo real (é catálogo fixo — atendente resolve conflitos no check-in)
|
||||
- Integração com PMS externo
|
||||
- Login de cliente / histórico de reservas do cliente
|
||||
- Reserva de suíte específica (sempre por categoria)
|
||||
- Segunda metade do pagamento online (50% restantes ficam para o check-in)
|
||||
|
||||
---
|
||||
|
||||
## 2. Decisões-chave
|
||||
|
||||
| Decisão | Escolha | Motivo |
|
||||
|---|---|---|
|
||||
| App separado do Chatwoot | ✅ Sim | Stack diferente (React vs Rails/Vue 2), deploy diferente, Chatwoot é dashboard interno ruim para página de conversão |
|
||||
| Stack | Vite + React 19 + TS | Mantém o POC existente, evita overkill do Next.js para app de checkout |
|
||||
| UI | Tailwind v4 + shadcn/ui + Radix | Mantém base do POC, adiciona shadcn oficial |
|
||||
| Animação | framer-motion (já tem) + anime.js (adicionar) | Pedido do usuário |
|
||||
| Banco | Supabase Postgres + Auth + Storage | Usuário já usa Supabase |
|
||||
| Deploy | Vercel | Grátis, deploy em 30s |
|
||||
| Geração de PIX | **Chatwoot API** (novo endpoint) | Reusa `Captain::Inter::CobService`, `PixCharge`, webhook Inter e `ConfirmationService` — zero duplicação, auto-mensagem no WhatsApp de graça |
|
||||
| Detecção de pagamento | Webhook Inter existente (`/api/v1/captain/webhooks/inter_pix`) | Já funciona hoje; novo app só consulta status |
|
||||
| Repositório | `fazer-ai-kanban/reserva-1001/` (irmão do `chatwoot/`) | Separado mas próximo |
|
||||
|
||||
---
|
||||
|
||||
## 3. Identidade visual — paleta premium
|
||||
|
||||
Inspiração: hotelaria de luxo boutique, tema árabe noturno de 1001 Noites, sensual sem ser brega.
|
||||
|
||||
| Token | Hex | Uso |
|
||||
|---|---|---|
|
||||
| `obsidian` | `#0B0D12` | Fundo principal |
|
||||
| `midnight` | `#0F1A2E` | Superfícies elevadas (cards, modais) |
|
||||
| `champagne` | `#C9A961` | Ação primária, destaques de luxo, botão "Confirmar e Pagar" |
|
||||
| `rose-gold` | `#E8B4A0` | Ação secundária, acentos sensuais, labels de carinho |
|
||||
| `ivory` | `#F5F1E8` | Texto principal sobre fundos escuros |
|
||||
| `slate` | `#6B7280` | Texto secundário, placeholders |
|
||||
| `emerald` | `#10B981` | Estado de sucesso (pagamento confirmado) |
|
||||
| `ruby` | `#E11D48` | Estado de erro, validações |
|
||||
|
||||
**Tipografia:** manter **Inter** (já no POC) para UI. Adicionar **Fraunces** (serif display) para hero e títulos — dá contraste editorial/luxo.
|
||||
|
||||
**Gradientes:** `obsidian → midnight` no fundo, `champagne → rose-gold` em CTAs.
|
||||
|
||||
---
|
||||
|
||||
## 4. Arquitetura de alto nível
|
||||
|
||||
```
|
||||
┌────────────────────────┐ ┌────────────────────────┐
|
||||
│ reserva-1001 │ │ Chatwoot (Rails) │
|
||||
│ React + Vite │──API─▶│ │
|
||||
│ Supabase │ │ Novo controller: │
|
||||
│ Vercel │ │ PublicReservations │
|
||||
│ │ │ │
|
||||
│ • Página pública │ │ Reusa existente: │
|
||||
│ • Admin │ │ • Captain::Inter:: │
|
||||
│ • Checkout PIX │ │ CobService │
|
||||
└─────────┬──────────────┘ │ • PixCharge │
|
||||
│ │ • ConfirmationSvc │
|
||||
▼ │ • Webhook Inter │
|
||||
┌─────────────┐ │ • Auto-msg WhatsApp │
|
||||
│ Supabase │ └────────────────────────┘
|
||||
│ Postgres │ ▲
|
||||
│ Auth │ │
|
||||
│ Storage │ webhook
|
||||
└─────────────┘ │
|
||||
┌───────┴──────┐
|
||||
│ Banco Inter │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
**Separação de responsabilidades:**
|
||||
|
||||
| Sistema | É dono de |
|
||||
|---|---|
|
||||
| **reserva-1001** | UX pública, UX admin, cadastro (marcas/unidades/categorias/preços/fotos/extras), formulário de reserva, tela de checkout, polling de status |
|
||||
| **Chatwoot** | Contato, conversa, inbox WhatsApp, geração de PIX via Inter, PixCharge, detecção de pagamento, mensagem automática na conversa da atendente |
|
||||
|
||||
O novo app **não** duplica nada do Chatwoot — ele consome a API.
|
||||
|
||||
---
|
||||
|
||||
## 5. Modelo de dados (Supabase)
|
||||
|
||||
Reformulação sobre o schema do POC, corrigindo problemas e adicionando o que falta.
|
||||
|
||||
```sql
|
||||
-- Marcas (4 fixas inicialmente)
|
||||
brands (
|
||||
id bigserial primary key,
|
||||
name text not null,
|
||||
slug text not null unique,
|
||||
logo_url text,
|
||||
primary_color text,
|
||||
created_at timestamptz default now()
|
||||
)
|
||||
|
||||
-- Unidades físicas de cada marca
|
||||
hotel_units (
|
||||
id bigserial primary key,
|
||||
brand_id bigint references brands(id) on delete cascade,
|
||||
name text not null,
|
||||
slug text not null,
|
||||
chatwoot_unit_id bigint not null, -- FK lógica pro Captain::Unit do Chatwoot
|
||||
active boolean default true,
|
||||
created_at timestamptz default now(),
|
||||
unique (brand_id, slug)
|
||||
)
|
||||
|
||||
-- Categorias de suíte (antes era JSON em hotel_units)
|
||||
suite_categories (
|
||||
id bigserial primary key,
|
||||
unit_id bigint references hotel_units(id) on delete cascade,
|
||||
name text not null,
|
||||
description text,
|
||||
sort_order int default 0,
|
||||
active boolean default true,
|
||||
created_at timestamptz default now()
|
||||
)
|
||||
|
||||
-- Fotos por categoria (antes era JSON)
|
||||
suite_images (
|
||||
id bigserial primary key,
|
||||
category_id bigint references suite_categories(id) on delete cascade,
|
||||
storage_path text not null, -- path no Supabase Storage
|
||||
alt text,
|
||||
sort_order int default 0,
|
||||
created_at timestamptz default now()
|
||||
)
|
||||
|
||||
-- Preços por categoria + faixa de dia + tipo de permanência (em centavos)
|
||||
pricing (
|
||||
id bigserial primary key,
|
||||
category_id bigint references suite_categories(id) on delete cascade,
|
||||
day_range text not null, -- 'weekday' | 'weekend' (enum)
|
||||
stay_type text not null, -- '2hrs' | '3hrs' | '4hrs' | 'pernoite' | 'diaria'
|
||||
price_cents int not null check (price_cents >= 0),
|
||||
created_at timestamptz default now(),
|
||||
unique (category_id, day_range, stay_type)
|
||||
)
|
||||
|
||||
-- Extras (antes era localStorage)
|
||||
extras (
|
||||
id bigserial primary key,
|
||||
brand_id bigint references brands(id) on delete cascade,
|
||||
title text not null,
|
||||
description text,
|
||||
price_cents int not null,
|
||||
image_url text,
|
||||
active boolean default true,
|
||||
sort_order int default 0,
|
||||
created_at timestamptz default now()
|
||||
)
|
||||
|
||||
-- Reservas (NOVA — hoje só vai pro N8N, perdendo histórico)
|
||||
reservations (
|
||||
id bigserial primary key,
|
||||
brand_id bigint references brands(id),
|
||||
unit_id bigint references hotel_units(id),
|
||||
category_id bigint references suite_categories(id),
|
||||
stay_type text not null,
|
||||
checkin_at timestamptz not null,
|
||||
customer_name text not null,
|
||||
customer_phone text not null,
|
||||
customer_cpf text not null,
|
||||
customer_email text,
|
||||
notes text,
|
||||
total_cents int not null,
|
||||
deposit_cents int not null,
|
||||
chatwoot_contact_id bigint,
|
||||
chatwoot_conversation_id bigint,
|
||||
chatwoot_pix_charge_id bigint,
|
||||
pix_txid text,
|
||||
status text not null default 'pending', -- pending|paid|expired|canceled
|
||||
created_at timestamptz default now(),
|
||||
paid_at timestamptz
|
||||
)
|
||||
|
||||
-- Reserva ↔ extras escolhidos
|
||||
reservation_extras (
|
||||
reservation_id bigint references reservations(id) on delete cascade,
|
||||
extra_id bigint references extras(id),
|
||||
price_cents int not null, -- snapshot do preço no momento
|
||||
primary key (reservation_id, extra_id)
|
||||
)
|
||||
```
|
||||
|
||||
**RLS (Row Level Security):**
|
||||
- Leitura pública: `brands`, `hotel_units` (active), `suite_categories` (active), `suite_images`, `pricing`, `extras` (active)
|
||||
- Escrita: só pro role `admin` (Supabase Auth)
|
||||
- `reservations`: leitura só da própria (via service_role no backend Vite)
|
||||
|
||||
**Bug corrigido do POC:**
|
||||
- `day_range` hoje checa `dayOfWeek >= 1 && <= 3`, mas domingo é 0, fazendo domingo cair em "quinta a domingo" errado.
|
||||
- Novo schema usa enum `'weekday' | 'weekend'` e a função de mapeamento é:
|
||||
```ts
|
||||
// weekday: segunda(1) a quinta(4)
|
||||
// weekend: sexta(5), sábado(6), domingo(0)
|
||||
const isWeekend = (d: Date) => [0, 5, 6].includes(d.getDay())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Integração Chatwoot — endpoint novo
|
||||
|
||||
Único código novo no Chatwoot: um controller público autenticado por token.
|
||||
|
||||
### Arquivo novo
|
||||
`enterprise/app/controllers/public/api/v1/captain/public_reservations_controller.rb`
|
||||
|
||||
### Rotas
|
||||
```ruby
|
||||
# config/routes.rb — dentro do enterprise namespace
|
||||
namespace :public, defaults: { format: 'json' } do
|
||||
namespace :api do
|
||||
namespace :v1 do
|
||||
namespace :captain do
|
||||
resources :public_reservations, only: [:create, :show] do
|
||||
member do
|
||||
get :status
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### Autenticação
|
||||
Token opaco gerado como variável de ambiente no Chatwoot (`RESERVA_1001_API_TOKEN`), validado por `before_action`. **Não é login de agente.**
|
||||
|
||||
### POST `/public/api/v1/captain/public_reservations`
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"chatwoot_unit_id": 42,
|
||||
"category": "Spa-Hidromassagem",
|
||||
"stay_type": "3hrs",
|
||||
"checkin_at": "2026-04-14T23:57:00-03:00",
|
||||
"customer": {
|
||||
"name": "João da Silva",
|
||||
"phone": "+5561999998888",
|
||||
"cpf": "123.456.789-00",
|
||||
"email": "joao@exemplo.com"
|
||||
},
|
||||
"total_cents": 17000,
|
||||
"deposit_cents": 8500,
|
||||
"notes": "Chegaremos com 15 min de atraso"
|
||||
}
|
||||
```
|
||||
|
||||
**Fluxo interno do controller:**
|
||||
1. Valida token
|
||||
2. Carrega `Captain::Unit` por `chatwoot_unit_id`
|
||||
3. Cria ou atualiza `Contact` no account da unit (match por CPF ou telefone)
|
||||
4. Cria `Conversation` no inbox WhatsApp da unit com nota inicial da reserva
|
||||
5. Cria `Captain::Reservation` (status pending)
|
||||
6. Chama `Captain::Inter::CobService#call` com CPF, valor do depósito, PIX key da unit
|
||||
7. Cria `Captain::PixCharge` vinculada à reservation
|
||||
8. Retorna payload de checkout
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"reservation_id": 9931,
|
||||
"conversation_id": 4421,
|
||||
"pix": {
|
||||
"txid": "a1b2c3d4e5...",
|
||||
"copia_e_cola": "00020126...",
|
||||
"qrcode_base64": "data:image/png;base64,iVBORw0...",
|
||||
"expires_at": "2026-04-14T00:57:00-03:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET `/public/api/v1/captain/public_reservations/:id/status`
|
||||
|
||||
Retorna `{ "status": "pending" | "paid" | "expired" }`. Usado pelo front pra polling a cada 3s na tela de checkout.
|
||||
|
||||
### Pagamento
|
||||
- Cliente paga no app do banco dele
|
||||
- Inter bate webhook no endpoint **que já existe**: `/api/v1/captain/webhooks/inter_pix`
|
||||
- `Captain::Payments::ConfirmationService` já marca a reservation como `paid`, adiciona labels `pagamento_confirmado` + `reserva_feita`, e **já dispara a mensagem automática "✅ Pagamento confirmado!" na conversa da atendente**
|
||||
|
||||
**Zero código novo pro pagamento.** O controller novo só orquestra a criação.
|
||||
|
||||
---
|
||||
|
||||
## 7. Fluxo do cliente (UX)
|
||||
|
||||
```
|
||||
1. Landing pública
|
||||
↓
|
||||
2. Hero section ("Reserve a experiência que você merece")
|
||||
↓
|
||||
3. Formulário em cascata:
|
||||
Marca → Unidade → Permanência → Categoria → Data/Hora
|
||||
↓
|
||||
4. Preview: fotos da categoria (carrossel + lightbox)
|
||||
+ preço total destacado
|
||||
+ valor do PIX (50%) destacado
|
||||
+ extras opcionais (se tiver)
|
||||
↓
|
||||
5. Dados pessoais: nome, telefone, CPF, email, observação
|
||||
↓
|
||||
6. [Confirmar e Pagar Reserva]
|
||||
↓
|
||||
7. Loading (skeleton enquanto chama API)
|
||||
↓
|
||||
8. Tela de checkout:
|
||||
- QR code (com glow animado champagne)
|
||||
- Copia-e-cola (botão de copy com feedback)
|
||||
- Timer regressivo ("Válido por 59:48")
|
||||
- Polling de status a cada 3s
|
||||
↓
|
||||
9. Cliente paga no banco
|
||||
↓
|
||||
10. Status muda pra "paid" → animação de sucesso:
|
||||
- Confetti champagne + rose-gold
|
||||
- Check desenhado com anime.js (stroke draw)
|
||||
- Mensagem: "Reserva confirmada! Sua atendente já foi avisada."
|
||||
↓
|
||||
11. Botão "Voltar ao início" / link do WhatsApp da atendente
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Página admin
|
||||
|
||||
`/admin` — Supabase Auth (email + senha).
|
||||
|
||||
**Abas:**
|
||||
- **Marcas** — CRUD simples (nome, logo, cor primária)
|
||||
- **Unidades** — CRUD vinculado a marca, com `chatwoot_unit_id` (dropdown buscando via API do Chatwoot)
|
||||
- **Categorias** — CRUD vinculado a unidade, ordem, ativo/inativo
|
||||
- **Fotos** — upload drag-and-drop pro Supabase Storage, preview, reorder
|
||||
- **Preços** — tabela editável (categoria × day_range × stay_type)
|
||||
- **Extras** — CRUD vinculado a marca
|
||||
- **Reservas** — só leitura, lista com filtros (status, data, unidade), detalhe com link pra conversa no Chatwoot
|
||||
|
||||
---
|
||||
|
||||
## 9. Refatoração do POC — o que herdar, o que refazer
|
||||
|
||||
### Herdar (copiar direto ou com ajustes mínimos)
|
||||
- `components/FormField.tsx`, `components/SelectField.tsx`
|
||||
- `components/ui/*` (shadcn base)
|
||||
- Estrutura de seleção em cascata
|
||||
- `index.css` (design tokens base)
|
||||
- `vite.config.ts`, `tsconfig.json`
|
||||
|
||||
### Refazer
|
||||
- `App.tsx` (730 linhas, monolito) → quebrar em:
|
||||
- `pages/ReservationPage.tsx`
|
||||
- `components/reservation/HeroSection.tsx`
|
||||
- `components/reservation/ReservationForm.tsx`
|
||||
- `components/reservation/ImageCarousel.tsx`
|
||||
- `components/reservation/PriceSummary.tsx`
|
||||
- `components/reservation/ExtrasGrid.tsx`
|
||||
- `components/reservation/CustomerForm.tsx`
|
||||
- `components/checkout/PixCheckout.tsx`
|
||||
- `components/checkout/SuccessScreen.tsx`
|
||||
- `hooks/useReservationForm.ts` (consolida os 14+ useState)
|
||||
- `components/AdminPage.tsx` (881 linhas) → uma aba por arquivo em `pages/admin/*`, com `AuthGate`
|
||||
- `services/apiService.ts` → novo `services/chatwootApi.ts` que fala com o controller novo
|
||||
- `services/*.ts` (brand/unit/pricing/suite) → regenerar após novo schema
|
||||
- `supabaseClient.ts` → mover chaves pra `.env.local`, usar `import.meta.env.VITE_SUPABASE_*`
|
||||
- `index.html` → remover `importmap` do `esm.sh`, Vite bundla tudo
|
||||
- `types.ts` → regenerar via `supabase gen types typescript`
|
||||
|
||||
### Bug pra corrigir
|
||||
- Lógica de `day_range` (domingo no ramo errado) — ver seção 5
|
||||
|
||||
---
|
||||
|
||||
## 10. Melhorias visuais (animações + polish)
|
||||
|
||||
1. **Hero section** — fundo com parallax suave, gradiente `obsidian → midnight`, título em Fraunces serif com reveal escalonado (framer-motion `staggerChildren`)
|
||||
2. **Stagger entrance** nas opções de categoria/unidade quando muda a marca
|
||||
3. **Carrossel de fotos** — swipe horizontal, indicadores, clique pra lightbox em tela cheia
|
||||
4. **Pulse animation** no preço total quando recalcula (anime.js `scale: [1, 1.08, 1]`)
|
||||
5. **QR code com glow** — borda animada pulsando champagne (anime.js `keyframes`)
|
||||
6. **Skeleton screens** durante fetch inicial e submissão
|
||||
7. **Tela de sucesso** — confetti + check SVG desenhado com anime.js `stroke-dashoffset` (efeito de "desenhar" o check)
|
||||
8. **Flip cards** nos extras (CSS `rotateY` on hover)
|
||||
9. **Transições entre etapas** — `AnimatePresence` do framer-motion, slide + fade
|
||||
10. **Tipografia editorial** — Fraunces nos títulos, Inter no resto, kerning generoso
|
||||
11. **Microinterações** em botões — hover com `scale: 1.02` + glow champagne sutil
|
||||
12. **Dark glassmorphism** nos cards de categoria (backdrop-blur sobre fundo escuro)
|
||||
|
||||
---
|
||||
|
||||
## 11. Plano de entrega em fases
|
||||
|
||||
| Fase | Escopo | Critério de pronto |
|
||||
|---|---|---|
|
||||
| **1. Fundação** | Novo projeto Vite limpo em `reserva-1001/`, migração do POC, Supabase novo schema aplicado, Tailwind v4 com paleta premium, `.env` configurado, remover `importmap` do HTML | `pnpm dev` roda, Tailwind tokens ativos, schema no Supabase |
|
||||
| **2. Backend Chatwoot** | Controller `PublicReservationsController` com 2 endpoints + token auth + testes RSpec de integração | POST retorna PIX real, GET retorna status |
|
||||
| **3. Fluxo público core** | Refatoração do App em componentes, hook `useReservationForm`, integração com API nova, checkout com polling, tela de sucesso | Cliente completa reserva end-to-end em ambiente de teste |
|
||||
| **4. Admin** | Abas separadas, Supabase Auth, upload de fotos pro Storage, CRUD de todas entidades | Admin cadastra marca→unidade→categoria→fotos→preço |
|
||||
| **5. Polish visual** | Hero, carrossel, animações (framer-motion + anime.js), skeletons, tipografia, microinterações | Revisão visual aprovada |
|
||||
| **6. Deploy + QA** | Vercel com subdomínio, teste ponta-a-ponta com unidade real do Chatwoot, ajustes finais | Reserva real paga, mensagem cai na conversa da atendente |
|
||||
|
||||
---
|
||||
|
||||
## 12. Riscos e mitigações
|
||||
|
||||
| Risco | Mitigação |
|
||||
|---|---|
|
||||
| mTLS Inter falhar no controller novo | Controller reusa `Captain::Inter::CobService` — se falhar pra atendente, falha aqui também. Mesmo comportamento, mesmo suporte |
|
||||
| Webhook Inter bate antes do front terminar de criar a reservation no Supabase | Chatwoot é a fonte de verdade da reserva e do PIX. Supabase só cacheia o ID pra tela do front. Ordem: chama Chatwoot → salva IDs no Supabase |
|
||||
| Cliente sai da tela de checkout antes de pagar | Webhook Inter ainda dispara, reserva é marcada como paga no Chatwoot. Front perde a tela de sucesso mas a atendente recebe o aviso e entra em contato |
|
||||
| Admin sem autenticação hoje (POC) | Fase 4 adiciona Supabase Auth obrigatório |
|
||||
| Chave anon do Supabase exposta no repo do POC | Rotacionar antes do deploy, mover pra `.env` |
|
||||
| Domingo precificado errado | Corrigido no novo schema (seção 5) |
|
||||
|
||||
---
|
||||
|
||||
## 13. Itens fora de escopo (V2)
|
||||
|
||||
- Segunda metade do pagamento online
|
||||
- Disponibilidade em tempo real (bater PMS)
|
||||
- Login de cliente / área logada
|
||||
- Remarcação / cancelamento online
|
||||
- E-mail transacional (confirmação)
|
||||
- SMS de confirmação
|
||||
- Google Analytics / tracking de conversão
|
||||
- Multi-idioma (PT-BR apenas)
|
||||
- App mobile nativo
|
||||
|
||||
---
|
||||
|
||||
## 14. Glossário
|
||||
|
||||
- **PIX Copia-e-cola**: string que o cliente cola no app do banco para pagar
|
||||
- **txid**: ID único de transação PIX na Inter
|
||||
- **PixCharge**: modelo no Chatwoot que rastreia uma cobrança PIX
|
||||
- **Captain::Unit**: modelo no Chatwoot que representa uma unidade do hotel, com credenciais Inter próprias
|
||||
- **Day range**: se o dia do check-in é dia de semana ou fim de semana, afeta preço
|
||||
- **Stay type**: tipo de permanência (2hrs, 3hrs, 4hrs, pernoite, diária)
|
||||
Loading…
Reference in New Issue
Block a user