From ee084c291855650a6ed2053c91eb00efd02f2cae Mon Sep 17 00:00:00 2001 From: Leonardo Date: Wed, 6 May 2026 09:38:18 -0300 Subject: [PATCH] Pacientes restore unificado + MelissaLinkExterno nativa MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trabalho de continuidade pós-blueprint: A) Botao "Restaurar" visivel direto na linha da PatientsListPage (layout Rail) quando paciente.status === 'Arquivado' — atalho pra usuarios que filtram por arquivados sem precisar abrir o menu de "..." (que ja tinha "Reativar" via PatientActionMenu). Icone pi-undo + label "Restaurar" + tooltip + click chama reactivatePatient do usePatientLifecycle. Aplicado tanto no DataTable desktop quanto nos cards mobile. B) Consolidacao: removido restorePatient do patientsRepository (era duplicado com reactivatePatient do usePatientLifecycle). MelissaPacientes agora consome reactivatePatient direto, fonte unica de verdade pra toda transicao de status pra 'Ativo'. C) MelissaLinkExterno (nova pagina nativa Melissa). Substitui o embed via MelissaEmbed que duplicava 3 headers (layout + embed + hero sticky da pagina interna). Lógica preservada (RPC issue_patient_invite + rotate_patient_invite_token_v2 + copy/openLink), so o chrome muda pra casar com o blueprint Melissa: 1 header com status pill (Link ativo/Gerando) + botao "Gerar novo link" + Recarregar + Voltar; subheader explicativo; body 2-col (esquerda card "Seu link publico" com InputGroup + 2 CTAs grandes + card "Mensagem pronta"; direita cards "Como funciona" + "Boas praticas"); mobile vira 1-col. PatientsExternalLinkPage continua intacta — segue funcionando no layout Rail. Wire-up no MelissaLayout: import + render block + 'link-externo' literal em NON_CONFIG_SLUGS; removido de MELISSA_EMBED_KEYS. Entry removido do EMBED_MAP no MelissaEmbed. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/features/patients/PatientsListPage.vue | 33 + .../patients/services/patientsRepository.js | 18 +- src/layout/melissa/MelissaEmbed.vue | 9 +- src/layout/melissa/MelissaLayout.vue | 13 +- src/layout/melissa/MelissaLinkExterno.vue | 805 ++++++++++++++++++ src/layout/melissa/MelissaPacientes.vue | 12 +- 6 files changed, 862 insertions(+), 28 deletions(-) create mode 100644 src/layout/melissa/MelissaLinkExterno.vue diff --git a/src/features/patients/PatientsListPage.vue b/src/features/patients/PatientsListPage.vue index 2a8ff52..297d065 100644 --- a/src/features/patients/PatientsListPage.vue +++ b/src/features/patients/PatientsListPage.vue @@ -34,6 +34,7 @@ import { useRoute, useRouter } from 'vue-router'; import ComponentCadastroRapido from '@/components/ComponentCadastroRapido.vue'; import PatientActionMenu from '@/components/patients/PatientActionMenu.vue'; +import { usePatientLifecycle } from '@/composables/usePatientLifecycle'; import PatientCadastroDialog from '@/components/ui/PatientCadastroDialog.vue'; import PatientCreatePopover from '@/components/ui/PatientCreatePopover.vue'; import PatientProntuario from '@/features/patients/prontuario/PatientProntuario.vue'; @@ -104,6 +105,36 @@ const conversationDrawerStore = useConversationDrawerStore(); const route = useRoute(); const toast = useToast(); const confirm = useConfirm(); +const { reactivatePatient } = usePatientLifecycle(); + +// Restaurar paciente arquivado — atalho visível direto na linha (em vez +// de exigir abrir o menu de "..."). Compartilha reactivatePatient com +// PatientActionMenu pra manter fonte única de verdade. +function restaurarPaciente(p) { + if (!p?.id) return; + confirm.require({ + message: `Restaurar "${p.nome_completo}" pra lista de pacientes ativos?`, + header: 'Restaurar paciente', + icon: 'pi pi-undo', + acceptLabel: 'Restaurar', + rejectLabel: 'Cancelar', + accept: async () => { + try { + const result = await reactivatePatient(p.id); + if (!result?.ok) throw result?.error || new Error('Falha ao restaurar.'); + toast.add({ severity: 'success', summary: 'Restaurado', detail: p.nome_completo, life: 2200 }); + await fetchAll(); + } catch (e) { + toast.add({ + severity: 'error', + summary: 'Falha ao restaurar', + detail: e?.message || 'Tente novamente.', + life: 4000 + }); + } + } + }); +} // ── Hero sticky ─────────────────────────────────────────── const headerEl = ref(null); @@ -1079,6 +1110,7 @@ function isRecent(row) {