diff --git a/src/layout/melissa/MelissaPaciente.vue b/src/layout/melissa/MelissaPaciente.vue index b29e637..ac40248 100644 --- a/src/layout/melissa/MelissaPaciente.vue +++ b/src/layout/melissa/MelissaPaciente.vue @@ -44,6 +44,7 @@ import { fmtDayShort, fmtRecurrenceLabel, fmtRecurrenceFim, + WEEKDAY_LABEL as WEEKDAY_LABEL_BLOCK, fmtCPF, fmtRG, fmtGender, @@ -456,6 +457,9 @@ function addFinancial() { } // Atalho: navega pra aba Agenda + abre dialog de nova sessao. +// Frequencia espelha AgendaEventDialog: avulsa | semanal | quinzenal | +// diasEspecificos. Avulsa cria 1 row em agenda_eventos; demais criam +// regra em recurrence_rules via useRecurrence. const novaSessaoOpen = ref(false); const novaSessaoForm = ref({ tipo: 'sessao', @@ -465,11 +469,50 @@ const novaSessaoForm = ref({ modalidade: 'presencial', titulo_custom: '', observacoes: '', - // Recorrencia (integra com useRecurrence — schema recurrence_rules) - repetir: false, - fim_tipo: 'open', // open | data | count - fim_data: '', - fim_count: 12 + freq: 'avulsa', + diasSelecionados: [], + qtdMode: '12', + qtdCustom: 12 +}); +const FREQ_OPCOES = [ + { value: 'avulsa', label: 'Avulsa' }, + { value: 'semanal', label: 'Semanal' }, + { value: 'quinzenal', label: 'Quinzenal' }, + { value: 'diasEspecificos', label: 'Dias específicos' } +]; +const DIAS_SEMANA_OPCOES = [ + { value: 1, short: 'Seg' }, + { value: 2, short: 'Ter' }, + { value: 3, short: 'Qua' }, + { value: 4, short: 'Qui' }, + { value: 5, short: 'Sex' }, + { value: 6, short: 'Sáb' }, + { value: 0, short: 'Dom' } +]; +const QTD_SESSOES_OPCOES = [ + { value: '4', label: '4 sessões' }, + { value: '8', label: '8 sessões' }, + { value: '12', label: '12 sessões' }, + { value: 'personalizar', label: 'Personalizar' } +]; + +function toggleDiaSelecionado(d) { + const arr = [...(novaSessaoForm.value.diasSelecionados || [])]; + const idx = arr.indexOf(d); + if (idx === -1) arr.push(d); + else arr.splice(idx, 1); + novaSessaoForm.value.diasSelecionados = arr; +} + +const qtdSessoesEfetiva = computed(() => { + const f = novaSessaoForm.value; + if (f.qtdMode === 'personalizar') return Number(f.qtdCustom) || null; + return Number(f.qtdMode) || null; +}); + +// Label dinamico do botao "Salvar" +const novaSessaoCtaLabel = computed(() => { + return novaSessaoForm.value.freq === 'avulsa' ? 'Agendar sessão' : 'Criar recorrência'; }); const SESSAO_TIPOS = [ { label: 'Sessão', value: 'sessao' }, @@ -510,10 +553,10 @@ function goAgendar() { modalidade: 'presencial', titulo_custom: '', observacoes: '', - repetir: false, - fim_tipo: 'open', - fim_data: '', - fim_count: 12 + freq: 'avulsa', + diasSelecionados: [], + qtdMode: '12', + qtdCustom: 12 }; novaSessaoOpen.value = true; } @@ -536,15 +579,30 @@ async function salvarSessao() { } // Caminho RECORRENTE: cria regra em recurrence_rules via useRecurrence. - // Ocorrencias sao geradas dinamicamente — nao precisa popular agenda_eventos - // futuros (sessoes confirmadas/realizadas viram rows reais sob demanda). - if (f.repetir) { - if (f.fim_tipo === 'data' && !f.fim_data) { - toast.add({ severity: 'warn', summary: 'Informe a data de fim', life: 2500 }); - return; + // Ocorrencias sao geradas dinamicamente. + if (f.freq !== 'avulsa') { + // Mapeamento freq -> { type, interval, weekdays } + let type, interval, weekdays; + if (f.freq === 'semanal') { + type = 'weekly'; + interval = 1; + weekdays = [inicio.getDay()]; + } else if (f.freq === 'quinzenal') { + type = 'biweekly'; + interval = 2; + weekdays = [inicio.getDay()]; + } else if (f.freq === 'diasEspecificos') { + if (!f.diasSelecionados.length) { + toast.add({ severity: 'warn', summary: 'Selecione ao menos um dia da semana', life: 3000 }); + return; + } + type = 'custom_weekdays'; + interval = 1; + weekdays = [...f.diasSelecionados].sort(); } - if (f.fim_tipo === 'count' && (!f.fim_count || Number(f.fim_count) < 1)) { - toast.add({ severity: 'warn', summary: 'Informe o número de ocorrências', life: 2500 }); + const max = qtdSessoesEfetiva.value; + if (!max || max < 1) { + toast.add({ severity: 'warn', summary: 'Quantidade de sessões inválida', life: 2500 }); return; } try { @@ -553,12 +611,12 @@ async function salvarSessao() { const rule = { patient_id: props.patientId, owner_id: ownerId, - type: 'weekly', - interval: 1, - weekdays: [inicio.getDay()], + type, + interval, + weekdays, start_date: f.data, - end_date: f.fim_tipo === 'data' ? f.fim_data : null, - max_occurrences: f.fim_tipo === 'count' ? Number(f.fim_count) : null, + end_date: null, + max_occurrences: max, start_time: f.hora, duration_min: Number(f.duracao_min) || 50, modalidade: f.modalidade, @@ -570,12 +628,10 @@ async function salvarSessao() { toast.add({ severity: 'success', summary: 'Recorrência criada', - detail: 'A série semanal está ativa. Veja em "Recorrências".', + detail: `${max} sessões previstas. Veja em "Recorrências".`, life: 3000 }); novaSessaoOpen.value = false; - // Recarrega sessoes (caso start_date seja hoje) + recorrencias - // (a regra recem-criada precisa aparecer no bloco da Tab Agenda). await Promise.all([ sessionsHook.load(props.patientId), recorrenciasHook.load(props.patientId) @@ -2404,46 +2460,77 @@ onBeforeUnmount(() => { /> - +