feat(master): abrir formulario de novo cliente em modal popup

This commit is contained in:
Tiago
2026-10-10 16:43:15 -03:00
parent 602dd4cc5b
commit b2fa6d1bb9
2 changed files with 40 additions and 30 deletions
+25 -21
View File
@@ -22,7 +22,7 @@
<button class="search-icon-btn" type="button" onclick="alternarBusca()" aria-label="Buscar clientes" title="Buscar">
<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"></circle><path d="m16.5 16.5 4 4"></path></svg>
</button>
<button class="header-add-btn" type="button" onclick="alternarCadastro()" title="Novo cadastro" aria-label="Novo cadastro">
<button class="header-add-btn" type="button" onclick="abrirModalCadastro()" title="Novo cliente" aria-label="Novo cliente">
<svg viewBox="0 0 24 24" aria-hidden="true"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
</button>
</div>
@@ -32,26 +32,6 @@
<input id="busca" placeholder="Buscar por slug, nome, CNPJ, status ou plano">
</div>
<div id="cadastro-wrap" class="hidden" style="margin-bottom: 20px; padding: 18px; background: var(--panel-muted); border: 1px solid var(--line); border-radius: var(--radius);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px;">
<h3 style="margin: 0; font-size: 16px; font-weight: 800;">Novo cadastro</h3>
<button class="btn secondary" type="button" onclick="alternarCadastro(false)" style="min-height: 32px; padding: 4px 10px; font-size: 13px;">Fechar</button>
</div>
<form id="empresa-form" class="grid cols">
<div class="field"><label>Slug</label><input name="slug" required></div>
<div class="field"><label>Nome</label><input name="nome" required></div>
<div class="field"><label>CNPJ</label><input name="cnpj"></div>
<div class="field"><label>Plano</label><select name="plano_id" id="plano-select"><option value="">Sem plano</option></select></div>
<div class="field"><label>WhatsApp</label><input name="telefone" placeholder="5599999999999"></div>
<div class="field"><label>E-mail de login</label><input name="email" type="email" required></div>
<div class="field"><label>Senha inicial</label><input name="senha" type="password" required></div>
<div class="row" style="align-self: end; gap: 8px;">
<button class="btn" type="submit">Cadastrar</button>
<button class="btn secondary" type="button" onclick="alternarCadastro(false)">Cancelar</button>
</div>
</form>
</div>
<div class="table-wrap">
<table>
<thead>
@@ -67,6 +47,30 @@
</table>
</div>
</section>
<!-- Modal de Novo Cadastro (Popup) -->
<div id="cadastro-modal" class="modal hidden">
<div class="modal-backdrop" onclick="fecharModalCadastro()"></div>
<section class="modal-panel">
<div class="modal-head">
<h2>Novo cliente</h2>
<button class="btn secondary" type="button" onclick="fecharModalCadastro()">Fechar</button>
</div>
<form id="empresa-form" class="grid cols">
<div class="field"><label>Slug</label><input name="slug" required></div>
<div class="field"><label>Nome</label><input name="nome" required></div>
<div class="field"><label>CNPJ</label><input name="cnpj"></div>
<div class="field"><label>Plano</label><select name="plano_id" id="plano-select"><option value="">Sem plano</option></select></div>
<div class="field"><label>WhatsApp</label><input name="telefone" placeholder="5599999999999"></div>
<div class="field"><label>E-mail de login</label><input name="email" type="email" required></div>
<div class="field"><label>Senha inicial</label><input name="senha" type="password" required></div>
<div class="modal-actions" style="grid-column: 1 / -1;">
<button class="btn secondary" type="button" onclick="fecharModalCadastro()">Cancelar</button>
<button class="btn" type="submit">Cadastrar</button>
</div>
</form>
</section>
</div>
</main>
<script>Layout.mount('master','clientes');</script>
<script src="/master/clientes.js"></script>
+15 -9
View File
@@ -1,4 +1,4 @@
const empresaForm=document.querySelector('#empresa-form'),rows=document.querySelector('#rows'),busca=document.querySelector('#busca'),planoSelect=document.querySelector('#plano-select');let empresas=[],planos=[],modo=null,selecionado=null;
const empresaForm=document.querySelector('#empresa-form'),rows=document.querySelector('#rows'),busca=document.querySelector('#busca'),planoSelect=document.querySelector('#plano-select'),cadastroModal=document.querySelector('#cadastro-modal');let empresas=[],planos=[],modo=null,selecionado=null;
function esc(v){return String(v??'').replace(/[&<>'"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[c]))}
function planoLabel(p){return `${p.nome} - ${Util.money(p.valor_mensal_centavos)}`}
function planoOptions(valor){return '<option value="">Sem plano</option>'+planos.map(p=>`<option value="${p.id}" ${String(valor||'')===String(p.id)?'selected':''}>${planoLabel(p)}</option>`).join('')}
@@ -18,16 +18,22 @@ window.alternarBusca=()=>{
}
};
window.abrirModalCadastro=()=>{
cadastroModal?.classList.remove('hidden');
empresaForm.querySelector('input[name="slug"]')?.focus();
};
window.fecharModalCadastro=()=>{
cadastroModal?.classList.add('hidden');
};
window.alternarCadastro=(forcar)=>{
const wrap=document.querySelector('#cadastro-wrap');
if(!wrap)return;
if(typeof forcar==='boolean'){
wrap.classList.toggle('hidden',!forcar);
if(forcar) abrirModalCadastro();
else fecharModalCadastro();
}else{
wrap.classList.toggle('hidden');
}
if(!wrap.classList.contains('hidden')){
empresaForm.querySelector('input[name="slug"]')?.focus();
if(cadastroModal?.classList.contains('hidden')) abrirModalCadastro();
else fecharModalCadastro();
}
};
@@ -36,7 +42,7 @@ empresaForm.onsubmit=async e=>{
try{
await Api.post('/api/master/empresas',Util.formData(empresaForm));
empresaForm.reset();
alternarCadastro(false);
fecharModalCadastro();
Util.toast('Cliente cadastrado');
load();
}catch(err){