Frontend — Chronos
Visao Geral
Aplicacao construida com Next.js 16 + React 19 + TypeScript + Tailwind CSS usando App Router e Server Actions.
Paginas
Auth
| Rota |
Descricao |
/login |
Login (email/senha via NextAuth) |
/signup-complete |
Completar cadastro |
Dashboard (Protegido)
| Rota |
Descricao |
/dashboard |
Dashboard com calendario e proximos agendamentos |
/appointments |
Lista de agendamentos |
/schedule |
Gestao de agenda |
/services |
Catalogo de servicos |
/professionals |
Equipe |
/customers |
Clientes |
/locations |
Locais de atendimento |
/rooms |
Salas e consultórios |
/promotions |
Codigos de desconto |
/settings |
Configuracoes do tenant |
Publico (Booking)
| Rota |
Descricao |
/c/{tenantSlug} |
Pagina de agendamento do tenant |
/c/{tenantSlug}/p/{profSlug} |
Agendamento com profissional especifico |
Autenticacao
1. Login form → email + password
2. NextAuth → POST {OATH_URL}/auth/login
(provider=OATH, application=chronos)
3. JWT decodificado → user context
4. Session enriched com: jwt, uid, roles, isOwner
5. Middleware protege rotas /dashboard/*
Middleware (middleware.ts)
- Publico:
/c/*, /login, /signup-complete
- Protegido: Todas as demais rotas
- Redirect: Auth →
/dashboard, No auth → /login
Server Actions
O Chronos usa Next.js Server Actions ao inves de hooks React Query:
Appointments
getAppointments(from?, to?, professionalId?)
getAppointment(id)
updateAppointmentStatus(id, status, reason?, notes?)
createDashboardAppointment(data)
Availability
getAvailability(tenantSlug, serviceId, date, professionalId?, locationId?)
getProfessionalAvailability(tenantSlug, profSlug, serviceId, date)
Booking (Public)
createPublicBooking(tenantSlug, data)
validatePublicPromotion(tenantSlug, data)
Dashboard
getDashboardSummary()
getDashboardCalendar(from?, to?)
getDashboardUpcoming(limit?)
CRUD Actions
// Services
getServices() / getService(id) / createService() / updateService() / deleteService()
// Professionals
getProfessionals() / createProfessional() / updateProfessional() / deleteProfessional()
// Customers
getCustomers() / createCustomer() / updateCustomer() / deleteCustomer()
// Schedules
getSchedules(profId) / createSchedule() / updateSchedule() / deleteSchedule()
createScheduleException() / deleteScheduleException()
// Locations, Rooms, Promotions, Tenant — mesma pattern
API Client (lib/api.ts)
Duas funcoes utilitarias:
| Funcao |
Auth |
Uso |
fetchChronosAPI(route, tenantId?, options) |
Bearer JWT + X-Tenant-Id |
Dashboard |
fetchPublicAPI(route, options) |
Nenhuma |
Booking publico |
Base URL: NEXT_PUBLIC_CHRONOS_API_URL (default: http://localhost:5050)
Componentes Chave
Dashboard
| Componente |
Funcao |
AppointmentCalendar |
Calendario mensal com indicadores de agendamento |
UpcomingAppointments |
Proximos 8 agendamentos |
Booking Publico
| Componente |
Funcao |
BookingWizard |
5 etapas: servico → profissional → data/hora → dados → confirmacao |
ProfessionalBooking |
4 etapas (sem selecao de profissional) |
Calendario
- Status com cores: PENDING (amarelo), CONFIRMED (azul), IN_PROGRESS (violeta), COMPLETED (verde)
- Navegacao mensal + botao "Hoje"
- Click no dia mostra detalhes
Multi-Tenant
Resolucao do Tenant
// lib/tenant.ts
getCurrentTenantId() // Busca de /bff/auth/me → primary ou first
getCurrentTenant() // Retorna { id, name, slug, role, isPrimary }
O tenantId e enviado como header X-Tenant-Id em todas as chamadas autenticadas.
Utilitarios (lib/utils.ts)
| Funcao |
Descricao |
cn() |
Merge classes Tailwind (clsx + twMerge) |
formatCurrency(centavos) |
Formata BRL (centavos → R$ X,XX) |
formatDate(date) |
Data curta pt-BR |
formatDateTime(date) |
Data + hora pt-BR |
formatTime(date) |
Hora pt-BR |
Caching
- ISR (
next: { revalidate: 60 }) para paginas publicas
cache: 'no-store' para queries de disponibilidade
revalidatePath() apos mutacoes