From 9141b48056bb3a99756936e7d79f676e9789cbf4 Mon Sep 17 00:00:00 2001 From: "[Valentino Heman Budiarto]" <[hemanvalentino@gmail.com]> Date: Mon, 22 Jun 2026 16:19:20 +0700 Subject: [PATCH] . --- frontend/app/admin/page.tsx | 88 +++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 28 deletions(-) diff --git a/frontend/app/admin/page.tsx b/frontend/app/admin/page.tsx index 94c8d93..97c4921 100644 --- a/frontend/app/admin/page.tsx +++ b/frontend/app/admin/page.tsx @@ -8,37 +8,59 @@ export default function AdminDashboard() { const [pendingBookings, setPendingBookings] = useState([]); const [roomStats, setRoomStats] = useState([]); const [loading, setLoading] = useState(true); + + // STATE BARU: Penampung total daya asli khusus Kelas D101 + const [d101Power, setD101Power] = useState(0); useEffect(() => { fetchAdminData(); - // Refresh data konsumsi daya setiap 10 detik agar terlihat real-time - const interval = setInterval(fetchAdminData, 10000); - return () => clearInterval(interval); + fetchD101Power(); // Panggil fungsi daya saat pertama kali render + + // Refresh data ruangan setiap 10 detik + const intervalAdmin = setInterval(fetchAdminData, 10000); + // Refresh data konsumsi daya D101 lebih cepat (tiap 5 detik) agar sangat responsif + const intervalPower = setInterval(fetchD101Power, 5000); + + return () => { + clearInterval(intervalAdmin); + clearInterval(intervalPower); + }; }, []); + // FUNGSI BARU: Mengambil data asli dari Smart Meter via Golang API + const fetchD101Power = async () => { + try { + const res = await axios.get("http://172.17.172.17:8080/api/power-status"); + // Kalkulasi total seluruh alat (Lampu/Proyektor + AC 1 + AC 2) + const totalWatt = (res.data.umum || 0) + (res.data.ac1 || 0) + (res.data.ac2 || 0); + setD101Power(parseFloat(totalWatt.toFixed(1))); + } catch (err) { + console.error("Gagal mengambil data daya aktual D101", err); + } + }; + const fetchAdminData = async () => { try { const token = localStorage.getItem("token"); - // 1. Ambil SEMUA booking pakai endpoint yang sudah ada, lalu filter di Frontend + // 1. Ambil SEMUA booking const bookRes = await axios.get("http://172.17.172.17:8080/api/bookings", { headers: { Authorization: `Bearer ${token}` } }); const allBookings = bookRes.data.data || []; - // Saring hanya yang statusnya "Pending" atau kosong const pendingOnly = allBookings.filter((b: any) => b.status === "Pending" || !b.status); setPendingBookings(pendingOnly); - // 2. Ambil daftar ruangan biasa, lalu kita sisipkan "Dummy Power" untuk UI + // 2. Ambil daftar ruangan const roomRes = await axios.get("http://172.17.172.17:8080/api/rooms", { headers: { Authorization: `Bearer ${token}` } }); const roomsWithDummyPower = (roomRes.data.data || []).map((room: any) => ({ ...room, - // Simulasi daya acak antara 0 sampai 15 Watt untuk keperluan UI - power_consumption: Math.floor(Math.random() * 15) + // Berikan simulasi dummy HANYA untuk ruangan SELAIN D101 + power_consumption: room.name === "Kelas D101" ? 0 : Math.floor(Math.random() * 15) })); setRoomStats(roomsWithDummyPower); @@ -49,17 +71,15 @@ export default function AdminDashboard() { } }; - // PERBAIKAN 1: Ubah tipe id menjadi 'string' karena kita menggunakan UUID const handleAction = async (id: string, status: string) => { try { const token = localStorage.getItem("token"); - // Mengirim status 'Approved' atau 'Rejected' ke backend await axios.put(`http://172.17.172.17:8080/api/bookings/${id}/status`, { status: status }, { headers: { Authorization: `Bearer ${token}` } } ); alert(`Permintaan berhasil di-${status}`); - fetchAdminData(); // Refresh data setelah aksi + fetchAdminData(); } catch (err: any) { console.error(err); alert("Gagal memproses pendaftaran."); @@ -76,22 +96,37 @@ export default function AdminDashboard() { Real-time Room Energy
- {/* TAMBAHKAN PENGURUTAN ABJAD DI SINI */} {[...roomStats] .sort((a, b) => a.name.localeCompare(b.name)) - .map((room) => ( -
-
- {room.name} -
5 ? 'bg-orange-500 animate-pulse' : 'bg-gray-300'}`} /> -
-
- {room.power_consumption || 0} - Watts -
-

Last updated: Just now

-
- ))} + .map((room) => { + // LOGIKA INJEKSI DATA ASLI: Cek apakah kelas ini adalah D101 + const isD101 = room.name === "Kelas D101"; + const displayedPower = isD101 ? d101Power : room.power_consumption; + const isPowerActive = displayedPower > 0; + + return ( +
+ +
+ + {room.name} {isD101 && SENSOR ASLI} + +
+
+ +
+ + {displayedPower} + + Watts +
+ +

Last updated: Just now

+
+ ); + })}
@@ -116,12 +151,10 @@ export default function AdminDashboard() { {pendingBookings.map((b) => ( - // PERBAIKAN 2: Gunakan booking_id sebagai key {b.user?.full_name || "Tanpa Nama"} {b.room?.name || "Ruangan Tidak Diketahui"} - {/* PERBAIKAN 3: Format Waktu Mulai dan Selesai yang Rapi */}
{new Date(b.start_time).toLocaleTimeString('id-ID', {hour: '2-digit', minute:'2-digit'})} - {new Date(b.end_time).toLocaleTimeString('id-ID', {hour: '2-digit', minute:'2-digit'})} @@ -134,7 +167,6 @@ export default function AdminDashboard() { {b.purpose}
- {/* PERBAIKAN 4: Gunakan b.booking_id di fungsi onClick */}