chore(tenants): conteudo de publico/ atualizado
This commit is contained in:
@@ -1451,6 +1451,15 @@ data:
|
|||||||
.lista-faturas .selo { margin: 0; }
|
.lista-faturas .selo { margin: 0; }
|
||||||
.lista-faturas a { color: var(--orange-600, #c2410c); font-weight: 600; }
|
.lista-faturas a { color: var(--orange-600, #c2410c); font-weight: 600; }
|
||||||
|
|
||||||
|
/* ── a troca de plano, dentro do cartao ───────────────────────────────────── */
|
||||||
|
.plano-troca { align-self: stretch; margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--line);
|
||||||
|
display: flex; flex-direction: column; gap: 8px; align-items: flex-start; font-size: 14px; }
|
||||||
|
.lista-planos { list-style: none; margin: 4px 0 0; padding: 0; align-self: stretch; }
|
||||||
|
.lista-planos li { padding: 8px 0; border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; }
|
||||||
|
.lista-planos li.atual { background: transparent; }
|
||||||
|
.lista-planos .selo { margin: 0; }
|
||||||
|
.plano-troca .link { background: none; border: 0; color: var(--orange-600); font-weight: 600; cursor: pointer; padding: 0; font: inherit; }
|
||||||
|
|
||||||
minha-conta.html: |
|
minha-conta.html: |
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="pt-BR">
|
<html lang="pt-BR">
|
||||||
@@ -1475,7 +1484,7 @@ data:
|
|||||||
numero a cada publicacao que mexa nesses arquivos.
|
numero a cada publicacao que mexa nesses arquivos.
|
||||||
-->
|
-->
|
||||||
<link rel="stylesheet" href="/publico/fontes/fontes.css">
|
<link rel="stylesheet" href="/publico/fontes/fontes.css">
|
||||||
<link rel="stylesheet" href="/publico/minha-conta.css?v=2.84">
|
<link rel="stylesheet" href="/publico/minha-conta.css?v=2.85">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
@@ -1545,7 +1554,7 @@ data:
|
|||||||
|
|
||||||
<footer class="direitos">© 2026 Athletic Map. Todos os direitos reservados.</footer>
|
<footer class="direitos">© 2026 Athletic Map. Todos os direitos reservados.</footer>
|
||||||
|
|
||||||
<script src="/publico/minha-conta.js?v=2.84"></script>
|
<script src="/publico/minha-conta.js?v=2.85"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
@@ -1585,7 +1594,8 @@ data:
|
|||||||
API: "/api/cliente/meus-produtos",
|
API: "/api/cliente/meus-produtos",
|
||||||
COBRANCA: "/api/cliente/cobranca",
|
COBRANCA: "/api/cliente/cobranca",
|
||||||
TERMO: "/api/cliente/termo-de-dados",
|
TERMO: "/api/cliente/termo-de-dados",
|
||||||
FATURAS: "/api/cliente/faturas"
|
FATURAS: "/api/cliente/faturas",
|
||||||
|
PLANO: "/api/cliente/plano"
|
||||||
};
|
};
|
||||||
|
|
||||||
var CHAVE_VERIFIER = "atm.conta.verifier";
|
var CHAVE_VERIFIER = "atm.conta.verifier";
|
||||||
@@ -1757,6 +1767,7 @@ data:
|
|||||||
produtos.innerHTML = (lista || []).map(cartao).join("");
|
produtos.innerHTML = (lista || []).map(cartao).join("");
|
||||||
nenhum.classList.toggle("oculto", (lista || []).length > 0);
|
nenhum.classList.toggle("oculto", (lista || []).length > 0);
|
||||||
mostrar(conteudo);
|
mostrar(conteudo);
|
||||||
|
(lista || []).forEach(function (p) { if (p.tenant && p.situacao === "ATIVA") acrescentarBotaoDePlano(p.tenant); });
|
||||||
return Promise.all([carregarCobranca(), carregarTermo(), carregarFaturas()]);
|
return Promise.all([carregarCobranca(), carregarTermo(), carregarFaturas()]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1907,6 +1918,99 @@ data:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── A TROCA DE PLANO ───────────────────────────────────────────────────────
|
||||||
|
*
|
||||||
|
* Regras do dono: upgrade vale na hora e o valor novo so na proxima cobranca;
|
||||||
|
* downgrade vale no proximo vencimento (o cliente fica com o plano que pagou
|
||||||
|
* ate la). A tela diz isso ANTES de confirmar, com a data. */
|
||||||
|
|
||||||
|
var NOME_DO_PLANO = { bronze: "Bronze", prata: "Prata", ouro: "Ouro", institucional: "Institucional" };
|
||||||
|
|
||||||
|
function acrescentarBotaoDePlano(tenant) {
|
||||||
|
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>');
|
||||||
|
}
|
||||||
|
|
||||||
|
function cartaoDo(tenant) {
|
||||||
|
var alvo = null;
|
||||||
|
produtos.querySelectorAll("article[data-tenant]").forEach(function (el) {
|
||||||
|
if (el.getAttribute("data-tenant") === tenant) alvo = el;
|
||||||
|
});
|
||||||
|
return alvo;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pedirPlano(metodo, tenant, corpo) {
|
||||||
|
var h = { Authorization: "Bearer " + token };
|
||||||
|
if (corpo) h["Content-Type"] = "application/json";
|
||||||
|
return fetch(CONFIG.PLANO + "/" + encodeURIComponent(tenant), {
|
||||||
|
method: metodo, headers: h, body: corpo ? JSON.stringify(corpo) : undefined
|
||||||
|
}).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 blocoDePlano(d) {
|
||||||
|
var pend = d.pendente;
|
||||||
|
var aviso = pend
|
||||||
|
? '<p class="ajuda">Troca agendada: <b>' + escapar(NOME_DO_PLANO[pend.para] || pend.para) + "</b> a partir de "
|
||||||
|
+ escapar(dataCurta(pend.efetivaEm)) + '. <button type="button" class="link" data-plano-acao="cancelar">'
|
||||||
|
+ "Cancelar a troca</button></p>"
|
||||||
|
: "";
|
||||||
|
var opcoes = (d.planos || []).map(function (p) {
|
||||||
|
var nome = escapar(NOME_DO_PLANO[p.plano] || p.plano);
|
||||||
|
var valor = escapar(reais(p.valor)) + (d.ciclo === "ANUAL" ? "/ano" : "/mês");
|
||||||
|
if (p.atual) return '<li class="atual"><b>' + nome + "</b> " + valor + ' <span class="selo ok">seu plano</span></li>';
|
||||||
|
var quando = p.tipo === "UPGRADE"
|
||||||
|
? "vale na hora; o valor novo entra na próxima cobrança"
|
||||||
|
: "vale a partir de " + escapar(dataCurta(d.proximoVencimento)) + ", no fim do período já pago";
|
||||||
|
return "<li><b>" + nome + "</b> " + valor + ' <span class="ajuda">(' + quando + ")</span> "
|
||||||
|
+ '<button type="button" class="btn secundario" data-plano-acao="pedir" data-plano="' + escapar(p.plano)
|
||||||
|
+ '" data-quando="' + escapar(quando) + '">Mudar para ' + nome + "</button></li>";
|
||||||
|
}).join("");
|
||||||
|
return aviso + '<ul class="lista-planos">' + opcoes + '</ul><p class="erro-form oculto"></p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mostrarPlano(tenant, d) {
|
||||||
|
var caixa = produtos.querySelector('[data-tenant-plano="' + tenant + '"]');
|
||||||
|
if (!caixa) return;
|
||||||
|
caixa.innerHTML = '<span class="cobranca-titulo">Plano</span>' + blocoDePlano(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
function agirNoPlano(botao) {
|
||||||
|
var caixa = botao.closest("[data-tenant-plano]");
|
||||||
|
var tenant = caixa.getAttribute("data-tenant-plano");
|
||||||
|
var acao = botao.getAttribute("data-plano-acao");
|
||||||
|
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 pedirPlano("GET", tenant).then(function (d) { mostrarPlano(tenant, d); }).catch(erro);
|
||||||
|
}
|
||||||
|
if (acao === "pedir") {
|
||||||
|
var plano = botao.getAttribute("data-plano");
|
||||||
|
if (typeof window.confirm === "function" && !window.confirm("Mudar para " + (NOME_DO_PLANO[plano] || plano)
|
||||||
|
+ "? " + botao.getAttribute("data-quando") + ".")) { botao.disabled = false; return Promise.resolve(); }
|
||||||
|
return pedirPlano("POST", tenant, { plano: plano }).then(function (d) { mostrarPlano(tenant, d); }).catch(erro);
|
||||||
|
}
|
||||||
|
if (acao === "cancelar") {
|
||||||
|
return pedirPlano("DELETE", tenant).then(function (d) { mostrarPlano(tenant, d); }).catch(erro);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (produtos) produtos.addEventListener("click", function (ev) {
|
||||||
|
var b = ev.target && ev.target.closest ? ev.target.closest("[data-plano-acao]") : null;
|
||||||
|
if (b) agirNoPlano(b);
|
||||||
|
});
|
||||||
|
|
||||||
/* ── AS FATURAS DA ASSINATURA ────────────────────────────────────────────────
|
/* ── AS FATURAS DA ASSINATURA ────────────────────────────────────────────────
|
||||||
*
|
*
|
||||||
* As cobranças da Athletic Map para o cliente (não as dos alunos), com o link
|
* As cobranças da Athletic Map para o cliente (não as dos alunos), com o link
|
||||||
|
|||||||
@@ -1451,6 +1451,15 @@ data:
|
|||||||
.lista-faturas .selo { margin: 0; }
|
.lista-faturas .selo { margin: 0; }
|
||||||
.lista-faturas a { color: var(--orange-600, #c2410c); font-weight: 600; }
|
.lista-faturas a { color: var(--orange-600, #c2410c); font-weight: 600; }
|
||||||
|
|
||||||
|
/* ── a troca de plano, dentro do cartao ───────────────────────────────────── */
|
||||||
|
.plano-troca { align-self: stretch; margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--line);
|
||||||
|
display: flex; flex-direction: column; gap: 8px; align-items: flex-start; font-size: 14px; }
|
||||||
|
.lista-planos { list-style: none; margin: 4px 0 0; padding: 0; align-self: stretch; }
|
||||||
|
.lista-planos li { padding: 8px 0; border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; gap: 6px 10px; align-items: center; }
|
||||||
|
.lista-planos li.atual { background: transparent; }
|
||||||
|
.lista-planos .selo { margin: 0; }
|
||||||
|
.plano-troca .link { background: none; border: 0; color: var(--orange-600); font-weight: 600; cursor: pointer; padding: 0; font: inherit; }
|
||||||
|
|
||||||
minha-conta.html: |
|
minha-conta.html: |
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="pt-BR">
|
<html lang="pt-BR">
|
||||||
@@ -1475,7 +1484,7 @@ data:
|
|||||||
numero a cada publicacao que mexa nesses arquivos.
|
numero a cada publicacao que mexa nesses arquivos.
|
||||||
-->
|
-->
|
||||||
<link rel="stylesheet" href="/publico/fontes/fontes.css">
|
<link rel="stylesheet" href="/publico/fontes/fontes.css">
|
||||||
<link rel="stylesheet" href="/publico/minha-conta.css?v=2.84">
|
<link rel="stylesheet" href="/publico/minha-conta.css?v=2.85">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
@@ -1545,7 +1554,7 @@ data:
|
|||||||
|
|
||||||
<footer class="direitos">© 2026 Athletic Map. Todos os direitos reservados.</footer>
|
<footer class="direitos">© 2026 Athletic Map. Todos os direitos reservados.</footer>
|
||||||
|
|
||||||
<script src="/publico/minha-conta.js?v=2.84"></script>
|
<script src="/publico/minha-conta.js?v=2.85"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
@@ -1585,7 +1594,8 @@ data:
|
|||||||
API: "/api/cliente/meus-produtos",
|
API: "/api/cliente/meus-produtos",
|
||||||
COBRANCA: "/api/cliente/cobranca",
|
COBRANCA: "/api/cliente/cobranca",
|
||||||
TERMO: "/api/cliente/termo-de-dados",
|
TERMO: "/api/cliente/termo-de-dados",
|
||||||
FATURAS: "/api/cliente/faturas"
|
FATURAS: "/api/cliente/faturas",
|
||||||
|
PLANO: "/api/cliente/plano"
|
||||||
};
|
};
|
||||||
|
|
||||||
var CHAVE_VERIFIER = "atm.conta.verifier";
|
var CHAVE_VERIFIER = "atm.conta.verifier";
|
||||||
@@ -1757,6 +1767,7 @@ data:
|
|||||||
produtos.innerHTML = (lista || []).map(cartao).join("");
|
produtos.innerHTML = (lista || []).map(cartao).join("");
|
||||||
nenhum.classList.toggle("oculto", (lista || []).length > 0);
|
nenhum.classList.toggle("oculto", (lista || []).length > 0);
|
||||||
mostrar(conteudo);
|
mostrar(conteudo);
|
||||||
|
(lista || []).forEach(function (p) { if (p.tenant && p.situacao === "ATIVA") acrescentarBotaoDePlano(p.tenant); });
|
||||||
return Promise.all([carregarCobranca(), carregarTermo(), carregarFaturas()]);
|
return Promise.all([carregarCobranca(), carregarTermo(), carregarFaturas()]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1907,6 +1918,99 @@ data:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── A TROCA DE PLANO ───────────────────────────────────────────────────────
|
||||||
|
*
|
||||||
|
* Regras do dono: upgrade vale na hora e o valor novo so na proxima cobranca;
|
||||||
|
* downgrade vale no proximo vencimento (o cliente fica com o plano que pagou
|
||||||
|
* ate la). A tela diz isso ANTES de confirmar, com a data. */
|
||||||
|
|
||||||
|
var NOME_DO_PLANO = { bronze: "Bronze", prata: "Prata", ouro: "Ouro", institucional: "Institucional" };
|
||||||
|
|
||||||
|
function acrescentarBotaoDePlano(tenant) {
|
||||||
|
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>');
|
||||||
|
}
|
||||||
|
|
||||||
|
function cartaoDo(tenant) {
|
||||||
|
var alvo = null;
|
||||||
|
produtos.querySelectorAll("article[data-tenant]").forEach(function (el) {
|
||||||
|
if (el.getAttribute("data-tenant") === tenant) alvo = el;
|
||||||
|
});
|
||||||
|
return alvo;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pedirPlano(metodo, tenant, corpo) {
|
||||||
|
var h = { Authorization: "Bearer " + token };
|
||||||
|
if (corpo) h["Content-Type"] = "application/json";
|
||||||
|
return fetch(CONFIG.PLANO + "/" + encodeURIComponent(tenant), {
|
||||||
|
method: metodo, headers: h, body: corpo ? JSON.stringify(corpo) : undefined
|
||||||
|
}).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 blocoDePlano(d) {
|
||||||
|
var pend = d.pendente;
|
||||||
|
var aviso = pend
|
||||||
|
? '<p class="ajuda">Troca agendada: <b>' + escapar(NOME_DO_PLANO[pend.para] || pend.para) + "</b> a partir de "
|
||||||
|
+ escapar(dataCurta(pend.efetivaEm)) + '. <button type="button" class="link" data-plano-acao="cancelar">'
|
||||||
|
+ "Cancelar a troca</button></p>"
|
||||||
|
: "";
|
||||||
|
var opcoes = (d.planos || []).map(function (p) {
|
||||||
|
var nome = escapar(NOME_DO_PLANO[p.plano] || p.plano);
|
||||||
|
var valor = escapar(reais(p.valor)) + (d.ciclo === "ANUAL" ? "/ano" : "/mês");
|
||||||
|
if (p.atual) return '<li class="atual"><b>' + nome + "</b> " + valor + ' <span class="selo ok">seu plano</span></li>';
|
||||||
|
var quando = p.tipo === "UPGRADE"
|
||||||
|
? "vale na hora; o valor novo entra na próxima cobrança"
|
||||||
|
: "vale a partir de " + escapar(dataCurta(d.proximoVencimento)) + ", no fim do período já pago";
|
||||||
|
return "<li><b>" + nome + "</b> " + valor + ' <span class="ajuda">(' + quando + ")</span> "
|
||||||
|
+ '<button type="button" class="btn secundario" data-plano-acao="pedir" data-plano="' + escapar(p.plano)
|
||||||
|
+ '" data-quando="' + escapar(quando) + '">Mudar para ' + nome + "</button></li>";
|
||||||
|
}).join("");
|
||||||
|
return aviso + '<ul class="lista-planos">' + opcoes + '</ul><p class="erro-form oculto"></p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
function mostrarPlano(tenant, d) {
|
||||||
|
var caixa = produtos.querySelector('[data-tenant-plano="' + tenant + '"]');
|
||||||
|
if (!caixa) return;
|
||||||
|
caixa.innerHTML = '<span class="cobranca-titulo">Plano</span>' + blocoDePlano(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
function agirNoPlano(botao) {
|
||||||
|
var caixa = botao.closest("[data-tenant-plano]");
|
||||||
|
var tenant = caixa.getAttribute("data-tenant-plano");
|
||||||
|
var acao = botao.getAttribute("data-plano-acao");
|
||||||
|
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 pedirPlano("GET", tenant).then(function (d) { mostrarPlano(tenant, d); }).catch(erro);
|
||||||
|
}
|
||||||
|
if (acao === "pedir") {
|
||||||
|
var plano = botao.getAttribute("data-plano");
|
||||||
|
if (typeof window.confirm === "function" && !window.confirm("Mudar para " + (NOME_DO_PLANO[plano] || plano)
|
||||||
|
+ "? " + botao.getAttribute("data-quando") + ".")) { botao.disabled = false; return Promise.resolve(); }
|
||||||
|
return pedirPlano("POST", tenant, { plano: plano }).then(function (d) { mostrarPlano(tenant, d); }).catch(erro);
|
||||||
|
}
|
||||||
|
if (acao === "cancelar") {
|
||||||
|
return pedirPlano("DELETE", tenant).then(function (d) { mostrarPlano(tenant, d); }).catch(erro);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (produtos) produtos.addEventListener("click", function (ev) {
|
||||||
|
var b = ev.target && ev.target.closest ? ev.target.closest("[data-plano-acao]") : null;
|
||||||
|
if (b) agirNoPlano(b);
|
||||||
|
});
|
||||||
|
|
||||||
/* ── AS FATURAS DA ASSINATURA ────────────────────────────────────────────────
|
/* ── AS FATURAS DA ASSINATURA ────────────────────────────────────────────────
|
||||||
*
|
*
|
||||||
* As cobranças da Athletic Map para o cliente (não as dos alunos), com o link
|
* As cobranças da Athletic Map para o cliente (não as dos alunos), com o link
|
||||||
|
|||||||
Reference in New Issue
Block a user