This commit is contained in:
Saufi
2026-06-16 15:04:58 +08:00
commit 77a87fbdf1
171 changed files with 21225 additions and 0 deletions

View File

@@ -0,0 +1,257 @@
@php
$user = auth()->user();
$isPublicPortal = $user?->isPublicUser();
$notifications = $user?->notifications()->latest()->take(5)->get() ?? collect();
$menus = match($user?->role?->slug) {
'admin' => [
['route' => 'admin.dashboard', 'label' => 'Dashboard', 'icon' => 'bi-grid-1x2-fill'],
['route' => 'admin.users.index', 'label' => 'Pengurusan Pengguna', 'icon' => 'bi-people-fill'],
['route' => 'admin.roles.index', 'label' => 'Pengurusan Peranan', 'icon' => 'bi-shield-lock-fill'],
['route' => 'admin.applications.index', 'label' => 'Permohonan', 'icon' => 'bi-journal-text'],
['route' => 'admin.installment-accounts.index', 'label' => 'Akaun Ansuran', 'icon' => 'bi-calendar-range-fill'],
['route' => 'admin.payments.index', 'label' => 'Bayaran', 'icon' => 'bi-credit-card-2-front-fill'],
['route' => 'admin.tasks.index', 'label' => 'Tugasan', 'icon' => 'bi-list-task'],
['route' => 'admin.communications.index', 'label' => 'Notifikasi & Emel', 'icon' => 'bi-envelope-paper-fill'],
['route' => 'admin.property-accounts.index', 'label' => 'Data Harta', 'icon' => 'bi-house-check-fill'],
['route' => 'admin.import.index', 'label' => 'Import Excel', 'icon' => 'bi-file-earmark-arrow-up-fill'],
['route' => 'admin.settings.index', 'label' => 'Tetapan Sistem', 'icon' => 'bi-gear-fill'],
['route' => 'admin.reports.index', 'label' => 'Laporan', 'icon' => 'bi-bar-chart-fill'],
['route' => 'admin.audit-trail.index', 'label' => 'Audit Trail', 'icon' => 'bi-clock-history'],
],
'staff' => [
['route' => 'staff.dashboard', 'label' => 'Dashboard Staff', 'icon' => 'bi-speedometer2'],
['route' => 'staff.applications.index', 'label' => 'Permohonan', 'icon' => 'bi-folder2-open'],
['route' => 'staff.bulk-payments.index', 'label' => 'Kemaskini Bayaran Pukal', 'icon' => 'bi-file-earmark-spreadsheet-fill'],
['route' => 'staff.import.index', 'label' => 'Import Excel', 'icon' => 'bi-file-earmark-arrow-up-fill'],
],
default => [
['route' => 'portal.dashboard', 'label' => 'Dashboard', 'icon' => 'bi-house-door-fill'],
['route' => 'portal.applications.index', 'label' => 'Permohonan Saya', 'icon' => 'bi-journal-check'],
['route' => 'portal.applications.create', 'label' => 'Permohonan Baharu', 'icon' => 'bi-plus-circle-fill'],
['route' => 'portal.profile.edit', 'label' => 'Profil Pengguna', 'icon' => 'bi-person-vcard-fill'],
],
};
@endphp
<!DOCTYPE html>
<html lang="ms">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title', 'MyAnsuran')</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<style>
:root {
--ma-navy: #10375c;
--ma-blue: #1d5d9b;
--ma-green: #5c8374;
--ma-gold: #f0b86e;
--ma-soft: #f4f8fc;
--ma-border: #dbe6f0;
}
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(180deg, #eef5fb 0%, #f7f9fc 100%);
color: #17354d;
}
.shell-sidebar {
background:
radial-gradient(circle at top left, rgba(240, 184, 110, 0.2), transparent 35%),
linear-gradient(180deg, #11385e 0%, #0e2c47 100%);
min-height: 100vh;
color: #fff;
}
.shell-content {
min-height: 100vh;
}
.sidebar-link {
color: rgba(255, 255, 255, 0.88);
border-radius: 1rem;
padding: .78rem 1rem;
display: flex;
align-items: center;
gap: .85rem;
text-decoration: none;
transition: .2s ease;
}
.sidebar-link:hover,
.sidebar-link.active {
background: rgba(255, 255, 255, 0.12);
color: #fff;
}
.portal-topbar,
.surface-card,
.stat-card {
border: none;
border-radius: 1.2rem;
box-shadow: 0 18px 42px rgba(22, 48, 78, 0.08);
}
.portal-topbar {
background: rgba(255, 255, 255, 0.92);
backdrop-filter: blur(12px);
}
.stat-card {
background: linear-gradient(135deg, #ffffff 0%, #f8fbff 100%);
}
.stat-icon {
width: 3rem;
height: 3rem;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 1rem;
background: rgba(29, 93, 155, 0.12);
color: var(--ma-blue);
}
.banner-card {
background:
radial-gradient(circle at top right, rgba(240, 184, 110, 0.24), transparent 22%),
linear-gradient(135deg, rgba(16, 55, 92, 0.98), rgba(29, 93, 155, 0.88));
color: #fff;
border-radius: 1.4rem;
border: none;
}
.table thead th {
color: #4f667a;
font-size: .85rem;
text-transform: uppercase;
letter-spacing: .04em;
border-bottom-width: 1px;
}
.top-nav-link {
color: #31526a;
text-decoration: none;
font-weight: 600;
}
.mini-label {
text-transform: uppercase;
letter-spacing: .08em;
font-size: .75rem;
color: #6a8094;
}
.public-layout {
max-width: 1240px;
margin: 0 auto;
}
</style>
@stack('styles')
</head>
<body>
@if ($isPublicPortal)
<div class="container-fluid px-lg-4 py-3 public-layout">
<nav class="portal-topbar navbar navbar-expand-lg mb-4 px-3">
<div class="container-fluid">
<a class="navbar-brand fw-bold text-primary" href="{{ route('portal.dashboard') }}">MyAnsuran</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#publicNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="publicNav">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
@foreach ($menus as $menu)
<li class="nav-item">
<a class="nav-link top-nav-link {{ request()->routeIs(str_replace('.index', '.*', $menu['route'])) || request()->routeIs($menu['route']) ? 'text-primary' : '' }}"
href="{{ route($menu['route']) }}">{{ $menu['label'] }}</a>
</li>
@endforeach
</ul>
<div class="d-flex align-items-center gap-3">
<div class="dropdown">
<button class="btn btn-light position-relative" data-bs-toggle="dropdown">
<i class="bi bi-bell"></i>
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">{{ $notifications->count() }}</span>
</button>
<div class="dropdown-menu dropdown-menu-end p-3" style="width: 320px;">
<div class="fw-semibold mb-2">Notifikasi</div>
@forelse ($notifications as $notification)
<div class="border-bottom pb-2 mb-2">
<div class="fw-semibold small">{{ $notification->title }}</div>
<div class="text-muted small">{{ $notification->message }}</div>
</div>
@empty
<div class="text-muted small">Tiada notifikasi baharu.</div>
@endforelse
</div>
</div>
<div class="text-end">
<div class="fw-semibold">{{ $user->displayName() }}</div>
<div class="text-muted small">{{ $user->email }}</div>
</div>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button class="btn btn-outline-secondary">Logout</button>
</form>
</div>
</div>
</div>
</nav>
@include('components.flash')
@yield('content')
</div>
@else
<div class="container-fluid">
<div class="row">
<aside class="col-lg-3 col-xl-2 shell-sidebar px-3 py-4">
<div class="d-flex align-items-center gap-3 mb-4">
<div class="rounded-4 bg-white bg-opacity-10 p-3">
<i class="bi bi-bank2 fs-4"></i>
</div>
<div>
<div class="fw-bold fs-5">MyAnsuran</div>
<div class="small text-white-50">Portal Demo KIK</div>
</div>
</div>
<div class="mb-4 pb-2 border-bottom border-light border-opacity-25">
<div class="fw-semibold">{{ $user->displayName() }}</div>
<div class="small text-white-50">{{ $user->role->name }}</div>
</div>
<nav class="d-grid gap-2">
@foreach ($menus as $menu)
<a href="{{ route($menu['route']) }}"
class="sidebar-link {{ request()->routeIs(str_replace('.index', '.*', $menu['route'])) || request()->routeIs($menu['route']) ? 'active' : '' }}">
<i class="bi {{ $menu['icon'] }}"></i>
<span>{{ $menu['label'] }}</span>
</a>
@endforeach
</nav>
</aside>
<main class="col-lg-9 col-xl-10 shell-content p-3 p-lg-4">
<div class="portal-topbar px-4 py-3 mb-4 d-flex flex-wrap align-items-center justify-content-between gap-3">
<div>
<div class="mini-label">@yield('page-label', 'Modul Sistem')</div>
<h1 class="h4 mb-0 fw-bold">@yield('page-title', 'MyAnsuran')</h1>
</div>
<div class="d-flex align-items-center gap-3">
<div class="dropdown">
<button class="btn btn-light position-relative" data-bs-toggle="dropdown">
<i class="bi bi-bell"></i>
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">{{ $notifications->count() }}</span>
</button>
<div class="dropdown-menu dropdown-menu-end p-3" style="width: 320px;">
<div class="fw-semibold mb-2">Notifikasi Terkini</div>
@forelse ($notifications as $notification)
<div class="border-bottom pb-2 mb-2">
<div class="fw-semibold small">{{ $notification->title }}</div>
<div class="text-muted small">{{ $notification->message }}</div>
</div>
@empty
<div class="text-muted small">Tiada notifikasi untuk dipaparkan.</div>
@endforelse
</div>
</div>
@yield('page-actions')
<form method="POST" action="{{ route('logout') }}">
@csrf
<button class="btn btn-outline-secondary">Logout</button>
</form>
</div>
</div>
@include('components.flash')
@yield('content')
</main>
</div>
</div>
@endif
</body>
</html>