carousel, agenda arquivados, agenda cor, agenda arquivados, grupos pacientes, pacientes arquivados - desativados, sessoes verificadas, ajuste notificações, Prontuario, Agenda Animation, Menu Profile, bagdes Profile, Offline
This commit is contained in:
@@ -102,6 +102,21 @@
|
||||
Este dia é folga na sua jornada. Você ainda pode salvar se necessário.
|
||||
</Message>
|
||||
|
||||
<!-- ── Restrições de status do paciente ───────────── -->
|
||||
<Message v-if="isArchivedPastEdit" severity="warn" class="mb-3" :closable="false">
|
||||
<i class="pi pi-lock mr-1" />
|
||||
<b>Paciente arquivado.</b> O histórico de sessões é somente leitura.
|
||||
</Message>
|
||||
<Message v-if="isEdit && form.paciente_status === 'Inativo' && isSessionFuture" severity="warn" class="mb-3" :closable="false">
|
||||
<i class="pi pi-ban mr-1" />
|
||||
<b>Paciente inativo.</b> Remarcação de sessões está bloqueada.
|
||||
</Message>
|
||||
<Message v-if="!isEdit && isSessionEvent && form.paciente_id && !agendaPerms.canCreateSession" severity="error" class="mb-3" :closable="false">
|
||||
<i class="pi pi-ban mr-1" />
|
||||
<b>{{ form.paciente_status === 'Arquivado' ? 'Paciente arquivado.' : 'Paciente inativo.' }}</b>
|
||||
Novos agendamentos estão bloqueados.
|
||||
</Message>
|
||||
|
||||
<!-- ── Alerta: solicitação pendente neste horário ─── -->
|
||||
<Message v-if="solicitacaoPendente && isSessionEvent && !isEdit" severity="info" class="mb-3" :closable="false">
|
||||
<div class="flex items-center justify-between gap-3 w-full flex-wrap">
|
||||
@@ -182,7 +197,13 @@
|
||||
/>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="font-bold text-base truncate">{{ form.paciente_nome }}</div>
|
||||
<div class="text-xs text-color-secondary">Paciente vinculado</div>
|
||||
<div class="flex items-center gap-1.5 flex-wrap">
|
||||
<span class="text-xs text-color-secondary">Paciente vinculado</span>
|
||||
<span
|
||||
v-if="form.paciente_status === 'Inativo' || form.paciente_status === 'Arquivado'"
|
||||
style="display:inline-block;background:#f97316;color:#fff;font-size:9px;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;padding:1px 6px;border-radius:3px;line-height:1.5;"
|
||||
>{{ form.paciente_status === 'Arquivado' ? 'arquivado' : 'desativado' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-1 shrink-0">
|
||||
<Button v-if="!patientLocked" icon="pi pi-pencil" severity="secondary" outlined size="small" class="rounded-full h-8 w-8" v-tooltip.top="'Trocar'" @click="openPacientePicker" />
|
||||
@@ -265,10 +286,12 @@
|
||||
<div class="field-card__body">
|
||||
<SelectButton
|
||||
v-model="form.status"
|
||||
:options="statusOptions"
|
||||
:options="statusOptionsFiltered"
|
||||
optionLabel="label"
|
||||
optionValue="value"
|
||||
optionDisabled="disabled"
|
||||
:allowEmpty="false"
|
||||
:disabled="isArchivedPastEdit"
|
||||
class="w-full status-select-btn"
|
||||
/>
|
||||
</div>
|
||||
@@ -684,6 +707,7 @@
|
||||
variant="filled"
|
||||
rows="3"
|
||||
autoResize
|
||||
:disabled="isArchivedPastEdit"
|
||||
/>
|
||||
<label for="aed-observacoes-side">Observação</label>
|
||||
</FloatLabel>
|
||||
@@ -692,6 +716,11 @@
|
||||
<!-- Opção de recorrência para sessão SEM série (criação ou avulsa) -->
|
||||
<template v-if="!hasSerie">
|
||||
<div class="side-card__title mb-2">Frequência</div>
|
||||
<Message v-if="isSessionEvent && form.paciente_id && !agendaPerms.canCreateRecurrence" severity="warn" class="mb-3" :closable="false">
|
||||
<i class="pi pi-ban mr-1" />
|
||||
<b>{{ form.paciente_status === 'Arquivado' ? 'Paciente arquivado.' : 'Paciente inativo.' }}</b>
|
||||
Criação de recorrências está bloqueada.
|
||||
</Message>
|
||||
|
||||
<!-- Data de início (= form.dia) com botão Hoje -->
|
||||
<div class="rec-startdate-row mb-3">
|
||||
@@ -708,8 +737,12 @@
|
||||
v-for="f in freqOpcoes"
|
||||
:key="f.value"
|
||||
class="freq-chip"
|
||||
:class="{ 'freq-chip--active': recorrenciaType === f.value }"
|
||||
@click="recorrenciaType = f.value"
|
||||
:class="{
|
||||
'freq-chip--active': recorrenciaType === f.value,
|
||||
'opacity-40 cursor-not-allowed': f.value !== 'avulsa' && !agendaPerms.canCreateRecurrence
|
||||
}"
|
||||
:disabled="f.value !== 'avulsa' && !agendaPerms.canCreateRecurrence"
|
||||
@click="(!agendaPerms.canCreateRecurrence && f.value !== 'avulsa') ? null : (recorrenciaType = f.value)"
|
||||
>{{ f.label }}</button>
|
||||
</div>
|
||||
|
||||
@@ -1101,6 +1134,7 @@ import { useServices } from '@/features/agenda/composables/useServices'
|
||||
import { useCommitmentServices } from '@/features/agenda/composables/useCommitmentServices'
|
||||
import { usePatientDiscounts } from '@/features/agenda/composables/usePatientDiscounts'
|
||||
import { useInsurancePlans } from '@/features/agenda/composables/useInsurancePlans'
|
||||
import { getPatientAgendaPermissions } from '@/composables/usePatientLifecycle'
|
||||
|
||||
function patientInitials (nome) {
|
||||
const parts = String(nome || '').trim().split(/\s+/).filter(Boolean)
|
||||
@@ -1663,7 +1697,8 @@ const patients = ref([])
|
||||
|
||||
const filteredPatients = computed(() => {
|
||||
const q = String(pacienteSearch.value || '').trim().toLowerCase()
|
||||
const list = patients.value || []
|
||||
// Somente pacientes Ativos podem ser selecionados para novos agendamentos
|
||||
const list = (patients.value || []).filter(p => p.status === 'Ativo')
|
||||
if (!q) return list
|
||||
return list.filter(p => {
|
||||
const nome = String(p.nome || '').toLowerCase()
|
||||
@@ -2137,6 +2172,39 @@ const pillDeleteMenuItems = computed(() => {
|
||||
})
|
||||
|
||||
function isPast (iso) { return iso ? new Date(iso) < new Date() : false }
|
||||
|
||||
// ── Permissões de agenda por status do paciente ───────────────────────────
|
||||
const agendaPerms = computed(() => getPatientAgendaPermissions(form.value.paciente_status || ''))
|
||||
|
||||
// Sessão atual é futura? (para edição: usa inicio_em do evento original)
|
||||
const isSessionFuture = computed(() => {
|
||||
if (!isEdit.value) return true
|
||||
const iso = props.eventRow?.inicio_em
|
||||
return iso ? new Date(iso) > new Date() : true
|
||||
})
|
||||
|
||||
// Arquivado editando sessão passada → somente leitura
|
||||
const isArchivedPastEdit = computed(() =>
|
||||
isEdit.value &&
|
||||
form.value.paciente_status === 'Arquivado' &&
|
||||
!isSessionFuture.value
|
||||
)
|
||||
|
||||
// Inativo editando sessão futura → remarcar bloqueado
|
||||
const isInativoFutureEdit = computed(() =>
|
||||
isEdit.value &&
|
||||
form.value.paciente_status === 'Inativo' &&
|
||||
isSessionFuture.value
|
||||
)
|
||||
|
||||
// StatusOptions com remarcar desabilitado para Inativo
|
||||
const statusOptionsFiltered = computed(() => [
|
||||
{ label: 'Agendado', value: 'agendado' },
|
||||
{ label: 'Realizado', value: 'realizado' },
|
||||
{ label: 'Faltou', value: 'faltou' },
|
||||
{ label: 'Cancelado', value: 'cancelado' },
|
||||
{ label: 'Remarcar', value: 'remarcar', disabled: isInativoFutureEdit.value },
|
||||
])
|
||||
function fmtWeekdayShort (iso) { return new Date(iso).toLocaleDateString('pt-BR', { weekday: 'short' }).replace('.', '').slice(0, 3) }
|
||||
function fmtDayNum (iso) { return new Date(iso).getDate() }
|
||||
function fmtMonthShort (iso) { return new Date(iso).toLocaleDateString('pt-BR', { month: 'short' }).replace('.', '') }
|
||||
@@ -2411,6 +2479,18 @@ const canSave = computed(() => {
|
||||
if (!form.value.commitment_id) return false
|
||||
if (requiresPatient.value && !form.value.paciente_id) return false
|
||||
if (isSessionEvent.value && billingType.value === 'particular' && commitmentItems.value.length === 0) return false
|
||||
|
||||
// ── Restrições por status do paciente ────────────────────
|
||||
if (isSessionEvent.value && form.value.paciente_status) {
|
||||
const perms = agendaPerms.value
|
||||
// Criar sessão avulsa ou com recorrência: bloqueado para Inativo/Arquivado
|
||||
if (!isEdit.value && !perms.canCreateSession) return false
|
||||
// Criar recorrência: bloqueado para Inativo/Arquivado
|
||||
if (!isEdit.value && recorrenciaType.value !== 'avulsa' && !perms.canCreateRecurrence) return false
|
||||
// Arquivado tentando salvar sessão passada: bloqueado
|
||||
if (isArchivedPastEdit.value) return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
@@ -2615,9 +2695,10 @@ function resetForm () {
|
||||
id: r?.id || null,
|
||||
owner_id: r?.owner_id || props.ownerId || '',
|
||||
terapeuta_id: r?.terapeuta_id ?? null,
|
||||
paciente_id: r?.paciente_id ?? null,
|
||||
paciente_nome: r?.paciente_nome ?? r?.patient_name ?? '',
|
||||
paciente_id: r?.paciente_id ?? null,
|
||||
paciente_nome: r?.paciente_nome ?? r?.patient_name ?? '',
|
||||
paciente_avatar: r?.paciente_avatar ?? '',
|
||||
paciente_status: r?.paciente_status ?? '',
|
||||
commitment_id: r?.determined_commitment_id ?? null,
|
||||
titulo_custom: r?.titulo_custom || '',
|
||||
status: r?.status || 'agendado',
|
||||
|
||||
Reference in New Issue
Block a user