Files
agenciapsilmno/src/features/patients/composables/usePatientDocuments.js
T
Leonardo 1c2a2b6e19 M2: patients — selects + repository + 8 composables refatorados
Modulo 2 da Fase 1 de padronizacao em batch unico. patientsSelects.js
nova com 11 constantes de select. patientsRepository.js estendido com
~15 funcoes novas (markIntakeConverted, list/get/update por
contexto, etc). 8 composables refatorados em paralelo (usePatients,
useDetail, Financial, Sessions, Messages, Documents, Recurrences,
SupportContacts) — zero supabase.from() em qualquer composable de
patients. _lastPatientId movido pra DENTRO das functions nos 3
composables que tinham. CadastrosRecebidosPage + MelissaCadastros
Recebidos pegam carona dos selects. Aguarda teste batch consolidado.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 04:20:08 -03:00

82 lines
2.6 KiB
JavaScript

/*
|--------------------------------------------------------------------------
| Agência PSI
|--------------------------------------------------------------------------
| Arquivo: src/features/patients/composables/usePatientDocuments.js
|
| Documentos do paciente — campos pra KPIs (count, tipo, última atualização).
| O detalhe completo fica em DocumentsListPage. Filtra deletados.
|
| I/O delegada ao patientsRepository.
|--------------------------------------------------------------------------
*/
import { ref, computed } from 'vue';
import { listDocumentsByPatient } from '@/features/patients/services/patientsRepository';
import { fmtSize, DOC_TYPE_LABEL } from '@/features/patients/utils/patientFormatters';
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 {
documents.value = await listDocumentsByPatient(patientId);
} 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);
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 };
});
const pendentes = computed(() => documents.value.filter((d) => d.status_revisao === 'pendente').length);
const sizeTotalFormatted = computed(() => fmtSize(totalBytes.value));
return {
documents,
loading,
error,
load,
total,
totalBytes,
tiposCount,
ultimo,
topType,
pendentes,
sizeTotalFormatted
};
}