feat(rgpd): política de privacidade e termos, mapa a pedido, fotos locais, retenção, tema claro/escuro
- Política de privacidade reescrita: tabela de dados/finalidades/fundamento (inclui os pedidos de aula, inscrição e eventos com IP), prazos concretos, subcontratantes, Google Maps e reviews, cookies. Termos e condições novos (/home/termos), no rodapé e no sitemap. Campos [ENTRE PARÊNTESES RETOS] e revisão por jurista pendentes antes de publicar no domínio real. - Google Maps só carrega ao carregar em «Mostrar mapa» (map_click_to_load); as fotos dos autores das reviews são guardadas pelo servidor em uploads/reviews/ e servidas localmente (review_avatar_url). - Retenção que a política declara, aplicada pelo cron (04:00): leads com mais de 12 meses → lixeira; blocked_submissions e outbox de segurança apagados aos 90 dias (trash_retention_sweep, auditado). - Backoffice e login com tema claro/escuro/automático: data-bs-theme aplicado no <head> antes do CSS (sem flash), escolha em localStorage, segue o sistema em tempo real, color-scheme e theme-color para os dois. Cores próprias passaram a variáveis do Bootstrap. lang="pt-PT". Testado numa cópia da BD de produção: 72/72 verificações. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
04c8c83e66
commit
b202262da0
16 files changed
+297
-34
No files matched your search
@@ -34,6 +34,39 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
});
|
||||
});
|
||||
|
||||
// Tema: claro / escuro / automático (o <head> já aplicou o guardado).
|
||||
(function () {
|
||||
var root = document.documentElement, btn = document.getElementById('themeToggle');
|
||||
var mq = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
var icons = { light: 'bi-sun', dark: 'bi-moon-stars', auto: 'bi-circle-half' };
|
||||
var names = { light: 'claro', dark: 'escuro', auto: 'automático' };
|
||||
function apply(pref) {
|
||||
var dark = pref === 'dark' || (pref === 'auto' && mq.matches);
|
||||
root.setAttribute('data-bs-theme', dark ? 'dark' : 'light');
|
||||
root.setAttribute('data-theme-pref', pref);
|
||||
if (btn) {
|
||||
btn.querySelector('i').className = 'bi ' + icons[pref];
|
||||
btn.setAttribute('aria-label', 'Tema: ' + names[pref]);
|
||||
}
|
||||
document.querySelectorAll('[data-theme-set]').forEach(function (b) {
|
||||
var on = b.getAttribute('data-theme-set') === pref;
|
||||
b.classList.toggle('active', on);
|
||||
b.setAttribute('aria-pressed', on ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
var pref = root.getAttribute('data-theme-pref') || 'auto';
|
||||
apply(pref);
|
||||
document.querySelectorAll('[data-theme-set]').forEach(function (b) {
|
||||
b.addEventListener('click', function () {
|
||||
pref = b.getAttribute('data-theme-set');
|
||||
try { localStorage.setItem('bo-theme', pref); } catch (e) {}
|
||||
apply(pref);
|
||||
});
|
||||
});
|
||||
// O sistema mudou de tema: só conta em «automático».
|
||||
mq.addEventListener('change', function () { if (pref === 'auto') apply('auto'); });
|
||||
})();
|
||||
|
||||
// Mobile off-canvas sidebar: hamburger toggles .sidebar.open + the backdrop;
|
||||
// tapping the backdrop, a nav link, Escape, or resizing to desktop closes it.
|
||||
(function () {
|
||||
|
||||
Reference in new issue
Block a user