From 3d475b72d6a4c35848e53d18fe687dcea442b2ec Mon Sep 17 00:00:00 2001 From: Tiago Date: Fri, 9 Oct 2026 09:03:22 -0300 Subject: [PATCH] Melhora modais e confirmacoes --- src/main/webapp/cliente/assembleias.js | 4 +- src/main/webapp/cliente/condominio-detalhe.js | 2 +- src/main/webapp/cliente/configuracoes.js | 2 +- src/main/webapp/css/app.css | 109 +++++++++++++++++- src/main/webapp/js/util.js | 2 +- src/main/webapp/master/backup.js | 2 +- src/main/webapp/master/configuracoes.js | 2 +- src/main/webapp/master/financeiro.js | 2 +- 8 files changed, 111 insertions(+), 14 deletions(-) diff --git a/src/main/webapp/cliente/assembleias.js b/src/main/webapp/cliente/assembleias.js index 2bc1e2f..c0d0b2e 100644 --- a/src/main/webapp/cliente/assembleias.js +++ b/src/main/webapp/cliente/assembleias.js @@ -9,7 +9,7 @@ function destinatariosLabel(a){return (a.destinatarios||[]).map(x=>x.nome+' ('+x function diasLabel(v){return String(v||'').split(',').filter(x=>x!=='').map(x=>diasNomes[Number(x)]||x).join(', ')||'-'} function formHtml(r={}){ const dias=new Set(String(r.dias_semana||'').split(',')); - return `
${diasNomes.map((d,i)=>``).join('')}
`; + return ``; } function renderAssembleias(){ @@ -63,7 +63,7 @@ window.alternarBuscaAssembleias=()=>{ window.abrirNovoResponsavel=()=>abrirResponsavel({}); window.editarResponsavel=id=>{const r=responsaveis.find(x=>Number(x.id)===Number(id));if(r)abrirResponsavel(r)}; window.fecharResponsavelModal=()=>{modal.classList.add('hidden');modalBody.innerHTML=''}; -window.excluirResponsavel=async id=>{if(!confirm('Excluir este responsável de assembleia?'))return;try{await Api.request('/api/assembleia-responsaveis/'+id,{method:'DELETE'});Util.toast('Responsável excluído');await loadResponsaveis();await load()}catch(e){Util.toast(e.message,true)}}; +window.excluirResponsavel=async id=>{if(!await Util.confirm('Excluir este responsável de assembleia?','Excluir responsável'))return;try{await Api.request('/api/assembleia-responsaveis/'+id,{method:'DELETE'});Util.toast('Responsável excluído');await loadResponsaveis();await load()}catch(e){Util.toast(e.message,true)}}; document.querySelector('#assembleia-search-input')?.addEventListener('input',renderAssembleias); if(!Auth.isAdminEmpresa())document.querySelector('[onclick="abrirNovoResponsavel()"]')?.classList.add('hidden'); diff --git a/src/main/webapp/cliente/condominio-detalhe.js b/src/main/webapp/cliente/condominio-detalhe.js index ed21ef0..6e48465 100644 --- a/src/main/webapp/cliente/condominio-detalhe.js +++ b/src/main/webapp/cliente/condominio-detalhe.js @@ -19,7 +19,7 @@ window.fecharCalendarioAssembleias=()=>document.querySelector('#assembleia-calen window.mudarMesCalendario=delta=>{calMonth=new Date(calMonth.getFullYear(),calMonth.getMonth()+delta,1);renderCalendarioAssembleias()}; window.selecionarDiaCalendario=(key,mark=true)=>{if(mark)document.querySelectorAll('.calendar-day').forEach(x=>x.classList.toggle('selected',x.dataset.date===key));const list=document.querySelector('#calendar-day-list'),title=document.querySelector('#calendar-day-title'),items=assembleiasCalendario.filter(a=>dateKey(a.data_hora)===key);const [yy,mm,dd]=key.split('-');title.textContent=dd+'/'+mm+'/'+yy;if(!items.length){list.innerHTML='

Nenhuma assembleia agendada neste dia.

';return;}list.innerHTML=items.map(a=>{const dest=(a.destinatarios||[]).map(x=>x.nome+' ('+x.tipo+')').join(', ')||'Nenhum destinatário registrado';return '
'+a.condominio_nome+''+Util.date(a.data_hora)+''+a.tipo+' - '+(a.local||'-')+'

'+dest+'

'}).join('')}; window.reenviarAvisoAssembleia=async(cond,aid)=>{try{const a=assembleiasCalendario.find(x=>Number(x.id)===Number(aid));if(!a||!a.aviso_id)throw new Error('Aviso da assembleia não encontrado.');await Api.post('/api/condominios/'+cond+'/avisos/'+a.aviso_id+'/reenviar',{});Util.toast('Notificação reenviada')}catch(e){Util.toast(e.message,true)}}; -window.cancelarAssembleiaCalendario=async(cond,aid)=>{if(!confirm('Cancelar esta assembleia?'))return;try{await Api.put('/api/condominios/'+cond+'/assembleias/'+aid,{status:'cancelada'});Util.toast('Assembleia cancelada');await abrirCalendarioAssembleias();await loadAssembleias();await load()}catch(e){Util.toast(e.message,true)}}; +window.cancelarAssembleiaCalendario=async(cond,aid)=>{if(!await Util.confirm('Cancelar esta assembleia?','Cancelar assembleia'))return;try{await Api.put('/api/condominios/'+cond+'/assembleias/'+aid,{status:'cancelada'});Util.toast('Assembleia cancelada');await abrirCalendarioAssembleias();await loadAssembleias();await load()}catch(e){Util.toast(e.message,true)}}; function ensureAvisoNotifModal(){let m=document.querySelector('#aviso-notif-modal');if(m)return m;document.body.insertAdjacentHTML('beforeend','');return document.querySelector('#aviso-notif-modal')} function avisoDestInputs(){return [...document.querySelectorAll('#aviso-dests-hidden input[name=dest]')]} function updateAvisoNotifSummary(){const n=avisoDestInputs().filter(x=>x.checked).length;const el=document.querySelector('#aviso-notif-summary');if(el)el.textContent=n?(n+' selecionado'+(n>1?'s':'')):'Nenhuma pessoa selecionada'} diff --git a/src/main/webapp/cliente/configuracoes.js b/src/main/webapp/cliente/configuracoes.js index 27e1570..d02fef2 100644 --- a/src/main/webapp/cliente/configuracoes.js +++ b/src/main/webapp/cliente/configuracoes.js @@ -1 +1 @@ -const form=document.querySelector('#wa-form'),statusEl=document.querySelector('#status'),qr=document.querySelector('#qr'),qrBox=document.querySelector('#qr-box'),pairing=document.querySelector('#pairing'),btnQr=document.querySelector('#btn-qr'),btnReconnect=document.querySelector('#btn-reconnect'),btnDisconnect=document.querySelector('#btn-disconnect');async function load(){try{const d=await Api.get('/api/config/evolution-instancia/status');const i=d.instancia;const evo=d.evolution||{};statusEl.innerHTML=i?`

Status aprovacao: ${Util.badge(i.status)}

Numero: ${i.numero_whatsapp||'-'}

Conexao: ${Util.badge(evo.state||'-')}

`:`

Status: ${Util.badge(d.status)}

`;const has=i!=null;btnQr.disabled=!has;btnReconnect.disabled=!has;btnDisconnect.disabled=!has}catch(e){Util.toast(e.message,true)}}function showQr(d){qrBox.classList.remove('hidden');const base64=d.qrcode_base64||d.qr_code_base64;if(base64){qr.src=base64.startsWith('data:image/')?base64:'data:image/png;base64,'+base64;qr.classList.remove('hidden')}else{qr.classList.add('hidden');Util.toast('Evolution nao retornou QR Code nesta tentativa',true)}pairing.value=d.pairing_code||''}form.onsubmit=async e=>{e.preventDefault();try{const d=await Api.post('/api/config/evolution-instancia/conectar',Util.formData(form));statusEl.innerHTML=`

WhatsApp cadastrado com sucesso. Aguarde a liberacao no painel Master.

Status aprovacao: ${Util.badge(d.status)}

Instancia: ${d.instance_name}

`;showQr(d);Util.toast('WhatsApp cadastrado com sucesso');setTimeout(load,1600)}catch(err){Util.toast(err.message,true)}};btnQr.onclick=async()=>{try{const d=await Api.post('/api/config/evolution-instancia/qrcode',{});showQr(d);Util.toast('QR Code atualizado')}catch(e){Util.toast(e.message,true)}};btnReconnect.onclick=async()=>{try{await Api.post('/api/config/evolution-instancia/reconectar',{});Util.toast('Reconexao solicitada');setTimeout(load,1200)}catch(e){Util.toast(e.message,true)}};btnDisconnect.onclick=async()=>{if(!confirm('Desconectar esta sessao do WhatsApp?'))return;try{await Api.post('/api/config/evolution-instancia/desconectar',{});Util.toast('Sessao desconectada');setTimeout(load,1200)}catch(e){Util.toast(e.message,true)}};load(); \ No newline at end of file +const form=document.querySelector('#wa-form'),statusEl=document.querySelector('#status'),qr=document.querySelector('#qr'),qrBox=document.querySelector('#qr-box'),pairing=document.querySelector('#pairing'),btnQr=document.querySelector('#btn-qr'),btnReconnect=document.querySelector('#btn-reconnect'),btnDisconnect=document.querySelector('#btn-disconnect');async function load(){try{const d=await Api.get('/api/config/evolution-instancia/status');const i=d.instancia;const evo=d.evolution||{};statusEl.innerHTML=i?`

Status aprovacao: ${Util.badge(i.status)}

Numero: ${i.numero_whatsapp||'-'}

Conexao: ${Util.badge(evo.state||'-')}

`:`

Status: ${Util.badge(d.status)}

`;const has=i!=null;btnQr.disabled=!has;btnReconnect.disabled=!has;btnDisconnect.disabled=!has}catch(e){Util.toast(e.message,true)}}function showQr(d){qrBox.classList.remove('hidden');const base64=d.qrcode_base64||d.qr_code_base64;if(base64){qr.src=base64.startsWith('data:image/')?base64:'data:image/png;base64,'+base64;qr.classList.remove('hidden')}else{qr.classList.add('hidden');Util.toast('Evolution nao retornou QR Code nesta tentativa',true)}pairing.value=d.pairing_code||''}form.onsubmit=async e=>{e.preventDefault();try{const d=await Api.post('/api/config/evolution-instancia/conectar',Util.formData(form));statusEl.innerHTML=`

WhatsApp cadastrado com sucesso. Aguarde a liberacao no painel Master.

Status aprovacao: ${Util.badge(d.status)}

Instancia: ${d.instance_name}

`;showQr(d);Util.toast('WhatsApp cadastrado com sucesso');setTimeout(load,1600)}catch(err){Util.toast(err.message,true)}};btnQr.onclick=async()=>{try{const d=await Api.post('/api/config/evolution-instancia/qrcode',{});showQr(d);Util.toast('QR Code atualizado')}catch(e){Util.toast(e.message,true)}};btnReconnect.onclick=async()=>{try{await Api.post('/api/config/evolution-instancia/reconectar',{});Util.toast('Reconexao solicitada');setTimeout(load,1200)}catch(e){Util.toast(e.message,true)}};btnDisconnect.onclick=async()=>{if(!await Util.confirm('Desconectar esta sessao do WhatsApp?','Desconectar WhatsApp'))return;try{await Api.post('/api/config/evolution-instancia/desconectar',{});Util.toast('Sessao desconectada');setTimeout(load,1200)}catch(e){Util.toast(e.message,true)}};load(); diff --git a/src/main/webapp/css/app.css b/src/main/webapp/css/app.css index e5209f7..2bab213 100644 --- a/src/main/webapp/css/app.css +++ b/src/main/webapp/css/app.css @@ -664,24 +664,25 @@ th { display: grid; place-items: center; padding: 24px; + overflow: auto; } .modal-backdrop { position: absolute; inset: 0; - background: rgba(15, 23, 42, .50); - backdrop-filter: blur(2px); + background: rgba(15, 23, 42, .56); + backdrop-filter: blur(3px); } .modal-panel { position: relative; - width: min(860px, 100%); + width: min(920px, 100%); max-height: calc(100vh - 48px); overflow: auto; background: #fff; border: 1px solid var(--line); border-radius: var(--radius-lg); - padding: 18px; + padding: 24px; box-shadow: var(--shadow-lg); } @@ -689,8 +690,83 @@ th { display: flex; justify-content: space-between; gap: 12px; + align-items: flex-start; + margin-bottom: 22px; + padding-bottom: 14px; + border-bottom: 1px solid var(--line); +} + +.modal-head h2 { + margin: 0; + font-size: 22px; +} + +.modal-head .btn { + min-height: 38px; + padding: 8px 13px; +} + +.modal-form { + display: grid; + gap: 20px; +} + +.form-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 16px; + align-items: start; +} + +.field-wide { + grid-column: 1 / -1; +} + +.check-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); + gap: 10px; + padding: 12px; + border: 1px solid var(--line); + border-radius: var(--radius); + background: var(--panel-muted); +} + +.check-grid label, +#notif-modal-body label, +#aviso-notif-body label { + min-height: 38px; + display: flex; align-items: center; - margin-bottom: 16px; + gap: 8px; + margin: 0; + padding: 8px 10px; + border: 1px solid var(--line); + border-radius: var(--radius-sm); + background: #fff; +} + +.modal-actions { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 12px; + flex-wrap: wrap; + padding-top: 16px; + border-top: 1px solid var(--line); +} + +.modal-actions .btn { + min-width: 120px; +} + +.confirm-panel { + width: min(460px, 100%); +} + +.confirm-panel p { + margin: 0 0 6px; + color: var(--muted-strong); } .modal-grid { @@ -1087,10 +1163,15 @@ th { } @media (max-width: 720px) { - .modal-grid { + .modal-grid, + .form-grid { grid-template-columns: 1fr; } + .check-grid { + grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); + } + .modal { padding: 12px; } @@ -1134,12 +1215,28 @@ th { .modal-head { align-items: flex-start; + display: grid; + grid-template-columns: 1fr auto; + gap: 10px; } .modal-head .btn { width: auto; } + .modal-actions { + display: grid; + grid-template-columns: 1fr; + } + + .modal-actions .btn { + width: 100%; + } + + .check-grid { + grid-template-columns: 1fr; + } + .calendar-grid { font-size: 12px; } diff --git a/src/main/webapp/js/util.js b/src/main/webapp/js/util.js index e8a04bb..4c71f7a 100644 --- a/src/main/webapp/js/util.js +++ b/src/main/webapp/js/util.js @@ -1 +1 @@ -window.Util={money(cents){return(Number(cents||0)/100).toLocaleString('pt-BR',{style:'currency',currency:'BRL'})},date(value){return value?new Date(value).toLocaleString('pt-BR'):'-'},toast(message,error){const el=document.createElement('div');el.className='toast'+(error?' error':'');el.textContent=message;document.body.appendChild(el);setTimeout(()=>el.remove(),3600)},formData(form){return Object.fromEntries(new FormData(form).entries())},badge(status){const s=status||'-';const klass=['ativa','ativo','pago','enviado','aprovada'].includes(s)?'ok':(['pendente','bloqueada','falhou'].includes(s)?'warn':'');return `${s}`}}; \ No newline at end of file +window.Util={money(cents){return(Number(cents||0)/100).toLocaleString('pt-BR',{style:'currency',currency:'BRL'})},date(value){return value?new Date(value).toLocaleString('pt-BR'):'-'},toast(message,error){const el=document.createElement('div');el.className='toast'+(error?' error':'');el.textContent=message;document.body.appendChild(el);setTimeout(()=>el.remove(),3600)},confirm(message,title='Confirmar ação'){return new Promise(resolve=>{const id='confirm-'+Date.now();document.body.insertAdjacentHTML('beforeend',``);const el=document.querySelector('#'+id);el.querySelectorAll('button').forEach(b=>b.onclick=()=>{const ok=b.dataset.value==='true';el.remove();resolve(ok)});el.querySelector('.modal-backdrop').onclick=()=>{el.remove();resolve(false)}})},formData(form){return Object.fromEntries(new FormData(form).entries())},badge(status){const s=status||'-';const klass=['ativa','ativo','pago','enviado','aprovada'].includes(s)?'ok':(['pendente','bloqueada','falhou'].includes(s)?'warn':'');return `${s}`}}; diff --git a/src/main/webapp/master/backup.js b/src/main/webapp/master/backup.js index a4b092b..6f2e75e 100644 --- a/src/main/webapp/master/backup.js +++ b/src/main/webapp/master/backup.js @@ -1,6 +1,6 @@ const btn=document.querySelector('#backup-btn'),statusEl=document.querySelector('#backup-status'); btn.onclick=async()=>{ - if(!confirm('Gerar backup geral do sistema e de todos os clientes?'))return; + if(!await Util.confirm('Gerar backup geral do sistema e de todos os clientes?','Gerar backup'))return; btn.disabled=true; statusEl.textContent='Gerando backup...'; try{ diff --git a/src/main/webapp/master/configuracoes.js b/src/main/webapp/master/configuracoes.js index ef60ce4..0617a59 100644 --- a/src/main/webapp/master/configuracoes.js +++ b/src/main/webapp/master/configuracoes.js @@ -1 +1 @@ -const emailForm=document.querySelector('#email-form'),abacateForm=document.querySelector('#abacate-form'),emailRows=document.querySelector('#email-rows'),abacateRows=document.querySelector('#abacate-rows'),evolutionRows=document.querySelector('#evolution-rows');let empresas=[];const emailKeys=['smtp_from','smtp_host','smtp_password','smtp_port','smtp_starttls','smtp_user'];const abacateKeys=['abacatepay_api_key','abacatepay_webhook_secret'];function renderConfig(target,cfg,keys,labels){target.innerHTML=keys.map(k=>`

${labels[k]||k}: ${cfg[k]||''}

`).join('')}async function load(){try{const d=await Api.get('/api/master/configuracoes');const cfg=d.configuracoes||{};for(const [k,v] of Object.entries(cfg)){if(emailForm.elements[k])emailForm.elements[k].value=v;if(abacateForm.elements[k])abacateForm.elements[k].value=v}renderConfig(emailRows,cfg,emailKeys,{smtp_from:'Remetente',smtp_host:'Host',smtp_password:'Senha',smtp_port:'Porta',smtp_starttls:'StartTLS',smtp_user:'Usuario'});renderConfig(abacateRows,cfg,abacateKeys,{abacatepay_api_key:'API Key',abacatepay_webhook_secret:'Webhook Secret'});await loadEvolution()}catch(e){Util.toast(e.message,true)}}async function loadEvolution(){const d=await Api.get('/api/master/empresas');empresas=d.empresas||[];const grupos=await Promise.all(empresas.map(async e=>{try{const r=await Api.get(`/api/master/empresas/${e.id}/evolution-instancias`);return (r.instancias||[]).map(i=>({...i,empresa_nome:e.nome}))}catch(_){return[]}}));const instancias=grupos.flat();evolutionRows.innerHTML=instancias.length?instancias.map(i=>`${i.empresa_nome}${i.numero_whatsapp||'-'}${Util.badge(i.status)}${Util.date(i.solicitado_em)} `).join(''):'Nenhuma solicitacao encontrada.'}async function aprovar(emp,id){try{await Api.post(`/api/master/empresas/${emp}/evolution-instancias/${id}/aprovar`,{});Util.toast('Acesso liberado');loadEvolution()}catch(e){Util.toast(e.message,true)}}async function rejeitar(emp,id){try{await Api.post(`/api/master/empresas/${emp}/evolution-instancias/${id}/rejeitar`,{});Util.toast('Acesso rejeitado');loadEvolution()}catch(e){Util.toast(e.message,true)}}async function excluir(emp,id){if(!confirm('Excluir esta conexao de WhatsApp?'))return;try{await Api.request(`/api/master/empresas/${emp}/evolution-instancias/${id}`,{method:'DELETE'});Util.toast('Conexao excluida');loadEvolution()}catch(e){Util.toast(e.message,true)}}emailForm.onsubmit=async e=>{e.preventDefault();try{await Api.put('/api/master/configuracoes',Util.formData(emailForm));Util.toast('Configuracoes de e-mail salvas');load()}catch(err){Util.toast(err.message,true)}};abacateForm.onsubmit=async e=>{e.preventDefault();try{await Api.put('/api/master/configuracoes',Util.formData(abacateForm));Util.toast('Configuracoes AbacatePay salvas');load()}catch(err){Util.toast(err.message,true)}};load(); \ No newline at end of file +const emailForm=document.querySelector('#email-form'),abacateForm=document.querySelector('#abacate-form'),emailRows=document.querySelector('#email-rows'),abacateRows=document.querySelector('#abacate-rows'),evolutionRows=document.querySelector('#evolution-rows');let empresas=[];const emailKeys=['smtp_from','smtp_host','smtp_password','smtp_port','smtp_starttls','smtp_user'];const abacateKeys=['abacatepay_api_key','abacatepay_webhook_secret'];function renderConfig(target,cfg,keys,labels){target.innerHTML=keys.map(k=>`

${labels[k]||k}: ${cfg[k]||''}

`).join('')}async function load(){try{const d=await Api.get('/api/master/configuracoes');const cfg=d.configuracoes||{};for(const [k,v] of Object.entries(cfg)){if(emailForm.elements[k])emailForm.elements[k].value=v;if(abacateForm.elements[k])abacateForm.elements[k].value=v}renderConfig(emailRows,cfg,emailKeys,{smtp_from:'Remetente',smtp_host:'Host',smtp_password:'Senha',smtp_port:'Porta',smtp_starttls:'StartTLS',smtp_user:'Usuario'});renderConfig(abacateRows,cfg,abacateKeys,{abacatepay_api_key:'API Key',abacatepay_webhook_secret:'Webhook Secret'});await loadEvolution()}catch(e){Util.toast(e.message,true)}}async function loadEvolution(){const d=await Api.get('/api/master/empresas');empresas=d.empresas||[];const grupos=await Promise.all(empresas.map(async e=>{try{const r=await Api.get(`/api/master/empresas/${e.id}/evolution-instancias`);return (r.instancias||[]).map(i=>({...i,empresa_nome:e.nome}))}catch(_){return[]}}));const instancias=grupos.flat();evolutionRows.innerHTML=instancias.length?instancias.map(i=>`${i.empresa_nome}${i.numero_whatsapp||'-'}${Util.badge(i.status)}${Util.date(i.solicitado_em)} `).join(''):'Nenhuma solicitacao encontrada.'}async function aprovar(emp,id){try{await Api.post(`/api/master/empresas/${emp}/evolution-instancias/${id}/aprovar`,{});Util.toast('Acesso liberado');loadEvolution()}catch(e){Util.toast(e.message,true)}}async function rejeitar(emp,id){try{await Api.post(`/api/master/empresas/${emp}/evolution-instancias/${id}/rejeitar`,{});Util.toast('Acesso rejeitado');loadEvolution()}catch(e){Util.toast(e.message,true)}}async function excluir(emp,id){if(!await Util.confirm('Excluir esta conexao de WhatsApp?','Excluir conexão'))return;try{await Api.request(`/api/master/empresas/${emp}/evolution-instancias/${id}`,{method:'DELETE'});Util.toast('Conexao excluida');loadEvolution()}catch(e){Util.toast(e.message,true)}}emailForm.onsubmit=async e=>{e.preventDefault();try{await Api.put('/api/master/configuracoes',Util.formData(emailForm));Util.toast('Configuracoes de e-mail salvas');load()}catch(err){Util.toast(err.message,true)}};abacateForm.onsubmit=async e=>{e.preventDefault();try{await Api.put('/api/master/configuracoes',Util.formData(abacateForm));Util.toast('Configuracoes AbacatePay salvas');load()}catch(err){Util.toast(err.message,true)}};load(); diff --git a/src/main/webapp/master/financeiro.js b/src/main/webapp/master/financeiro.js index 27aa5e3..ccde91c 100644 --- a/src/main/webapp/master/financeiro.js +++ b/src/main/webapp/master/financeiro.js @@ -4,5 +4,5 @@ function periodo(e){return ''+data(e.data_inicio)+' a '+data(e.data_fim) async function load(){try{const d=await Api.get('/api/master/empresas');const es=d.empresas||[];cards.innerHTML='
Ativas'+es.filter(e=>e.status==='ativa').length+'
Bloqueadas'+es.filter(e=>e.status==='bloqueada').length+'
Pagas'+es.filter(e=>e.periodo_status==='pago').length+'
';rows.innerHTML=es.map(e=>{const bloqueada=e.status==='bloqueada'||e.periodo_status==='bloqueado';const liberar=bloqueada?' ':'';return ''+e.nome+''+Util.badge(e.status)+''+periodo(e)+'
'+liberar+''}).join('')}catch(e){Util.toast(e.message,true)}} async function salvarVencimento(id,dia){try{await Api.put('/api/master/empresas/'+id+'/vencimento',{dia_vencimento:Number(dia)});Util.toast('Vencimento atualizado');load()}catch(e){Util.toast(e.message,true)}} async function lembrar(id){try{await Api.post('/api/master/empresas/'+id+'/lembrete-cobranca',{canal:'email'});Util.toast('Lembrete registrado')}catch(e){Util.toast(e.message,true)}} -async function desbloquear(id){if(!confirm('Desbloquear manualmente esta empresa e liberar o periodo atual?'))return;try{await Api.post('/api/master/empresas/'+id+'/desbloquear',{});Util.toast('Empresa desbloqueada');load()}catch(e){Util.toast(e.message,true)}} +async function desbloquear(id){if(!await Util.confirm('Desbloquear manualmente esta empresa e liberar o periodo atual?','Desbloquear empresa'))return;try{await Api.post('/api/master/empresas/'+id+'/desbloquear',{});Util.toast('Empresa desbloqueada');load()}catch(e){Util.toast(e.message,true)}} load();