From 2dae4a11ae47108cd82f5a64ac92e48b71e42a29 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 21 May 2026 05:17:51 -0300 Subject: [PATCH] roadmap #11: recently viewed (ultimos 5 pacientes acessados) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ROADMAP item #1.3 #11. localStorage por user_id pra isolar sessoes diferentes no mesmo browser. ROADMAP sugeria localStorage OU tabela user_recent_access — escolhi localStorage por simplicidade (sem migration adicional + zero round-trip por visita). composables/useRecentPatients.js: - useRecentPatients() — composable reativo Tipo A: items + hasItems + addVisit + remove + clear + refresh - registerPatientVisit(patient) — helper stateless pra usar fora de setup (ex: navigation guards, action handlers) - Sincroniza entre instancias na mesma aba via CustomEvent + 'storage' - Max 5 items. Dedup por id, novo no topo. Wire-up de visita (registra ao carregar prontuario): - MelissaPaciente.vue: registerPatientVisit no loadAll apos detail.load - PatientProntuario.vue: registerPatientVisit em loadDetail apos p resolved Wire-up de visualizacao (mostra quando query vazia): - GlobalSearch.vue: grupo "Acessados recentemente" antes dos Atalhos. goTo("recent") navega pra /therapist/patients/:id. - MelissaBusca.vue: grupo "Acessados recentemente". emit('paciente') reusando a logica do MelissaLayout que ja navega pra /melissa/paciente?id=X. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/search/GlobalSearch.vue | 38 ++++ src/composables/useRecentPatients.js | 171 ++++++++++++++++++ .../patients/prontuario/PatientProntuario.vue | 3 + src/layout/melissa/MelissaBusca.vue | 28 +++ src/layout/melissa/MelissaPaciente.vue | 8 + 5 files changed, 248 insertions(+) create mode 100644 src/composables/useRecentPatients.js diff --git a/src/components/search/GlobalSearch.vue b/src/components/search/GlobalSearch.vue index e108fbc..e3a5a24 100644 --- a/src/components/search/GlobalSearch.vue +++ b/src/components/search/GlobalSearch.vue @@ -15,9 +15,11 @@ import InputText from 'primevue/inputtext'; import { supabase } from '@/lib/supabase/client'; import { useTenantStore } from '@/stores/tenantStore'; import { searchPages } from './pagesIndex'; +import { useRecentPatients } from '@/composables/useRecentPatients'; const router = useRouter(); const tenantStore = useTenantStore(); +const { items: recentPatients, hasItems: hasRecentPatients } = useRecentPatients(); // ──────────────────────────────────────────────────────────── // State @@ -67,9 +69,14 @@ const filteredPages = computed(() => { // ──────────────────────────────────────────────────────────── // Flat list pra navegação por teclado // ──────────────────────────────────────────────────────────── +// Recently-viewed só aparece quando a query está vazia — não polui resultados de busca. +const showRecent = computed(() => !query.value.trim() && hasRecentPatients.value); +const recentItems = computed(() => showRecent.value ? (recentPatients.value || []).slice(0, 5) : []); + const flatList = computed(() => { const out = []; filteredActions.value.forEach((a, i) => out.push({ group: 'actions', item: a, idx: i })); + recentItems.value.forEach((p, i) => out.push({ group: 'recent', item: p, idx: i })); results.value.patients.forEach((p, i) => out.push({ group: 'patients', item: p, idx: i })); results.value.intakes.forEach((r, i) => out.push({ group: 'intakes', item: r, idx: i })); results.value.appointments.forEach((a, i) => out.push({ group: 'appointments', item: a, idx: i })); @@ -195,6 +202,16 @@ function onInputKeydown(e) { } async function goTo(entry) { + // Recent patients: usa id pra navegar pro prontuário do paciente + if (entry?.group === 'recent' && entry?.item?.id) { + showPanel.value = false; + query.value = ''; + resetResults(); + activeIndex.value = -1; + await router.push({ path: '/therapist/patients/' + entry.item.id }); + return; + } + const target = entry?.item?.to || entry?.item?.deeplink || entry?.item?.path; if (!target) return; showPanel.value = false; @@ -266,6 +283,27 @@ const kbdModifier = kbdIsMac ? '⌘' : 'Ctrl';