MelissaPaciente Fase 7: Tabs Documentos + Conversas (KPIs + embed componentes existentes)

Duas tabs entregues numa sessao — sao mais leves porque reusam
DocumentsListPage e PatientConversationsTab existentes (testados em
producao no PatientProntuario legacy) com KPIs Melissa por cima.

EXTENSAO src/features/patients/utils/patientFormatters.js
- fmtSize(bytes): legivel B/KB/MB/GB
- DOC_TYPE_LABEL map: atestado/receita/laudo/encaminhamento/termo/etc
- chConvLabel(c): whatsapp -> WhatsApp / sms -> SMS / email -> E-mail

EXTENSAO src/features/patients/composables/usePatientDocuments.js
- topType computed: { tipo, count, label } do tipo mais comum
- pendentes computed: count status_revisao === 'pendente'
- sizeTotalFormatted computed: fmtSize(totalBytes)

EXTENSAO src/features/patients/composables/usePatientMessages.js
- primeiraMensagem computed (mais antiga)
- canais computed: Set de m.channel unicos

MELISSAPACIENTE.VUE — Tab Documentos
- 4 KPIs adaptativos (so renderizam com dados):
  Total + sizeTotalFormatted / Mais comum / Ultimo / Revisao pendente
- DocumentsListPage embedded no card Melissa (mpa-embed wrapper).
  Reusa upload/preview/listagem testados.

MELISSAPACIENTE.VUE — Tab Conversas
- 4 KPIs: Mensagens com canais / Recebidas % / Enviadas % / Ultima
- CTA "Abrir conversa no drawer" estilo WhatsApp pill verde #25d366
  que emite open-whatsapp pro parent (Fase 8 integra com
  conversationDrawerStore.openForPatient)
- PatientConversationsTab embedded — thread completa com filter/media

CSS: ~50L novos (mpa-conv-cta + mpa-embed wrapper).

Removido kpiDocumentos nao usado (substituido por documentsHook.total
direto).

ESLint: 0 errors da minha mudanca.

PROXIMA: Fase 8 wire-up final (Dialog -> router.push em MelissaPacientes/
MelissaAgenda; decisao sobre TherapistDashboard + PatientsListPage).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-05-08 10:06:29 -03:00
parent e7c0f6c4f5
commit 167e864b8a
5 changed files with 364 additions and 32 deletions
@@ -11,6 +11,7 @@
*/
import { ref, computed } from 'vue';
import { supabase } from '@/lib/supabase/client';
import { fmtSize, DOC_TYPE_LABEL } from '@/features/patients/utils/patientFormatters';
export function usePatientDocuments() {
const documents = ref([]);
@@ -57,6 +58,34 @@ export function usePatientDocuments() {
});
const ultimo = computed(() => documents.value[0] || null);
/**
* Tipo de documento mais comum (alimenta KPI "Mais comum").
* Retorna { tipo, count, label } ou null se vazio.
*/
const topType = computed(() => {
const por = {};
for (const d of documents.value) {
const t = d.tipo_documento || 'outro';
por[t] = (por[t] || 0) + 1;
}
const entries = Object.entries(por).sort((a, b) => b[1] - a[1]);
if (!entries.length) return null;
const [tipo, count] = entries[0];
return { tipo, count, label: DOC_TYPE_LABEL[tipo] || tipo };
});
/**
* Count de documentos com status_revisao === 'pendente'.
*/
const pendentes = computed(() =>
documents.value.filter((d) => d.status_revisao === 'pendente').length
);
/**
* Tamanho total formatado em string legivel (B/KB/MB/GB).
*/
const sizeTotalFormatted = computed(() => fmtSize(totalBytes.value));
return {
documents,
loading,
@@ -65,6 +94,9 @@ export function usePatientDocuments() {
total,
totalBytes,
tiposCount,
ultimo
ultimo,
topType,
pendentes,
sizeTotalFormatted
};
}