chore(tenants): conteudo de publico/ atualizado
This commit is contained in:
@@ -1554,7 +1554,7 @@ data:
|
||||
|
||||
<footer class="direitos">© 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
|
||||
|
||||
@@ -1554,7 +1554,7 @@ data:
|
||||
|
||||
<footer class="direitos">© 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
|
||||
|
||||
Reference in New Issue
Block a user