From 71ee51d38fc53da33032e1eb723d5da3003eef19 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 8 May 2026 10:21:35 -0300 Subject: [PATCH] MelissaPaciente Fase 8: wire-up final (Dialog -> route /melissa/paciente?id=X) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PLANO DE 8 FASES COMPLETO. Os 2 callsites Melissa do PatientProntuario.vue legacy (3593L Dialog) trocam por navegacao pra MelissaPaciente nativo via router.push. PatientProntuario continua intocado pros 2 callsites legacy fora do Melissa (TherapistDashboard, PatientsListPage). MELISSAPACIENTE.VUE — wire-up interno - Imports: useRouter + useConversationDrawerStore - close(): emit + router.push('/melissa/pacientes') - editPatient(): emit + router.push('/melissa/pacientes', query: {edit: id}) pra MelissaPacientes auto-abrir o cadastroFullDialog - openWhatsapp(): emit + conversationDrawerStore.openForPatient({id, name, phone, avatar_url}) — drawer global desce sobre Melissa - addFinancial(): emit + toast "Em breve" (Fase 9 — dialog inline) MELISSAPACIENTES.VUE - Removeu import PatientProntuario + refs prontuarioOpen/prontuarioPatient - Removeu template (substituido por comentario) - abrirProntuario(p): router.push('/melissa/paciente', query: {id}) - onMounted detecta route.query.edit -> abre cadastroFullDialog + router.replace pra limpar query (handshake com MelissaPaciente) - Comentario header atualizado MELISSAAGENDA.VUE - Removeu import PatientProntuario + refs prontuarioOpen/prontuarioPatient - Removeu template - abrirProntuarioPorId(id): router.push pra rota Melissa nativa - abrirProntuarioPaciente / openProntuario / kebab "Prontuario" delegam pra abrirProntuarioPorId MELISSALAYOUT.VUE - Render simplificado: so @close="fecharSecao". Acoes edit/open-whatsapp/add-financial ficam internas. ESLint: 0 errors da minha mudanca (9 pre-existentes nos arquivos tocados sao baseline; confirmados via git stash — mesmos errors em ambos lados). PLANO COMPLETO. Total de 8 commits no branch (Fases 1-8). MelissaPaciente.vue ~2400L + 5 composables (~407L) + utils ~280L. PatientProntuario.vue intocado pra fallback legacy (TherapistDashboard, PatientsListPage). Co-Authored-By: Claude Opus 4.7 (1M context) --- Obsidian/Brain/log.md | 55 ++++++++++++++++++++++++ src/layout/melissa/MelissaAgenda.vue | 39 +++++------------ src/layout/melissa/MelissaLayout.vue | 9 ++-- src/layout/melissa/MelissaPaciente.vue | 57 +++++++++++++++++++++++-- src/layout/melissa/MelissaPacientes.vue | 36 ++++++++-------- 5 files changed, 142 insertions(+), 54 deletions(-) diff --git a/Obsidian/Brain/log.md b/Obsidian/Brain/log.md index b318e87..398681c 100644 --- a/Obsidian/Brain/log.md +++ b/Obsidian/Brain/log.md @@ -50,6 +50,61 @@ Touched: none ## [2026-05-08 00:00] session | Melissa cfg-* nativas + temas + cronometro DB Touched: none +## [2026-05-08 19:30] session | MelissaPaciente Fase 8 — wire-up final (Dialog -> route) +Touched: none +Detalhes: PLANO DE 8 FASES COMPLETO. Os 2 callsites Melissa do +PatientProntuario.vue legacy (3593L Dialog) trocam por router.push pra +/melissa/paciente?id=X. PatientProntuario continua intocado pros 2 +callsites legacy (TherapistDashboard, PatientsListPage) quando user nao +esta no layout Melissa. + +MELISSAPACIENTE.VUE — wire-up +- useRouter + useConversationDrawerStore. +- close(): emit + router.push('/melissa/pacientes') (volta pra lista). +- editPatient(): emit + router.push('/melissa/pacientes', query: {edit: id}) + pra MelissaPacientes detectar e abrir o cadastroFullDialog automaticamente. +- openWhatsapp(): emit + conversationDrawerStore.openForPatient({id, name, + phone, avatar_url}) — drawer global desce sobre Melissa sem fechar. +- addFinancial(): emit + toast "Em breve" (Fase 9 — dialog inline). + +MELISSAPACIENTES.VUE — wire-up +- Removeu import PatientProntuario, refs prontuarioOpen/prontuarioPatient, + template PatientProntuario. +- abrirProntuario(p): router.push('/melissa/paciente', query: {id}). +- onMounted: detecta route.query.edit -> abre cadastroFullDialog + + router.replace pra limpar a query. Permite navegacao MelissaPaciente + -> MelissaPacientes?edit=X -> auto-open do cadastro. +- Comentario header atualizado. + +MELISSAAGENDA.VUE — wire-up +- Removeu import PatientProntuario, refs prontuarioOpen/prontuarioPatient, + template PatientProntuario. +- abrirProntuarioPorId(id): router.push('/melissa/paciente', query: {id}). +- abrirProntuarioPaciente() / openProntuario(patient) / item kebab + "Prontuario" todos delegam pra abrirProntuarioPorId. + +MELISSALAYOUT.VUE +- Render do simplificado: so passa @close="fecharSecao". + Acoes edit/open-whatsapp/add-financial agora ficam internas no MelissaPaciente. + +ESLint: 0 errors da minha mudanca (9 errors pre-existentes nos arquivos +tocados, mesmos de antes do diff — confirmados via git stash baseline). + +PLANO COMPLETO. Status final por fase: +1. Foundation (composables + skeleton) — done (Fase 1) +2. Tab Visao Geral (KPIs ricos + timeline + msgs) — done (Fase 2) +3. Tab Perfil (6 sections stacked + anchors) — done (Fase 3) +4. Tab Prontuario MVP (evolucao via observacoes) — done (Fase 4) +5. Tab Agenda (KPIs + filtros + grupos + acoes) — done (Fase 5) +6. Tab Financeiro (KPIs + tabela + mark paid) — done (Fase 6) +7. Tabs Documentos + Conversas (KPIs + embeds) — done (Fase 7) +8. Wire-up final (Dialog -> route) — done (Fase 8) + +PatientProntuario.vue (3593L) NAO foi deletado — continua usado pelo +TherapistDashboard.vue (homepage do role therapist) e PatientsListPage.vue +(rota /therapist/patients fora do Melissa). Quando user troca pra Melissa +em /account/profile, ele ve a versao nativa (MelissaPaciente). + ## [2026-05-08 18:30] session | MelissaPaciente Fase 7 — Tabs Documentos + Conversas Touched: none Detalhes: Duas tabs entregues numa sessao (sao mais leves: KPIs + embed diff --git a/src/layout/melissa/MelissaAgenda.vue b/src/layout/melissa/MelissaAgenda.vue index c173c8b..4b1ff5e 100644 --- a/src/layout/melissa/MelissaAgenda.vue +++ b/src/layout/melissa/MelissaAgenda.vue @@ -34,7 +34,6 @@ import MelissaAgendaSearchPopover from './MelissaAgendaSearchPopover.vue'; import MelissaAgendaActionsPopover from './MelissaAgendaActionsPopover.vue'; import PatientCadastroDialog from '@/components/ui/PatientCadastroDialog.vue'; import ComponentCadastroRapido from '@/components/ComponentCadastroRapido.vue'; -import PatientProntuario from '@/features/patients/prontuario/PatientProntuario.vue'; import { useConversationDrawerStore } from '@/stores/conversationDrawerStore'; import { getSessionCounts } from '@/features/patients/services/patientsRepository'; // `Menu` PrimeVue: NÃO importar explicitamente — projeto usa auto-import @@ -234,13 +233,9 @@ function pacienteRowDblclick(id) { abrirProntuarioPorId(id); } function abrirProntuarioPorId(id) { - const p = - props.pacientes.find((x) => x.id === id) || - pacientesAside.value.find((x) => x.id === id) || - null; - if (!p) return; - prontuarioPatient.value = { ...p }; - prontuarioOpen.value = true; + if (!id) return; + // Fase 8 wire-up: navega pra MelissaPaciente nativo. + router.push({ path: '/melissa/paciente', query: { id: String(id) } }); } // ── Calendar (FullCalendar) ─────────────────────────────────── @@ -992,8 +987,6 @@ function onPatientCreated() { // Pattern espelha PatientsListPage (goEdit/goConversation/openProntuario). // Aparece no .melissa-dock via Teleport quando há paciente selecionado. const conversationDrawerStore = useConversationDrawerStore(); -const prontuarioOpen = ref(false); -const prontuarioPatient = ref(null); const sessionCountsMap = ref(new Map()); // id → count (cache) // Cache pra patients carregados sob demanda — quando o pacienteSelecionadoId @@ -1169,9 +1162,8 @@ function abrirWhatsappPaciente() { } function abrirProntuarioPaciente() { const p = pacienteSelecionado.value; - if (!p) return; - prontuarioPatient.value = { ...p }; - prontuarioOpen.value = true; + if (!p?.id) return; + abrirProntuarioPorId(p.id); } // API pública pra MelissaLayout chamar via ref (botão "Editar paciente" // do MelissaEventoPanel). Abre o PatientCadastroDialog já no modo edição. @@ -1211,7 +1203,7 @@ const kebabItems = computed(() => { return [ { label: 'Sessões', icon: 'pi pi-history', command: () => { pacienteSelecionadoId.value = p.id; abrirSessoesPaciente(); } }, { label: 'WhatsApp', icon: 'pi pi-whatsapp', command: () => conversationDrawerStore.openForPatient(String(p.id)) }, - { label: 'Prontuário', icon: 'pi pi-file', command: () => { prontuarioPatient.value = { ...p }; prontuarioOpen.value = true; } }, + { label: 'Prontuário', icon: 'pi pi-file', command: () => abrirProntuarioPorId(p.id) }, { label: 'Editar', icon: 'pi pi-pencil', command: () => { editPatientId.value = String(p.id); cadastroFullDialog.value = true; } } ]; }); @@ -1220,9 +1212,8 @@ const kebabItems = computed(() => { // MelissaEventoPanel emite ações que o parent precisa orquestrar com // a Agenda — aqui ficam os métodos invocáveis via ref. function openProntuario(patient) { - if (!patient) return; - prontuarioPatient.value = { ...patient }; - prontuarioOpen.value = true; + if (!patient?.id) return; + abrirProntuarioPorId(patient.id); } defineExpose({ refetch: refetchEventosFc, @@ -1905,17 +1896,9 @@ defineExpose({ - - + + diff --git a/src/layout/melissa/MelissaLayout.vue b/src/layout/melissa/MelissaLayout.vue index da0200d..17b1e43 100644 --- a/src/layout/melissa/MelissaLayout.vue +++ b/src/layout/melissa/MelissaLayout.vue @@ -1865,15 +1865,14 @@ function onKeydown(e) { @close="fecharSecao" /> - + sessionsHook.totalRealizadas.value); const kpiMensagens = computed(() => messagesHook.messages.value.length); // ── Acoes ────────────────────────────────────────────────── -function close() { emit('close'); } -function editPatient() { emit('edit', props.patientId); } -function addFinancial() { emit('add-financial', props.patientId); } -function openWhatsapp() { emit('open-whatsapp', props.patientId); } +// Volta pra lista de pacientes (preserva o estado de Melissa). +function close() { + emit('close'); + router.push('/melissa/pacientes'); +} + +// Edit: navega pra /melissa/pacientes?edit= e a propria +// MelissaPacientes detecta esse query param e abre o cadastroFullDialog. +function editPatient() { + emit('edit', props.patientId); + router.push({ path: '/melissa/pacientes', query: { edit: props.patientId } }); +} + +// Open WhatsApp: usa o conversationDrawerStore global (mesmo padrao +// que MelissaPacientes usa). O drawer desce sobre o Melissa sem fechar. +function openWhatsapp() { + emit('open-whatsapp', props.patientId); + if (!props.patientId) return; + const data = patientData.value || {}; + try { + if (typeof conversationDrawerStore.openForPatient === 'function') { + conversationDrawerStore.openForPatient({ + id: props.patientId, + name: data.nome_completo || data.nome || '', + phone: data.telefone || data.phone || '', + avatar_url: data.avatar_url || data.avatar || '' + }); + } + } catch (e) { + toast.add({ + severity: 'error', + summary: 'Falha ao abrir conversa', + detail: e?.message || 'Erro ao abrir o drawer.', + life: 3500 + }); + } +} + +// Add financial: por enquanto so emite. Futuro: dialog inline de +// novo lancamento (Fase 9). +function addFinancial() { + emit('add-financial', props.patientId); + toast.add({ + severity: 'info', + summary: 'Em breve', + detail: 'Dialog de novo lançamento será adicionado numa próxima sessão.', + life: 3000 + }); +} // ── Load data quando patientId muda ──────────────────────── async function loadAll(id) { diff --git a/src/layout/melissa/MelissaPacientes.vue b/src/layout/melissa/MelissaPacientes.vue index 6e70ddc..503d1bc 100644 --- a/src/layout/melissa/MelissaPacientes.vue +++ b/src/layout/melissa/MelissaPacientes.vue @@ -18,13 +18,14 @@ * e patient_patient_tag (via patientsRepository.listGroupsByPatient/Tags...) * * Integrações: - * - PatientProntuario (overlay dialog) — abre via duplo-click no card ou + * - MelissaPaciente (rota /melissa/paciente?id=X) — abre via duplo-click ou * botão "Abrir prontuário" da COL 3 * - PatientCadastroDialog — cadastro completo / edição * - PatientCreatePopover + ComponentCadastroRapido — fluxo de novo paciente * - conversationDrawerStore — botão WhatsApp da COL 3 */ import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'; +import { useRouter, useRoute } from 'vue-router'; import { useToast } from 'primevue/usetoast'; import { useConfirm } from 'primevue/useconfirm'; import { useMelissaPacientes } from './composables/useMelissaPacientes'; @@ -40,7 +41,6 @@ import { softDeletePatient } from '@/features/patients/services/patientsRepository'; import { usePatientLifecycle } from '@/composables/usePatientLifecycle'; -import PatientProntuario from '@/features/patients/prontuario/PatientProntuario.vue'; import PatientCreatePopover from '@/components/ui/PatientCreatePopover.vue'; import PatientCadastroDialog from '@/components/ui/PatientCadastroDialog.vue'; import ComponentCadastroRapido from '@/components/ComponentCadastroRapido.vue'; @@ -52,6 +52,8 @@ const emit = defineEmits(['close', 'patient-created', 'goto-agenda', 'goto-grupo const toast = useToast(); const confirm = useConfirm(); const tenantStore = useTenantStore(); +const router = useRouter(); +const route = useRoute(); const { reactivatePatient } = usePatientLifecycle(); const conversationDrawerStore = useConversationDrawerStore(); @@ -284,6 +286,13 @@ onMounted(() => { isCompact.value = _mqCompact.matches; _mqCompact.addEventListener('change', _onMqCompactChange); } + // Fase 8 wire-up: se navegou pra ca com ?edit= (vindo do + // MelissaPaciente), abre o cadastro full direto. + if (route.query.edit) { + editPatientId.value = String(route.query.edit); + cadastroFullDialog.value = true; + router.replace({ query: { ...route.query, edit: undefined } }); + } }); onBeforeUnmount(() => { if (_mqMobile) _mqMobile.removeEventListener('change', _onMqMobileChange); @@ -534,9 +543,6 @@ const cadastroFullDialog = ref(false); const quickDialog = ref(false); const editPatientId = ref(null); -const prontuarioOpen = ref(false); -const prontuarioPatient = ref(null); - function openCreatePopover(e) { createPopoverRef.value?.toggle(e); } @@ -551,10 +557,12 @@ function onPatientCreated() { refetchTudo(); } +// Abrir prontuario agora navega pra MelissaPaciente nativo (Fase 8 wire-up). +// O Dialog PatientProntuario.vue legacy continua existindo pros 2 callsites +// fora do Melissa (TherapistDashboard e PatientsListPage). function abrirProntuario(p) { - if (!p) return; - prontuarioPatient.value = { ...p }; - prontuarioOpen.value = true; + if (!p?.id) return; + router.push({ path: '/melissa/paciente', query: { id: String(p.id) } }); } function editarPaciente(p) { @@ -1349,15 +1357,9 @@ function sessaoStatusColor(s) { @created="onPatientCreated" /> - - + +