diff --git a/src/main/webapp/cliente/lembretes.html b/src/main/webapp/cliente/lembretes.html index 03e13ee..1081a14 100644 --- a/src/main/webapp/cliente/lembretes.html +++ b/src/main/webapp/cliente/lembretes.html @@ -1 +1 @@ -Lembrete

Lembrete

Novo lembrete

Lembretes

TituloData/horaStatusDestinatariosAcoes
\ No newline at end of file +Lembrete

Lembrete

Lembretes

TituloData/horaStatusDestinatariosAcoes
diff --git a/src/main/webapp/cliente/lembretes.js b/src/main/webapp/cliente/lembretes.js index 7e9029a..26d2515 100644 --- a/src/main/webapp/cliente/lembretes.js +++ b/src/main/webapp/cliente/lembretes.js @@ -1,20 +1,108 @@ -const form=document.querySelector('#lembrete-form'),rows=document.querySelector('#rows'),pessoasEl=document.querySelector('#pessoas'),submitBtn=document.querySelector('#submit-btn'),cancelBtn=document.querySelector('#cancel-edit'); -let pessoas=[],lembretes=[]; +const rows=document.querySelector('#rows'),modal=document.querySelector('#lembrete-modal'),modalTitle=document.querySelector('#lembrete-modal-title'),modalBody=document.querySelector('#lembrete-modal-body'); +let pessoas=[],lembretes=[],form=null,refreshTimer=null; + function esc(v){return String(v??'').replace(/[&<>'"]/g,c=>({'&':'&','<':'<','>':'>',"'":''','"':'"'}[c]))} function toInputDate(v){if(!v)return'';const d=new Date(v);if(Number.isNaN(d.getTime()))return'';const pad=n=>String(n).padStart(2,'0');return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`} function recLabel(v){return {1:"Mensal",3:"Trimestral",12:"Anual"}[Number(v)]||"Sem recorrencia"} -function selectedDestIds(){return new Set([...form.querySelectorAll('input[name=dest]:checked')].map(x=>String(x.value)))} +function termo(){return document.querySelector('#lembrete-search-input')?.value.trim().toLowerCase()||''} +function selectedDestIds(){return form?new Set([...form.querySelectorAll('input[name=dest]:checked')].map(x=>String(x.value))):new Set()} function updateNotifSummary(){const n=selectedDestIds().size;const el=document.querySelector('#notif-summary');if(el)el.textContent=n?(n+' selecionado'+(n>1?'s':'')):'Nenhuma pessoa selecionada'} + +function formHtml(){ + return '
'; +} + +function bindForm(){ + form=document.querySelector('#lembrete-form'); + renderPessoasForm(); + form.onsubmit=async e=>{ + e.preventDefault(); + const b=Util.formData(form); + b.destinatarios=[...form.querySelectorAll('input[name=dest]:checked')].map(x=>Number(x.value)); + try{ + if(form.id.value){ + await Api.put(`/api/lembretes/${form.id.value}`,b); + Util.toast('Lembrete atualizado'); + }else{ + const r=await Api.post('/api/lembretes',b); + const en=r.envio||{}; + Util.toast(en.enfileirado?'Lembrete enfileirado para envio':(en.falhas?('Lembrete salvo. Enviados: '+(en.enviados||0)+'. Falhas: '+en.falhas):'Lembrete cadastrado')); + } + fecharLembreteModal(); + await load(); + }catch(err){Util.toast(err.message,true)} + }; +} + +function renderPessoasForm(){ + const pessoasEl=document.querySelector('#pessoas'); + if(!pessoasEl)return; + pessoasEl.innerHTML=' Nenhuma pessoa selecionada'; + updateNotifSummary(); +} + +function renderLembretes(){ + const q=termo(); + const lista=lembretes.filter(l=>{ + const dest=(l.destinatarios||[]).map(x=>x.nome).join(' '); + return !q||[l.titulo,l.mensagem,l.status,dest,recLabel(l.recorrencia_meses)].some(v=>String(v??'').toLowerCase().includes(q)); + }); + rows.innerHTML=lista.map(l=>{ + const dest=(l.destinatarios||[]).map(x=>x.nome).join(', ')||'-'; + const acoes=l.pode_alterar?` ${l.pode_editar?``:''} `:'-'; + return `${esc(l.titulo)}
${esc(l.mensagem)}${Util.date(l.data_hora)}
${recLabel(l.recorrencia_meses)}${Util.badge(l.status)}${esc(dest)}${acoes}`; + }).join('')||'Nenhum lembrete encontrado.'; +} + +async function loadPessoas(){const d=await Api.get('/api/lembrete-pessoas');pessoas=d.pessoas||[]} +async function load(){try{const d=await Api.get('/api/lembretes');lembretes=d.lembretes||[];renderLembretes()}catch(e){Util.toast(e.message,true)}} + +window.abrirNovoLembrete=()=>{ + modalTitle.textContent='Novo lembrete'; + modalBody.innerHTML=formHtml(); + modal.classList.remove('hidden'); + bindForm(); +}; + +window.fecharLembreteModal=()=>{ + modal.classList.add('hidden'); + modalBody.innerHTML=''; + form=null; +}; + +window.alternarBuscaLembretes=()=>{ + const strip=document.querySelector('#lembrete-search'),input=document.querySelector('#lembrete-search-input'); + strip.classList.toggle('hidden'); + if(!strip.classList.contains('hidden'))input.focus(); +}; + function ensureNotifModal(){let m=document.querySelector('#notif-modal');if(m)return m;document.body.insertAdjacentHTML('beforeend','');return document.querySelector('#notif-modal')} -window.abrirNotificacao=()=>{const m=ensureNotifModal(),ids=selectedDestIds();document.querySelector('#notif-modal-body').innerHTML=pessoas.map(p=>'').join('')||'

Nenhum funcionario ativo.

';m.classList.remove('hidden')}; +window.abrirNotificacao=()=>{if(!form)return;const m=ensureNotifModal(),ids=selectedDestIds();document.querySelector('#notif-modal-body').innerHTML=pessoas.map(p=>'').join('')||'

Nenhum funcionario ativo.

';m.classList.remove('hidden')}; window.fecharNotificacao=()=>document.querySelector('#notif-modal')?.classList.add('hidden'); -window.salvarNotificacao=()=>{const ids=new Set([...document.querySelectorAll('#notif-modal-body input:checked')].map(x=>String(x.value)));form.querySelectorAll('input[name=dest]').forEach(x=>x.checked=ids.has(String(x.value)));updateNotifSummary();fecharNotificacao()}; -async function loadPessoas(){const d=await Api.get('/api/lembrete-pessoas');pessoas=d.pessoas||[];pessoasEl.innerHTML=' Nenhuma pessoa selecionada';updateNotifSummary()} -async function load(){try{const d=await Api.get('/api/lembretes');lembretes=d.lembretes||[];rows.innerHTML=lembretes.map(l=>{const dest=(l.destinatarios||[]).map(x=>x.nome).join(', ')||'-';const acoes=l.pode_alterar?` ${l.pode_editar?``:''} `:'-';return `${esc(l.titulo)}
${esc(l.mensagem)}${Util.date(l.data_hora)}
${recLabel(l.recorrencia_meses)}${Util.badge(l.status)}${esc(dest)}${acoes}`}).join('')||'Nenhum lembrete cadastrado.'}catch(e){Util.toast(e.message,true)}} -function resetForm(){form.reset();form.id.value='';form.recorrencia_meses.value='0';submitBtn.textContent='Cadastrar lembrete';cancelBtn.classList.add('hidden');form.querySelectorAll('input[name=dest]').forEach(x=>x.checked=false);updateNotifSummary()} -window.editar=id=>{const l=lembretes.find(x=>Number(x.id)===Number(id));if(!l)return;if(!l.pode_editar){Util.toast('Este lembrete ja foi enviado e nao pode mais ser editado.',true);return;}form.id.value=l.id;form.titulo.value=l.titulo||'';form.mensagem.value=l.mensagem||'';form.data_hora.value=toInputDate(l.data_hora);form.status.value='ativo';form.recorrencia_meses.value=String(l.recorrencia_meses||0);const ids=new Set((l.destinatarios||[]).map(x=>Number(x.id)));form.querySelectorAll('input[name=dest]').forEach(x=>x.checked=ids.has(Number(x.value)));updateNotifSummary();submitBtn.textContent='Salvar alteracao';cancelBtn.classList.remove('hidden');scrollTo({top:0,behavior:'smooth'})}; +window.salvarNotificacao=()=>{if(!form)return;const ids=new Set([...document.querySelectorAll('#notif-modal-body input:checked')].map(x=>String(x.value)));form.querySelectorAll('input[name=dest]').forEach(x=>x.checked=ids.has(String(x.value)));updateNotifSummary();fecharNotificacao()}; + +window.editar=id=>{ + const l=lembretes.find(x=>Number(x.id)===Number(id)); + if(!l)return; + if(!l.pode_editar){Util.toast('Este lembrete ja foi enviado e nao pode mais ser editado.',true);return;} + modalTitle.textContent='Editar lembrete'; + modalBody.innerHTML=formHtml(); + modal.classList.remove('hidden'); + bindForm(); + form.id.value=l.id; + form.titulo.value=l.titulo||''; + form.mensagem.value=l.mensagem||''; + form.data_hora.value=toInputDate(l.data_hora); + form.status.value='ativo'; + form.recorrencia_meses.value=String(l.recorrencia_meses||0); + const ids=new Set((l.destinatarios||[]).map(x=>Number(x.id))); + form.querySelectorAll('input[name=dest]').forEach(x=>x.checked=ids.has(Number(x.value))); + document.querySelector('#submit-btn').textContent='Salvar alteracao'; + updateNotifSummary(); +}; + window.enviar=async id=>{try{const r=await Api.post(`/api/lembretes/${id}/enviar`,{});const en=r.envio||{};Util.toast(en.falhas?("Enviados: "+(en.enviados||0)+". Falhas: "+en.falhas):("Lembrete enviado para "+(en.enviados||0)));await load()}catch(e){Util.toast(e.message,true)}}; -window.excluir=async id=>{try{await Api.request(`/api/lembretes/${id}`,{method:'DELETE'});Util.toast('Lembrete excluido');await load();resetForm()}catch(e){Util.toast(e.message,true)}}; -cancelBtn.onclick=resetForm; -form.onsubmit=async e=>{e.preventDefault();const b=Util.formData(form);b.destinatarios=[...form.querySelectorAll('input[name=dest]:checked')].map(x=>Number(x.value));try{if(form.id.value){await Api.put(`/api/lembretes/${form.id.value}`,b);Util.toast('Lembrete atualizado')}else{const r=await Api.post('/api/lembretes',b);const en=r.envio||{};Util.toast(en.enfileirado?'Lembrete enfileirado para envio':(en.falhas?('Lembrete salvo. Enviados: '+(en.enviados||0)+'. Falhas: '+en.falhas):'Lembrete cadastrado'))}resetForm();await load()}catch(err){Util.toast(err.message,true)}}; -(async()=>{try{await loadPessoas();await load();setInterval(load,5000)}catch(e){Util.toast(e.message,true)}})(); +window.excluir=async id=>{try{await Api.request(`/api/lembretes/${id}`,{method:'DELETE'});Util.toast('Lembrete excluido');await load();fecharLembreteModal()}catch(e){Util.toast(e.message,true)}}; + +document.querySelector('#lembrete-search-input')?.addEventListener('input',renderLembretes); +(async()=>{try{await loadPessoas();await load();refreshTimer=setInterval(load,5000)}catch(e){Util.toast(e.message,true)}})();