897 lines
29 KiB
PHP
897 lines
29 KiB
PHP
<!DOCTYPE html>
|
|
<html lang="id">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Dashboard User</title>
|
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
|
|
<style>
|
|
:root {
|
|
--primary: #1d4ed8;
|
|
--primary-soft: #e0e7ff;
|
|
--bg: #f4f6fb;
|
|
--card: #ffffff;
|
|
--border: #e5e7eb;
|
|
--text: #111827;
|
|
--muted: #6b7280;
|
|
--danger: #dc2626;
|
|
--success: #16a34a;
|
|
--warning: #f59e0b;
|
|
--info: #2563eb;
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
font-family: 'Inter', sans-serif;
|
|
}
|
|
|
|
body {
|
|
background: var(--bg);
|
|
display: flex
|
|
}
|
|
|
|
/* ─── SIDEBAR ─── */
|
|
.sidebar {
|
|
width: 280px;
|
|
height: 100vh;
|
|
background: #fff;
|
|
padding: 24px 18px;
|
|
border-right: 1px solid var(--border);
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: sticky;
|
|
top: 0;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.logo {
|
|
display: flex;
|
|
gap: 12px;
|
|
align-items: center;
|
|
margin-bottom: 18px
|
|
}
|
|
|
|
.logo img {
|
|
width: 54px;
|
|
height: 54px;
|
|
object-fit: contain
|
|
}
|
|
|
|
.logo-text .top,
|
|
.logo-text .mid {
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
line-height: 1.4;
|
|
color: #111827
|
|
}
|
|
|
|
.logo-text .bot {
|
|
font-size: 11px;
|
|
color: var(--muted);
|
|
margin-top: 2px
|
|
}
|
|
|
|
.divider {
|
|
height: 1px;
|
|
background: var(--border);
|
|
margin: 14px 0
|
|
}
|
|
|
|
.menu {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px
|
|
}
|
|
|
|
.menu a {
|
|
padding: 11px 13px;
|
|
border-radius: 10px;
|
|
text-decoration: none;
|
|
color: #374151;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
font-size: 14px;
|
|
transition: .2s;
|
|
}
|
|
|
|
.menu a:hover {
|
|
background: #f3f4f6
|
|
}
|
|
|
|
.menu a.active {
|
|
background: var(--primary-soft);
|
|
color: var(--primary);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.menu a svg {
|
|
flex-shrink: 0;
|
|
opacity: .7
|
|
}
|
|
|
|
.menu a.active svg {
|
|
opacity: 1
|
|
}
|
|
|
|
.bottom {
|
|
margin-top: auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px
|
|
}
|
|
|
|
.menu-item {
|
|
padding: 11px 13px;
|
|
color: #374151;
|
|
text-decoration: none;
|
|
border-radius: 10px;
|
|
font-size: 14px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
transition: .2s;
|
|
}
|
|
|
|
.menu-item:hover {
|
|
background: #f3f4f6
|
|
}
|
|
|
|
.menu-item svg {
|
|
opacity: .7
|
|
}
|
|
|
|
.logout-btn {
|
|
width: 100%;
|
|
padding: 11px 13px;
|
|
border: none;
|
|
background: none;
|
|
color: var(--danger);
|
|
cursor: pointer;
|
|
text-align: left;
|
|
border-radius: 10px;
|
|
font-size: 14px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
transition: .2s;
|
|
}
|
|
|
|
.logout-btn:hover {
|
|
background: #fef2f2
|
|
}
|
|
|
|
/* ─── MAIN ─── */
|
|
.main {
|
|
flex: 1;
|
|
padding: 28px 32px;
|
|
overflow-y: auto;
|
|
height: 100vh
|
|
}
|
|
|
|
/* ─── HEADER ─── */
|
|
.header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 28px;
|
|
}
|
|
|
|
.search-wrap {
|
|
position: relative;
|
|
width: 340px
|
|
}
|
|
|
|
.search-wrap svg {
|
|
position: absolute;
|
|
left: 13px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
pointer-events: none;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.search {
|
|
width: 100%;
|
|
padding: 10px 14px 10px 40px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 12px;
|
|
transition: .2s;
|
|
font-size: 14px;
|
|
background: #fff;
|
|
}
|
|
|
|
.search:focus {
|
|
outline: none;
|
|
border-color: var(--primary);
|
|
box-shadow: 0 0 0 3px rgba(29, 78, 216, .08);
|
|
}
|
|
|
|
/* ─── USER ─── */
|
|
.user {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px
|
|
}
|
|
|
|
.avatar {
|
|
width: 40px;
|
|
height: 40px;
|
|
background: #1e3a8a;
|
|
color: #fff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 50%;
|
|
font-weight: 700;
|
|
font-size: 15px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* ─── NOTIF ─── */
|
|
.notif {
|
|
position: relative;
|
|
cursor: pointer
|
|
}
|
|
|
|
.notif-btn {
|
|
width: 40px;
|
|
height: 40px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: #fff;
|
|
cursor: pointer;
|
|
transition: .2s;
|
|
}
|
|
|
|
.notif-btn:hover {
|
|
background: #f3f4f6
|
|
}
|
|
|
|
.badge {
|
|
position: absolute;
|
|
top: -5px;
|
|
right: -5px;
|
|
background: #ef4444;
|
|
color: #fff;
|
|
font-size: 11px;
|
|
border-radius: 999px;
|
|
padding: 2px 6px;
|
|
font-weight: 600;
|
|
min-width: 20px;
|
|
text-align: center;
|
|
}
|
|
|
|
.dropdown {
|
|
position: absolute;
|
|
right: 0;
|
|
top: 50px;
|
|
width: 320px;
|
|
background: #fff;
|
|
border: 1px solid var(--border);
|
|
border-radius: 14px;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, .1);
|
|
display: none;
|
|
z-index: 100;
|
|
}
|
|
|
|
.dropdown.show {
|
|
display: block
|
|
}
|
|
|
|
.dropdown-header {
|
|
padding: 13px 16px;
|
|
font-weight: 600;
|
|
font-size: 14px;
|
|
border-bottom: 1px solid var(--border);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.dropdown-header a {
|
|
font-size: 12px;
|
|
color: var(--primary);
|
|
text-decoration: none;
|
|
font-weight: 500
|
|
}
|
|
|
|
.dropdown-item {
|
|
padding: 13px 16px;
|
|
border-bottom: 1px solid var(--border);
|
|
font-size: 13px;
|
|
line-height: 1.5;
|
|
color: var(--text);
|
|
}
|
|
|
|
.dropdown-item:last-child {
|
|
border-bottom: none
|
|
}
|
|
|
|
.dropdown-item.unread {
|
|
background: #eef2ff
|
|
}
|
|
|
|
.dropdown-empty {
|
|
padding: 24px;
|
|
text-align: center;
|
|
color: var(--muted);
|
|
font-size: 13px
|
|
}
|
|
|
|
/* ─── PAGE TITLE ─── */
|
|
.page-title {
|
|
font-size: 24px;
|
|
font-weight: 700;
|
|
margin-bottom: 4px;
|
|
color: var(--text)
|
|
}
|
|
|
|
.page-subtitle {
|
|
color: var(--muted);
|
|
font-size: 14px;
|
|
margin-bottom: 22px
|
|
}
|
|
|
|
/* ─── CARDS ─── */
|
|
.cards {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 16px;
|
|
margin-bottom: 24px
|
|
}
|
|
|
|
.card {
|
|
background: #fff;
|
|
padding: 20px 22px;
|
|
border-radius: 14px;
|
|
border: 1px solid var(--border);
|
|
transition: .2s;
|
|
}
|
|
|
|
.card:hover {
|
|
transform: translateY(-3px);
|
|
box-shadow: 0 8px 20px rgba(0, 0, 0, .06)
|
|
}
|
|
|
|
.card h4 {
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
letter-spacing: .05em;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.card h2 {
|
|
font-size: 32px;
|
|
font-weight: 700
|
|
}
|
|
|
|
.card.total h4,
|
|
.card.total h2 {
|
|
color: var(--info)
|
|
}
|
|
|
|
.card.proses h4,
|
|
.card.proses h2 {
|
|
color: var(--warning)
|
|
}
|
|
|
|
.card.selesai h4,
|
|
.card.selesai h2 {
|
|
color: var(--success)
|
|
}
|
|
|
|
.card-icon {
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.card.total .card-icon {
|
|
background: #dbeafe
|
|
}
|
|
|
|
.card.proses .card-icon {
|
|
background: #fef3c7
|
|
}
|
|
|
|
.card.selesai .card-icon {
|
|
background: #dcfce7
|
|
}
|
|
|
|
/* ─── LIST ─── */
|
|
.list {
|
|
background: #fff;
|
|
border-radius: 14px;
|
|
border: 1px solid var(--border);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.list-header {
|
|
padding: 16px 20px;
|
|
font-weight: 600;
|
|
font-size: 14px;
|
|
border-bottom: 1px solid var(--border);
|
|
background: #fafafa;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.list-header a {
|
|
font-size: 13px;
|
|
color: var(--primary);
|
|
text-decoration: none;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.list-header a:hover {
|
|
text-decoration: underline
|
|
}
|
|
|
|
.item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 16px 20px;
|
|
border-bottom: 1px solid var(--border);
|
|
transition: .2s;
|
|
}
|
|
|
|
.item:last-child {
|
|
border-bottom: none
|
|
}
|
|
|
|
.item:hover {
|
|
background: #f9fafb
|
|
}
|
|
|
|
.item-left strong {
|
|
display: block;
|
|
margin-bottom: 3px;
|
|
font-size: 14px
|
|
}
|
|
|
|
.item-left small {
|
|
color: var(--muted);
|
|
font-size: 12px
|
|
}
|
|
|
|
.badge-status {
|
|
padding: 5px 12px;
|
|
border-radius: 999px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.badge-success {
|
|
background: #dcfce7;
|
|
color: var(--success)
|
|
}
|
|
|
|
.badge-warning {
|
|
background: #fef3c7;
|
|
color: #b45309
|
|
}
|
|
|
|
.badge-info {
|
|
background: #dbeafe;
|
|
color: #1d4ed8
|
|
}
|
|
|
|
.badge-danger {
|
|
background: #fee2e2;
|
|
color: #dc2626
|
|
}
|
|
|
|
/* ─── EMPTY STATE ─── */
|
|
.empty-state {
|
|
padding: 48px 20px;
|
|
text-align: center;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.empty-state svg {
|
|
margin: 0 auto 12px;
|
|
display: block;
|
|
opacity: .35
|
|
}
|
|
|
|
.empty-state p {
|
|
font-size: 14px
|
|
}
|
|
|
|
/* ─── NO RESULT ─── */
|
|
.no-result {
|
|
display: none;
|
|
padding: 32px 20px;
|
|
text-align: center;
|
|
color: var(--muted);
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* ─── RESPONSIVE ─── */
|
|
@media (max-width: 1024px) {
|
|
.cards { grid-template-columns: repeat(2, 1fr); }
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
body { flex-direction: column; }
|
|
.sidebar {
|
|
width: 100%;
|
|
height: auto;
|
|
position: relative;
|
|
border-right: none;
|
|
border-bottom: 1px solid var(--border);
|
|
padding: 16px;
|
|
flex-direction: column;
|
|
}
|
|
.logo {
|
|
justify-content: center;
|
|
margin-bottom: 12px;
|
|
}
|
|
.divider { display: none; }
|
|
.menu {
|
|
flex-direction: row;
|
|
flex-wrap: wrap;
|
|
overflow-x: visible;
|
|
gap: 8px;
|
|
padding-bottom: 8px;
|
|
}
|
|
.menu a { white-space: nowrap; justify-content: center; flex: 1 1 calc(50% - 8px); text-align: center; font-size: 13px; padding: 10px; }
|
|
.bottom {
|
|
flex-direction: row;
|
|
margin-top: 8px;
|
|
gap: 8px;
|
|
border-top: 1px solid var(--border);
|
|
padding-top: 12px;
|
|
}
|
|
.bottom a, .bottom button { white-space: nowrap; justify-content: center; flex: 1 1 calc(50% - 8px); font-size: 13px; padding: 10px; }
|
|
|
|
.main { padding: 20px 16px; height: auto; }
|
|
.header { flex-direction: column-reverse; align-items: flex-start; gap: 20px; margin-bottom: 20px; }
|
|
.search-wrap { width: 100%; }
|
|
.user { width: 100%; justify-content: space-between; }
|
|
.dropdown { width: 300px; left: -10px; right: auto; top: 55px; max-width: calc(100vw - 32px); }
|
|
|
|
.cards { grid-template-columns: 1fr; gap: 12px; }
|
|
.item { flex-direction: column; align-items: flex-start; gap: 12px; }
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<!-- ═══ SIDEBAR ═══ -->
|
|
<div class="sidebar">
|
|
|
|
<div class="logo">
|
|
<img src="{{ asset('Kalimantan-Barat-Logo-Vector.png') }}" alt="Logo">
|
|
<div class="logo-text">
|
|
<div class="top">DINAS TENAGA KERJA</div>
|
|
<div class="mid">DAN TRANSMIGRASI</div>
|
|
<div class="bot">PROVINSI KALIMANTAN BARAT</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<div class="menu">
|
|
|
|
<a href="{{ route('user.dashboard') }}"
|
|
class="{{ request()->routeIs('user.dashboard') ? 'active' : '' }}">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
stroke="currentColor" stroke-width="2">
|
|
<rect x="3" y="3" width="7" height="7" rx="1" />
|
|
<rect x="13" y="3" width="8" height="7" rx="1" />
|
|
<rect x="13" y="13" width="8" height="8" rx="1" />
|
|
<rect x="3" y="13" width="7" height="8" rx="1" />
|
|
</svg>
|
|
Dashboard
|
|
</a>
|
|
|
|
<a href="{{ route('input.activity') }}"
|
|
class="{{ request()->routeIs('input.activity') ? 'active' : '' }}">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
stroke="currentColor" stroke-width="2">
|
|
<path d="M11 5H6a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2v-5" />
|
|
<path d="M17.5 3.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 8.5-8.5z" />
|
|
</svg>
|
|
Input Aktivitas
|
|
</a>
|
|
|
|
<a href="{{ route('activity.list') }}"
|
|
class="{{ request()->routeIs('activity.list') ? 'active' : '' }}">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
stroke="currentColor" stroke-width="2">
|
|
<path d="M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2" />
|
|
<rect x="9" y="3" width="6" height="4" rx="1" />
|
|
<path d="M9 12h6M9 16h4" />
|
|
</svg>
|
|
Daftar Aktivitas
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<div class="bottom">
|
|
<a href="{{ route('settings') }}" class="menu-item">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="12" cy="12" r="3" />
|
|
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" />
|
|
</svg>
|
|
Pengaturan
|
|
</a>
|
|
|
|
<form method="POST" action="{{ route('logout') }}">
|
|
@csrf
|
|
<button class="logout-btn" type="submit">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
|
|
<polyline points="16 17 21 12 16 7" />
|
|
<line x1="21" y1="12" x2="9" y2="12" />
|
|
</svg>
|
|
Logout
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- ═══ MAIN ═══ -->
|
|
<div class="main">
|
|
|
|
<!-- HEADER -->
|
|
<div class="header">
|
|
|
|
<div class="search-wrap">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none"
|
|
stroke="currentColor" stroke-width="2">
|
|
<circle cx="11" cy="11" r="8" />
|
|
<path d="m21 21-4.35-4.35" />
|
|
</svg>
|
|
<input type="text" class="search" placeholder="Cari aktivitas..."
|
|
oninput="filterAktivitas(this.value)">
|
|
</div>
|
|
|
|
<div class="user">
|
|
|
|
<!-- NOTIF -->
|
|
<div class="notif">
|
|
<div class="notif-btn" onclick="toggleNotif()">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" />
|
|
<path d="M13.73 21a2 2 0 0 1-3.46 0" />
|
|
</svg>
|
|
</div>
|
|
|
|
@if($unreadCount > 0)
|
|
<div class="badge">{{ $unreadCount }}</div>
|
|
@endif
|
|
|
|
<div class="dropdown" id="notifDropdown">
|
|
<div class="dropdown-header">
|
|
Notifikasi
|
|
@if(count($notifications) > 0)
|
|
<a href="#" onclick="markAllAsRead(event)">Tandai semua dibaca</a>
|
|
@endif
|
|
</div>
|
|
|
|
<div id="notifListContainer">
|
|
@forelse($notifications as $n)
|
|
<div class="dropdown-item {{ !$n['read_at'] ? 'unread' : '' }}">
|
|
{{ $n['data']['message'] ?? 'Ada notifikasi baru' }}
|
|
<br><small style="color:var(--muted); font-size:11px;">{{ \Carbon\Carbon::parse($n['created_at'])->diffForHumans() }}</small>
|
|
</div>
|
|
@empty
|
|
<div class="dropdown-empty">Tidak ada notifikasi</div>
|
|
@endforelse
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- USER INFO -->
|
|
<div>
|
|
<strong style="font-size:14px">
|
|
{{ session('user')['name'] ?? 'User' }}
|
|
</strong><br>
|
|
|
|
<small style="color:var(--muted);font-size:12px">Pegawai</small>
|
|
</div>
|
|
|
|
<div class="avatar">
|
|
{{ strtoupper(substr(session('user')['name'] ?? 'U', 0, 1)) }}
|
|
</div>
|
|
|
|
</div>{{-- end .user --}}
|
|
|
|
</div>{{-- end .header --}}
|
|
|
|
<!-- PAGE TITLE -->
|
|
<div class="page-title">Dashboard Monitoring</div>
|
|
<div class="page-subtitle">Pantau aktivitas kamu</div>
|
|
|
|
<!-- CARDS -->
|
|
<div class="cards">
|
|
<div class="card total">
|
|
<div class="card-icon">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
stroke="#2563eb" stroke-width="2">
|
|
<rect x="3" y="3" width="7" height="7" rx="1" />
|
|
<rect x="13" y="3" width="8" height="7" rx="1" />
|
|
<rect x="13" y="13" width="8" height="8" rx="1" />
|
|
<rect x="3" y="13" width="7" height="8" rx="1" />
|
|
</svg>
|
|
</div>
|
|
<h4>TOTAL</h4>
|
|
<h2>{{ $activities->count() }}</h2>
|
|
</div>
|
|
<div class="card proses">
|
|
<div class="card-icon">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
stroke="#f59e0b" stroke-width="2">
|
|
<circle cx="12" cy="12" r="10" />
|
|
<polyline points="12 6 12 12 16 14" />
|
|
</svg>
|
|
</div>
|
|
<h4>ON PROGRESS</h4>
|
|
<h2>{{ $onProgres }}</h2>
|
|
</div>
|
|
<div class="card selesai">
|
|
<div class="card-icon">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
stroke="#16a34a" stroke-width="2">
|
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
|
|
<polyline points="22 4 12 14.01 9 11.01" />
|
|
</svg>
|
|
</div>
|
|
<h4>SELESAI</h4>
|
|
<h2>{{ $selesai }}</h2>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- RECENT ACTIVITIES -->
|
|
<div class="list">
|
|
<div class="list-header">
|
|
<span>Recent Activities</span>
|
|
<a href="{{ route('activity.list') }}">Lihat Semua →</a>
|
|
</div>
|
|
|
|
<div id="activity-list">
|
|
@forelse($activities->take(5) as $item)
|
|
<div class="item" data-name="{{ strtolower($item->nama_kegiatan) }}">
|
|
<div class="item-left">
|
|
<strong>{{ $item->nama_kegiatan }}</strong>
|
|
<small>
|
|
{{ $item->user->name ?? 'Pegawai' }}
|
|
·
|
|
{{ \Carbon\Carbon::parse($item->tanggal ?? $item->created_at)->translatedFormat('d M Y') }}
|
|
@if(!empty($item->tanggal_selesai))
|
|
- {{ \Carbon\Carbon::parse($item->tanggal_selesai)->translatedFormat('d M Y') }}
|
|
@endif
|
|
|
|
@if(!empty($item->lokasi))
|
|
· {{ $item->lokasi }}
|
|
@endif
|
|
</small>
|
|
</div>
|
|
<div>
|
|
@php
|
|
$isOverdue = !empty($item->tanggal_selesai) && \Carbon\Carbon::parse($item->tanggal_selesai)->isPast() && $item->status !== 'selesai' && $item->status !== 'telah_ditinjau';
|
|
@endphp
|
|
@if($item->status == 'selesai')
|
|
<span class="badge-status badge-success">Selesai</span>
|
|
@elseif(!empty($item->reviewed_at) || $item->status == 'ditinjau' || $item->status == 'telah_ditinjau')
|
|
<span class="badge-status badge-info">Ditinjau</span>
|
|
@elseif($item->status == 'ditolak')
|
|
<span class="badge-status badge-danger">Ditolak</span>
|
|
@elseif($isOverdue)
|
|
<span class="badge-status badge-danger" style="background:#fef2f2; color:#dc2626; border-color:#fecaca;">Terlambat</span>
|
|
@else
|
|
<span class="badge-status badge-warning">On Progress</span>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@empty
|
|
<div class="empty-state">
|
|
<svg width="44" height="44" viewBox="0 0 24 24" fill="none"
|
|
stroke="currentColor" stroke-width="1.5">
|
|
<path d="M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2" />
|
|
<rect x="9" y="3" width="6" height="4" rx="1" />
|
|
<path d="M9 12h6M9 16h4" />
|
|
</svg>
|
|
<p>Belum ada aktivitas yang diinput.</p>
|
|
<a href="{{ route('input.activity') }}"
|
|
style="display:inline-block;margin-top:12px;padding:8px 18px;
|
|
background:var(--primary);color:#fff;border-radius:8px;
|
|
text-decoration:none;font-size:13px;font-weight:500">
|
|
+ Input Aktivitas
|
|
</a>
|
|
</div>
|
|
@endforelse
|
|
</div>
|
|
|
|
<!-- No result saat search -->
|
|
<div class="no-result" id="no-result">
|
|
Tidak ada aktivitas yang cocok dengan pencarian.
|
|
</div>
|
|
</div>
|
|
|
|
</div>{{-- end .list --}}
|
|
|
|
</div>{{-- end .main --}}
|
|
|
|
<script>
|
|
// ─── TOGGLE NOTIF ───
|
|
function toggleNotif() {
|
|
document.getElementById("notifDropdown").classList.toggle("show");
|
|
}
|
|
document.addEventListener('click', function(e) {
|
|
const notif = document.querySelector('.notif');
|
|
if (notif && !notif.contains(e.target)) {
|
|
document.getElementById('notifDropdown').classList.remove('show');
|
|
}
|
|
});
|
|
|
|
async function markAllAsRead(e) {
|
|
e.preventDefault();
|
|
try {
|
|
await fetch('/user/notifications-api/read', {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRF-TOKEN': '{{ csrf_token() }}',
|
|
'Content-Type': 'application/json'
|
|
}
|
|
});
|
|
// Hapus badge dan ganti class unread
|
|
const badge = document.querySelector('.badge');
|
|
if (badge) badge.style.display = 'none';
|
|
document.querySelectorAll('.dropdown-item.unread').forEach(el => {
|
|
el.classList.remove('unread');
|
|
});
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
|
|
// ─── FILTER SEARCH ───
|
|
function filterAktivitas(keyword) {
|
|
const items = document.querySelectorAll('#activity-list .item');
|
|
const noResult = document.getElementById('no-result');
|
|
keyword = keyword.toLowerCase().trim();
|
|
let visibleCount = 0;
|
|
|
|
items.forEach(item => {
|
|
const name = item.getAttribute('data-name') || '';
|
|
if (name.includes(keyword)) {
|
|
item.style.display = 'flex';
|
|
visibleCount++;
|
|
} else {
|
|
item.style.display = 'none';
|
|
}
|
|
});
|
|
|
|
if (visibleCount === 0 && items.length > 0) {
|
|
noResult.style.display = 'block';
|
|
} else {
|
|
noResult.style.display = 'none';
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |