39401-vm/includes/layout.php
2026-03-30 17:47:50 +00:00

163 lines
7.4 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/bootstrap.php';
function render_brand_mark(string $projectName, string $extraClass = ''): void
{
$logoUrl = public_asset_url(app_logo_url());
$className = trim('brand-mark ' . $extraClass . ($logoUrl !== '' ? ' brand-mark-image' : ''));
?>
<span class="<?= e($className) ?>">
<?php if ($logoUrl !== ''): ?>
<img src="<?= e($logoUrl) ?>" alt="<?= e($projectName) ?> logo">
<?php else: ?>
<?= e(app_brand_initial()) ?>
<?php endif; ?>
</span>
<?php
}
function render_page_start(array $options = []): void
{
$title = $options['title'] ?? 'ServisIngat';
$description = $options['description'] ?? app_env('PROJECT_DESCRIPTION', 'Dashboard pengingat servis kendaraan agar tidak telat ganti oli, filter, CVT, gardan, busi, dan servis rutin lainnya.');
$page = $options['page'] ?? '';
$robots = $options['robots'] ?? 'index, follow';
$projectName = app_project_name();
$projectDescription = app_env('PROJECT_DESCRIPTION', $description);
$projectImageUrl = app_env('PROJECT_IMAGE_URL', '');
$isLoggedIn = is_user_logged_in();
$userName = current_user_name();
$bodyClass = trim('app-body page-' . ($page !== '' ? $page : 'default') . ' ' . (string) ($options['body_class'] ?? ''));
?>
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= e($title) ?> · <?= e($projectName) ?></title>
<meta name="description" content="<?= e($description) ?>">
<meta name="robots" content="<?= e($robots) ?>">
<meta property="og:title" content="<?= e($title . ' · ' . $projectName) ?>">
<meta property="og:description" content="<?= e($projectDescription) ?>">
<meta property="twitter:title" content="<?= e($title . ' · ' . $projectName) ?>">
<meta property="twitter:description" content="<?= e($projectDescription) ?>">
<?php if ($projectImageUrl): ?>
<meta property="og:image" content="<?= e($projectImageUrl) ?>">
<meta property="twitter:image" content="<?= e($projectImageUrl) ?>">
<?php endif; ?>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link rel="stylesheet" href="<?= e(asset_url('assets/css/custom.css')) ?>?v=<?= urlencode((string) filemtime(__DIR__ . '/../assets/css/custom.css')) ?>">
<?php $faviconUrl = public_asset_url(app_favicon_url()); ?>
<?php if ($faviconUrl !== ''): ?>
<link rel="icon" type="image/x-icon" href="<?= e($faviconUrl) ?>">
<?php endif; ?>
<?php $headCode = head_ad_code(); ?>
<?php if ($headCode !== ''): ?>
<?= $headCode ?>
<?php endif; ?>
</head>
<body class="<?= e($bodyClass) ?>">
<?php $bodyCode = body_ad_code(); ?>
<?php if ($bodyCode !== ''): ?>
<?= $bodyCode ?>
<?php endif; ?>
<header class="site-header border-bottom sticky-top">
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container py-2">
<div class="nav-shell w-100 d-flex align-items-center justify-content-between gap-3">
<a class="navbar-brand d-flex align-items-center gap-3 fw-semibold text-dark m-0" href="<?= e(app_url()) ?>" aria-label="<?= e($projectName) ?> beranda">
<?php render_brand_mark($projectName); ?>
<span>
<span class="brand-title"><?= e($projectName) ?></span>
<span class="brand-subtitle">maintenance tracker</span>
</span>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav" aria-controls="mainNav" aria-expanded="false" aria-label="Buka navigasi">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="mainNav">
<ul class="navbar-nav ms-auto align-items-lg-center gap-lg-2">
<li class="nav-item"><a class="nav-link <?= $page === 'home' ? 'active' : '' ?>" href="<?= e(app_url()) ?>">Beranda</a></li>
<li class="nav-item"><a class="nav-link <?= in_array($page, ['dashboard', 'detail'], true) ? 'active' : '' ?>" href="<?= e(app_url('dashboard.php')) ?>">Dashboard</a></li>
<?php if ($isLoggedIn): ?>
<li class="nav-item"><span class="nav-user-badge"><?= e($userName) ?></span></li>
<li class="nav-item ms-lg-2"><a class="btn btn-dark btn-sm px-3" href="<?= e(app_url('logout.php')) ?>">Logout</a></li>
<?php else: ?>
<li class="nav-item"><a class="nav-link <?= $page === 'login' ? 'active' : '' ?>" href="<?= e(app_url('login.php')) ?>">Login</a></li>
<li class="nav-item"><a class="nav-link <?= $page === 'register' ? 'active' : '' ?>" href="<?= e(app_url('register.php')) ?>">Daftar</a></li>
<li class="nav-item ms-lg-2"><a class="btn btn-dark btn-sm px-3" href="<?= e(app_url('register.php')) ?>">Mulai Catat</a></li>
<?php endif; ?>
</ul>
</div>
</div>
</div>
</nav>
</header>
<main>
<?php
}
function render_flash(?array $flash): void
{
if (!$flash || empty($flash['message'])) {
return;
}
$type = (string) ($flash['type'] ?? 'info');
$message = (string) $flash['message'];
$color = match ($type) {
'success' => 'success',
'warning' => 'warning',
'danger', 'error' => 'danger',
default => 'secondary',
};
?>
<div class="toast-container position-fixed top-0 end-0 p-3">
<div class="toast align-items-center text-bg-<?= e($color) ?> border-0 show app-toast" role="status" aria-live="polite" aria-atomic="true" data-bs-delay="5000">
<div class="d-flex">
<div class="toast-body"><?= e($message) ?></div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Tutup"></button>
</div>
</div>
</div>
<?php
}
function render_page_end(): void
{
$projectName = app_project_name();
?>
</main>
<footer class="site-footer border-top mt-5">
<div class="container py-4 py-lg-5">
<div class="footer-shell d-flex flex-column flex-lg-row justify-content-between gap-4 align-items-lg-center">
<div>
<div class="footer-brand d-flex align-items-center gap-3 mb-2">
<?php render_brand_mark($projectName, 'brand-mark-sm'); ?>
<div>
<div class="fw-semibold text-dark"><?= e($projectName) ?></div>
<div class="small text-muted">MVP pengingat servis kendaraan multi-user untuk motor, mobil, dan bengkel kecil.</div>
</div>
</div>
<div class="footer-chips d-flex flex-wrap gap-2">
<span class="summary-chip">Dashboard privat</span>
<span class="summary-chip">Reminder terstruktur</span>
<span class="summary-chip">Multi-user aman</span>
</div>
</div>
<div class="small text-muted text-lg-end">
Data servis tiap akun dipisahkan agar tidak saling terlihat.<br>
<a class="text-decoration-none" href="<?= e(app_url('healthz.php')) ?>">Health check</a>
</div>
</div>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
<script src="<?= e(asset_url('assets/js/main.js')) ?>?v=<?= urlencode((string) filemtime(__DIR__ . '/../assets/js/main.js')) ?>"></script>
</body>
</html>
<?php
}