"use client"; import { useEffect, useState } from "react"; import axios from "axios"; import { CalendarDays, MapPin, Clock, ChevronLeft, ChevronRight, Calendar as CalendarIcon } from "lucide-react"; export default function CalendarViewPage() { const [bookings, setBookings] = useState([]); const [rooms, setRooms] = useState([]); const [loading, setLoading] = useState(true); // --- STATE UNTUK NAVIGASI MINGGU --- const [startDate, setStartDate] = useState(() => { const d = new Date(); d.setHours(0, 0, 0, 0); return d; }); // Generate 7 Hari ke depan berdasarkan startDate const weekDates = Array.from({ length: 7 }).map((_, i) => { const d = new Date(startDate); d.setDate(startDate.getDate() + i); return d; }); // FORMAT RENTANG TANGGAL const firstDay = weekDates[0].toLocaleDateString('id-ID', { day: 'numeric', month: 'short' }); const lastDay = weekDates[6].toLocaleDateString('id-ID', { day: 'numeric', month: 'short', year: 'numeric' }); const dateRangeLabel = `${firstDay} - ${lastDay}`; // Fungsi Navigasi const goToPreviousWeek = () => { setStartDate(prev => { const newDate = new Date(prev); newDate.setDate(prev.getDate() - 7); return newDate; }); }; const goToNextWeek = () => { setStartDate(prev => { const newDate = new Date(prev); newDate.setDate(prev.getDate() + 7); return newDate; }); }; const goToToday = () => { const d = new Date(); d.setHours(0, 0, 0, 0); setStartDate(d); }; // ------------------------------------------ useEffect(() => { const fetchData = async () => { try { const token = localStorage.getItem("token"); const [roomsRes, bookingsRes] = await Promise.all([ axios.get("http://localhost:8080/api/rooms", { headers: { Authorization: `Bearer ${token}` } }), axios.get("http://localhost:8080/api/bookings", { headers: { Authorization: `Bearer ${token}` } }) ]); setRooms(roomsRes.data.data || []); setBookings(bookingsRes.data.data || []); } catch (error) { console.error("Gagal memuat data", error); } finally { setLoading(false); } }; fetchData(); }, []); // Fungsi memfilter booking const getBookingsForCell = (roomId: number, dateObj: Date) => { return bookings.filter(b => { if (b.room_id !== roomId) return false; const bDate = new Date(b.start_time); return ( bDate.getDate() === dateObj.getDate() && bDate.getMonth() === dateObj.getMonth() && bDate.getFullYear() === dateObj.getFullYear() ); }); }; // Format Jam const formatTime = (isoString: string) => { return new Date(isoString).toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit' }); }; if (loading) return
Menyusun matriks jadwal...
; return (
{/* HEADER & NAVIGASI */}

Weekly Calendar View

Pantau kepadatan jadwal ruangan S-CLASS.

{/* Kontrol Navigasi Minggu */}
{/* TULISAN RENTANG TANGGAL DINAMIS (Lebar Fix w-44 untuk menghilangkan warning Tailwind) */}
{/* Pembungkus Tabel */}
{/* Lebar tabel dipertahankan menggunakan min-w-[1000px] karena ini ukuran presisi khusus */} {/* HEADER TABEL: Sumbu X (Tanggal) */} {weekDates.map((date, idx) => ( ))} {/* BODY TABEL: Sumbu Y (Ruangan) */} {/* --- DAFTAR RUANGAN YANG SUDAH DIURUTKAN --- */} {[...rooms] .sort((a, b) => a.name.localeCompare(b.name)) .map((room) => ( {/* (Kodingan untuk kolom hari dan jadwal peminjamanmu biarkan tetap berada di bawah sini) */} {weekDates.map((date, idx) => { const dailyBookings = getBookingsForCell(room.room_id, date); return ( ); })} ))}
Ruangan
{date.toLocaleDateString('id-ID', { weekday: 'long' })}
{date.toLocaleDateString('id-ID', { day: 'numeric', month: 'short', year: 'numeric' })}
{room.name}
{room.category}
{dailyBookings.length > 0 ? (
{dailyBookings // 1. FILTER: Hanya tampilkan yang Pending atau Approved .filter((b) => b.status === "Pending" || b.status === "Approved") // 2. SORT: Urutkan berdasarkan waktu mulai (dari pagi ke malam) .sort((a, b) => new Date(a.start_time).getTime() - new Date(b.start_time).getTime()) // 3. MAP: Render ke layar .map((b) => (

{b.purpose}

{formatTime(b.start_time)} - {formatTime(b.end_time)} {b.status || 'Pending'}
))}
) : (
-
)}
); }