173 lines
6.7 KiB
PHP
173 lines
6.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Announcement;
|
|
use App\Models\Book;
|
|
use App\Models\Loan;
|
|
use App\Models\Recommendation;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
class DashboardController extends Controller
|
|
{
|
|
public function index()
|
|
{
|
|
$user = Auth::user();
|
|
|
|
// Fetch active loans for the user
|
|
$loans = Loan::with('book')
|
|
->where('user_id', $user->id)
|
|
->whereIn('status', ['Dipinjam', 'Terlambat'])
|
|
->get();
|
|
|
|
$bukuPinjamOffline = $loans->map(function ($loan) {
|
|
$dueAt = Carbon::parse($loan->due_at);
|
|
$sisaHari = (int) now()->diffInDays($dueAt, false);
|
|
|
|
return [
|
|
'id' => $loan->book->id,
|
|
'judul' => $loan->book->judul,
|
|
'penulis' => $loan->book->penulis,
|
|
'sisa_hari' => $sisaHari,
|
|
'cover' => $loan->book->cover,
|
|
];
|
|
});
|
|
|
|
// Check if user has overdue books
|
|
$isTelat = $bukuPinjamOffline->contains(fn($b) => $b['sisa_hari'] < 0);
|
|
|
|
if ($isTelat && $user->role === 'siswa') {
|
|
$user->update(['is_banned' => true]);
|
|
}
|
|
|
|
// Stats calculation
|
|
$stats = [
|
|
['label' => 'Buku yang dipinjam', 'value' => $loans->count(), 'icon' => 'bi-book-half', 'color' => 'primary'],
|
|
['label' => 'Tenggat Waktu', 'value' => $bukuPinjamOffline->where('sisa_hari', '<=', 3)->where('sisa_hari', '>=', 0)->count(), 'icon' => 'bi-clock-history', 'color' => 'danger'],
|
|
['label' => 'Buku dikembalikan', 'value' => Loan::where('user_id', $user->id)->where('status', 'Dikembalikan')->count(), 'icon' => 'bi-check-circle', 'color' => 'success'],
|
|
['label' => 'History Baca', 'value' => Loan::where('user_id', $user->id)->count(), 'icon' => 'bi-hourglass-split', 'color' => 'warning'],
|
|
];
|
|
|
|
$pengumuman = Announcement::latest()->take(5)->get();
|
|
|
|
// Placeholder for pemberitahuan (system notifications)
|
|
$pemberitahuan = collect([
|
|
['type' => 'info', 'icon' => 'bi-bell-fill', 'title' => 'Selamat Datang', 'content' => 'Selamat datang di perpustakaan digital SMKN 1.', 'badge' => 'Baru']
|
|
]);
|
|
|
|
// Dynamic reading progress based on returned vs total books
|
|
$totalUserLoans = Loan::where('user_id', $user->id)->count();
|
|
$returnedLoans = Loan::where('user_id', $user->id)->where('status', 'Dikembalikan')->count();
|
|
$progressSelesai = $totalUserLoans > 0 ? round(($returnedLoans / $totalUserLoans) * 100) : 0;
|
|
|
|
$progressMembaca = ['selesai' => $progressSelesai, 'sisa' => 100 - $progressSelesai];
|
|
|
|
// Dynamic monthly stats for the last 7 months
|
|
$labels = [];
|
|
$data = [];
|
|
for ($i = 6; $i >= 0; $i--) {
|
|
$month = Carbon::now()->subMonths($i);
|
|
$labels[] = $month->translatedFormat('M');
|
|
$data[] = Loan::where('user_id', $user->id)
|
|
->whereMonth('borrowed_at', $month->month)
|
|
->whereYear('borrowed_at', $month->year)
|
|
->count();
|
|
}
|
|
|
|
$statistikBulanan = [
|
|
'labels' => $labels,
|
|
'data' => $data,
|
|
];
|
|
|
|
// Online books (books with 'online' in tipe_akses)
|
|
$bacaBukuOnline = $loans->filter(function ($loan) {
|
|
return in_array('online', $loan->book->tipe_akses ?? []);
|
|
})->map(fn($loan) => [
|
|
'judul' => $loan->book->judul,
|
|
'penulis' => $loan->book->penulis,
|
|
'progress' => 0, // Placeholder
|
|
'cover' => $loan->book->cover,
|
|
]);
|
|
|
|
$recommendations = Recommendation::all();
|
|
$rekomendasiPembelajaran = $recommendations->map(function ($item) {
|
|
$videoId = $this->extractYouTubeId($item->youtube_link);
|
|
return [
|
|
'id' => $item->id,
|
|
'judul' => $item->judul,
|
|
'kategori' => $item->kategori,
|
|
'thumbnail' => $videoId ? "https://img.youtube.com/vi/{$videoId}/hqdefault.jpg" : 'https://via.placeholder.com/150?text=No+Preview',
|
|
'youtube_link' => $item->youtube_link,
|
|
'deskripsi' => $item->deskripsi,
|
|
];
|
|
});
|
|
|
|
// Dynamic notifications based on loans
|
|
$personalNotif = collect();
|
|
foreach ($bukuPinjamOffline as $buku) {
|
|
if ($buku['sisa_hari'] < 0) {
|
|
$hariTelat = abs($buku['sisa_hari']);
|
|
$denda = $hariTelat * 1000;
|
|
$personalNotif->push([
|
|
'icon' => 'bi-exclamation-octagon-fill',
|
|
'color' => 'danger',
|
|
'title' => 'TERLAMBAT: ' . $buku['judul'],
|
|
'content' => "Telat {$hariTelat} hari. Denda: Rp " . number_format($denda, 0, ',', '.'),
|
|
'time' => 'Sekarang',
|
|
'read' => false,
|
|
'type' => 'denda_active',
|
|
]);
|
|
} elseif ($buku['sisa_hari'] <= 3) {
|
|
$personalNotif->push([
|
|
'icon' => 'bi-exclamation-triangle-fill',
|
|
'color' => 'warning',
|
|
'title' => 'Jatuh Tempo: ' . $buku['judul'],
|
|
'content' => "Sisa waktu tinggal " . $buku['sisa_hari'] . " hari lagi.",
|
|
'time' => 'Segera',
|
|
'read' => false,
|
|
'type' => 'warning_jatuh_tempo',
|
|
]);
|
|
}
|
|
}
|
|
|
|
$personalNotif->push([
|
|
'icon' => 'bi-info-circle-fill',
|
|
'color' => 'primary',
|
|
'title' => 'Selamat Datang!',
|
|
'content' => 'Jelajahi koleksi buku terbaru kami.',
|
|
'time' => 'Baru saja',
|
|
'read' => true,
|
|
'type' => 'info',
|
|
]);
|
|
|
|
$dendaAlert = $personalNotif->where('type', 'denda_active');
|
|
|
|
$hour = date('H');
|
|
$greeting = "Selamat Pagi";
|
|
if ($hour >= 12 && $hour < 15) $greeting = "Selamat Siang";
|
|
elseif ($hour >= 15 && $hour < 18) $greeting = "Selamat Sore";
|
|
elseif ($hour >= 18) $greeting = "Selamat Malam";
|
|
|
|
return view('dashboard', compact(
|
|
'user',
|
|
'stats',
|
|
'pengumuman',
|
|
'pemberitahuan',
|
|
'dendaAlert',
|
|
'progressMembaca',
|
|
'statistikBulanan',
|
|
'bukuPinjamOffline',
|
|
'bacaBukuOnline',
|
|
'greeting',
|
|
'rekomendasiPembelajaran'
|
|
))->with('notifikasi', $personalNotif);
|
|
}
|
|
|
|
private function extractYouTubeId(string $url): ?string
|
|
{
|
|
preg_match('/(v=|vi=|youtu.be\/|embed\/|\/v\/|\?v=|\&v=)(.+?)\b/i', $url, $matches);
|
|
return $matches[2] ?? null;
|
|
}
|
|
} |