useHybridBackend inicializa data como null, não undefined — o default = []
na desestruturação não se aplica a null, causando TypeError ao fazer
dentistas[0]. Substituído por operador ?? após a desestruturação.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ReceitaModal: gerenciamento de modelos de receita por especialidade com
drag-and-drop para reordenar medicamentos e preview de impressão
- PedidoExameModal: pedido de exames por catálogo (Raio-X / Tomografia /
Outros) com DnD para ordenar, campos de região/observação por item e
preview de impressão
- EditarPacienteModal: reformulado em 4 páginas (Dados / Família /
Endereço / Histórico) com navegação anterior/próximo e modal 2xl
- Backend: tabelas modelos_receita, items_receita, pedidos_exame,
items_pedido_exame criadas na migração; colunas de endereço adicionadas
em pacientes; endpoints CRUD para receitas e pedidos de exame
- Integração: botões Receita e Raio-X no menu clínico agora abrem os
novos modais reais em vez do placeholder
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix dataNascimento date format error: convert dd/MM/yyyy → yyyy-MM-dd when
loading EditarPacienteModal so <input type="date"> validates correctly
- Change convênio field from free text to dropdown populated from planos table
- Redesign grupo familiar: search a patient as family member instead of named
group, with parentesco field (datalist with common options, accepts custom)
- GET /api/pacientes: proper camelCase aliases, LEFT JOINs for grupoFamiliarNome
and indicadoPorNome, sort parameter support (az/za/convenio/recentes)
- Add startup migrations: ADD COLUMN IF NOT EXISTS for grupofamiliarid,
grupofamiliarrelacao, indicadorporid on pacientes table
- savePaciente: preserve caller-supplied id instead of overwriting with Math.random
- Add grupoFamiliarRelacao to Paciente type
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AgendaView:
- Fix agendamentos?.filter(...).map(...) crash: optional chain didn't guard .map when agendamentos is null on initial render
- Fix getPacientes fetcher to extract .data array — API now returns {data, total} not Paciente[], causing searchResults.map crash
LoginView:
- Restore 3s preloader splash screen with {APP_VERSION} instead of hardcoded version string
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix agendamentos?.filter(...).map(...) — optional chain didn't protect .map, crashing when agendamentos is null on first render
- Add Array.isArray guard in AutocompleteField before setResults to prevent non-array from backend error responses breaking subsequent .map
- Add array guard in getGruposFamiliares to return [] on backend error instead of propagating error object
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Script runs before vite build via package.json "build" script.
Reads/writes APP_VERSION in frontend/constants.ts (now at V1.0.3).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ensures values.update and values.get use the actual tab title returned by
ensureSheetTab (case-insensitive match) so writes don't fail when existing
Apps Script tabs have different casing than our expected names.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
process.env is only set if env var exists; credentials saved via UI
live in googleCreds. Guard was blocking users who saved via DB.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Backend:
- Load GOOGLE_CLIENT_ID/SECRET from DB at startup (env vars take priority)
- GET /api/settings/google-credentials → masked status (secret never returned)
- POST /api/settings/google-credentials → save to DB, hot-reload in memory
- /api/auth/google/url returns 503 with clear message when unconfigured
Frontend (ConfiguracoesView):
- OAuth credential inputs (Client ID + Client Secret with show/hide toggle)
- Shows configured status badge (ENV vs DB) and masked clientIdHint
- Instructions with redirect URI shown inline
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add APP_URL and GOOGLE_REDIRECT_URI=https://scoreodonto.com/api/oauth2callback
to docker-compose backend environment
- /api/auth/google/url returns 503 with clear message when CLIENT_ID/SECRET unset
- GoogleConnectButton shows alert instead of silently breaking on API error
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move user profile card and Google connect button from sidebar footer
to a dedicated Configurações view. Sidebar footer now shows a compact
user button that navigates to settings. All roles have access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove all window.location.hash assignments and hashchange events.
Navigate with history.pushState; listen on popstate. Fix base href to
'/' so assets resolve correctly on deep paths. Update magic link URL.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>