feat(condominios): adicionar opcoes de editar e excluir condominios e funcionarios com icones
This commit is contained in:
@@ -72,7 +72,7 @@ public final class ClienteHandlers implements HttpHandler {
|
||||
if(p.length==4&&"condominios".equals(p[0])&&"avisos".equals(p[2])){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} if("GET".equals(method)) detalheAviso(ex,c,cond,id(p[3])); else if("DELETE".equals(method)) excluirAviso(ex,c,empresaId,cond,id(p[3]),funcionarioId); else HttpResponses.methodNotAllowed(ex); return; }
|
||||
if(p.length==5&&"condominios".equals(p[0])&&"avisos".equals(p[2])&&"reenviar".equals(p[4])&&"POST".equals(method)){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} reenviarAviso(ex,c,empresaId,cond,id(p[3])); return; }
|
||||
if(p.length==1&&"condominios".equals(p[0])){ if("POST".equals(method)) criarCondominio(ex,c,funcionarioId,cargo); else if("GET".equals(method)) listarCondominios(ex,c,funcionarioId,cargo); else HttpResponses.methodNotAllowed(ex); return; }
|
||||
if(p.length==2&&"condominios".equals(p[0])){ long id=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,id)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} if("GET".equals(method)) detalheCondominio(ex,c,id); else if("PUT".equals(method)) atualizarCondominio(ex,c,id,funcionarioId); else HttpResponses.methodNotAllowed(ex); return; }
|
||||
if(p.length==2&&"condominios".equals(p[0])){ long id=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,id)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} if("GET".equals(method)) detalheCondominio(ex,c,id); else if("PUT".equals(method)) atualizarCondominio(ex,c,id,funcionarioId); else if("DELETE".equals(method)) excluirCondominio(ex,c,empresaId,id,funcionarioId,cargo); else HttpResponses.methodNotAllowed(ex); return; }
|
||||
if(p.length==3&&"condominios".equals(p[0])&&"respostas".equals(p[2])){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} if("GET".equals(method)) listarRespostas(ex,c,cond); else if("POST".equals(method)) registrarResposta(ex,c,funcionarioId,cond); else HttpResponses.methodNotAllowed(ex); return; }
|
||||
if(p.length==1&&"contatos".equals(p[0])&&"POST".equals(method)){ criarContato(ex,c,funcionarioId); return; }
|
||||
if(p.length==3&&"condominios".equals(p[0])&&"contatos".equals(p[2])&&"GET".equals(method)){ long cond=id(p[1]); if(!podeAcessarCondominio(c,cargo,funcionarioId,cond)){HttpResponses.json(ex,403,Map.of("erro","condominio_nao_vinculado"));return;} listarContatos(ex,c,cond); return; }
|
||||
@@ -96,7 +96,8 @@ public final class ClienteHandlers implements HttpHandler {
|
||||
private void listarCondominios(HttpExchange ex,Connection c,long fid,String cargo)throws Exception{if(adminEmpresa(cargo)){listar(ex,c,"SELECT * FROM condominios ORDER BY nome","condominios");return;}HttpResponses.json(ex,200,Map.of("condominios",rows(c,"SELECT c.* FROM condominios c JOIN funcionario_condominio fc ON fc.condominio_id=c.id WHERE fc.funcionario_id=? ORDER BY c.nome",Arrays.asList(fid))));}
|
||||
private boolean podeAcessarCondominio(Connection c,String cargo,long fid,long cond)throws SQLException{return adminEmpresa(cargo)||count(c,"SELECT count(*) FROM funcionario_condominio WHERE funcionario_id=? AND condominio_id=?",fid,cond)>0;}
|
||||
private void detalheCondominio(HttpExchange ex,Connection c,long id)throws Exception{Map<String,Object> cond=one(c,"SELECT * FROM condominios WHERE id=?",Arrays.asList(id)); if(cond==null){HttpResponses.json(ex,404,Map.of("erro","condominio_nao_encontrado"));return;} Map<String,Object> sind=one(c,"SELECT cc.*, c.nome contato_nome,c.telefone contato_telefone,c.email contato_email FROM contato_condominio cc JOIN contatos c ON c.id=cc.contato_id WHERE cc.condominio_id=? AND cc.tipo='sindico' AND cc.status='ativo' ORDER BY cc.data_inicio_mandato DESC NULLS LAST LIMIT 1",Arrays.asList(id)); long ass=count(c,"SELECT count(*) FROM assembleias WHERE condominio_id=? AND data_hora>now() AND status='agendada'",id); long av=count(c,"SELECT count(*) FROM avisos WHERE condominio_id=? AND (data_expiracao IS NULL OR data_expiracao>now())",id); Map<String,Object> resp=new LinkedHashMap<>();resp.put("condominio",cond);resp.put("sindico_atual",sind);resp.put("assembleias_futuras",ass);resp.put("avisos_ativos",av);HttpResponses.json(ex,200,resp);}
|
||||
private void atualizarCondominio(HttpExchange ex,Connection c,long id,long fid)throws Exception{Map<String,String>b=body(ex); Map<String,Object> old=one(c,"SELECT * FROM condominios WHERE id=?",Arrays.asList(id)); if(old==null){HttpResponses.json(ex,404,Map.of("erro","condominio_nao_encontrado"));return;} try(PreparedStatement ps=c.prepareStatement("UPDATE condominios SET nome=COALESCE(?,nome), cnpj=COALESCE(?,cnpj), endereco=COALESCE(?,endereco) WHERE id=?")){ps.setString(1,b.get("nome"));ps.setString(2,b.get("cnpj"));ps.setString(3,b.get("endereco"));ps.setLong(4,id);ps.executeUpdate();} audit(c,fid,"update","condominios",id,old,b); detalheCondominio(ex,c,id);}
|
||||
private void atualizarCondominio(HttpExchange ex,Connection c,long id,long fid)throws Exception{Map<String,String>b=body(ex); Map<String,Object> old=one(c,"SELECT * FROM condominios WHERE id=?",Arrays.asList(id)); if(old==null){HttpResponses.json(ex,404,Map.of("erro","condominio_nao_encontrado"));return;} String cnpjVal=null; if(b.get("cnpj")!=null&&!b.get("cnpj").isBlank()){cnpjVal=cnpj(b.get("cnpj")); if(one(c,"SELECT id FROM condominios WHERE regexp_replace(cnpj,'\\D','','g')=? AND id<>?",Arrays.asList(cnpjVal,id))!=null){HttpResponses.json(ex,400,Map.of("erro","cnpj_duplicado","mensagem","Já existe outro condomínio cadastrado com este CNPJ."));return;}} try(PreparedStatement ps=c.prepareStatement("UPDATE condominios SET nome=COALESCE(?,nome), cnpj=COALESCE(?,cnpj), endereco=COALESCE(?,endereco) WHERE id=?")){ps.setString(1,b.get("nome")!=null&&!b.get("nome").isBlank()?b.get("nome"):null);ps.setString(2,cnpjVal);ps.setString(3,b.get("endereco"));ps.setLong(4,id);ps.executeUpdate();} audit(c,fid,"update","condominios",id,old,b); detalheCondominio(ex,c,id);}
|
||||
private void excluirCondominio(HttpExchange ex,Connection c,long emp,long cond,long fid,String cargo)throws Exception{if(!adminEmpresa(cargo)){HttpResponses.json(ex,403,Map.of("erro","acesso_restrito","mensagem","Apenas administradores podem excluir condomínios."));return;} Map<String,Object> old=one(c,"SELECT * FROM condominios WHERE id=?",Arrays.asList(cond)); if(old==null){HttpResponses.json(ex,404,Map.of("erro","condominio_nao_encontrado"));return;} c.setAutoCommit(false); try{try(PreparedStatement ps=c.prepareStatement("DELETE FROM respostas WHERE condominio_id=?")){ps.setLong(1,cond);ps.executeUpdate();} List<Map<String,Object>> avisos=rows(c,"SELECT id FROM avisos WHERE condominio_id=?",Arrays.asList(cond)); for(Map<String,Object> av:avisos){long aid=((Number)av.get("id")).longValue(); try(PreparedStatement ps=c.prepareStatement("DELETE FROM aviso_documentos WHERE aviso_id=?")){ps.setLong(1,aid);ps.executeUpdate();} try(PreparedStatement ps=c.prepareStatement("DELETE FROM aviso_destinatarios WHERE aviso_id=?")){ps.setLong(1,aid);ps.executeUpdate();} try(PreparedStatement ps=c.prepareStatement("DELETE FROM fila_envio WHERE tipo='aviso' AND referencia_id=?")){ps.setLong(1,aid);ps.executeUpdate();} try(PreparedStatement ps=c.prepareStatement("DELETE FROM avisos WHERE id=?")){ps.setLong(1,aid);ps.executeUpdate();}} try(Connection m=masterDs.getMasterConnection();PreparedStatement ps=m.prepareStatement("DELETE FROM logs_envio_avisos WHERE empresa_id=? AND condominio_id=?")){ps.setLong(1,emp);ps.setLong(2,cond);ps.executeUpdate();} try(PreparedStatement ps=c.prepareStatement("DELETE FROM assembleias WHERE condominio_id=?")){ps.setLong(1,cond);ps.executeUpdate();} try(PreparedStatement ps=c.prepareStatement("DELETE FROM espacos_comuns WHERE condominio_id=?")){ps.setLong(1,cond);ps.executeUpdate();} try(PreparedStatement ps=c.prepareStatement("DELETE FROM documentos WHERE condominio_id=?")){ps.setLong(1,cond);ps.executeUpdate();} try(PreparedStatement ps=c.prepareStatement("DELETE FROM contato_condominio WHERE condominio_id=?")){ps.setLong(1,cond);ps.executeUpdate();} try(PreparedStatement ps=c.prepareStatement("DELETE FROM funcionario_condominio WHERE condominio_id=?")){ps.setLong(1,cond);ps.executeUpdate();} try(PreparedStatement ps=c.prepareStatement("DELETE FROM condominios WHERE id=?")){ps.setLong(1,cond);ps.executeUpdate();} audit(c,fid,"delete","condominios",cond,old,Map.of("ok",true)); c.commit(); HttpResponses.json(ex,200,Map.of("ok",true));}catch(Exception err){c.rollback();throw err;}finally{c.setAutoCommit(true);}}
|
||||
private void listarRespostas(HttpExchange ex,Connection c,long cond)throws Exception{HttpResponses.json(ex,200,Map.of("respostas",rows(c,"SELECT r.*, co.nome contato_nome, co.telefone contato_telefone, co.email contato_email FROM respostas r LEFT JOIN contatos co ON co.id=r.contato_id WHERE r.condominio_id=? ORDER BY r.recebido_em DESC,id DESC",Arrays.asList(cond))));}
|
||||
private void registrarResposta(HttpExchange ex,Connection c,long fid,Long condPath)throws Exception{String raw=rawBody(ex);Map<String,String>b=SimpleJson.parseObject(raw);Long contato=optLong(firstNonBlank(b.get("contato_id"),b.get("destinatario_id")));Long cond=condPath!=null?condPath:optLong(b.get("condominio_id"));if(cond==null&&contato!=null){Map<String,Object> link=one(c,"SELECT condominio_id FROM contato_condominio WHERE contato_id=? AND status='ativo' ORDER BY CASE WHEN tipo='sindico' THEN 0 ELSE 1 END, condominio_id LIMIT 1",Arrays.asList(contato));if(link!=null)cond=((Number)link.get("condominio_id")).longValue();}if(cond==null){HttpResponses.json(ex,400,Map.of("erro","condominio_obrigatorio","mensagem","Informe condominio_id ou contato_id vinculado a um condomínio."));return;}Map<String,Object> contatoRow=contato==null?null:one(c,"SELECT id,nome,telefone,email FROM contatos WHERE id=?",Arrays.asList(contato));String texto=firstNonBlank(b.get("resposta"),b.get("resposta_texto"),b.get("mensagem"),b.get("texto"),b.get("body"));if(texto.isBlank()){HttpResponses.json(ex,400,Map.of("erro","resposta_obrigatoria","mensagem","Informe a resposta recebida."));return;}long rid=insert(c,"INSERT INTO respostas (condominio_id,contato_id,mensagem_id,tipo_origem,nome_origem,telefone_origem,resposta_texto,mensagem_original,payload,origem,status) VALUES (?,?,?,?,?,?,?,?,?,?,?)",Arrays.asList(cond,contato,optLong(b.get("mensagem_id")),nullable(firstNonBlank(b.get("tipo"),b.get("tipo_origem"))),nullable(firstNonBlank(b.get("nome"),contatoRow==null?null:str(contatoRow.get("nome")))),nullable(firstNonBlank(b.get("telefone"),contatoRow==null?null:str(contatoRow.get("telefone")))),texto,nullable(firstNonBlank(b.get("mensagem_original"),b.get("pergunta"),b.get("mensagem_enviada"))),raw,firstNonBlank(b.get("origem"),"n8n"),firstNonBlank(b.get("status"),"recebida")));audit(c,fid,"create","respostas",rid,null,b);HttpResponses.json(ex,201,Map.of("ok",true,"resposta",one(c,"SELECT * FROM respostas WHERE id=?",Arrays.asList(rid)))) ;}
|
||||
private void criarContato(HttpExchange ex,Connection c,long fid)throws Exception{Map<String,String>b=body(ex); long id=insert(c,"INSERT INTO contatos (nome,telefone,email) VALUES (?,?,?)",Arrays.asList(req(b,"nome"),nullable(b.get("telefone")),nullable(b.get("email")))); audit(c,fid,"create","contatos",id,null,b); HttpResponses.json(ex,201,Map.of("contato",one(c,"SELECT * FROM contatos WHERE id=?",Arrays.asList(id))));}
|
||||
|
||||
@@ -17,7 +17,7 @@ const Icons = {
|
||||
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=>`<tr><td>${c.id}</td><td>${esc(c.nome)}</td><td>${esc(c.cnpj||'')}</td><td>${esc(c.endereco||'')}</td><td style="text-align:right"><div class="table-actions"><a class="table-icon-btn" href="/cliente/condominio-detalhe.html?id=${c.id}" title="Abrir condomínio" aria-label="Abrir condomínio">${Icons.eye}</a></div></td></tr>`).join('')||'<tr><td colspan="5">Nenhum condomínio encontrado.</td></tr>';
|
||||
rows.innerHTML=lista.map(c=>`<tr><td>${c.id}</td><td>${esc(c.nome)}</td><td>${esc(c.cnpj||'')}</td><td>${esc(c.endereco||'')}</td><td style="text-align:right"><div class="table-actions"><a class="table-icon-btn" href="/cliente/condominio-detalhe.html?id=${c.id}" title="Abrir condomínio" aria-label="Abrir condomínio">${Icons.eye}</a><button class="table-icon-btn" type="button" onclick="abrirEditarCondominio(${c.id})" title="Editar condomínio" aria-label="Editar condomínio">${Icons.edit}</button><button class="table-icon-btn danger" type="button" onclick="abrirExcluirCondominio(${c.id})" title="Excluir condomínio" aria-label="Excluir condomínio">${Icons.trash}</button></div></td></tr>`).join('')||'<tr><td colspan="5">Nenhum condomínio encontrado.</td></tr>';
|
||||
}
|
||||
|
||||
async function load(){
|
||||
@@ -28,6 +28,8 @@ async function load(){
|
||||
}catch(e){Util.toast(e.message,true)}
|
||||
}
|
||||
|
||||
function condominioPorId(id){return condominios.find(x=>Number(x.id)===Number(id))}
|
||||
|
||||
window.abrirNovoCondominio=()=>{
|
||||
abrirModal('Novo condomínio','<form id="cond-form" class="grid cols"><div class="field"><label>Nome</label><input name="nome" required></div><div class="field"><label>CNPJ</label><input name="cnpj" required></div><div class="field"><label>Endereço</label><input name="endereco"></div>'+formActions('Criar')+'</form>');
|
||||
document.querySelector('#cond-form').onsubmit=async e=>{
|
||||
@@ -42,6 +44,38 @@ window.abrirNovoCondominio=()=>{
|
||||
};
|
||||
};
|
||||
|
||||
window.abrirEditarCondominio=id=>{
|
||||
const c=condominioPorId(id);
|
||||
if(!c)return;
|
||||
abrirModal('Editar condomínio','<form id="cond-edit-form" class="grid cols"><div class="field"><label>Nome</label><input name="nome" required value="'+esc(c.nome||'')+'"></div><div class="field"><label>CNPJ</label><input name="cnpj" required value="'+esc(c.cnpj||'')+'"></div><div class="field"><label>Endereço</label><input name="endereco" value="'+esc(c.endereco||'')+'"></div>'+formActions('Salvar alterações')+'</form>');
|
||||
document.querySelector('#cond-edit-form').onsubmit=async e=>{
|
||||
e.preventDefault();
|
||||
try{
|
||||
await Api.put('/api/condominios/'+id,Util.formData(e.target));
|
||||
Util.toast('Condomínio atualizado com sucesso');
|
||||
fecharModalCondominios();
|
||||
await load();
|
||||
if(Auth.isAdminEmpresa())await loadFuncionarios();
|
||||
}catch(err){Util.toast(err.message,true)}
|
||||
};
|
||||
};
|
||||
|
||||
window.abrirExcluirCondominio=async id=>{
|
||||
const c=condominioPorId(id);
|
||||
if(!c)return;
|
||||
if(!Auth.isAdminEmpresa()){
|
||||
Util.toast('Apenas o administrador pode excluir condomínios.',true);
|
||||
return;
|
||||
}
|
||||
if(!await Util.confirm('Deseja realmente excluir o condomínio "'+esc(c.nome||'')+'"? Todos os avisos, assembleias, documentos e vínculos deste condomínio serão permanentemente removidos.','Excluir condomínio'))return;
|
||||
try{
|
||||
await Api.request('/api/condominios/'+id,{method:'DELETE'});
|
||||
Util.toast('Condomínio excluído com sucesso');
|
||||
await load();
|
||||
if(Auth.isAdminEmpresa())await loadFuncionarios();
|
||||
}catch(err){Util.toast(err.message,true)}
|
||||
};
|
||||
|
||||
async function linksPorFuncionario(){
|
||||
const mapa=new Map();
|
||||
await Promise.all(condominios.map(async c=>{
|
||||
@@ -64,7 +98,7 @@ function renderFuncionarios(){
|
||||
const lista=funcionarios.filter(f=>contem(f,q,['nome','email','telefone','cargo','status']));
|
||||
funcRows.innerHTML=lista.map(f=>{
|
||||
const acao=f.cargo==='admin_empresa'?'<span class="muted">Acesso total</span>':`<div class="table-actions start"><button class="table-icon-btn" type="button" onclick="abrirModalCondominios(${f.id})" title="Vincular condomínios" aria-label="Vincular condomínios">${Icons.building}</button></div>`;
|
||||
const opcoes=f.cargo==='admin_empresa'?'<span class="muted">-</span>':`<div class="table-actions start"><button class="table-icon-btn" type="button" onclick="abrirEditarFuncionario(${f.id})" title="Editar funcionário" aria-label="Editar funcionário">${Icons.edit}</button><button class="table-icon-btn danger" type="button" onclick="abrirExcluirFuncionario(${f.id})" title="Excluir funcionário" aria-label="Excluir funcionário">${Icons.trash}</button></div>`;
|
||||
const opcoes=`<div class="table-actions start"><button class="table-icon-btn" type="button" onclick="abrirEditarFuncionario(${f.id})" title="Editar funcionário" aria-label="Editar funcionário">${Icons.edit}</button><button class="table-icon-btn danger" type="button" onclick="abrirExcluirFuncionario(${f.id})" title="Excluir funcionário" aria-label="Excluir funcionário">${Icons.trash}</button></div>`;
|
||||
return '<tr><td>'+esc(f.nome)+'</td><td>'+esc(f.email)+'</td><td>'+esc(f.telefone||'')+'</td><td>'+esc(f.cargo||'')+'</td><td>'+Util.badge(f.status)+'</td><td>'+acao+'</td><td>'+opcoes+'</td></tr>';
|
||||
}).join('')||'<tr><td colspan="7">Nenhum funcionário encontrado.</td></tr>';
|
||||
}
|
||||
@@ -95,10 +129,53 @@ window.abrirNovoFuncionario=()=>{
|
||||
};
|
||||
|
||||
function funcionarioPorId(funcId){return funcionarios.find(x=>Number(x.id)===Number(funcId))}
|
||||
window.abrirEditarFuncionario=funcId=>{const f=funcionarioPorId(funcId);if(!f)return;abrirModal('Editar funcionário','<form id="func-edit-form" class="grid cols"><div class="field"><label>Nome</label><input name="nome" required value="'+esc(f.nome||'')+'"></div><div class="field"><label>E-mail de login</label><input name="email" type="email" required value="'+esc(f.email||'')+'"></div><div class="field"><label>WhatsApp</label><input name="telefone" value="'+esc(f.telefone||'')+'"></div><div class="field"><label>Status</label><select name="status"><option value="ativo" '+(f.status==='ativo'?'selected':'')+'>Ativo</option><option value="inativo" '+(f.status==='inativo'?'selected':'')+'>Inativo</option></select></div><div class="field"><label>Nova senha</label><input name="senha" type="password"></div>'+formActions('Salvar')+'</form>');document.querySelector('#func-edit-form').onsubmit=async e=>{e.preventDefault();try{await Api.put('/api/funcionarios/'+funcId,Util.formData(e.target));Util.toast('Funcionário atualizado');fecharModalCondominios();loadFuncionarios()}catch(err){Util.toast(err.message,true)}}};
|
||||
window.abrirExcluirFuncionario=async funcId=>{const f=funcionarioPorId(funcId);if(!f)return;if(!await Util.confirm('Deseja realmente excluir o acesso de "'+esc(f.nome||'')+'"? O funcionário será inativado e perderá o acesso ao sistema.','Excluir funcionário'))return;try{await Api.request('/api/funcionarios/'+funcId,{method:'DELETE'});Util.toast('Funcionário inativado');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=`Condomínios de ${f.nome}`;const listaVinculados=vinculados.map(c=>`<div class="cond-item"><span>${esc(c.nome)}</span><button class="btn danger" type="button" onclick="desvincularFuncionarioCondominio(${funcAtual},${c.id})">Desvincular</button></div>`).join('')||'<p class="muted">Nenhum condomínio vinculado.</p>';const listaDisponiveis=disponiveis.map(c=>`<div class="cond-item"><span>${esc(c.nome)}</span><button class="btn secondary" type="button" onclick="vincularFuncionarioCondominio(${funcAtual},${c.id})">Vincular</button></div>`).join('')||'<p class="muted">Todos os condomínios já estão vinculados.</p>';modalBody.innerHTML=`<div class="modal-grid"><section><h3>Vinculados</h3>${listaVinculados}</section><section><h3>Não vinculados</h3>${listaDisponiveis}</section></div><div class="modal-actions" style="margin-top: 18px;"><button class="btn secondary" type="button" onclick="fecharModalCondominios()">Fechar</button></div>`}
|
||||
window.abrirEditarFuncionario=funcId=>{
|
||||
const f=funcionarioPorId(funcId);
|
||||
if(!f)return;
|
||||
const isAdmin=f.cargo==='admin_empresa';
|
||||
abrirModal(
|
||||
isAdmin?'Editar administrador':'Editar funcionário',
|
||||
'<form id="func-edit-form" class="grid cols"><div class="field"><label>Nome</label><input name="nome" required value="'+esc(f.nome||'')+'"></div><div class="field"><label>E-mail de login</label><input name="email" type="email" required value="'+esc(f.email||'')+'"></div><div class="field"><label>WhatsApp</label><input name="telefone" value="'+esc(f.telefone||'')+'"></div>'+(isAdmin?'':'<div class="field"><label>Status</label><select name="status"><option value="ativo" '+(f.status==='ativo'?'selected':'')+'>Ativo</option><option value="inativo" '+(f.status==='inativo'?'selected':'')+'>Inativo</option></select></div>')+'<div class="field"><label>Nova senha</label><input name="senha" type="password" placeholder="Deixe em branco para manter a atual"></div>'+formActions('Salvar alterações')+'</form>'
|
||||
);
|
||||
document.querySelector('#func-edit-form').onsubmit=async e=>{
|
||||
e.preventDefault();
|
||||
try{
|
||||
await Api.put('/api/funcionarios/'+funcId,Util.formData(e.target));
|
||||
Util.toast('Cadastro atualizado com sucesso');
|
||||
fecharModalCondominios();
|
||||
loadFuncionarios();
|
||||
}catch(err){Util.toast(err.message,true)}
|
||||
};
|
||||
};
|
||||
|
||||
window.abrirExcluirFuncionario=async funcId=>{
|
||||
const f=funcionarioPorId(funcId);
|
||||
if(!f)return;
|
||||
if(f.cargo==='admin_empresa'){
|
||||
Util.toast('A conta principal (admin_empresa) não pode ser excluída.',true);
|
||||
return;
|
||||
}
|
||||
if(!await Util.confirm('Deseja realmente excluir o acesso de "'+esc(f.nome||'')+'"? O funcionário será inativado e perderá o acesso ao sistema.','Excluir funcionário'))return;
|
||||
try{
|
||||
await Api.request('/api/funcionarios/'+funcId,{method:'DELETE'});
|
||||
Util.toast('Funcionário inativado');
|
||||
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=`Condomínios de ${f.nome}`;
|
||||
const listaVinculados=vinculados.map(c=>`<div class="cond-item"><span>${esc(c.nome)}</span><button class="btn danger" type="button" onclick="desvincularFuncionarioCondominio(${funcAtual},${c.id})">Desvincular</button></div>`).join('')||'<p class="muted">Nenhum condomínio vinculado.</p>';
|
||||
const listaDisponiveis=disponiveis.map(c=>`<div class="cond-item"><span>${esc(c.nome)}</span><button class="btn secondary" type="button" onclick="vincularFuncionarioCondominio(${funcAtual},${c.id})">Vincular</button></div>`).join('')||'<p class="muted">Todos os condomínios já estão vinculados.</p>';
|
||||
modalBody.innerHTML=`<div class="modal-grid"><section><h3>Vinculados</h3>${listaVinculados}</section><section><h3>Não vinculados</h3>${listaDisponiveis}</section></div><div class="modal-actions" style="margin-top: 18px;"><button class="btn secondary" type="button" onclick="fecharModalCondominios()">Fechar</button></div>`;
|
||||
}
|
||||
|
||||
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;modalBody.innerHTML=''};
|
||||
window.vincularFuncionarioCondominio=async (funcId,condId)=>{try{await Api.post(`/api/condominios/${condId}/funcionarios-vinculados`,{funcionario_id:funcId});Util.toast('Funcionário vinculado');await refreshLinks();renderModalCondominios()}catch(err){Util.toast(err.message,true)}};
|
||||
|
||||
Reference in New Issue
Block a user