/* |-------------------------------------------------------------------------- | Agência PSI |-------------------------------------------------------------------------- | Criado e desenvolvido por Leonardo Nohama | | Tecnologia aplicada à escuta. | Estrutura para o cuidado. | | Arquivo: src/composables/Usedocshealth.js | Data: 2026 | Local: São Carlos/SP — Brasil |-------------------------------------------------------------------------- | © 2026 — Todos os direitos reservados |-------------------------------------------------------------------------- */ // Critério de "atenção": mais de 30% dos votos são negativos // (mínimo 3 votos totais para evitar falso-positivo com 1 voto negativo). // // O `countAtencao` é exportado como singleton para uso no menu SaaS: // // import { countAtencao } from '@/composables/useDocsHealth' // // No lugar onde saasMenu() é chamado: // saasMenu(sessionCtx, { mismatchCount, docsAtencaoCount: countAtencao.value }) import { ref, computed } from 'vue'; const THRESHOLD_NEGATIVO = 0.3; // 30% const MIN_VOTOS = 3; // mínimo de votos para considerar // Estado singleton — alimentado pelo SaasDocsPage após load() const _docs = ref([]); // ── Classificação individual (exportada standalone p/ uso externo) ─ export function saudeDocItem(doc) { const total = (doc.votos_util || 0) + (doc.votos_nao_util || 0); if (total < MIN_VOTOS) return 'sem_dados'; const pctNeg = (doc.votos_nao_util || 0) / total; return pctNeg > THRESHOLD_NEGATIVO ? 'atencao' : 'ok'; } // ── Singleton reativo — use no menu ou em qualquer lugar ────── export const countAtencao = computed(() => _docs.value.filter((d) => saudeDocItem(d) === 'atencao').length); export function useDocsHealth() { function setDocs(docs) { _docs.value = docs; } function saudeDoc(doc) { return saudeDocItem(doc); } function pctNegativo(doc) { const total = (doc.votos_util || 0) + (doc.votos_nao_util || 0); if (!total) return 0; return Math.round(((doc.votos_nao_util || 0) / total) * 100); } // ── Métricas globais ─────────────────────────────────────── const totalDocs = computed(() => _docs.value.length); const docsAtencao = computed(() => _docs.value.filter((d) => saudeDoc(d) === 'atencao')); const docsOk = computed(() => _docs.value.filter((d) => saudeDoc(d) === 'ok')); const docsSemDados = computed(() => _docs.value.filter((d) => saudeDoc(d) === 'sem_dados')); // Doc mais útil (maior % positivo com mínimo de votos) const docMaisUtil = computed(() => { const comVotos = _docs.value.filter((d) => (d.votos_util || 0) + (d.votos_nao_util || 0) >= MIN_VOTOS); if (!comVotos.length) return null; return comVotos.reduce((best, d) => { const pct = (d.votos_util || 0) / ((d.votos_util || 0) + (d.votos_nao_util || 0)); const bestPct = (best.votos_util || 0) / ((best.votos_util || 0) + (best.votos_nao_util || 0)); return pct > bestPct ? d : best; }); }); // ── Ordenação por saúde ──────────────────────────────────── // Problemáticas primeiro → ok → sem dados function sortBySaude(lista) { const ordem = { atencao: 0, ok: 1, sem_dados: 2 }; return [...lista].sort((a, b) => { const sa = saudeDoc(a); const sb = saudeDoc(b); if (ordem[sa] !== ordem[sb]) return ordem[sa] - ordem[sb]; return pctNegativo(b) - pctNegativo(a); }); } return { setDocs, saudeDoc, pctNegativo, totalDocs, docsAtencao, docsOk, docsSemDados, countAtencao, docMaisUtil, sortBySaude, THRESHOLD_NEGATIVO, MIN_VOTOS }; }