agenda: C10 pos-test fixes + lock sessao encerrada + addendum doc
Bugs descobertos durante testes C10/A2/B/C com user:
1) _reloadRange not defined: _buildHandlers nao destruturava
_reloadRange do deps (passava mas nao desempacotava). Toast
ReferenceError ao tentar reload pos-status change. Fix em
useMelissaAgenda.js:_buildHandlers.
2) Badge $ amber em sessao cancelada: MelissaAgenda.vue badge gate
ignorava status. Cancelado+state=none (records cancelled
filtrados) ainda recebia badge "cobranca pendente". Fix: gate
sessaoEncerrada (cancelado/faltou) -> sem badge nunca.
3) Botao "Gerar cobranca" em sessao encerrada: AgendaEventoFinanceiro
Panel mostrava botao mesmo em cancelado/faltou -> user podia
emitir fatura nova em sessao que nao aconteceu. Fix: v-if
!isSessaoEncerrada + label muda pra "Sessao cancelada · sem
cobranca ativa".
4) paymentLabel usava ev.price em vez de paymentAmount pra state
'pending': caso multa R$ 30 mostrava R$ 150 (ev.price original).
Fix: usar paymentAmount tambem em pending.
5) Lock total em sessao encerrada (cancelado/faltou):
- "Editar sessao" SOME do popover
- Realizada/Falta/Reagendar/Cancelar disabled com tooltip
- Apenas "Agendada" continua funcional (caminho explicito de
recuperacao). Single path de saida do estado encerrado.
Adicoes UX em AgendaStatusChangeConfirmDialog:
- Hint contextual sobre min_hours_notice explicando POR QUE multa
veio (des)marcada por padrao: "Cancelou 18.5h antes da sessao.
Regra: multa apenas quando cancelamento <2h -> sem multa por
padrao." Terapeuta ve a razao e pode inverter conscientemente.
Adicoes UX em MelissaEventoPanel:
- Botao "Agendada" (variante --info azul cyan) no grupo status
pra reset/recuperacao. CSS .evento-act--info hover + is-current.
Doc:
- Addendum C10 no topo de src/docs/agenda-compromisso-financeiro
-cenarios.html capturando todas as divergencias/melhorias vs
mockup original + 3 pendencias pos-C13 (reverse transitions,
popover snapshot, A2 markPaid stale).
Pendencias salvas em memoria pra puxar pos-C13.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -100,6 +100,20 @@ const scenario = computed(() => {
|
||||
|
||||
const canAct = computed(() => record.value && (record.value.status === 'pending' || record.value.status === 'overdue'));
|
||||
|
||||
// Sessão encerrada (não rolou) — bloqueia geração de cobrança nova.
|
||||
// Multa em cancelado/faltou deve passar pelo AgendaStatusChangeConfirmDialog,
|
||||
// não por "Gerar cobrança" solto que ignora o motivo.
|
||||
const isSessaoEncerrada = computed(() => {
|
||||
const s = String(props.evento?.status || '').toLowerCase();
|
||||
return s === 'cancelado' || s === 'cancelada' || s === 'faltou';
|
||||
});
|
||||
const semCobrancaLabel = computed(() => {
|
||||
const s = String(props.evento?.status || '').toLowerCase();
|
||||
if (s === 'cancelado' || s === 'cancelada') return 'Sessão cancelada · sem cobrança ativa';
|
||||
if (s === 'faltou') return 'Sessão não realizada · sem cobrança ativa';
|
||||
return 'Sem cobrança gerada';
|
||||
});
|
||||
|
||||
// ── buscar financial_record pelo evento ───────────────────────────────────────
|
||||
async function fetchRecord() {
|
||||
if (!props.evento.id) return;
|
||||
@@ -235,10 +249,13 @@ function requestCancel() {
|
||||
<div v-else-if="scenario === 'sem-cobranca'" class="fin-panel__body fin-panel__body--empty">
|
||||
<div class="flex items-center gap-2 text-[var(--text-color-secondary)]">
|
||||
<i class="pi pi-minus-circle text-sm opacity-50" />
|
||||
<span class="text-sm">Sem cobrança gerada</span>
|
||||
<span class="text-sm">{{ semCobrancaLabel }}</span>
|
||||
</div>
|
||||
<Button label="Gerar cobrança" icon="pi pi-plus" size="small" class="rounded-full mt-2" :loading="generating || finLoading" @click="onGerarCobranca" />
|
||||
<div v-if="props.evento.price" class="text-xs text-[var(--text-color-secondary)] mt-1">Valor da sessão: {{ fmtBRL(props.evento.price) }}</div>
|
||||
<!-- Botão "Gerar cobrança" só aparece em status ativo (agendado/realizado).
|
||||
Pra cancelado/faltou: sessão não aconteceu → cobrança nova não cabe
|
||||
aqui. Pra registrar multa, usar o dialog de status change. -->
|
||||
<Button v-if="!isSessaoEncerrada" label="Gerar cobrança" icon="pi pi-plus" size="small" class="rounded-full mt-2" :loading="generating || finLoading" @click="onGerarCobranca" />
|
||||
<div v-if="props.evento.price && !isSessaoEncerrada" class="text-xs text-[var(--text-color-secondary)] mt-1">Valor da sessão: {{ fmtBRL(props.evento.price) }}</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Carregando o financial_record ────────────────────────────────── -->
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
<aside class="text-xs sticky top-20 self-start max-h-[80vh] overflow-y-auto">
|
||||
<p class="font-semibold text-slate-700 uppercase tracking-wide mb-2 text-[.65rem]">Cenários</p>
|
||||
<nav class="space-y-0.5" id="toc">
|
||||
<a href="#addendum-c10" class="toc-link block px-2 py-1 rounded hover:bg-slate-100 text-violet-700">✦ Addendum C10 (20/05)</a>
|
||||
<a href="#indicadores" class="toc-link block px-2 py-1 rounded hover:bg-slate-100 text-violet-700">★ Indicadores visuais</a>
|
||||
<a href="#c1" class="toc-link block px-2 py-1 rounded hover:bg-slate-100">1 · Bloqueio</a>
|
||||
<p class="font-semibold text-slate-500 uppercase mt-3 text-[.6rem] px-2">Avulsa</p>
|
||||
@@ -143,6 +144,138 @@
|
||||
<!-- Main -->
|
||||
<main class="space-y-6">
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- ADDENDUM 2026-05-20 — Divergências e melhorias C10 -->
|
||||
<!-- ============================================================ -->
|
||||
<section id="addendum-c10" class="scene">
|
||||
<header class="mb-2">
|
||||
<h2 class="text-base font-semibold text-slate-900 flex items-center gap-2">
|
||||
<span class="pill pill-violet">✦ addendum</span>
|
||||
Implementado em 20/05 (C10) — divergências e melhorias vs mockup
|
||||
</h2>
|
||||
<p class="text-xs text-slate-500 ml-1 mt-1">
|
||||
O mockup original deste doc foi escrito antes da implementação real. Durante a bateria de testes C10 (status change avulsa), surgiram bugs, melhorias UX e travas que foram implementadas mas não estão refletidas nas seções abaixo. Este addendum captura essas mudanças. Cenários C1-C9 continuam fiéis ao mockup; C10 deve ser lido com este addendum em mente.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-head">
|
||||
<i class="pi pi-wrench"></i>
|
||||
<h4>O que ficou diferente / melhor que o mockup original</h4>
|
||||
</div>
|
||||
<div class="card-body p-4 space-y-3 text-sm">
|
||||
|
||||
<!-- 1. Multa cancela original + cria novo -->
|
||||
<div>
|
||||
<div class="font-semibold text-slate-800 mb-1">1. Multa <span class="pill pill-violet">cancela original + cria novo</span></div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
Antes do fix: <code>_applyStatusDecisions</code> INSERIA o record da multa MAS deixava o original pending → cobrança dupla (R$ 200 + R$ 30 = R$ 230). Fix em <code>useMelissaAgenda.js:1450-1505</code>: aplicar multa agora cancela o <code>ctx.pendingRecord</code> com nota de auditoria em <code>notes</code> ("[YYYY-MM-DD] Cancelada — substituída por multa de no-show"). Description do novo record carrega data da sessão pra paciente identificar na fatura: <code>"Multa por falta · sessão dd/mm/aa"</code>. ✅ Match com o mock C10/b.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. Hint contextual no dialog -->
|
||||
<div>
|
||||
<div class="font-semibold text-slate-800 mb-1">2. Hint contextual explicando regra <code>min_hours_notice</code> <span class="pill pill-info">novo</span></div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
No bloco "Aplicar multa?" do <code>AgendaStatusChangeConfirmDialog</code>, embaixo do checkbox aparece texto explicando por que veio (des)marcado por padrão:
|
||||
<ul class="list-disc pl-5 mt-1 space-y-0.5">
|
||||
<li><b>> janela:</b> "Cancelou 18.5h antes da sessão. Regra: multa apenas quando cancelamento ocorre com menos de 2h de antecedência → sem multa por padrão."</li>
|
||||
<li><b>< janela:</b> "Cancelou 45min antes da sessão (menos que os 2h da regra) → multa aplicada por padrão."</li>
|
||||
<li><b>Após início:</b> "Cancelou 0.5h após o início da sessão (menos que os 2h da regra) → multa aplicada por padrão."</li>
|
||||
</ul>
|
||||
Terapeuta vê a razão da pré-seleção e pode inverter conscientemente.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Botão Agendada -->
|
||||
<div>
|
||||
<div class="font-semibold text-slate-800 mb-1">3. Botão "Agendada" no popover <span class="pill pill-info">novo</span></div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
O grupo "Marcar sessão como:" agora tem 5 botões (antes 4): <b>Agendada</b> (pi-calendar, variante <code>--info</code> cyan) | Realizada | Falta | Reagendar | Cancelar. Permite reset de status (realizado/faltou/cancelado → agendado) direto do popover sem precisar abrir o AgendaEventDialog completo. Único caminho de saída do estado encerrado (ver item 5).
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. Label financeiro pra sessão encerrada -->
|
||||
<div>
|
||||
<div class="font-semibold text-slate-800 mb-1">4. Label do popover muda em sessão encerrada <span class="pill pill-info">UX</span></div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
Antes mostrava "A cobrar R$ 150" + botão "Gerar fatura" mesmo em sessão cancelada — sugeria que dava pra cobrar uma sessão que não aconteceu. Agora:
|
||||
<ul class="list-disc pl-5 mt-1 space-y-0.5">
|
||||
<li><code>status='cancelado'</code> + sem record ativo → "Sessão cancelada · sem cobrança ativa"</li>
|
||||
<li><code>status='faltou'</code> + sem record ativo → "Sessão não realizada · sem cobrança ativa"</li>
|
||||
<li>Multa pending continua mostrando "A receber R$ X (pendente)" normalmente</li>
|
||||
</ul>
|
||||
Bug paralelo fixado: <code>paymentLabel</code> agora usa <code>paymentAmount</code> também pra <code>'pending'</code> (antes só pra <code>'paid'</code>; multa de R$ 30 mostrava R$ 150 do <code>ev.price</code> original).
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 5. Lock em sessão encerrada -->
|
||||
<div>
|
||||
<div class="font-semibold text-slate-800 mb-1">5. Lock em sessão encerrada (cancelado/faltou) <span class="pill pill-cancel">trava</span></div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
Sessão com status <code>cancelado</code> ou <code>faltou</code> bloqueia ações que abrem porta pra dados inconsistentes:
|
||||
<ul class="list-disc pl-5 mt-1 space-y-0.5">
|
||||
<li>Botão <b>"Editar sessão"</b> some do popover</li>
|
||||
<li>Botão <b>"Gerar cobrança"</b> some do <code>AgendaEventoFinanceiroPanel</code> (dentro do AgendaEventDialog) — antes dava pra emitir fatura nova mesmo em sessão cancelada</li>
|
||||
<li>Botões <b>Realizada / Falta / Reagendar / Cancelar</b> ficam <code>disabled</code> com tooltip "Sessão encerrada — use Agendada pra reativar antes"</li>
|
||||
<li>SÓ <b>Agendada</b> continua funcional (caminho explícito de recuperação caso tenha sido marcado por engano)</li>
|
||||
<li>Badge $ amber some do card no FullCalendar (sessão encerrada + record cancelled → no badge)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 6. Bubble + reloadRange -->
|
||||
<div>
|
||||
<div class="font-semibold text-slate-800 mb-1">6. <code>_reloadRange()</code> após status change <span class="pill pill-info">fix</span></div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
<code>onUpdateSeriesEvent</code> não chamava <code>_reloadRange()</code> após <code>_applyStatusDecisions</code> — badge $ e label "A receber" ficavam stale até trocar de view ou F5. Fix: reload no fim do flow. Bug paralelo: <code>_reloadRange</code> não estava destruturado em <code>_buildHandlers(deps)</code> (era passado em deps mas não desempacotado) → toast "ReferenceError: _reloadRange is not defined" ao tentar reload. Ambos corrigidos.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 7. Dormant -->
|
||||
<div>
|
||||
<div class="font-semibold text-slate-800 mb-1">7. Bug dormente em <code>useAgendaFinanceiro.js</code> <span class="pill pill-info">fix</span></div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
<code>calcChargeAmount</code> comparava <code>charge_mode === 'fixed'</code>, mas o schema usa <code>'fixed_fee'</code>. Off-by-key silencioso que caía no fallback. Path não exercitado na Melissa (que usa <code>_applyStatusDecisions</code>, não <code>handleStatusChange</code>), mas iria quebrar se algum dia fosse. Fix: <code>'fixed_fee'</code>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pendências -->
|
||||
<div class="card mt-3">
|
||||
<div class="card-head">
|
||||
<i class="pi pi-flag"></i>
|
||||
<h4>Pendências mapeadas durante C10 — implementar pós-C13</h4>
|
||||
</div>
|
||||
<div class="card-body p-4 space-y-3 text-sm">
|
||||
|
||||
<div>
|
||||
<div class="font-semibold text-amber-700 mb-1">⚠ Reverse transitions com multa órfã</div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
Caso: terapeuta marca "Faltou" com multa R$ 30 → percebe que foi engano → clica "Agendada" pra reativar → status volta pra agendado MAS multa R$ 30 fica pending órfã. Hoje precisa cancelar manualmente em <code>/financeiro</code>. Solução planejada: confirm dialog ao reverter de cancelado/faltou pra agendado com record/multa pending → oferecer auto-cancelar a multa também (radio sim/não). Memória salva em <code>project_agenda_reverse_transitions.md</code>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="font-semibold text-amber-700 mb-1">⚠ Popover Melissa = snapshot do clique</div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
<code>eventoSelecionado.value</code> é setado uma vez em <code>abrirEvento(ev)</code> — quando <code>_paymentStateMap</code> updata depois (ex: bulk-load assíncrono pós F5 leva 1-3s), o popover NÃO re-renderiza com state novo. Caso típico: F5 + clique rapidíssimo no card → popover mostra "A cobrar R$ 150" (state='none' default) porque snapshot pegou map vazio. Fix planejado: guardar <code>ev.id</code> em vez de <code>ev</code>, popover deriva via computed <code>eventos.value.find(...)</code>. Memória em <code>project_melissa_popover_snapshot.md</code>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="font-semibold text-amber-700 mb-1">⚠ A2 do João Almeida com markPaid não persistiu</div>
|
||||
<div class="text-slate-600 text-xs leading-relaxed">
|
||||
Durante teste C10/A2, usuário marcou Realizada + "Sim, registrar pagamento" + Maquininha. Toast verde, card mudou visual, mas DB mostra <code>financial_records.status='pending'</code> em vez de <code>'paid'</code>. A investigar pós-C13 — pode ser que o reset/realizada de novo tenha sobrescrito, ou o markPaid não tenha entrado no caminho de UPDATE.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- Legenda: Indicadores visuais de pagamento (badge $ + linha) -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
@@ -182,6 +182,26 @@ function _calcInitialFineApply() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Texto explicativo de porquê a multa veio (des)marcada por padrão.
|
||||
// Aparece abaixo do checkbox no bloco multa pra deixar a regra visível
|
||||
// ao terapeuta no momento da decisão.
|
||||
const fineDefaultReason = computed(() => {
|
||||
const r = props.regraExcecao;
|
||||
if (!r || r.charge_mode === 'none') return '';
|
||||
if (props.novoStatus !== 'cancelado' || r.min_hours_notice == null || !props.evento?.inicio_em) return '';
|
||||
const horasAteSessao = (new Date(props.evento.inicio_em).getTime() - Date.now()) / (1000 * 60 * 60);
|
||||
const min = Number(r.min_hours_notice);
|
||||
const horasFmt = horasAteSessao < 0
|
||||
? `${Math.abs(horasAteSessao).toFixed(1)}h após o início`
|
||||
: horasAteSessao < 1
|
||||
? `${Math.round(horasAteSessao * 60)}min antes`
|
||||
: `${horasAteSessao.toFixed(1)}h antes`;
|
||||
if (horasAteSessao >= min) {
|
||||
return `Cancelou ${horasFmt} da sessão. Regra: multa apenas quando cancelamento ocorre com menos de ${min}h de antecedência → sem multa por padrão.`;
|
||||
}
|
||||
return `Cancelou ${horasFmt} da sessão (menos que os ${min}h da regra) → multa aplicada por padrão.`;
|
||||
});
|
||||
|
||||
// ─── Actions ───────────────────────────────────────────────────────────
|
||||
function onConfirm() {
|
||||
emit('confirm', {
|
||||
@@ -264,6 +284,9 @@ function onCancel() {
|
||||
class="asccd-fine-input"
|
||||
/>
|
||||
</div>
|
||||
<small v-if="fineDefaultReason" class="asccd-hint">
|
||||
<i class="pi pi-info-circle" /> {{ fineDefaultReason }}
|
||||
</small>
|
||||
<small v-if="isPacoteUpfront" class="asccd-hint">
|
||||
ℹ Pacote já pago; multa entra como cobrança adicional avulsa.
|
||||
</small>
|
||||
|
||||
@@ -655,7 +655,13 @@ const fcOptions = computed(() => ({
|
||||
// REAL sem cobrança ainda ('none'). Virtuais com 'none' (saldo,
|
||||
// sem pacote, ou virtuais limpas) ficam SEM badge — só virtuais
|
||||
// herdando 'pending' de pacote upfront mostram o badge.
|
||||
const wantBadge = isSessao && ext.patient_id && ext.paymentState !== 'paid' && (
|
||||
// Sessão encerrada (cancelado/faltou) NÃO ganha badge mesmo com
|
||||
// state='none' (records cancelled filtrados) — sessão não rolou,
|
||||
// cobrança nova não cabe. Multa pendente vem com state='pending'
|
||||
// e aí entra pelo ramo anterior, ok.
|
||||
const statusLower = String(ext.status || '').toLowerCase();
|
||||
const sessaoEncerrada = statusLower === 'cancelado' || statusLower === 'cancelada' || statusLower === 'faltou';
|
||||
const wantBadge = isSessao && ext.patient_id && ext.paymentState !== 'paid' && !sessaoEncerrada && (
|
||||
ext.paymentState === 'pending' || ext.paymentState === 'overdue' ||
|
||||
(!ext.is_occurrence && (ext.paymentState === 'none' || !ext.paymentState))
|
||||
);
|
||||
|
||||
@@ -135,6 +135,13 @@ const isSessaoComPaciente = computed(
|
||||
() => ev.value.tipo === 'sessao' && (ev.value.patient_id || ev.value.pacienteNome)
|
||||
);
|
||||
|
||||
// Sessão "encerrada" — não rolou (cancelada ou paciente faltou).
|
||||
// Bloqueia: editar sessão (dados não cabem mais) + transições de status
|
||||
// pra realizado/faltou/cancelar (não faz sentido marcar um cancelado como
|
||||
// "faltou"). Mantém SÓ "Agendada" funcional como caminho de recuperação
|
||||
// caso tenha sido marcado por engano.
|
||||
const isSessaoEncerrada = computed(() => statusSlug.value === 'cancelado' || statusSlug.value === 'faltou');
|
||||
|
||||
// Estado de pagamento — vem anotado pelo useMelissaAgenda via bulk-query
|
||||
// em financial_records. 'paid' | 'pending' | 'none'. Renderiza linha
|
||||
// curta abaixo do horário pra sessão com paciente (espelha os 3 canais
|
||||
@@ -177,7 +184,12 @@ const paymentLabel = computed(() => {
|
||||
if (state === 'pending') {
|
||||
return valorFmt ? `A receber ${valorFmt} (cobrança pendente)` : 'Cobrança pendente';
|
||||
}
|
||||
// 'none' — sessão sem cobrança gerada ainda
|
||||
// 'none' — sessão sem cobrança ativa
|
||||
// Quando status='cancelado'/'faltou' + sem record ativo, deixa claro
|
||||
// que não há cobrança em aberto (em vez de "A cobrar R$ X" enganoso).
|
||||
const slug = String(ev.value.status || '').toLowerCase();
|
||||
if (slug === 'cancelado' || slug === 'cancelada') return 'Sessão cancelada · sem cobrança ativa';
|
||||
if (slug === 'faltou') return 'Sessão não realizada · sem cobrança ativa';
|
||||
return valorFmt ? `A cobrar ${valorFmt}` : 'Cobrança ainda não gerada';
|
||||
});
|
||||
|
||||
@@ -238,6 +250,7 @@ function modalidadeIcon(mod) {
|
||||
</span>
|
||||
<div class="evento-row__edit-stack">
|
||||
<button
|
||||
v-if="!isSessaoEncerrada"
|
||||
type="button"
|
||||
class="evento-row__edit evento-row__edit--primary"
|
||||
:disabled="busy"
|
||||
@@ -285,7 +298,7 @@ function modalidadeIcon(mod) {
|
||||
sessions_used) — gerar fatura solta aqui criaria
|
||||
cobrança duplicada e dessincronizaria o saldo. -->
|
||||
<button
|
||||
v-if="paymentVariant === 'none' && !ev.is_occurrence && !contractInfo"
|
||||
v-if="paymentVariant === 'none' && !ev.is_occurrence && !contractInfo && statusSlug !== 'cancelado' && statusSlug !== 'faltou'"
|
||||
type="button"
|
||||
class="evento-row__pay-action"
|
||||
:disabled="busy"
|
||||
@@ -372,7 +385,8 @@ function modalidadeIcon(mod) {
|
||||
<button
|
||||
class="evento-act evento-act--ok"
|
||||
:class="{ 'is-current': statusSlug === 'realizado' }"
|
||||
:disabled="busy"
|
||||
:disabled="busy || isSessaoEncerrada"
|
||||
v-tooltip.top="isSessaoEncerrada ? 'Sessão encerrada — use Agendada pra reativar antes' : null"
|
||||
@click="emit('concluir')"
|
||||
>
|
||||
<i class="pi pi-check-circle" />
|
||||
@@ -381,7 +395,8 @@ function modalidadeIcon(mod) {
|
||||
<button
|
||||
class="evento-act evento-act--warn"
|
||||
:class="{ 'is-current': statusSlug === 'faltou' }"
|
||||
:disabled="busy"
|
||||
:disabled="busy || isSessaoEncerrada"
|
||||
v-tooltip.top="isSessaoEncerrada ? 'Sessão encerrada — use Agendada pra reativar antes' : null"
|
||||
@click="emit('faltou')"
|
||||
>
|
||||
<i class="pi pi-user-minus" />
|
||||
@@ -390,7 +405,8 @@ function modalidadeIcon(mod) {
|
||||
<button
|
||||
class="evento-act"
|
||||
:class="{ 'is-current': statusSlug === 'remarcar' || statusSlug === 'remarcado' }"
|
||||
:disabled="busy"
|
||||
:disabled="busy || isSessaoEncerrada"
|
||||
v-tooltip.top="isSessaoEncerrada ? 'Sessão encerrada — use Agendada pra reativar antes' : null"
|
||||
@click="emit('remarcar')"
|
||||
>
|
||||
<i class="pi pi-calendar-clock" />
|
||||
@@ -399,7 +415,8 @@ function modalidadeIcon(mod) {
|
||||
<button
|
||||
class="evento-act evento-act--danger"
|
||||
:class="{ 'is-current': statusSlug === 'cancelado' }"
|
||||
:disabled="busy"
|
||||
:disabled="busy || isSessaoEncerrada"
|
||||
v-tooltip.top="isSessaoEncerrada ? 'Sessão encerrada — use Agendada pra reativar antes' : null"
|
||||
@click="emit('cancelar')"
|
||||
>
|
||||
<i class="pi pi-ban" />
|
||||
|
||||
@@ -853,6 +853,7 @@ function _buildHandlers(deps) {
|
||||
dialogOpen, dialogEventRow, dialogStartISO, dialogEndISO,
|
||||
occDialogOpen, occDialogEventRow, occDialogStartISO, occDialogEndISO,
|
||||
_openStatusDialog,
|
||||
_reloadRange,
|
||||
bloqueioCobrindo,
|
||||
dialogBlockOverlap
|
||||
} = deps;
|
||||
|
||||
Reference in New Issue
Block a user