MIF_E31232406/resources/views/layouts/app.blade.php

344 lines
13 KiB
PHP

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<link rel="icon" type="image/png" href="{{ asset('Lambang_Kabupaten_Pasuruan.png') }}">
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet"/>
@vite(['resources/css/app.css', 'resources/js/app.js'])
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
body{font-family:'Figtree',sans-serif;background:#f1f5f9;min-height:100dvh;-webkit-font-smoothing:antialiased;}
/* ══ NAVBAR ══ */
#nb-wrap{
position:sticky;top:0;z-index:50;
padding:10px 16px 0;
transition:padding .25s;
}
#nb-wrap.scrolled{ padding-top:0; }
#nb-shell{
max-width:80rem;margin:0 auto;
background:rgba(255,255,255,.96);
backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
border:1.5px solid #e2e8f0;
border-radius:16px;
box-shadow:0 4px 24px rgba(15,23,42,.07);
padding:14px 22px;
transition:border-radius .25s,box-shadow .25s;
will-change:transform;
transform:translateZ(0);
}
#nb-wrap.scrolled #nb-shell{
border-radius:0 0 16px 16px;
border-top:none;
box-shadow:0 8px 32px rgba(15,23,42,.10);
}
.nb-row{ display:flex;align-items:center;gap:12px; }
/* ── LINKS ── */
.nb-links{ display:flex;align-items:center;gap:8px;flex:1; }
.nb-links a{
display:inline-flex;align-items:center;
padding:10px 18px;border-radius:12px;
font-size:15px;font-weight:700;
color:#475569;background:#f8fafc;
border:1.5px solid transparent;
text-decoration:none;white-space:nowrap;
letter-spacing:.01em;
transition:background .15s,color .15s,border-color .15s,box-shadow .15s,
max-width .2s ease, opacity .2s ease, padding .2s ease, margin .2s ease;
max-width:200px;
overflow:hidden;
opacity:1;
will-change:max-width, opacity;
}
.nb-links a:hover{ background:#fff;border-color:#e2e8f0;color:#1e293b; }
.nb-links a.nb-active{
background:#2563eb;color:#fff;
border-color:#2563eb;
box-shadow:0 3px 10px rgba(37,99,235,.25);
}
.nb-links.hide-inactive a:not(.nb-active){
max-width:0;opacity:0;
padding-left:0;padding-right:0;
margin:0;border-width:0;
pointer-events:none;
}
/* ── USER ── */
.nb-user{ display:flex;align-items:center;gap:10px;flex-shrink:0; }
.nb-avatar{
width:40px;height:40px;border-radius:50%;
background:linear-gradient(135deg,#3b82f6,#2563eb);
display:flex;align-items:center;justify-content:center;
color:#fff;font-size:15px;font-weight:800;
box-shadow:0 2px 8px rgba(37,99,235,.22);flex-shrink:0;
}
.nb-name{ font-size:14px;font-weight:700;color:#374151;white-space:nowrap; }
.nb-logout{
font-size:14px;font-weight:700;color:#ef4444;
background:#fff1f2;border:1.5px solid #fecdd3;
padding:8px 16px;border-radius:10px;cursor:pointer;
transition:background .15s;white-space:nowrap;
}
.nb-logout:hover{ background:#ffe4e6; }
/* ══ MOBILE ══ */
@media(max-width:768px){
#nb-wrap{ padding:8px 8px 0; }
#nb-shell{ padding:10px 12px 12px; border-radius:14px; }
.nb-row{ flex-direction:column; align-items:stretch; gap:8px; }
/* Baris user: avatar + nama + tombol keluar */
.nb-user{
justify-content:space-between;
width:100%;
background:#f8fafc;
border:1.5px solid #e2e8f0;
border-radius:12px;
padding:10px 14px;
}
.nb-user > div:first-child{ display:flex; align-items:center; gap:10px; flex:1; }
.nb-avatar{ width:38px; height:38px; font-size:16px; flex-shrink:0; }
.nb-name{
display:block !important;
font-size:15px;
font-weight:700;
color:#1e293b;
}
.nb-logout{
font-size:14px;
font-weight:700;
padding:9px 18px;
border-radius:10px;
min-height:44px;
display:flex;
align-items:center;
white-space:nowrap;
flex-shrink:0;
}
/* Nav links: scroll horizontal, semua label tampil penuh */
.nb-links{
overflow-x:auto;
-webkit-overflow-scrolling:touch;
scrollbar-width:none;
gap:6px;
padding-bottom:2px;
display:flex !important;
flex-wrap:nowrap;
}
.nb-links::-webkit-scrollbar{ display:none; }
.nb-links a{
font-size:14px !important;
font-weight:700 !important;
padding:12px 20px !important;
border-radius:10px !important;
min-height:48px !important;
display:inline-flex !important;
align-items:center !important;
white-space:nowrap !important;
/* Paksa tampil semua — override hide-inactive */
max-width:none !important;
opacity:1 !important;
border-width:1.5px !important;
pointer-events:auto !important;
overflow:visible !important;
}
/* Paksa semua link tetap terlihat di mobile */
.nb-links.hide-inactive a:not(.nb-active){
max-width:none !important;
opacity:1 !important;
padding:12px 20px !important;
margin:0 !important;
border-width:1.5px !important;
pointer-events:auto !important;
}
}
@media(max-width:400px){
.nb-links a{ font-size:13px !important; padding:11px 16px !important; min-height:44px !important; }
.nb-logout{ font-size:13px; padding:9px 14px; }
.nb-name{ font-size:14px; }
}
/* ══ LAYOUT ══ */
.page-header{ max-width:80rem;margin:14px auto 0;padding:0 16px; }
.page-header-inner{
background:#fff;border:1.5px solid #e2e8f0;border-radius:16px;
box-shadow:0 2px 12px rgba(15,23,42,.05);padding:14px 18px;
}
.page-main{
max-width:80rem;margin:14px auto 24px;padding:0 16px;
display:flex;flex-direction:column;gap:14px;
}
@media(max-width:768px){
.page-header{ padding:0 10px;margin-top:12px; }
.page-header-inner{ padding:14px 16px;border-radius:14px; }
.page-main{ padding:0 10px;margin-top:12px;margin-bottom:24px;gap:12px; }
}
</style>
</head>
<body>
<!-- ══ NAVBAR ══ -->
<div id="nb-wrap">
<div id="nb-shell">
<div class="nb-row">
@php $role = Auth::user()->role ?? null; @endphp
<!-- USER -->
<div class="nb-user">
<div style="display:flex;align-items:center;gap:10px;">
<div class="nb-avatar">{{ strtoupper(substr(Auth::user()->name ?? 'U', 0, 1)) }}</div>
<span class="nb-name">{{ Auth::user()->name ?? '' }}</span>
</div>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit" class="nb-logout">Keluar</button>
</form>
</div>
<!-- LINKS -->
<nav class="nb-links" id="nb-links">
@if($role === 'admin')
<a href="{{ route('admin.dashboard') }}"
class="{{ request()->routeIs('admin.dashboard') ? 'nb-active' : '' }}">Dashboard</a>
<a href="{{ route('admin.data-warga') }}"
class="{{ request()->routeIs('admin.data-warga') ? 'nb-active' : '' }}">Data Warga</a>
<a href="{{ route('admin.data-akun') }}"
class="{{ request()->routeIs('admin.data-akun') ? 'nb-active' : '' }}">Data Akun</a>
<a href="{{ route('admin.filterisasi') }}"
class="{{ request()->routeIs('admin.filterisasi') ? 'nb-active' : '' }}">Filterisasi</a>
<a href="{{ route('admin.laporan') }}"
class="{{ request()->routeIs('admin.laporan') ? 'nb-active' : '' }}">Laporan</a>
@else
<a href="{{ route('dashboard') }}"
class="{{ request()->routeIs('dashboard') ? 'nb-active' : '' }}">Dashboard</a>
<a href="{{ route('rt.calon-penerima.create') }}"
class="{{ request()->routeIs('rt.calon-penerima.create') ? 'nb-active' : '' }}">Inputkan Warga</a>
<a href="{{ route('rt.calon-penerima.index') }}"
class="{{ request()->routeIs('rt.calon-penerima.index') ? 'nb-active' : '' }}">Riwayat</a>
<a href="{{ route('rt.laporan.index') }}"
class="{{ request()->routeIs('rt.laporan.*') ? 'nb-active' : '' }}">Laporan</a>
@endif
</nav>
</div>
</div>
</div>
<!-- HEADER SLOT -->
@isset($header)
<div class="page-header">
<div class="page-header-inner">{{ $header }}</div>
</div>
@endisset
<!-- MAIN -->
<main class="page-main">{{ $slot }}</main>
<script>
(function(){
var wrap = document.getElementById('nb-wrap');
var links = document.getElementById('nb-links');
/* ── scrolled class: IntersectionObserver, zero reflow ── */
var sentinel = document.createElement('div');
sentinel.style.cssText = 'position:absolute;top:1px;left:0;width:1px;height:1px;pointer-events:none;';
document.body.prepend(sentinel);
new IntersectionObserver(function(e){
e[0].isIntersecting
? wrap.classList.remove('scrolled')
: wrap.classList.add('scrolled');
}, {threshold:0}).observe(sentinel);
var MOBILE_BP = 768;
var lastY = window.scrollY;
var peakY = window.scrollY;
var hidden = false;
var rafPending = null;
var DEAD_ZONE = 8;
var UP_THRESHOLD = 32;
var BOTTOM_GUARD = 12;
function isMobile(){ return window.innerWidth <= MOBILE_BP; }
function maxScroll(){
return Math.max(0, document.documentElement.scrollHeight - window.innerHeight);
}
function applyHide(val){
if(val === hidden) return;
hidden = val;
if(val) links.classList.add('hide-inactive');
else links.classList.remove('hide-inactive');
}
function tick(){
rafPending = null;
/* Mobile: selalu tampilkan semua link, jangan collapse */
if(isMobile()){
applyHide(false);
lastY = window.scrollY;
peakY = window.scrollY;
return;
}
var y = window.scrollY;
var diff = y - lastY;
if(y > peakY) peakY = y;
/* Bottom guard */
if(y >= maxScroll() - BOTTOM_GUARD){
if(y > 50) applyHide(true);
lastY = y;
return;
}
/* Dead zone */
if(Math.abs(diff) < DEAD_ZONE){
lastY = y;
return;
}
if(diff > 0 && y > 50){
applyHide(true);
} else if(diff < 0 && hidden){
if(peakY - y >= UP_THRESHOLD){
applyHide(false);
peakY = y;
}
}
lastY = y;
}
window.addEventListener('scroll', function(){
if(rafPending) return;
rafPending = requestAnimationFrame(tick);
}, {passive:true});
/* Resize: kalau user putar layar dari landscape ke portrait, reset state */
window.addEventListener('resize', function(){
if(isMobile()) applyHide(false);
}, {passive:true});
})();
</script>
</body>
</html>