diff --git a/src/features/agenda/components/AgendaEventDialogV2.vue b/src/features/agenda/components/AgendaEventDialogV2.vue
index 837db0b..28b9e6b 100644
--- a/src/features/agenda/components/AgendaEventDialogV2.vue
+++ b/src/features/agenda/components/AgendaEventDialogV2.vue
@@ -270,16 +270,22 @@ function onPatientCreatedRapido(p) {
cadRapidoOpen.value = false;
}
+// Mostra TODOS os pacientes (inclusive Inativo/Arquivado) — UX intencional:
+// nao-Ativos vem com badge + disabled no template, ordenados pro final.
+// selectPaciente bloqueia o clique se status !== 'Ativo'.
+const _aev2StatusRank = { Ativo: 0, Inativo: 1, Arquivado: 2 };
const filteredPatients = computed(() => {
const q = String(pacienteSearch.value || '').trim().toLowerCase();
- const list = (patients.value || []).filter((p) => p.status === 'Ativo');
- if (!q) return list;
- return list.filter((p) => {
- const nome = String(p.nome || '').toLowerCase();
- const email = String(p.email || '').toLowerCase();
- const tel = String(p.telefone || '').toLowerCase();
- return nome.includes(q) || email.includes(q) || tel.includes(q);
- });
+ const list = patients.value || [];
+ const matched = !q
+ ? [...list]
+ : list.filter((p) => {
+ const nome = String(p.nome || '').toLowerCase();
+ const email = String(p.email || '').toLowerCase();
+ const tel = String(p.telefone || '').toLowerCase();
+ return nome.includes(q) || email.includes(q) || tel.includes(q);
+ });
+ return matched.sort((a, b) => (_aev2StatusRank[a.status] ?? 3) - (_aev2StatusRank[b.status] ?? 3));
});
function goToAgendamentosRecebidos() {
@@ -924,6 +930,9 @@ const heroDateText = computed(() => {
:key="p.id"
type="button"
class="aev2-picker-item"
+ :class="{ 'aev2-picker-item--blocked': p.status && p.status !== 'Ativo' }"
+ :disabled="p.status && p.status !== 'Ativo'"
+ :title="p.status === 'Arquivado' ? 'Paciente arquivado — não é possível agendar' : p.status === 'Inativo' ? 'Paciente inativo — não é possível agendar' : ''"
@click="selectPaciente(p)"
>
@@ -932,6 +941,8 @@ const heroDateText = computed(() => {
{{ p.nome }}
{{ p.email || p.telefone }}
+
+
@@ -946,6 +957,7 @@ const heroDateText = computed(() => {
email-field="email_principal"
phone-field="telefone"
:extra-payload="{ status: 'Ativo' }"
+ hide-view-list-button
@created="onPatientCreatedRapido"
/>
@@ -1477,4 +1489,9 @@ const heroDateText = computed(() => {
transition: background .15s;
}
.aev2-picker-item:hover { background: var(--aev2-pill-bg); }
+.aev2-picker-item--blocked {
+ opacity: .6;
+ cursor: not-allowed;
+}
+.aev2-picker-item--blocked:hover { background: transparent; }
diff --git a/src/features/agenda/composables/__tests__/useAgendaEventPickerBilling.spec.js b/src/features/agenda/composables/__tests__/useAgendaEventPickerBilling.spec.js
index 3bf5170..b5f433e 100644
--- a/src/features/agenda/composables/__tests__/useAgendaEventPickerBilling.spec.js
+++ b/src/features/agenda/composables/__tests__/useAgendaEventPickerBilling.spec.js
@@ -333,6 +333,33 @@ describe('selectPaciente / clearPaciente', () => {
expect(composer.form.value.paciente_id).toBe(null);
});
+ it('selectPaciente copia status pro form quando Ativo', () => {
+ const composer = makeComposer();
+ const { selectPaciente } = setup({ composer });
+ selectPaciente({ id: 'p-1', nome: 'Ana', status: 'Ativo' });
+ expect(composer.form.value.paciente_id).toBe('p-1');
+ expect(composer.form.value.paciente_status).toBe('Ativo');
+ });
+
+ it('selectPaciente bloqueia paciente Arquivado (defesa em camadas)', () => {
+ const composer = makeComposer();
+ const { selectPaciente, pacientePickerOpen } = setup({ composer });
+ pacientePickerOpen.value = true;
+ selectPaciente({ id: 'p-arq', nome: 'Ana', status: 'Arquivado' });
+ // Form nao deve ter sido tocado
+ expect(composer.form.value.paciente_id).toBe(null);
+ expect(composer.form.value.paciente_status).toBeFalsy();
+ // Picker permanece aberto pro user escolher outro
+ expect(pacientePickerOpen.value).toBe(true);
+ });
+
+ it('selectPaciente bloqueia paciente Inativo', () => {
+ const composer = makeComposer();
+ const { selectPaciente } = setup({ composer });
+ selectPaciente({ id: 'p-ina', nome: 'Bruno', status: 'Inativo' });
+ expect(composer.form.value.paciente_id).toBe(null);
+ });
+
it('clearPaciente limpa form + samePatientConflict', () => {
const composer = makeComposer({
formExtra: { paciente_id: 'p-1', paciente_nome: 'Ana', paciente_avatar: 'url' }
diff --git a/src/features/agenda/composables/useAgendaEventPickerBilling.js b/src/features/agenda/composables/useAgendaEventPickerBilling.js
index 26915bf..b445903 100644
--- a/src/features/agenda/composables/useAgendaEventPickerBilling.js
+++ b/src/features/agenda/composables/useAgendaEventPickerBilling.js
@@ -286,9 +286,18 @@ export function useAgendaEventPickerBilling({
function selectPaciente(p) {
if (!p?.id) return;
+ // Bloqueia clique em paciente arquivado/inativo — defesa em camadas:
+ // o template do picker ja marca esses items como disabled, mas se
+ // alguem chamar selectPaciente programaticamente (cache stale, etc),
+ // a regra precisa valer.
+ if (p.status && p.status !== 'Ativo') return;
composer.form.value.paciente_id = p.id;
composer.form.value.paciente_nome = p.nome || '';
composer.form.value.paciente_avatar = p.avatar_url || '';
+ // Sem isso, form.paciente_status fica '' e canSave nao consegue
+ // aplicar getPatientAgendaPermissions — qualquer falha do filtro
+ // acima vira sessao criavel com paciente fora do escopo.
+ composer.form.value.paciente_status = p.status || '';
pacientePickerOpen.value = false;
}
@@ -296,6 +305,7 @@ export function useAgendaEventPickerBilling({
composer.form.value.paciente_id = null;
composer.form.value.paciente_nome = '';
composer.form.value.paciente_avatar = '';
+ composer.form.value.paciente_status = '';
actions.samePatientConflict.value = null;
}