feat: botao de gerar chave de reativacao por linha na lista de clientes

This commit is contained in:
Gustavo
2026-08-20 09:31:13 -03:00
parent b830ce14dc
commit 53dcd1c9d1
3 changed files with 90 additions and 1 deletions
+4
View File
@@ -242,6 +242,10 @@ a.botao:hover { border-color: var(--cor-acento); color: var(--cor-acento); }
.paginacao-atual { display: inline-flex; align-items: center; justify-content: center; min-width: 32px; height: 32px; padding: 0 6px; border-radius: 6px; background: var(--cor-acento); color: var(--cor-acento-texto); font-weight: 600; }
.paginacao-reticencias { padding: 0 4px; color: var(--cor-texto-secundario); }
.chave-feedback { margin-left: 6px; font-size: 0.85rem; color: var(--cor-sucesso); }
.chave-feedback-erro { color: var(--cor-perigo); }
.botao-gerar-chave { margin-left: 6px; }
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { transition: none !important; }
}
+69 -1
View File
@@ -39,7 +39,11 @@
<td>{{ c.RAZAO }}</td>
<td>{{ c.FANTASIA }}</td>
<td>{{ c.CNPJ }}</td>
<td><a class="botao" href="/clientes/{{ c.ID }}">Abrir</a></td>
<td>
<a class="botao" href="/clientes/{{ c.ID }}">Abrir</a>
<button type="button" class="botao botao-gerar-chave" data-codigo="{{ c.CODIGO }}" onclick="gerarChaveReativacao(this)">Gerar chave</button>
<span class="chave-feedback" aria-live="polite"></span>
</td>
</tr>
{% endfor %}
</table>
@@ -80,4 +84,68 @@
</div>
{% endif %}
</div>
<script>
// Gera a chave de reativação do mês vigente pro cliente da linha
// clicada, reaproveitando o endpoint já usado pelo gerador manual
// (/gerador-chave/gerar) — o algoritmo de cifra roda só no backend
// (app/gerador_chave.py), esta página só manda código+mês/ano e
// copia o resultado.
const CSRF_TOKEN = "{{ csrf_token }}";
function _mesAnoAtual() {
const hoje = new Date();
return `${hoje.getFullYear()}-${String(hoje.getMonth() + 1).padStart(2, '0')}`;
}
async function gerarChaveReativacao(botao) {
const codigo = botao.dataset.codigo;
const feedback = botao.parentElement.querySelector('.chave-feedback');
botao.disabled = true;
feedback.textContent = '';
feedback.classList.remove('chave-feedback-erro');
const corpo = new URLSearchParams({
csrf_token: CSRF_TOKEN,
tipo: 'reativacao',
codigo: codigo,
referencia: _mesAnoAtual(),
});
let resposta, dados;
try {
resposta = await fetch('/gerador-chave/gerar', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: corpo,
});
dados = await resposta.json();
} catch (e) {
feedback.textContent = 'Falha de rede — tente de novo.';
feedback.classList.add('chave-feedback-erro');
botao.disabled = false;
return;
}
if (!resposta.ok) {
feedback.textContent = dados.erro || 'Não foi possível gerar a chave.';
feedback.classList.add('chave-feedback-erro');
botao.disabled = false;
return;
}
try {
await navigator.clipboard.writeText(dados.chave);
feedback.textContent = 'Copiado!';
} catch (e) {
feedback.textContent = 'Chave gerada, mas não copiou automaticamente.';
feedback.classList.add('chave-feedback-erro');
}
botao.disabled = false;
setTimeout(() => {
feedback.textContent = '';
feedback.classList.remove('chave-feedback-erro');
}, 1500);
}
</script>
{% endblock %}