feat: sistema de design (tokens claro/escuro) + sidebar responsiva em base.html

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Gustavo
2026-08-13 21:53:30 -03:00
co-authored by Claude Sonnet 5
parent 7656f2261e
commit 310f5e1f71
4 changed files with 366 additions and 38 deletions
+79 -38
View File
@@ -3,46 +3,87 @@
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block titulo %}Painel de Clientes{% endblock %}</title>
<style>
body { font-family: system-ui, sans-serif; margin: 0; background: #17171a; color: #f4f4f5; }
nav { background: #232326; padding: 12px 20px; display: flex; gap: 16px; }
nav a { color: #f4f4f5; text-decoration: none; }
nav a:hover { color: #F5821F; }
main { padding: 20px; max-width: 960px; margin: 0 auto; }
table { width: 100%; border-collapse: collapse; margin-top: 12px; }
th, td { text-align: left; padding: 8px; border-bottom: 1px solid #3a3a3e; }
th a { color: inherit; text-decoration: none; white-space: nowrap; }
th a:hover { color: #F5821F; }
input, select { padding: 8px; border-radius: 6px; border: 1px solid #3a3a3e; background: #17171a; color: #f4f4f5; width: 100%; box-sizing: border-box; }
label { display: block; margin-top: 10px; font-size: 0.85rem; color: #a1a1aa; }
button { margin-top: 14px; padding: 10px 16px; border: none; border-radius: 6px; background: #F5821F; color: #17171a; font-weight: 700; cursor: pointer; }
.mensagem { padding: 10px; border-radius: 6px; margin-bottom: 12px; }
.mensagem.success { background: #14532d; }
.mensagem.danger { background: #7f1d1d; }
.mensagem.warning { background: #78350f; }
a.botao { display: inline-block; padding: 6px 10px; border: 1px solid #3a3a3e; border-radius: 6px; color: #f4f4f5; text-decoration: none; margin-right: 6px; }
</style>
<link rel="stylesheet" href="/static/estilo.css">
<script>
(function () {
var tema = localStorage.getItem("tema");
if (tema === "claro" || tema === "escuro") {
document.documentElement.setAttribute("data-tema", tema);
}
})();
</script>
</head>
<body>
<nav>
<a href="/clientes">Clientes</a>
<a href="/gerador-chave">Gerador de chave</a>
{% if request.state.usuario and request.state.usuario.eh_admin %}
<a href="/funcionarios">Funcionários</a>
{% endif %}
<a href="/log">Log</a>
{% if request.state.usuario %}
<a href="/minha-conta">Minha conta</a>
<form method="post" action="/logout" style="display:inline;margin:0">
<input type="hidden" name="csrf_token" value="{{ csrf_token or request.state.csrf_token }}">
<button type="submit" style="margin:0;padding:4px 10px;background:transparent;border:1px solid #3a3a3e;color:#f4f4f5;font-weight:400">Sair</button>
</form>
{% endif %}
</nav>
<main>
{% if mensagem %}<div class="mensagem {{ mensagem_tipo or 'success' }}">{{ mensagem }}</div>{% endif %}
{% block conteudo %}{% endblock %}
</main>
<div class="layout">
<div class="sidebar-backdrop" id="sidebar-backdrop"></div>
<aside class="sidebar" id="sidebar">
<div class="sidebar-topo">
<img src="/static/logo-gti-256x256.png" alt="GTI Grupo" class="sidebar-logo">
<span class="sidebar-titulo">Painel de Clientes</span>
</div>
<nav class="sidebar-nav">
<a href="/clientes">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 9h18M9 21V9"/></svg>
<span>Clientes</span>
</a>
<a href="/gerador-chave">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="8" cy="15" r="4"/><path d="M11 12l9-9M17 6l3 3M14 9l2 2"/></svg>
<span>Gerador de chave</span>
</a>
{% if request.state.usuario and request.state.usuario.eh_admin %}
<a href="/funcionarios">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="9" cy="7" r="4"/><path d="M2 21v-2a5 5 0 0 1 5-5h4a5 5 0 0 1 5 5v2M17 11l2 2 4-4"/></svg>
<span>Funcionários</span>
</a>
{% endif %}
<a href="/log">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-4"/><path d="M9 15h6M9 11h10M9 7h4"/></svg>
<span>Log</span>
</a>
{% if request.state.usuario %}
<a href="/minha-conta">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></svg>
<span>Minha conta</span>
</a>
{% endif %}
</nav>
<div class="sidebar-rodape">
{% if request.state.usuario %}
<div class="sidebar-usuario">{{ request.state.usuario.nome }}</div>
<button type="button" class="botao-tema" id="botao-tema" aria-label="Alternar tema claro/escuro">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>
<span>Tema claro/escuro</span>
</button>
<form method="post" action="/logout" class="form-logout">
<input type="hidden" name="csrf_token" value="{{ csrf_token or request.state.csrf_token }}">
<button type="submit" class="botao-sair">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><path d="M16 17l5-5-5-5M21 12H9"/></svg>
<span>Sair</span>
</button>
</form>
{% endif %}
<button type="button" class="botao-recolher" id="botao-recolher" aria-label="Recolher menu">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 19l-7-7 7-7M18 19l-7-7 7-7"/></svg>
<span>Recolher</span>
</button>
</div>
</aside>
<div class="conteudo-area">
<header class="topbar-mobile">
<button type="button" class="topbar-menu-btn" id="btn-menu-mobile" aria-label="Abrir menu">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:22px;height:22px"><path d="M3 6h18M3 12h18M3 18h18"/></svg>
</button>
<span class="topbar-titulo">{{ self.titulo() }}</span>
</header>
<main class="conteudo">
{% if mensagem %}<div class="mensagem {{ mensagem_tipo or 'success' }}">{{ mensagem }}</div>{% endif %}
{% block conteudo %}{% endblock %}
</main>
</div>
</div>
<script src="/static/sidebar.js" defer></script>
<script src="/static/tema.js" defer></script>
</body>
</html>