feat(master): gerar slug automaticamente ao cadastrar novo cliente
This commit is contained in:
@@ -57,7 +57,13 @@
|
|||||||
<button class="btn secondary" type="button" onclick="fecharModalCadastro()">Fechar</button>
|
<button class="btn secondary" type="button" onclick="fecharModalCadastro()">Fechar</button>
|
||||||
</div>
|
</div>
|
||||||
<form id="empresa-form" class="grid cols">
|
<form id="empresa-form" class="grid cols">
|
||||||
<div class="field"><label>Slug</label><input name="slug" required></div>
|
<div class="field">
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px;">
|
||||||
|
<label style="margin: 0;">Slug</label>
|
||||||
|
<button type="button" id="btn-slug-tipo" onclick="alternarTipoSlug()" style="background: none; border: none; color: var(--brand); font-size: 11px; cursor: pointer; padding: 0; text-decoration: underline;">Gerar do nome</button>
|
||||||
|
</div>
|
||||||
|
<input name="slug" id="slug-input" required placeholder="0002">
|
||||||
|
</div>
|
||||||
<div class="field"><label>Nome</label><input name="nome" 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>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>Plano</label><select name="plano_id" id="plano-select"><option value="">Sem plano</option></select></div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
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;
|
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;
|
||||||
|
let modoSlugAuto='sequencial';
|
||||||
|
|
||||||
const Icons = {
|
const Icons = {
|
||||||
edit: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>',
|
edit: '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>',
|
||||||
@@ -14,6 +15,25 @@ function match(e,q){if(!q)return true;return [e.slug,e.nome,e.cnpj,e.status,e.pl
|
|||||||
function statusAction(e){const acao=e.status==='ativa'?'Bloquear':'Ativar';return `<button class="status-action" onclick="alterarStatus(${e.id},'${e.status==='ativa'?'bloqueada':'ativa'}')">${Util.badge(e.status)}<span>${acao}</span></button>`}
|
function statusAction(e){const acao=e.status==='ativa'?'Bloquear':'Ativar';return `<button class="status-action" onclick="alterarStatus(${e.id},'${e.status==='ativa'?'bloqueada':'ativa'}')">${Util.badge(e.status)}<span>${acao}</span></button>`}
|
||||||
function detalheRow(e){if(selecionado!==e.id||!modo)return'';if(modo==='ver')return `<tr><td colspan="5"><div class="inline-panel"><h2>${esc(e.nome)}</h2><p><strong>Slug:</strong> ${esc(e.slug)}</p><p><strong>CNPJ:</strong> ${esc(e.cnpj||'-')}</p><p><strong>Status:</strong> ${esc(e.status)}</p><p><strong>Plano:</strong> ${e.plano?`${esc(e.plano)} ${e.plano_valor_centavos?'- '+Util.money(e.plano_valor_centavos):''}`:'-'}</p><div class="field"><label>API Key de integração</label><input readonly value="${esc(e.api_key||'')}" onclick="this.select()"></div><div class="row compact"><button class="btn secondary" type="button" onclick="copiarApiKey(${e.id})">Copiar API Key</button><button class="btn secondary" type="button" onclick="solicitarAlteracaoApiKey(${e.id})">Solicitar alteração</button></div><p><strong>Conta principal:</strong> abra Editar para alterar dados da empresa; funcionarios ficam no acesso da empresa.</p><button class="btn secondary" onclick="fecharDetalhe()">Fechar</button></div></td></tr>`;return `<tr><td colspan="5"><form class="inline-panel grid cols" onsubmit="salvarEdicao(event,${e.id})"><div class="field"><label>Nome</label><input name="nome" value="${esc(e.nome||'')}" required></div><div class="field"><label>CNPJ</label><input name="cnpj" value="${esc(e.cnpj||'')}"></div><div class="field"><label>Plano</label><select name="plano_id">${planoOptions(e.plano_id)}</select></div><div class="row"><button class="btn">Salvar</button><button type="button" class="btn secondary" onclick="fecharDetalhe()">Cancelar</button></div></form></td></tr>`}
|
function detalheRow(e){if(selecionado!==e.id||!modo)return'';if(modo==='ver')return `<tr><td colspan="5"><div class="inline-panel"><h2>${esc(e.nome)}</h2><p><strong>Slug:</strong> ${esc(e.slug)}</p><p><strong>CNPJ:</strong> ${esc(e.cnpj||'-')}</p><p><strong>Status:</strong> ${esc(e.status)}</p><p><strong>Plano:</strong> ${e.plano?`${esc(e.plano)} ${e.plano_valor_centavos?'- '+Util.money(e.plano_valor_centavos):''}`:'-'}</p><div class="field"><label>API Key de integração</label><input readonly value="${esc(e.api_key||'')}" onclick="this.select()"></div><div class="row compact"><button class="btn secondary" type="button" onclick="copiarApiKey(${e.id})">Copiar API Key</button><button class="btn secondary" type="button" onclick="solicitarAlteracaoApiKey(${e.id})">Solicitar alteração</button></div><p><strong>Conta principal:</strong> abra Editar para alterar dados da empresa; funcionarios ficam no acesso da empresa.</p><button class="btn secondary" onclick="fecharDetalhe()">Fechar</button></div></td></tr>`;return `<tr><td colspan="5"><form class="inline-panel grid cols" onsubmit="salvarEdicao(event,${e.id})"><div class="field"><label>Nome</label><input name="nome" value="${esc(e.nome||'')}" required></div><div class="field"><label>CNPJ</label><input name="cnpj" value="${esc(e.cnpj||'')}"></div><div class="field"><label>Plano</label><select name="plano_id">${planoOptions(e.plano_id)}</select></div><div class="row"><button class="btn">Salvar</button><button type="button" class="btn secondary" onclick="fecharDetalhe()">Cancelar</button></div></form></td></tr>`}
|
||||||
|
|
||||||
|
function proximoSlugSequencial(){
|
||||||
|
let max=0;
|
||||||
|
for(const e of empresas){
|
||||||
|
const n=parseInt(e.slug,10);
|
||||||
|
if(!isNaN(n)&&n>max)max=n;
|
||||||
|
}
|
||||||
|
return String(max+1).padStart(4,'0');
|
||||||
|
}
|
||||||
|
|
||||||
|
function slugify(text){
|
||||||
|
return String(text||'')
|
||||||
|
.normalize('NFD')
|
||||||
|
.replace(/[\u0300-\u036f]/g,'')
|
||||||
|
.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
.replace(/[^a-z0-9_-]+/g,'_')
|
||||||
|
.replace(/^_+|_+$/g,'');
|
||||||
|
}
|
||||||
|
|
||||||
function render(){
|
function render(){
|
||||||
const q=busca.value.trim();
|
const q=busca.value.trim();
|
||||||
const lista=empresas.filter(e=>match(e,q));
|
const lista=empresas.filter(e=>match(e,q));
|
||||||
@@ -43,9 +63,31 @@ window.alternarBusca=()=>{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.alternarTipoSlug=()=>{
|
||||||
|
const slugInput=empresaForm.querySelector('input[name="slug"]');
|
||||||
|
const nomeInput=empresaForm.querySelector('input[name="nome"]');
|
||||||
|
const btn=document.querySelector('#btn-slug-tipo');
|
||||||
|
if(modoSlugAuto==='sequencial'){
|
||||||
|
modoSlugAuto='nome';
|
||||||
|
if(btn)btn.textContent='Usar sequencial';
|
||||||
|
if(slugInput)slugInput.value=slugify(nomeInput?.value)||'cliente';
|
||||||
|
}else{
|
||||||
|
modoSlugAuto='sequencial';
|
||||||
|
if(btn)btn.textContent='Gerar do nome';
|
||||||
|
if(slugInput)slugInput.value=proximoSlugSequencial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
window.abrirModalCadastro=()=>{
|
window.abrirModalCadastro=()=>{
|
||||||
cadastroModal?.classList.remove('hidden');
|
cadastroModal?.classList.remove('hidden');
|
||||||
empresaForm.querySelector('input[name="slug"]')?.focus();
|
const slugInput=empresaForm.querySelector('input[name="slug"]');
|
||||||
|
const btn=document.querySelector('#btn-slug-tipo');
|
||||||
|
modoSlugAuto='sequencial';
|
||||||
|
if(btn)btn.textContent='Gerar do nome';
|
||||||
|
if(slugInput){
|
||||||
|
slugInput.value=proximoSlugSequencial();
|
||||||
|
}
|
||||||
|
empresaForm.querySelector('input[name="nome"]')?.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
window.fecharModalCadastro=()=>{
|
window.fecharModalCadastro=()=>{
|
||||||
@@ -62,8 +104,20 @@ window.alternarCadastro=(forcar)=>{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const nomeInput=empresaForm.querySelector('input[name="nome"]');
|
||||||
|
nomeInput?.addEventListener('input',()=>{
|
||||||
|
if(modoSlugAuto==='nome'){
|
||||||
|
const slugInput=empresaForm.querySelector('input[name="slug"]');
|
||||||
|
if(slugInput)slugInput.value=slugify(nomeInput.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
empresaForm.onsubmit=async e=>{
|
empresaForm.onsubmit=async e=>{
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
const slugInput=empresaForm.querySelector('input[name="slug"]');
|
||||||
|
if(slugInput&&!slugInput.value.trim()){
|
||||||
|
slugInput.value=proximoSlugSequencial();
|
||||||
|
}
|
||||||
try{
|
try{
|
||||||
await Api.post('/api/master/empresas',Util.formData(empresaForm));
|
await Api.post('/api/master/empresas',Util.formData(empresaForm));
|
||||||
empresaForm.reset();
|
empresaForm.reset();
|
||||||
|
|||||||
Reference in New Issue
Block a user