diff --git a/Obsidian/Brain/log.md b/Obsidian/Brain/log.md index a9b3eca..6e33ab9 100644 --- a/Obsidian/Brain/log.md +++ b/Obsidian/Brain/log.md @@ -50,6 +50,49 @@ Touched: none ## [2026-05-08 00:00] session | Melissa cfg-* nativas + temas + cronometro DB Touched: none +## [2026-05-08 15:30] session | MelissaPaciente Fase 4 — Tab Prontuario MVP +Touched: none +Detalhes: O legacy PatientProntuario.vue tem a aba Prontuario como +PLACEHOLDER ("Em breve"). MVP entregue aqui supera o legacy: usa +agenda_eventos.observacoes como nota evolutiva (pq nao tem schema de +anamnese/clinical_notes ainda). + +ESTADO + COMPUTEDS adicionados: +- pronFilter ref ('com-evolucao' default) + PRON_FILTERS array com 5 + opcoes (Com evolucao, Todas, Realizadas, Faltas, Cancelamentos). +- pronSessions computed: filtra sessions por status/observacoes presentes. +- sessoesComEvolucao computed: count de sessoes com observacoes nao-vazia. + +TEMPLATE Tab Prontuario (substitui placeholder Fase 1): +- Hint banner top: "Prontuario em construcao", explica que usa observacoes + de sessoes como historico evolutivo. +- 4 mini-stats em grid responsivo: com evolucao / realizadas / faltas / + total. Cada uma colorida + icone + value 800. +- 5 filter chips redondas (estilo Melissa): com-evolucao default; troca + pra todas/realiz/falt/cancel. +- Empty state contextual: + - Se nao tem sessoes: "Quando atender este paciente..." + - Se filtro 'com-evolucao' e zero: "Use o campo Observacoes ao editar + sessao..." + - Outro filtro: "Tente outro filtro acima." +- Lista de sessoes (pron-list) com: + - border-left colorida por status (verde realiz / vermelho falta / + amarelo cancel / cinza default) + - head com data + relative + chips status/modalidade/duracao + - titulo opcional (titulo_custom || titulo) + - block "Evolucao" quando tem observacoes (background medium, border- + left primary, label uppercase com icone, texto pre-wrap) + - mensagem "Sem evolucao registrada" italico cinza quando nao tem +- Roadmap card (border-dashed) listando 4 features futuras: anamnese + estruturada / plano terapeutico / evolucao por temas / assinatura + digital + LGPD Art. 18. + +CSS: ~200L novos pros componentes (mpa-pron-hint/stats/filters/list/ +item/roadmap). Padrao visual Melissa: chips redondas estilo MelissaTags, +border-left adaptativa, monospace inutilizado. + +ESLint: 0 errors da minha mudanca. + ## [2026-05-08 14:30] session | MelissaPaciente Fase 3 — Tab Perfil (6 sections stacked) Touched: none Detalhes: Substituiu o placeholder da aba Perfil por 6 sections stacked diff --git a/src/layout/melissa/MelissaPaciente.vue b/src/layout/melissa/MelissaPaciente.vue index 0bc2417..4e5c1c9 100644 --- a/src/layout/melissa/MelissaPaciente.vue +++ b/src/layout/melissa/MelissaPaciente.vue @@ -91,6 +91,16 @@ function selectTab(key) { if (isMobile.value) drawerOpen.value = false; } +// Filtros da aba Prontuario (MVP — usa session.observacoes como evolucao) +const pronFilter = ref('com-evolucao'); // com-evolucao | todas | realiz | falt | cancel +const PRON_FILTERS = [ + { value: 'com-evolucao', label: 'Com evolução', icon: 'pi pi-file-edit' }, + { value: 'todas', label: 'Todas', icon: 'pi pi-list' }, + { value: 'realiz', label: 'Realizadas', icon: 'pi pi-check-circle' }, + { value: 'falt', label: 'Faltas', icon: 'pi pi-user-minus' }, + { value: 'cancel', label: 'Cancelamentos', icon: 'pi pi-ban' } +]; + // Sub-nav da aba Perfil const PROFILE_SECTIONS = [ { key: 'pessoais', label: 'Informações Pessoais', icon: 'pi pi-pencil' }, @@ -185,6 +195,31 @@ const groupNames = computed(() => detail.groups.value.map((g) => g?.name).filter const groupLabel = computed(() => groupNames.value.length ? groupNames.value.join(', ') : '—'); const groupCountLabel = computed(() => groupNames.value.length <= 1 ? 'Grupo' : 'Grupos'); +// ── Tab Prontuario: lista filtrada de sessoes ────────────── +// MVP enquanto anamnese/evolucao_clinica nao existem no schema: +// usa agenda_eventos.observacoes como nota evolutiva. +const pronSessions = computed(() => { + const all = sessionsHook.sessions.value; + if (pronFilter.value === 'todas') return all; + if (pronFilter.value === 'com-evolucao') { + return all.filter((s) => s.observacoes && String(s.observacoes).trim()); + } + if (pronFilter.value === 'realiz') { + return all.filter((s) => /realiz|present/i.test(String(s.status || ''))); + } + if (pronFilter.value === 'falt') { + return all.filter((s) => /falt/i.test(String(s.status || ''))); + } + if (pronFilter.value === 'cancel') { + return all.filter((s) => /cancel|remarca/i.test(String(s.status || ''))); + } + return all; +}); +const pronSessionsCount = computed(() => pronSessions.value.length); +const sessoesComEvolucao = computed(() => + sessionsHook.sessions.value.filter((s) => s.observacoes && String(s.observacoes).trim()).length +); + // ── KPIs Visao Geral (Fase 2) ────────────────────────────── const kpiSessoes = computed(() => sessionsHook.totalSessoes.value); const kpiRealizadas = computed(() => sessionsHook.totalRealizadas.value); @@ -991,20 +1026,184 @@ void toast; - +
-
+ +
+ +
+ Prontuário em construção. + Por enquanto mostra as observações que você anota nas sessões + como histórico evolutivo. Anamnese estruturada, plano terapêutico e + evolução por temas chegam quando o módulo clínico for liberado. +
+
+ + +
+
+ +
+
{{ sessoesComEvolucao }}
+
com evolução
+
+
+
+ +
+
{{ sessionsHook.totalRealizadas.value }}
+
realizadas
+
+
+
+ +
+
{{ sessionsHook.totalFaltas.value }}
+
faltas
+
+
+
+ +
+
{{ sessionsHook.totalSessoes.value }}
+
total
+
+
+
+ + +
+ +
+ + +
+ Carregando… +
+
+
+
+ + + +
+
+ + + +
+
+
+
+
+
+ {{ fmtDateTimeBR(s.inicio_em) }} + {{ fmtRelative(s.inicio_em) }} +
+
+ + + + {{ s.modalidade === 'online' ? 'Online' : 'Presencial' }} + + + {{ sessionDuration(s.inicio_em, s.fim_em) }} + +
+
+
+ {{ s.titulo_custom || s.titulo }} +
+
+
+ + Evolução +
+

{{ s.observacoes }}

+
+
+ + Sem evolução registrada +
+
+
+ + +
-
+
-
Prontuário — Fase 4
-
Anamnese + sessões clínicas + evoluções
+
Em breve no prontuário
+
Roadmap clínico previsto
-

Em desenvolvimento — Fase 4.

+
    +
  • + +
    + Anamnese estruturada + Modelo configurável por terapeuta com seções (queixa, história, hipótese diagnóstica, objetivos). +
    +
  • +
  • + +
    + Plano terapêutico + Objetivos com prazo + acompanhamento de progresso ao longo das sessões. +
    +
  • +
  • + +
    + Evolução por temas + Tagging das notas pra cruzar evolução com objetivos e gerar relatórios. +
    +
  • +
  • + +
    + Assinatura digital + LGPD Art. 18 + Notas imutáveis com hash de auditoria, exportação compatível CFP. +
    +
  • +
-
+
@@ -2070,6 +2269,232 @@ void toast; font-size: 0.66rem !important; } +/* ═══════ Tab Prontuario (Fase 4 MVP) ═══════ */ +.mpa-pron-hint { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 12px 14px; + border-radius: 10px; + background: color-mix(in srgb, #06b6d4 9%, transparent); + border: 1px solid color-mix(in srgb, #06b6d4 28%, transparent); + color: var(--m-text); + font-size: 0.78rem; + line-height: 1.5; +} +.mpa-pron-hint > i { + color: #06b6d4; + font-size: 1rem; + margin-top: 2px; + flex-shrink: 0; +} + +.mpa-pron-stats { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); + gap: 8px; +} +.mpa-pron-stat { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + border-radius: 10px; + background: var(--m-bg-soft); + border: 1px solid var(--m-border); + border-left: 3px solid var(--c, var(--p-primary-color)); +} +.mpa-pron-stat > i { + color: var(--c, var(--p-primary-color)); + font-size: 1.05rem; + flex-shrink: 0; +} +.mpa-pron-stat__value { + font-size: 1.05rem; + font-weight: 800; + color: var(--m-text); + line-height: 1.1; +} +.mpa-pron-stat__label { + font-size: 0.7rem; + color: var(--m-text-muted); + text-transform: uppercase; + letter-spacing: 0.04em; + margin-top: 2px; +} + +.mpa-pron-filters { + display: flex; + flex-wrap: wrap; + gap: 6px; +} +.mpa-pron-filter { + display: inline-flex; + align-items: center; + gap: 5px; + padding: 6px 12px; + border-radius: 999px; + background: var(--m-bg-soft); + border: 1px solid var(--m-border); + color: var(--m-text); + cursor: pointer; + font-family: inherit; + font-size: 0.78rem; + font-weight: 600; + transition: all 120ms ease; +} +.mpa-pron-filter > i { font-size: 0.7rem; } +.mpa-pron-filter:hover { + background: var(--m-bg-soft-hover); + border-color: var(--m-border-strong); +} +.mpa-pron-filter.is-active { + background: var(--p-primary-color); + border-color: var(--p-primary-color); + color: var(--p-primary-contrast-color, #fff); +} + +.mpa-pron-list { + display: flex; + flex-direction: column; + gap: 10px; +} +.mpa-pron-item { + border-radius: 12px; + border: 1px solid var(--m-border); + background: var(--m-bg-soft); + padding: 12px 14px; + border-left: 3px solid var(--m-text-muted); + transition: border-color 120ms ease; +} +.mpa-pron-item[data-status*="realiz"], +.mpa-pron-item[data-status*="present"] { border-left-color: rgb(34, 197, 94); } +.mpa-pron-item[data-status*="falt"] { border-left-color: rgb(239, 68, 68); } +.mpa-pron-item[data-status*="cancel"], +.mpa-pron-item[data-status*="remarc"] { border-left-color: rgb(245, 158, 11); } +.mpa-pron-item__head { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 10px; + flex-wrap: wrap; + margin-bottom: 6px; +} +.mpa-pron-item__when { + display: flex; + flex-direction: column; + gap: 2px; + min-width: 0; +} +.mpa-pron-item__date { + font-size: 0.85rem; + font-weight: 700; + color: var(--m-text); +} +.mpa-pron-item__rel { + font-size: 0.7rem; + color: var(--m-text-muted); +} +.mpa-pron-item__chips { + display: flex; + align-items: center; + gap: 5px; + flex-wrap: wrap; +} +.mpa-pron-item__tag { font-size: 0.66rem !important; } +.mpa-pron-item__title { + font-size: 0.82rem; + font-weight: 600; + color: var(--m-text); + margin-bottom: 6px; +} + +.mpa-pron-item__evol { + margin-top: 8px; + padding: 10px 12px; + border-radius: 8px; + background: var(--m-bg-medium); + border-left: 2px solid var(--p-primary-color); +} +.mpa-pron-item__evol-label { + display: inline-flex; + align-items: center; + gap: 5px; + font-size: 0.66rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--p-primary-color); + margin-bottom: 4px; +} +.mpa-pron-item__evol-label > i { font-size: 0.62rem; } +.mpa-pron-item__evol-text { + font-size: 0.85rem; + color: var(--m-text); + line-height: 1.55; + white-space: pre-wrap; + word-break: break-word; +} +.mpa-pron-item__noevol { + margin-top: 6px; + display: inline-flex; + align-items: center; + gap: 4px; + font-size: 0.7rem; + color: var(--m-text-muted); + opacity: 0.65; + font-style: italic; +} +.mpa-pron-item__noevol > i { font-size: 0.5rem; } + +.mpa-pron-roadmap { + margin-top: 6px; + border-style: dashed; + background: transparent; +} +.mpa-pron-roadmap__list { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 12px; +} +.mpa-pron-roadmap__list > li { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 8px 0; + border-bottom: 1px solid var(--m-border); +} +.mpa-pron-roadmap__list > li:last-child { + border-bottom: none; + padding-bottom: 0; +} +.mpa-pron-roadmap__list > li > i { + color: var(--p-primary-color); + font-size: 0.95rem; + margin-top: 2px; + flex-shrink: 0; + width: 24px; + text-align: center; +} +.mpa-pron-roadmap__list > li > div { + flex: 1; + min-width: 0; +} +.mpa-pron-roadmap__list strong { + display: block; + font-size: 0.85rem; + color: var(--m-text); + margin-bottom: 2px; +} +.mpa-pron-roadmap__list span { + font-size: 0.74rem; + color: var(--m-text-muted); + line-height: 1.4; +} + /* ═══════ Notas e observacoes ═══════ */ .mpa-notes { display: flex;