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>
This commit is contained in:
Leonardo
2026-05-21 04:20:08 -03:00
parent 27467bbb68
commit 1c2a2b6e19
12 changed files with 687 additions and 508 deletions
@@ -4,13 +4,14 @@
|--------------------------------------------------------------------------
| 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).
| 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 { supabase } from '@/lib/supabase/client';
import { listDocumentsByPatient } from '@/features/patients/services/patientsRepository';
import { fmtSize, DOC_TYPE_LABEL } from '@/features/patients/utils/patientFormatters';
export function usePatientDocuments() {
@@ -27,15 +28,7 @@ export function usePatientDocuments() {
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 || [];
documents.value = await listDocumentsByPatient(patientId);
} catch (e) {
error.value = e?.message || 'Falha ao carregar documentos.';
documents.value = [];
@@ -45,9 +38,7 @@ export function usePatientDocuments() {
}
const total = computed(() => documents.value.length);
const totalBytes = computed(() =>
documents.value.reduce((acc, d) => acc + Number(d.tamanho_bytes || 0), 0)
);
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) => {
@@ -58,10 +49,6 @@ 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) {
@@ -74,16 +61,8 @@ export function usePatientDocuments() {
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
);
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 {