From c16473ecf056d94bb24c7dbaeb3b44028517f217 Mon Sep 17 00:00:00 2001 From: Tiago Date: Tue, 6 Oct 2026 14:42:51 -0300 Subject: [PATCH] Otimize cadastros com modais --- src/main/webapp/cliente/condominios.html | 2 +- src/main/webapp/cliente/condominios.js | 150 ++++++++++++++++++++--- src/main/webapp/css/app.css | 17 +++ 3 files changed, 152 insertions(+), 17 deletions(-) diff --git a/src/main/webapp/cliente/condominios.html b/src/main/webapp/cliente/condominios.html index 9b8a51a..ca51502 100644 --- a/src/main/webapp/cliente/condominios.html +++ b/src/main/webapp/cliente/condominios.html @@ -1 +1 @@ -Cadastro

Cadastro

Novo condominio

Condominios

IDNomeCNPJEndereco
\ No newline at end of file +Cadastro

Cadastro

Condominios

IDNomeCNPJEndereco
diff --git a/src/main/webapp/cliente/condominios.js b/src/main/webapp/cliente/condominios.js index b00fcb7..d68f3b0 100644 --- a/src/main/webapp/cliente/condominios.js +++ b/src/main/webapp/cliente/condominios.js @@ -1,29 +1,147 @@ -const form=document.querySelector('#cond-form'),rows=document.querySelector('#rows'); -let condominios=[],funcionarios=[],extras=[],funcLinks=new Map(),funcAtual=null,funcEditId=null; -async function load(){try{const d=await Api.get('/api/condominios');condominios=d.condominios||[];rows.innerHTML=condominios.map(c=>`${c.id}${c.nome}${c.cnpj||''}${c.endereco||''}Abrir`).join('')}catch(e){Util.toast(e.message,true)}} -form.onsubmit=async e=>{e.preventDefault();try{await Api.post('/api/condominios',Util.formData(form));form.reset();Util.toast('Condominio criado');await load();await loadFuncionarios()}catch(err){Util.toast(err.message,true)}}; -load(); +const rows=document.querySelector('#rows'),funcPanel=document.querySelector('#funcionarios-panel'),funcRows=document.querySelector('#func-rows'),extraPanel=document.querySelector('#extras-panel'),extraRows=document.querySelector('#extra-rows'),modal=document.querySelector('#cond-modal'),modalTitle=document.querySelector('#cond-modal-title'),modalBody=document.querySelector('#cond-modal-body'); +let condominios=[],funcionarios=[],extras=[],funcLinks=new Map(),funcAtual=null; -const funcPanel=document.querySelector('#funcionarios-panel'),funcForm=document.querySelector('#func-form'),funcRows=document.querySelector('#func-rows'),extraPanel=document.querySelector('#extras-panel'),extraForm=document.querySelector('#extra-form'),extraRows=document.querySelector('#extra-rows'),modal=document.querySelector('#cond-modal'),modalTitle=document.querySelector('#cond-modal-title'),modalBody=document.querySelector('#cond-modal-body'); function esc(v){return String(v??'').replace(/[&<>'"]/g,c=>({'&':'&','<':'<','>':'>',"'":''','"':'"'}[c]))} -async function linksPorFuncionario(){const mapa=new Map();await Promise.all(condominios.map(async c=>{try{const d=await Api.get(`/api/condominios/${c.id}/funcionarios-vinculados`);(d.funcionarios||[]).forEach(f=>{const fid=Number(f.funcionario_id||f.id);if(!mapa.has(fid))mapa.set(fid,[]);mapa.get(fid).push({id:Number(c.id),nome:c.nome});});}catch(e){}}));return mapa;} +function termo(id){return document.querySelector(id)?.value.trim().toLowerCase()||''} +function contem(item,q,campos){return !q||campos.some(c=>String(item[c]??'').toLowerCase().includes(q))} +function abrirModal(titulo,html){modalTitle.textContent=titulo;modalBody.innerHTML=html;modal.classList.remove('hidden')} +function formActions(label){return '
'} + +function renderCondominios(){ + const q=termo('#cond-search-input'); + const lista=condominios.filter(c=>contem(c,q,['id','nome','cnpj','endereco'])); + rows.innerHTML=lista.map(c=>`${c.id}${esc(c.nome)}${esc(c.cnpj||'')}${esc(c.endereco||'')}Abrir`).join('')||'Nenhum condominio encontrado.'; +} + +async function load(){ + try{ + const d=await Api.get('/api/condominios'); + condominios=d.condominios||[]; + renderCondominios(); + }catch(e){Util.toast(e.message,true)} +} + +window.abrirNovoCondominio=()=>{ + abrirModal('Novo condominio','
'+formActions('Criar')+'
'); + document.querySelector('#cond-form').onsubmit=async e=>{ + e.preventDefault(); + try{ + await Api.post('/api/condominios',Util.formData(e.target)); + Util.toast('Condominio criado'); + fecharModalCondominios(); + await load(); + await loadFuncionarios(); + }catch(err){Util.toast(err.message,true)} + }; +}; + +async function linksPorFuncionario(){ + const mapa=new Map(); + await Promise.all(condominios.map(async c=>{ + try{ + const d=await Api.get(`/api/condominios/${c.id}/funcionarios-vinculados`); + (d.funcionarios||[]).forEach(f=>{ + const fid=Number(f.funcionario_id||f.id); + if(!mapa.has(fid))mapa.set(fid,[]); + mapa.get(fid).push({id:Number(c.id),nome:c.nome}); + }); + }catch(e){} + })); + return mapa; +} + async function refreshLinks(){funcLinks=await linksPorFuncionario()} -async function loadFuncionarios(){if(!Auth.isAdminEmpresa())return;funcPanel.classList.remove('hidden');try{if(!condominios.length)await load();const d=await Api.get('/api/funcionarios');funcionarios=d.funcionarios||[];await refreshLinks();funcRows.innerHTML=funcionarios.map(f=>{const acao=f.cargo==='admin_empresa'?'Acesso total':'';const opcoes=f.cargo==='admin_empresa'?'-':' ';return ''+esc(f.nome)+''+esc(f.email)+''+esc(f.telefone||'')+''+esc(f.cargo||'')+''+Util.badge(f.status)+''+acao+''+opcoes+''}).join('')||'Nenhum funcionario cadastrado.'}catch(e){Util.toast(e.message,true)}} -if(funcForm){funcForm.onsubmit=async e=>{e.preventDefault();try{await Api.post('/api/funcionarios',Util.formData(funcForm));funcForm.reset();Util.toast('Funcionario cadastrado');loadFuncionarios()}catch(err){Util.toast(err.message,true)}}} + +function renderFuncionarios(){ + const q=termo('#func-search-input'); + const lista=funcionarios.filter(f=>contem(f,q,['nome','email','telefone','cargo','status'])); + funcRows.innerHTML=lista.map(f=>{ + const acao=f.cargo==='admin_empresa'?'Acesso total':''; + const opcoes=f.cargo==='admin_empresa'?'-':' '; + return ''+esc(f.nome)+''+esc(f.email)+''+esc(f.telefone||'')+''+esc(f.cargo||'')+''+Util.badge(f.status)+''+acao+''+opcoes+''; + }).join('')||'Nenhum funcionario encontrado.'; +} + +async function loadFuncionarios(){ + if(!Auth.isAdminEmpresa())return; + funcPanel.classList.remove('hidden'); + try{ + if(!condominios.length)await load(); + const d=await Api.get('/api/funcionarios'); + funcionarios=d.funcionarios||[]; + await refreshLinks(); + renderFuncionarios(); + }catch(e){Util.toast(e.message,true)} +} + +window.abrirNovoFuncionario=()=>{ + abrirModal('Novo funcionario','
'+formActions('Cadastrar funcionario')+'
'); + document.querySelector('#func-form').onsubmit=async e=>{ + e.preventDefault(); + try{ + await Api.post('/api/funcionarios',Util.formData(e.target)); + Util.toast('Funcionario cadastrado'); + fecharModalCondominios(); + loadFuncionarios(); + }catch(err){Util.toast(err.message,true)} + }; +}; + function funcionarioPorId(funcId){return funcionarios.find(x=>Number(x.id)===Number(funcId))} -window.abrirEditarFuncionario=funcId=>{const f=funcionarioPorId(funcId);if(!f)return;modalTitle.textContent='Editar funcionario';modalBody.innerHTML='
';modal.classList.remove('hidden');document.querySelector('#func-edit-form').onsubmit=async e=>{e.preventDefault();try{await Api.put('/api/funcionarios/'+funcId,Util.formData(e.target));Util.toast('Funcionario atualizado');fecharModalCondominios();loadFuncionarios()}catch(err){Util.toast(err.message,true)}}}; -window.abrirExcluirFuncionario=funcId=>{const f=funcionarioPorId(funcId);if(!f)return;modalTitle.textContent='Excluir funcionario';modalBody.innerHTML='

Deseja realmente excluir o acesso de '+esc(f.nome||'')+'?

O funcionario sera inativado e perdera acesso ao sistema.

';modal.classList.remove('hidden')}; +window.abrirEditarFuncionario=funcId=>{const f=funcionarioPorId(funcId);if(!f)return;abrirModal('Editar funcionario','
'+formActions('Salvar')+'
');document.querySelector('#func-edit-form').onsubmit=async e=>{e.preventDefault();try{await Api.put('/api/funcionarios/'+funcId,Util.formData(e.target));Util.toast('Funcionario atualizado');fecharModalCondominios();loadFuncionarios()}catch(err){Util.toast(err.message,true)}}}; +window.abrirExcluirFuncionario=funcId=>{const f=funcionarioPorId(funcId);if(!f)return;abrirModal('Excluir funcionario','

Deseja realmente excluir o acesso de '+esc(f.nome||'')+'?

O funcionario sera inativado e perdera acesso ao sistema.

')}; window.confirmarExcluirFuncionario=async funcId=>{try{await Api.request('/api/funcionarios/'+funcId,{method:'DELETE'});Util.toast('Funcionario inativado');fecharModalCondominios();loadFuncionarios()}catch(err){Util.toast(err.message,true)}}; + function renderModalCondominios(){const f=funcionarios.find(x=>Number(x.id)===Number(funcAtual));if(!f)return;const vinculados=funcLinks.get(Number(funcAtual))||[];const vinculadosIds=new Set(vinculados.map(c=>Number(c.id)));const disponiveis=condominios.filter(c=>!vinculadosIds.has(Number(c.id)));modalTitle.textContent=`Condominios de ${f.nome}`;const listaVinculados=vinculados.map(c=>`
${esc(c.nome)}
`).join('')||'

Nenhum condominio vinculado.

';const listaDisponiveis=disponiveis.map(c=>`
${esc(c.nome)}
`).join('')||'

Todos os condominios ja estao vinculados.

';modalBody.innerHTML=``} window.abrirModalCondominios=async funcId=>{funcAtual=Number(funcId);try{await refreshLinks();renderModalCondominios();modal.classList.remove('hidden')}catch(err){Util.toast(err.message,true)}}; -window.fecharModalCondominios=()=>{modal.classList.add('hidden');funcAtual=null}; +window.fecharModalCondominios=()=>{modal.classList.add('hidden');funcAtual=null;modalBody.innerHTML=''}; window.vincularFuncionarioCondominio=async (funcId,condId)=>{try{await Api.post(`/api/condominios/${condId}/funcionarios-vinculados`,{funcionario_id:funcId});Util.toast('Funcionario vinculado');await refreshLinks();renderModalCondominios()}catch(err){Util.toast(err.message,true)}}; window.desvincularFuncionarioCondominio=async (funcId,condId)=>{try{await Api.request(`/api/condominios/${condId}/funcionarios-vinculados/${funcId}`,{method:'DELETE'});Util.toast('Funcionario desvinculado');await refreshLinks();renderModalCondominios()}catch(err){Util.toast(err.message,true)}}; -loadFuncionarios(); -async function loadExtras(){if(!Auth.isAdminEmpresa())return;extraPanel.classList.remove('hidden');try{const d=await Api.get('/api/extras');extras=d.extras||[];extraRows.innerHTML=extras.map(x=>''+esc(x.nome)+''+esc(x.email||'')+''+esc(x.telefone||'')+''+Util.badge(x.status)+' ').join('')||'Nenhum destinatario extra cadastrado.'}catch(e){Util.toast(e.message,true)}} -if(extraForm){extraForm.onsubmit=async e=>{e.preventDefault();try{await Api.post('/api/extras',Util.formData(extraForm));extraForm.reset();Util.toast('Extra cadastrado');loadExtras()}catch(err){Util.toast(err.message,true)}}} +function renderExtras(){ + const q=termo('#extra-search-input'); + const lista=extras.filter(x=>contem(x,q,['nome','email','telefone','status'])); + extraRows.innerHTML=lista.map(x=>''+esc(x.nome)+''+esc(x.email||'')+''+esc(x.telefone||'')+''+Util.badge(x.status)+' ').join('')||'Nenhum destinatario extra encontrado.'; +} + +async function loadExtras(){ + if(!Auth.isAdminEmpresa())return; + extraPanel.classList.remove('hidden'); + try{ + const d=await Api.get('/api/extras'); + extras=d.extras||[]; + renderExtras(); + }catch(e){Util.toast(e.message,true)} +} + +window.abrirNovoExtra=()=>{ + abrirModal('Novo extra','
'+formActions('Cadastrar extra')+'
'); + document.querySelector('#extra-form').onsubmit=async e=>{ + e.preventDefault(); + try{ + await Api.post('/api/extras',Util.formData(e.target)); + Util.toast('Extra cadastrado'); + fecharModalCondominios(); + loadExtras(); + }catch(err){Util.toast(err.message,true)} + }; +}; + function extraPorId(id){return extras.find(x=>Number(x.id)===Number(id))} -window.abrirEditarExtra=id=>{const x=extraPorId(id);if(!x)return;modalTitle.textContent='Editar extra';modalBody.innerHTML='
';modal.classList.remove('hidden');document.querySelector('#extra-edit-form').onsubmit=async e=>{e.preventDefault();try{await Api.put('/api/extras/'+id,Util.formData(e.target));Util.toast('Extra atualizado');fecharModalCondominios();loadExtras()}catch(err){Util.toast(err.message,true)}}}; +window.abrirEditarExtra=id=>{const x=extraPorId(id);if(!x)return;abrirModal('Editar extra','
'+formActions('Salvar')+'
');document.querySelector('#extra-edit-form').onsubmit=async e=>{e.preventDefault();try{await Api.put('/api/extras/'+id,Util.formData(e.target));Util.toast('Extra atualizado');fecharModalCondominios();loadExtras()}catch(err){Util.toast(err.message,true)}}}; window.excluirExtra=async id=>{try{await Api.request('/api/extras/'+id,{method:'DELETE'});Util.toast('Extra excluido');loadExtras()}catch(err){Util.toast(err.message,true)}}; + +window.alternarBuscaCadastro=tipo=>{ + const strip=document.querySelector(`#${tipo}-search`),input=document.querySelector(`#${tipo}-search-input`); + if(!strip||!input)return; + strip.classList.toggle('hidden'); + if(!strip.classList.contains('hidden'))input.focus(); +}; + +document.querySelector('#cond-search-input')?.addEventListener('input',renderCondominios); +document.querySelector('#func-search-input')?.addEventListener('input',renderFuncionarios); +document.querySelector('#extra-search-input')?.addEventListener('input',renderExtras); + +load(); +loadFuncionarios(); loadExtras(); diff --git a/src/main/webapp/css/app.css b/src/main/webapp/css/app.css index d492f2f..b30fac0 100644 --- a/src/main/webapp/css/app.css +++ b/src/main/webapp/css/app.css @@ -380,6 +380,23 @@ h2 { margin-bottom: 16px; } +.section-actions { + display: flex; + gap: 10px; + align-items: center; + justify-content: flex-end; + flex-wrap: wrap; +} + +.section-actions .btn { + min-width: 92px; + box-shadow: none; +} + +.search-strip { + margin: 0 0 12px; +} + .panel-block { margin-top: 18px; }