first
This commit is contained in:
254
resources/views/admin/dashboard.blade.php
Normal file
254
resources/views/admin/dashboard.blade.php
Normal file
@@ -0,0 +1,254 @@
|
||||
@extends('layouts.admin')
|
||||
|
||||
@section('title', 'Dashboard')
|
||||
|
||||
@section('content')
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h4 class="fw-bold mb-0"><i class="bi bi-speedometer2 me-2 text-primary"></i>Dashboard Pentadbir</h4>
|
||||
<span class="text-muted small">{{ now()->format('d M Y, H:i') }}</span>
|
||||
</div>
|
||||
|
||||
{{-- Baris 1: Pengguna & Projek --}}
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-3">
|
||||
<div class="card stat-card bg-success text-white h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<div class="fs-1 fw-bold">{{ $stats['users_active'] }}</div>
|
||||
<div class="opacity-75 small">Pengguna Aktif</div>
|
||||
<div class="mt-1 opacity-60" style="font-size:0.78rem">
|
||||
{{ $stats['users_total'] }} jumlah •
|
||||
{{ $stats['users_inactive'] }} dinyahaktif
|
||||
</div>
|
||||
</div>
|
||||
<i class="bi bi-people-fill fs-2 opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card stat-card bg-primary text-white h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<div class="fs-1 fw-bold">{{ $stats['projects_total'] }}</div>
|
||||
<div class="opacity-75 small">Jumlah Projek</div>
|
||||
<div class="mt-1 opacity-60" style="font-size:0.78rem">
|
||||
+{{ $stats['projects_last_7'] }} (7 hari) •
|
||||
+{{ $stats['projects_last_30'] }} (30 hari)
|
||||
</div>
|
||||
</div>
|
||||
<i class="bi bi-folder-fill fs-2 opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card stat-card bg-info text-white h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<div class="fs-1 fw-bold">{{ $stats['projects_completed'] }}</div>
|
||||
<div class="opacity-75 small">Transkripsi Selesai</div>
|
||||
@php
|
||||
$pct = $stats['projects_total'] > 0
|
||||
? round($stats['projects_completed'] / $stats['projects_total'] * 100)
|
||||
: 0;
|
||||
@endphp
|
||||
<div class="mt-1 opacity-60" style="font-size:0.78rem">
|
||||
{{ $pct }}% kadar kejayaan
|
||||
</div>
|
||||
</div>
|
||||
<i class="bi bi-check-circle-fill fs-2 opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card stat-card bg-warning text-dark h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
@php
|
||||
$totalBytes = $stats['storage_bytes'];
|
||||
if ($totalBytes >= 1073741824) {
|
||||
$storageLabel = number_format($totalBytes / 1073741824, 2) . ' GB';
|
||||
} elseif ($totalBytes >= 1048576) {
|
||||
$storageLabel = number_format($totalBytes / 1048576, 1) . ' MB';
|
||||
} else {
|
||||
$storageLabel = number_format($totalBytes / 1024, 0) . ' KB';
|
||||
}
|
||||
$durationH = intdiv($stats['duration_total_seconds'], 3600);
|
||||
$durationM = intdiv($stats['duration_total_seconds'] % 3600, 60);
|
||||
@endphp
|
||||
<div class="fs-3 fw-bold">{{ $storageLabel }}</div>
|
||||
<div class="small" style="opacity:0.8">Storan Digunakan</div>
|
||||
<div class="mt-1" style="font-size:0.78rem; opacity:0.7">
|
||||
{{ $durationH }}j {{ $durationM }}m jumlah audio
|
||||
</div>
|
||||
</div>
|
||||
<i class="bi bi-hdd-fill fs-2 opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Baris 2: Status + Trend --}}
|
||||
<div class="row g-3 mb-3">
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-white fw-semibold">
|
||||
<i class="bi bi-pie-chart me-2 text-primary"></i>Status Transkripsi
|
||||
</div>
|
||||
<div class="card-body pb-2">
|
||||
<table class="table table-sm mb-0">
|
||||
<tbody>
|
||||
@php
|
||||
$statusRows = [
|
||||
['bg-secondary', 'Menunggu', $stats['projects_pending']],
|
||||
['bg-warning text-dark', 'Sedang Diproses', $stats['projects_processing']],
|
||||
['bg-success', 'Selesai', $stats['projects_completed']],
|
||||
['bg-danger', 'Gagal', $stats['projects_failed']],
|
||||
['bg-light text-muted border', 'Dipadam (soft)', $stats['projects_deleted']],
|
||||
];
|
||||
@endphp
|
||||
@foreach($statusRows as [$cls, $label, $count])
|
||||
<tr>
|
||||
<td><span class="badge {{ $cls }}">{{ $label }}</span></td>
|
||||
<td class="fw-bold">{{ $count }}</td>
|
||||
<td class="text-muted small">
|
||||
@if($stats['projects_total'] > 0)
|
||||
{{ round($count / ($stats['projects_total'] ?: 1) * 100) }}%
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-white fw-semibold">
|
||||
<i class="bi bi-bar-chart me-2 text-success"></i>Trend 30 Hari Lepas
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@if($trendRaw->isEmpty())
|
||||
<div class="text-muted small text-center py-4">Tiada data projek dalam 30 hari lepas.</div>
|
||||
@else
|
||||
<div class="table-responsive" style="max-height:220px; overflow-y:auto">
|
||||
<table class="table table-sm table-hover mb-0">
|
||||
<thead class="table-light sticky-top">
|
||||
<tr>
|
||||
<th>Tarikh</th>
|
||||
<th class="text-center">Baru</th>
|
||||
<th class="text-center text-success">Selesai</th>
|
||||
<th class="text-center text-danger">Gagal</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($trendRaw->sortByDesc('date') as $row)
|
||||
<tr>
|
||||
<td class="small">{{ \Carbon\Carbon::parse($row->date)->format('d/m') }}</td>
|
||||
<td class="text-center">{{ $row->total }}</td>
|
||||
<td class="text-center text-success">{{ $row->completed }}</td>
|
||||
<td class="text-center text-danger">{{ $row->failed }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-white fw-semibold">
|
||||
<i class="bi bi-trophy me-2 text-warning"></i>Pengguna Paling Aktif
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@if($topUsers->isEmpty())
|
||||
<div class="text-muted small text-center py-4">Tiada data pengguna.</div>
|
||||
@else
|
||||
<table class="table table-sm mb-0">
|
||||
<tbody>
|
||||
@foreach($topUsers as $i => $u)
|
||||
<tr>
|
||||
<td style="width:28px" class="text-center text-muted small">{{ $i + 1 }}</td>
|
||||
<td>
|
||||
<div class="small fw-semibold">{{ $u->name }}</div>
|
||||
<div class="text-muted" style="font-size:0.72rem">{{ $u->email }}</div>
|
||||
</td>
|
||||
<td class="text-end fw-bold small">{{ $u->owned_projects_count }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Baris 3: Jabatan + Tindakan Pantas --}}
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-white fw-semibold">
|
||||
<i class="bi bi-building me-2 text-secondary"></i>Projek Mengikut Jabatan
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
@if($deptStats->isEmpty())
|
||||
<div class="text-muted small text-center py-4">Tiada data jabatan.</div>
|
||||
@else
|
||||
<table class="table table-sm mb-0">
|
||||
<tbody>
|
||||
@foreach($deptStats as $dept)
|
||||
<tr>
|
||||
<td class="small">{{ $dept->name }}</td>
|
||||
<td class="text-end">
|
||||
<span class="badge bg-primary">{{ $dept->project_count }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-white fw-semibold">
|
||||
<i class="bi bi-lightning me-2 text-warning"></i>Tindakan Pantas
|
||||
</div>
|
||||
<div class="card-body d-flex flex-column gap-2">
|
||||
<a href="{{ route('admin.users.index') }}" class="btn btn-outline-primary">
|
||||
<i class="bi bi-people me-2"></i>Urus Pengguna
|
||||
<span class="badge bg-primary ms-1">{{ $stats['users_total'] }}</span>
|
||||
</a>
|
||||
<a href="{{ route('admin.users.create') }}" class="btn btn-outline-success">
|
||||
<i class="bi bi-person-plus me-2"></i>Daftar Pengguna Baru
|
||||
</a>
|
||||
<a href="{{ route('admin.projects.index') }}" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-folder2 me-2"></i>Senarai Projek (Metadata)
|
||||
<span class="badge bg-secondary ms-1">{{ $stats['projects_total'] }}</span>
|
||||
</a>
|
||||
<a href="{{ route('admin.audit-logs.index') }}" class="btn btn-outline-dark">
|
||||
<i class="bi bi-journal-text me-2"></i>Log Audit
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user