chore(tenants): conteudo de publico/ atualizado

This commit is contained in:
deploy
2026-09-28 15:33:11 +00:00
parent 1299c2a004
commit 404a1c34e8
2 changed files with 154 additions and 6 deletions
+77 -3
View File
@@ -1554,7 +1554,7 @@ data:
<footer class="direitos">&copy; 2026 Athletic Map. Todos os direitos reservados.</footer>
<script src="/publico/minha-conta.js?v=2.85"></script>
<script src="/publico/minha-conta.js?v=2.86"></script>
</body>
</html>
@@ -1595,7 +1595,8 @@ data:
COBRANCA: "/api/cliente/cobranca",
TERMO: "/api/cliente/termo-de-dados",
FATURAS: "/api/cliente/faturas",
PLANO: "/api/cliente/plano"
PLANO: "/api/cliente/plano",
MODULOS: "/api/cliente/modulos"
};
var CHAVE_VERIFIER = "atm.conta.verifier";
@@ -1930,7 +1931,8 @@ data:
var alvo = cartaoDo(tenant);
if (!alvo || alvo.querySelector(".plano-troca")) return;
alvo.insertAdjacentHTML("beforeend", '<div class="plano-troca" data-tenant-plano="' + escapar(tenant) + '">'
+ '<button type="button" class="btn secundario" data-plano-acao="abrir">Trocar de plano</button></div>');
+ '<button type="button" class="btn secundario" data-plano-acao="abrir">Trocar de plano</button> '
+ '<button type="button" class="btn secundario" data-modulo-acao="abrir">Módulos avulsos</button></div>');
}
function cartaoDo(tenant) {
@@ -2011,6 +2013,78 @@ data:
if (b) agirNoPlano(b);
});
/* ── A LOJA DE MODULOS ───────────────────────────────────────────────────────
*
* Mesmas regras da troca de plano: comprar vale na hora e o valor entra na
* proxima cobranca; cancelar vale no fim do periodo pago. O que o plano ja
* inclui aparece como incluido, sem botao. */
function pedirModulo(metodo, tenant, modulo) {
return fetch(CONFIG.MODULOS + "/" + encodeURIComponent(tenant) + (modulo ? "/" + encodeURIComponent(modulo) : ""), {
method: metodo, headers: { Authorization: "Bearer " + token }
}).then(function (r) {
if (r.ok) return r.json();
return r.json().catch(function () { return {}; }).then(function (d) {
throw new Error(d.erro || "Não consegui agora. Tente de novo em instantes.");
});
});
}
function blocoDaLoja(d) {
var sufixo = d.ciclo === "ANUAL" ? "/ano" : "/mês";
var itens = (d.modulos || []).map(function (m) {
var nome = escapar(m.nome);
if (m.incluidoNoPlano) return '<li><b>' + nome + '</b> <span class="selo ok">incluído no plano</span></li>';
if (m.comprado && m.cancelamentoEm) {
return '<li><b>' + nome + "</b> " + escapar(reais(m.valor)) + sufixo
+ ' <span class="ajuda">(sai em ' + escapar(dataCurta(m.cancelamentoEm)) + ")</span></li>";
}
if (m.comprado) {
return '<li><b>' + nome + "</b> " + escapar(reais(m.valor)) + sufixo + ' <span class="selo ok">comprado</span> '
+ '<button type="button" class="link" data-modulo-acao="cancelar" data-modulo="' + escapar(m.codigo)
+ '">cancelar</button></li>';
}
return '<li><b>' + nome + "</b> " + escapar(reais(m.valor)) + sufixo + " "
+ '<button type="button" class="btn secundario" data-modulo-acao="comprar" data-modulo="' + escapar(m.codigo)
+ '" data-nome="' + nome + '">Comprar</button></li>';
}).join("");
return '<span class="cobranca-titulo">Módulos avulsos</span>'
+ '<p class="ajuda">Comprar libera na hora; o valor entra na próxima cobrança. Cancelar vale no fim do período pago.</p>'
+ '<ul class="lista-planos">' + (itens || '<li class="ajuda">Nenhum módulo à venda agora.</li>') + "</ul>"
+ '<p class="erro-form oculto"></p>';
}
function agirNaLoja(botao) {
var caixa = botao.closest("[data-tenant-plano]");
var tenant = caixa.getAttribute("data-tenant-plano");
var acao = botao.getAttribute("data-modulo-acao");
var modulo = botao.getAttribute("data-modulo");
var mostrar = function (d) { caixa.innerHTML = blocoDaLoja(d); };
var erro = function (e) {
var p = caixa.querySelector(".erro-form");
if (p) { p.textContent = e.message; p.classList.remove("oculto"); }
botao.disabled = false;
};
botao.disabled = true;
if (acao === "abrir") return pedirModulo("GET", tenant).then(mostrar).catch(erro);
if (acao === "comprar") {
if (typeof window.confirm === "function" && !window.confirm("Comprar " + botao.getAttribute("data-nome")
+ "? Libera na hora; o valor entra na próxima cobrança.")) { botao.disabled = false; return Promise.resolve(); }
return pedirModulo("POST", tenant, modulo).then(mostrar).catch(erro);
}
if (acao === "cancelar") {
if (typeof window.confirm === "function" && !window.confirm("Cancelar este módulo? Ele continua até o fim do período pago."))
{ botao.disabled = false; return Promise.resolve(); }
return pedirModulo("DELETE", tenant, modulo).then(mostrar).catch(erro);
}
return Promise.resolve();
}
if (produtos) produtos.addEventListener("click", function (ev) {
var b = ev.target && ev.target.closest ? ev.target.closest("[data-modulo-acao]") : null;
if (b) agirNaLoja(b);
});
/* ── AS FATURAS DA ASSINATURA ────────────────────────────────────────────────
*
* As cobranças da Athletic Map para o cliente (não as dos alunos), com o link
+77 -3
View File
@@ -1554,7 +1554,7 @@ data:
<footer class="direitos">&copy; 2026 Athletic Map. Todos os direitos reservados.</footer>
<script src="/publico/minha-conta.js?v=2.85"></script>
<script src="/publico/minha-conta.js?v=2.86"></script>
</body>
</html>
@@ -1595,7 +1595,8 @@ data:
COBRANCA: "/api/cliente/cobranca",
TERMO: "/api/cliente/termo-de-dados",
FATURAS: "/api/cliente/faturas",
PLANO: "/api/cliente/plano"
PLANO: "/api/cliente/plano",
MODULOS: "/api/cliente/modulos"
};
var CHAVE_VERIFIER = "atm.conta.verifier";
@@ -1930,7 +1931,8 @@ data:
var alvo = cartaoDo(tenant);
if (!alvo || alvo.querySelector(".plano-troca")) return;
alvo.insertAdjacentHTML("beforeend", '<div class="plano-troca" data-tenant-plano="' + escapar(tenant) + '">'
+ '<button type="button" class="btn secundario" data-plano-acao="abrir">Trocar de plano</button></div>');
+ '<button type="button" class="btn secundario" data-plano-acao="abrir">Trocar de plano</button> '
+ '<button type="button" class="btn secundario" data-modulo-acao="abrir">Módulos avulsos</button></div>');
}
function cartaoDo(tenant) {
@@ -2011,6 +2013,78 @@ data:
if (b) agirNoPlano(b);
});
/* ── A LOJA DE MODULOS ───────────────────────────────────────────────────────
*
* Mesmas regras da troca de plano: comprar vale na hora e o valor entra na
* proxima cobranca; cancelar vale no fim do periodo pago. O que o plano ja
* inclui aparece como incluido, sem botao. */
function pedirModulo(metodo, tenant, modulo) {
return fetch(CONFIG.MODULOS + "/" + encodeURIComponent(tenant) + (modulo ? "/" + encodeURIComponent(modulo) : ""), {
method: metodo, headers: { Authorization: "Bearer " + token }
}).then(function (r) {
if (r.ok) return r.json();
return r.json().catch(function () { return {}; }).then(function (d) {
throw new Error(d.erro || "Não consegui agora. Tente de novo em instantes.");
});
});
}
function blocoDaLoja(d) {
var sufixo = d.ciclo === "ANUAL" ? "/ano" : "/mês";
var itens = (d.modulos || []).map(function (m) {
var nome = escapar(m.nome);
if (m.incluidoNoPlano) return '<li><b>' + nome + '</b> <span class="selo ok">incluído no plano</span></li>';
if (m.comprado && m.cancelamentoEm) {
return '<li><b>' + nome + "</b> " + escapar(reais(m.valor)) + sufixo
+ ' <span class="ajuda">(sai em ' + escapar(dataCurta(m.cancelamentoEm)) + ")</span></li>";
}
if (m.comprado) {
return '<li><b>' + nome + "</b> " + escapar(reais(m.valor)) + sufixo + ' <span class="selo ok">comprado</span> '
+ '<button type="button" class="link" data-modulo-acao="cancelar" data-modulo="' + escapar(m.codigo)
+ '">cancelar</button></li>';
}
return '<li><b>' + nome + "</b> " + escapar(reais(m.valor)) + sufixo + " "
+ '<button type="button" class="btn secundario" data-modulo-acao="comprar" data-modulo="' + escapar(m.codigo)
+ '" data-nome="' + nome + '">Comprar</button></li>';
}).join("");
return '<span class="cobranca-titulo">Módulos avulsos</span>'
+ '<p class="ajuda">Comprar libera na hora; o valor entra na próxima cobrança. Cancelar vale no fim do período pago.</p>'
+ '<ul class="lista-planos">' + (itens || '<li class="ajuda">Nenhum módulo à venda agora.</li>') + "</ul>"
+ '<p class="erro-form oculto"></p>';
}
function agirNaLoja(botao) {
var caixa = botao.closest("[data-tenant-plano]");
var tenant = caixa.getAttribute("data-tenant-plano");
var acao = botao.getAttribute("data-modulo-acao");
var modulo = botao.getAttribute("data-modulo");
var mostrar = function (d) { caixa.innerHTML = blocoDaLoja(d); };
var erro = function (e) {
var p = caixa.querySelector(".erro-form");
if (p) { p.textContent = e.message; p.classList.remove("oculto"); }
botao.disabled = false;
};
botao.disabled = true;
if (acao === "abrir") return pedirModulo("GET", tenant).then(mostrar).catch(erro);
if (acao === "comprar") {
if (typeof window.confirm === "function" && !window.confirm("Comprar " + botao.getAttribute("data-nome")
+ "? Libera na hora; o valor entra na próxima cobrança.")) { botao.disabled = false; return Promise.resolve(); }
return pedirModulo("POST", tenant, modulo).then(mostrar).catch(erro);
}
if (acao === "cancelar") {
if (typeof window.confirm === "function" && !window.confirm("Cancelar este módulo? Ele continua até o fim do período pago."))
{ botao.disabled = false; return Promise.resolve(); }
return pedirModulo("DELETE", tenant, modulo).then(mostrar).catch(erro);
}
return Promise.resolve();
}
if (produtos) produtos.addEventListener("click", function (ev) {
var b = ev.target && ev.target.closest ? ev.target.closest("[data-modulo-acao]") : null;
if (b) agirNaLoja(b);
});
/* ── AS FATURAS DA ASSINATURA ────────────────────────────────────────────────
*
* As cobranças da Athletic Map para o cliente (não as dos alunos), com o link