Files
cpone_dashboard/cpone-dashboard/templates/layout/base.html
2026-05-04 10:44:38 +07:00

129 lines
5.9 KiB
HTML

{{define "base"}}
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>{{block "title" .}}CpOne Dashboard{{end}}</title>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@500;600&display=swap" rel="stylesheet"/>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
<script src="https://unpkg.com/htmx.org@1.9.12/dist/ext/sse.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: {
sans: ['Plus Jakarta Sans', 'sans-serif'],
mono: ['IBM Plex Mono', 'monospace'],
},
colors: {
brand: {
50: '#eef0fb',
100: '#dde2f7',
200: '#bbc5ef',
300: '#8f9fe4',
400: '#6677d6',
500: '#3b50a0',
600: '#2d3d7a',
700: '#212d5a',
800: '#161e3c',
900: '#0b0f1e',
}
}
}
}
}
</script>
<style>
body { font-family: 'Plus Jakarta Sans', sans-serif; }
.num { font-family: 'IBM Plex Mono', monospace; }
.live-dot { animation: pulse-dot 2s infinite; }
@keyframes pulse-dot {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
.card { @apply rounded-2xl border border-slate-200 bg-white shadow-sm transition-shadow hover:shadow-md; }
</style>
<link rel="stylesheet" href="{{b "/static/css/custom.css"}}"/>
</head>
<body class="min-h-screen bg-slate-100 text-slate-800">
<!-- Header -->
<header class="w-full bg-brand-500 text-white">
<div class="mx-auto flex w-full items-center justify-between px-4 py-3 sm:px-6 lg:max-w-7xl lg:px-8">
<div class="flex items-center gap-4">
<a href="{{b "/dashboard"}}" class="shrink-0 rounded-lg bg-white px-3 py-1.5">
<img src="{{b "/static/img/logo.png"}}" alt="Logo" class="h-8 w-auto">
</a>
<div class="min-w-0">
<p class="text-sm font-semibold leading-tight">{{block "header-title" .}}Dashboard{{end}}</p>
</div>
</div>
<button
id="mobile-menu-toggle"
type="button"
class="inline-flex items-center justify-center rounded-lg p-2 text-white transition hover:bg-white/15 sm:hidden"
aria-label="Buka menu navigasi"
aria-controls="mobile-menu"
aria-expanded="false">
<svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16"/>
</svg>
</button>
<div class="hidden items-center gap-1 text-sm sm:flex">
<nav class="flex items-center gap-1">
<a href="{{b "/dashboard"}}" class="rounded-lg px-3 py-1.5 font-medium transition hover:bg-white/15">Dashboard</a>
<a href="{{b "/arrival"}}" class="rounded-lg px-3 py-1.5 font-medium transition hover:bg-white/15">Arrival</a>
<a href="{{b "/progress"}}" class="rounded-lg px-3 py-1.5 font-medium transition hover:bg-white/15">Progress</a>
<a href="{{b "/abnormal"}}" class="rounded-lg px-3 py-1.5 font-medium transition hover:bg-white/15">Abnormal</a>
<a href="{{b "/result"}}" class="rounded-lg px-3 py-1.5 font-medium transition hover:bg-white/15">Result</a>
</nav>
{{if .Username}}
<div class="ml-3 flex items-center gap-2 border-l border-white/20 pl-3">
<a href="{{b "/password"}}" class="rounded-full bg-white/15 px-3 py-1 text-xs font-semibold tracking-wide transition hover:bg-white/25">{{.Username}}</a>
<a href="{{b "/logout"}}" class="rounded-lg px-3 py-1.5 font-medium opacity-75 transition hover:bg-white/15 hover:opacity-100">Logout</a>
</div>
{{end}}
</div>
</div>
<div id="mobile-menu" class="hidden border-t border-white/20 px-4 py-3 sm:hidden">
<nav class="flex flex-col gap-1 text-sm">
<a href="{{b "/dashboard"}}" class="rounded-lg px-3 py-2 font-medium transition hover:bg-white/15">Dashboard</a>
<a href="{{b "/arrival"}}" class="rounded-lg px-3 py-2 font-medium transition hover:bg-white/15">Arrival</a>
<a href="{{b "/progress"}}" class="rounded-lg px-3 py-2 font-medium transition hover:bg-white/15">Progress</a>
<a href="{{b "/abnormal"}}" class="rounded-lg px-3 py-2 font-medium transition hover:bg-white/15">Abnormal</a>
<a href="{{b "/result"}}" class="rounded-lg px-3 py-2 font-medium transition hover:bg-white/15">Result</a>
</nav>
{{if .Username}}
<div class="mt-3 flex items-center justify-between gap-2 border-t border-white/20 pt-3">
<a href="{{b "/password"}}" class="rounded-full bg-white/15 px-3 py-1 text-xs font-semibold tracking-wide transition hover:bg-white/25">{{.Username}}</a>
<a href="{{b "/logout"}}" class="rounded-lg px-3 py-1.5 text-sm font-medium opacity-85 transition hover:bg-white/15 hover:opacity-100">Logout</a>
</div>
{{end}}
</div>
</header>
<main class="mx-auto w-full max-w-7xl space-y-5 px-4 py-5 sm:px-6 lg:px-8">
{{block "content" .}}{{end}}
</main>
<script>
(() => {
const btn = document.getElementById('mobile-menu-toggle');
const menu = document.getElementById('mobile-menu');
if (!btn || !menu) return;
btn.addEventListener('click', () => {
const expanded = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', expanded ? 'false' : 'true');
menu.classList.toggle('hidden');
});
})();
</script>
</body>
</html>
{{end}}