agenda popover: botao Agendada + fixes pos-C10/B
Adicoes (durante teste C10/A2): - Botao "Agendada" no popover (pi-calendar, variante --info azul cyan) pra permitir reset de status realizado/faltou/cancelado voltando pra agendado sem precisar abrir o AgendaEventDialog. Wire-up: emit 'agendar' -> onAgendar -> updateEventoStatus. - CSS .evento-act--info: hover + is-current com tom cyan (#38bdf8 do domainColors da agenda). Highlight generico rgba(255,255,255,0.12) era invisivel em light mode. Bug fixes durante teste C10/B com Otto Rank: - MelissaEventoPanel paymentLabel: usar paymentAmount tambem pra state='pending' (antes so 'paid' usava; pending caia em ev.price e mostrava R$ 150 original quando o pendente real era R$ 30 da multa). - useMelissaAgenda onUpdateSeriesEvent: chamar _reloadRange() apos _applyStatusDecisions. Sem isso o paymentStateMap+amountMap nao re-populavam apos status change com multa -> FullCalendar e popover ficavam stale ate F5/troca de view. Pendencia salva em memoria: travas em reverse transitions (faltou->agendado deixa multa orfa). User hit pra valer com Otto durante teste, R$ 30 limpo manualmente no DB. Implementar pos-C13. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
'close',
|
'close',
|
||||||
|
'agendar',
|
||||||
'concluir',
|
'concluir',
|
||||||
'faltou',
|
'faltou',
|
||||||
'cancelar',
|
'cancelar',
|
||||||
@@ -159,11 +160,12 @@ const paymentIcon = computed(() => {
|
|||||||
});
|
});
|
||||||
const paymentLabel = computed(() => {
|
const paymentLabel = computed(() => {
|
||||||
const state = ev.value.paymentState;
|
const state = ev.value.paymentState;
|
||||||
// Pra estado 'paid', usar o VALOR REAL pago (paymentAmount, vem do
|
// Pra estados 'paid' e 'pending' usar o VALOR REAL do record (paymentAmount).
|
||||||
// financial_record). Em pacote upfront, é o package_price total —
|
// Necessário pra cobrir caso de multa: original cancelled R$ 200 + multa
|
||||||
// o evento.price pode ter sido editado depois e divergir. Em outros
|
// pending R$ 30 → state='pending' mas paymentAmount=30 (não R$ 200 do ev.price).
|
||||||
// estados, fallback pro price/insurance_value do evento.
|
// Em pacote upfront paid, é o package_price total. Só cai no fallback de
|
||||||
const valor = state === 'paid' && ev.value.paymentAmount != null
|
// ev.price/insurance_value quando state='none' (sem record ativo).
|
||||||
|
const valor = (state === 'paid' || state === 'pending') && ev.value.paymentAmount != null
|
||||||
? ev.value.paymentAmount
|
? ev.value.paymentAmount
|
||||||
: (ev.value.price ?? ev.value.insurance_value);
|
: (ev.value.price ?? ev.value.insurance_value);
|
||||||
const valorFmt = (valor != null && !Number.isNaN(Number(valor)))
|
const valorFmt = (valor != null && !Number.isNaN(Number(valor)))
|
||||||
@@ -358,6 +360,15 @@ function modalidadeIcon(mod) {
|
|||||||
<section v-if="isSessaoComPaciente" class="evento-actions__section">
|
<section v-if="isSessaoComPaciente" class="evento-actions__section">
|
||||||
<div class="evento-actions__label">Marcar sessão como:</div>
|
<div class="evento-actions__label">Marcar sessão como:</div>
|
||||||
<div class="evento-actions__group">
|
<div class="evento-actions__group">
|
||||||
|
<button
|
||||||
|
class="evento-act evento-act--info"
|
||||||
|
:class="{ 'is-current': statusSlug === 'agendado' || statusSlug === '' }"
|
||||||
|
:disabled="busy"
|
||||||
|
@click="emit('agendar')"
|
||||||
|
>
|
||||||
|
<i class="pi pi-calendar" />
|
||||||
|
<span class="evento-act__label">Agendada</span>
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
class="evento-act evento-act--ok"
|
class="evento-act evento-act--ok"
|
||||||
:class="{ 'is-current': statusSlug === 'realizado' }"
|
:class="{ 'is-current': statusSlug === 'realizado' }"
|
||||||
@@ -905,6 +916,10 @@ html.app-dark .evento-row__pay-action--revogar {
|
|||||||
opacity: 0.45;
|
opacity: 0.45;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
.evento-act--info:hover:not(:disabled) {
|
||||||
|
color: rgb(56, 189, 248);
|
||||||
|
background: rgba(56, 189, 248, 0.10);
|
||||||
|
}
|
||||||
.evento-act--ok:hover:not(:disabled) {
|
.evento-act--ok:hover:not(:disabled) {
|
||||||
color: rgb(16, 185, 129);
|
color: rgb(16, 185, 129);
|
||||||
background: rgba(16, 185, 129, 0.15);
|
background: rgba(16, 185, 129, 0.15);
|
||||||
@@ -925,6 +940,11 @@ html.app-dark .evento-row__pay-action--revogar {
|
|||||||
background: rgba(255, 255, 255, 0.12);
|
background: rgba(255, 255, 255, 0.12);
|
||||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);
|
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25);
|
||||||
}
|
}
|
||||||
|
.evento-act--info.is-current {
|
||||||
|
color: rgb(56, 189, 248);
|
||||||
|
background: rgba(56, 189, 248, 0.18);
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(56, 189, 248, 0.55);
|
||||||
|
}
|
||||||
.evento-act--ok.is-current {
|
.evento-act--ok.is-current {
|
||||||
color: rgb(16, 185, 129);
|
color: rgb(16, 185, 129);
|
||||||
background: rgba(16, 185, 129, 0.18);
|
background: rgba(16, 185, 129, 0.18);
|
||||||
|
|||||||
@@ -708,6 +708,7 @@ async function updateEventoStatus(novoStatus, msgSucesso) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onAgendar() { updateEventoStatus('agendado', 'Sessão marcada como agendada'); }
|
||||||
function onConcluir() { updateEventoStatus('realizado', 'Sessão marcada como realizada'); }
|
function onConcluir() { updateEventoStatus('realizado', 'Sessão marcada como realizada'); }
|
||||||
function onFaltou() { updateEventoStatus('faltou', 'Marcada como falta'); }
|
function onFaltou() { updateEventoStatus('faltou', 'Marcada como falta'); }
|
||||||
function onCancelar() { updateEventoStatus('cancelado', 'Evento cancelado'); }
|
function onCancelar() { updateEventoStatus('cancelado', 'Evento cancelado'); }
|
||||||
@@ -2490,6 +2491,7 @@ function onKeydown(e) {
|
|||||||
:evento="eventoSelecionado"
|
:evento="eventoSelecionado"
|
||||||
:busy="eventoBusy"
|
:busy="eventoBusy"
|
||||||
@close="fecharEvento"
|
@close="fecharEvento"
|
||||||
|
@agendar="onAgendar"
|
||||||
@concluir="onConcluir"
|
@concluir="onConcluir"
|
||||||
@faltou="onFaltou"
|
@faltou="onFaltou"
|
||||||
@cancelar="onCancelar"
|
@cancelar="onCancelar"
|
||||||
|
|||||||
@@ -1258,6 +1258,12 @@ function _buildHandlers(deps) {
|
|||||||
ctx,
|
ctx,
|
||||||
decision
|
decision
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 3) Reload do range pra propagar paymentState/Amount atualizados
|
||||||
|
// pro FullCalendar + popover. Sem isso, badge $ e label "A receber"
|
||||||
|
// ficam stale até trocar de view ou F5. Caso típico: faltou+multa
|
||||||
|
// mostra R$ original (cancelled) em vez do R$ multa novo.
|
||||||
|
await _reloadRange();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast.add({ severity: 'warn', summary: 'Erro', detail: e?.message || 'Falha ao atualizar status.', life: 3000 });
|
toast.add({ severity: 'warn', summary: 'Erro', detail: e?.message || 'Falha ao atualizar status.', life: 3000 });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user