Files
kompress_eshop/assets/views/admin/base.html
2026-06-16 19:27:29 +02:00

175 lines
13 KiB
HTML

<!doctype html>
<html lang="{{ lang | default(value='sk') }}" data-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}{{ t(key="admin-title", lang=lang | default(value='sk')) }}{% endblock title %}</title>
<meta name="description" content="{% block meta_description %}{{ t(key="meta-description", lang=lang | default(value='sk')) }}{% endblock meta_description %}">
<link rel="icon" type="image/x-icon" href="/static/favicon/favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="180x180" href="/static/favicon/apple-touch-icon.png">
<link rel="manifest" href="/static/favicon/site.webmanifest">
<script>
function applyTheme(t) {
var dark = t === 'dark'
|| (t === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
document.documentElement.setAttribute('data-theme', dark ? 'dark' : 'light');
}
function setTheme(t) {
localStorage.setItem('theme', t);
applyTheme(t);
document.dispatchEvent(new CustomEvent('theme:changed', { detail: t }));
}
function currentTheme() { return localStorage.getItem('theme') || 'dark'; }
applyTheme(currentTheme());
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function () {
if (currentTheme() === 'system') applyTheme('system');
});
function markActiveNav() {
var path = location.pathname;
document.querySelectorAll('a[data-nav]').forEach(function (a) {
var h = a.getAttribute('data-nav');
var on = h === path || (h !== '/' && path.indexOf(h) === 0);
if (on) a.setAttribute('aria-current', 'page');
else a.removeAttribute('aria-current');
});
}
document.addEventListener('DOMContentLoaded', markActiveNav);
document.addEventListener('htmx:afterSwap', markActiveNav);
</script>
<link href="/static/css/app.css?v=2026-06-16" rel="stylesheet" type="text/css">
{% block head %}{% endblock head %}
<script src="/static/vendor/htmx/htmx-1.9.12.min.js"></script>
<script defer src="/static/vendor/alpine/alpinejs-3.14.9.min.js"></script>
</head>
<body
x-data="{ showSidebar: false }"
class="min-h-screen bg-surface text-on-surface antialiased dark:bg-surface-dark dark:text-on-surface-dark">
<!-- dark overlay for the open sidebar on small screens -->
<div x-cloak x-show="showSidebar" x-transition.opacity aria-hidden="true"
@click="showSidebar = false"
class="fixed inset-0 z-30 bg-black/50 md:hidden"></div>
<!-- sidebar -->
<nav aria-label="{{ t(key='menu', lang=lang | default(value='sk')) }}"
x-bind:class="showSidebar ? 'translate-x-0' : '-translate-x-60'"
class="fixed inset-y-0 left-0 z-40 flex w-60 flex-col border-r border-outline bg-surface-alt transition-transform duration-300 md:translate-x-0 dark:border-outline-dark dark:bg-surface-dark-alt">
<a href="/admin/dashboard"
class="flex h-16 items-center gap-2 border-b border-outline px-6 text-lg font-bold tracking-tight text-on-surface-strong dark:border-outline-dark dark:text-on-surface-dark-strong">
{{ t(key="admin-title", lang=lang | default(value='sk')) }}
</a>
<div class="flex flex-1 flex-col gap-1 overflow-y-auto p-4">
<a href="/admin/dashboard" data-nav="/admin/dashboard"
class="flex items-center gap-3 rounded-radius px-3 py-2 text-sm font-medium text-on-surface transition hover:bg-surface hover:text-primary aria-[current=page]:bg-primary aria-[current=page]:text-on-primary dark:text-on-surface-dark dark:hover:bg-surface-dark dark:hover:text-primary-dark dark:aria-[current=page]:bg-primary-dark dark:aria-[current=page]:text-on-primary-dark">
{{ t(key="admin-dashboard", lang=lang | default(value='sk')) }}
</a>
<a href="/admin/catalog/products" data-nav="/admin/catalog/products"
class="flex items-center gap-3 rounded-radius px-3 py-2 text-sm font-medium text-on-surface transition hover:bg-surface hover:text-primary aria-[current=page]:bg-primary aria-[current=page]:text-on-primary dark:text-on-surface-dark dark:hover:bg-surface-dark dark:hover:text-primary-dark dark:aria-[current=page]:bg-primary-dark dark:aria-[current=page]:text-on-primary-dark">
{{ t(key="admin-products", lang=lang | default(value='sk')) }}
</a>
<a href="/admin/catalog/categories" data-nav="/admin/catalog/categories"
class="flex items-center gap-3 rounded-radius px-3 py-2 text-sm font-medium text-on-surface transition hover:bg-surface hover:text-primary aria-[current=page]:bg-primary aria-[current=page]:text-on-primary dark:text-on-surface-dark dark:hover:bg-surface-dark dark:hover:text-primary-dark dark:aria-[current=page]:bg-primary-dark dark:aria-[current=page]:text-on-primary-dark">
{{ t(key="admin-categories", lang=lang | default(value='sk')) }}
</a>
<a href="/admin/orders" data-nav="/admin/orders"
class="flex items-center gap-3 rounded-radius px-3 py-2 text-sm font-medium text-on-surface transition hover:bg-surface hover:text-primary aria-[current=page]:bg-primary aria-[current=page]:text-on-primary dark:text-on-surface-dark dark:hover:bg-surface-dark dark:hover:text-primary-dark dark:aria-[current=page]:bg-primary-dark dark:aria-[current=page]:text-on-primary-dark">
{{ t(key="admin-orders", lang=lang | default(value='sk')) }}
</a>
<a href="/admin/shipping" data-nav="/admin/shipping"
class="flex items-center gap-3 rounded-radius px-3 py-2 text-sm font-medium text-on-surface transition hover:bg-surface hover:text-primary aria-[current=page]:bg-primary aria-[current=page]:text-on-primary dark:text-on-surface-dark dark:hover:bg-surface-dark dark:hover:text-primary-dark dark:aria-[current=page]:bg-primary-dark dark:aria-[current=page]:text-on-primary-dark">
{{ t(key="admin-shipping", lang=lang | default(value='sk')) }}
</a>
</div>
<div class="border-t border-outline p-4 dark:border-outline-dark">
<a href="/" class="flex items-center gap-3 rounded-radius px-3 py-2 text-sm font-medium text-info transition hover:bg-surface dark:hover:bg-surface-dark">
{{ t(key="admin-exit", lang=lang | default(value='sk')) }}
</a>
<form method="post" action="/admin/logout">
<button type="submit" class="flex w-full items-center gap-3 rounded-radius px-3 py-2 text-left text-sm font-medium text-danger transition hover:bg-surface dark:hover:bg-surface-dark">
{{ t(key="logout", lang=lang | default(value='sk')) }}
</button>
</form>
</div>
</nav>
<!-- content column -->
<div class="flex min-h-screen flex-col md:ml-60">
<header class="sticky top-0 z-20 flex h-16 items-center gap-4 border-b border-outline bg-surface/95 px-4 backdrop-blur dark:border-outline-dark dark:bg-surface-dark/95">
<button type="button" @click="showSidebar = !showSidebar" :aria-expanded="showSidebar"
aria-label="{{ t(key='menu', lang=lang | default(value='sk')) }}"
class="inline-flex size-9 items-center justify-center rounded-radius text-on-surface transition hover:bg-surface-alt md:hidden dark:text-on-surface-dark dark:hover:bg-surface-dark-alt">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>
</button>
<span class="text-sm font-semibold text-on-surface-strong dark:text-on-surface-dark-strong">
{% block crumb %}{{ t(key="admin-title", lang=lang | default(value='sk')) }}{% endblock crumb %}
</span>
<!-- settings (language + theme) dropdown -->
<div x-data="{ open: false }" @keydown.escape="open = false" class="relative ml-auto">
<button type="button" @click="open = !open" :aria-expanded="open"
aria-label="{{ t(key='settings', lang=lang | default(value='sk')) }}"
class="inline-flex size-9 items-center justify-center rounded-radius text-on-surface transition hover:bg-surface-alt dark:text-on-surface-dark dark:hover:bg-surface-dark-alt">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="size-5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
</button>
<div x-show="open" x-cloak @click.outside="open = false" x-transition.origin.top.right
class="absolute right-0 mt-2 w-56 rounded-radius border border-outline bg-surface p-2 shadow-lg dark:border-outline-dark dark:bg-surface-dark-alt">
<form method="post" action="/lang" hx-boost="false">
<p class="px-2 py-1 text-xs font-semibold uppercase tracking-wide text-on-surface/60 dark:text-on-surface-dark/60">
{{ t(key="settings-language", lang=lang | default(value='sk')) }}
</p>
<button type="submit" name="lang" value="en"
class="flex w-full items-center justify-between rounded-radius px-2 py-1.5 text-sm text-on-surface transition hover:bg-surface-alt dark:text-on-surface-dark dark:hover:bg-surface-dark">
<span>English</span>
{% if lang | default(value='sk') == "en" %}<span class="text-primary dark:text-primary-dark"></span>{% endif %}
</button>
<button type="submit" name="lang" value="sk"
class="flex w-full items-center justify-between rounded-radius px-2 py-1.5 text-sm text-on-surface transition hover:bg-surface-alt dark:text-on-surface-dark dark:hover:bg-surface-dark">
<span>Slovenčina</span>
{% if lang | default(value='sk') == "sk" %}<span class="text-primary dark:text-primary-dark"></span>{% endif %}
</button>
</form>
<p class="mt-1 px-2 py-1 text-xs font-semibold uppercase tracking-wide text-on-surface/60 dark:text-on-surface-dark/60">
{{ t(key="settings-theme", lang=lang | default(value='sk')) }}
</p>
<div x-data="{ theme: currentTheme() }" @theme:changed.document="theme = $event.detail">
<button type="button" @click="setTheme('system')"
class="flex w-full items-center justify-between rounded-radius px-2 py-1.5 text-sm text-on-surface transition hover:bg-surface-alt dark:text-on-surface-dark dark:hover:bg-surface-dark">
<span>{{ t(key="theme-system", lang=lang | default(value='sk')) }}</span>
<span x-show="theme === 'system'" class="text-primary dark:text-primary-dark"></span>
</button>
<button type="button" @click="setTheme('light')"
class="flex w-full items-center justify-between rounded-radius px-2 py-1.5 text-sm text-on-surface transition hover:bg-surface-alt dark:text-on-surface-dark dark:hover:bg-surface-dark">
<span>{{ t(key="theme-light", lang=lang | default(value='sk')) }}</span>
<span x-show="theme === 'light'" class="text-primary dark:text-primary-dark"></span>
</button>
<button type="button" @click="setTheme('dark')"
class="flex w-full items-center justify-between rounded-radius px-2 py-1.5 text-sm text-on-surface transition hover:bg-surface-alt dark:text-on-surface-dark dark:hover:bg-surface-dark">
<span>{{ t(key="theme-dark", lang=lang | default(value='sk')) }}</span>
<span x-show="theme === 'dark'" class="text-primary dark:text-primary-dark"></span>
</button>
</div>
</div>
</div>
</header>
<main class="mx-auto w-full max-w-5xl flex-1 px-4 py-8">
{% block content %}{% endblock content %}
</main>
</div>
</body>
</html>