df61cc4d99
Inicio do port do PatientProntuario.vue (3593L Dialog) pra Melissa nativo. Plano em 8 fases — esta entrega cobre apenas a Fase 1 (foundation). PatientProntuario continua intocado nos 4 callsites (TherapistDashboard, MelissaAgenda, MelissaPacientes, PatientsListPage); migration acontece nas fases 2-8. 5 COMPOSABLES NOVOS em src/features/patients/composables/ - usePatientDetail.js (108L): patients + groups + tags - usePatientSessions.js (83L): agenda_eventos + computeds proxima/ultima/totais - usePatientFinancial.js (82L): financial_records + computeds totalRecebido/Aberto/Atrasado - usePatientMessages.js (64L): conversation_messages + computeds recentes/totalIn/Out - usePatientDocuments.js (70L): documents + computeds total/Bytes/tiposCount Cada composable encapsula a query original do PatientProntuario.vue + adiciona computeds derivados. Reutilizaveis em outros lugares no futuro (dashboards, relatorios, etc). MELISSAPACIENTE.VUE NOVO (1190L) em src/layout/melissa/ - Prefixo CSS .mpa-*. Chrome glass + drawer mobile + right: max(...) >=1024px (mesmo padrao MelissaAgendador/Negocio). - Header: avatar + nome + ageLabel + pronomes + Tag status/convenio + risco-elevado pill + actions (Conversar / Editar / Close). - Subheader condicional: banner risco elevado. - Body 2-col: sidebar 320px (esquerda, drawer no mobile) + main flex 1. - Sidebar com 4 cards: Acoes Rapidas / Navegacao 7 tabs / Sub-nav Perfil / Vinculos (chips grupos+tags). - Main: 7 tabs (Visao Geral / Perfil / Prontuario / Agenda / Financeiro / Documentos / Conversas). Visao Geral ja mostra 4 KPIs reais via composables. Outras 6 abas com placeholders "Em desenvolvimento — Fase X". MELISSALAYOUT.VUE - Import MelissaPaciente. - SECOES.paciente entry novo. - 'paciente' adicionado ao MELISSA_NON_CONFIG_SLUGS. - Render condicional com :patient-id="String(route.query.id || '')" — navegacao via /melissa/paciente?id=xxx. ESLint: 0 errors da mudanca. 2 errors pre-existentes em MelissaLayout (duplicate key 'financeiro' L242, empty block L1130) — nao toquei essas linhas. PatientProntuario tem outros pre-existentes nao tocados. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
71 lines
2.2 KiB
JavaScript
71 lines
2.2 KiB
JavaScript
/*
|
|
|--------------------------------------------------------------------------
|
|
| Agência PSI
|
|
|--------------------------------------------------------------------------
|
|
| Arquivo: src/features/patients/composables/usePatientDocuments.js
|
|
|
|
|
| Documentos do paciente — carrega so os campos pra KPIs (count, tipo,
|
|
| ultima atualizacao). O detalhe completo fica em DocumentsListPage que
|
|
| tem composable proprio. Filtra deletados (deleted_at IS NULL).
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
import { ref, computed } from 'vue';
|
|
import { supabase } from '@/lib/supabase/client';
|
|
|
|
export function usePatientDocuments() {
|
|
const documents = ref([]);
|
|
const loading = ref(false);
|
|
const error = ref('');
|
|
|
|
async function load(patientId) {
|
|
if (!patientId) {
|
|
documents.value = [];
|
|
return;
|
|
}
|
|
loading.value = true;
|
|
error.value = '';
|
|
documents.value = [];
|
|
try {
|
|
const { data, error: err } = await supabase
|
|
.from('documents')
|
|
.select('id, tipo_documento, created_at, status_revisao, tamanho_bytes')
|
|
.eq('patient_id', patientId)
|
|
.is('deleted_at', null)
|
|
.order('created_at', { ascending: false })
|
|
.limit(200);
|
|
if (err) throw err;
|
|
documents.value = data || [];
|
|
} catch (e) {
|
|
error.value = e?.message || 'Falha ao carregar documentos.';
|
|
documents.value = [];
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
const total = computed(() => documents.value.length);
|
|
const totalBytes = computed(() =>
|
|
documents.value.reduce((acc, d) => acc + Number(d.tamanho_bytes || 0), 0)
|
|
);
|
|
const tiposCount = computed(() => {
|
|
const map = new Map();
|
|
documents.value.forEach((d) => {
|
|
const k = d.tipo_documento || 'outro';
|
|
map.set(k, (map.get(k) || 0) + 1);
|
|
});
|
|
return Object.fromEntries(map);
|
|
});
|
|
const ultimo = computed(() => documents.value[0] || null);
|
|
|
|
return {
|
|
documents,
|
|
loading,
|
|
error,
|
|
load,
|
|
total,
|
|
totalBytes,
|
|
tiposCount,
|
|
ultimo
|
|
};
|
|
}
|