[Valentino Heman Budiarto] 9d4cc8bfed Frontend
2026-02-19 18:14:19 +07:00

208 lines
7.3 KiB
TypeScript

"use client";
import { useState } from "react";
import { Search, Filter, Lightbulb, Projector, Wind } from "lucide-react";
// --- Tipe Data Mock ---
type Room = {
id: number;
name: string;
category: "Teori" | "Laboratorium";
capacity: number;
status: "Available" | "In Use" | "Maintenance";
devices: {
ac: boolean;
lamp: boolean;
projector: boolean;
};
floor: string;
};
// --- Data Dummy Ruangan (Mock Data) ---
const initialRooms: Room[] = [
{
id: 1,
name: "Ruang T-301",
category: "Teori",
capacity: 40,
status: "Available",
devices: { ac: false, lamp: false, projector: false },
floor: "Lantai 3",
},
{
id: 2,
name: "Ruang T-302",
category: "Teori",
capacity: 40,
status: "In Use",
devices: { ac: true, lamp: true, projector: true }, // Sedang dipakai
floor: "Lantai 3",
},
{
id: 3,
name: "Lab. Sistem Kendali",
category: "Laboratorium",
capacity: 20,
status: "Available",
devices: { ac: false, lamp: true, projector: false }, // Mungkin lampunya lupa dimatikan?
floor: "Lantai 2",
},
{
id: 4,
name: "Lab. IoT & Embedded",
category: "Laboratorium",
capacity: 25,
status: "In Use",
devices: { ac: true, lamp: true, projector: false },
floor: "Lantai 2",
},
{
id: 5,
name: "Ruang Sidang TA",
category: "Teori",
capacity: 15,
status: "Maintenance",
devices: { ac: false, lamp: false, projector: false },
floor: "Lantai 1",
},
];
export default function RoomsPage() {
const [rooms] = useState<Room[]>(initialRooms);
const [filterStatus, setFilterStatus] = useState<string>("All");
const [searchQuery, setSearchQuery] = useState("");
// --- Logika Filtering ---
const filteredRooms = rooms.filter((room) => {
// Filter berdasarkan Tab Status (All / Available / In Use)
const matchStatus =
filterStatus === "All" || room.status === filterStatus;
// Filter berdasarkan Search Box (Nama Ruangan)
const matchSearch = room.name
.toLowerCase()
.includes(searchQuery.toLowerCase());
return matchStatus && matchSearch;
});
return (
<div className="space-y-6">
{/* --- HEADER & CONTROLS --- */}
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between bg-white p-6 rounded-xl shadow-sm border border-gray-200">
<div>
<h2 className="text-2xl font-bold text-gray-800">Daftar Ruangan</h2>
<p className="text-sm text-gray-500">
Monitoring status ruangan dan perangkat IoT.
</p>
</div>
<div className="flex flex-col sm:flex-row gap-3">
{/* Search Box */}
<div className="relative">
<input
type="text"
placeholder="Cari ruangan..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-yellow-400 w-full sm:w-64"
/>
<Search className="absolute left-3 top-2.5 text-gray-400" size={18} />
</div>
{/* Filter Dropdown (Sederhana) */}
<div className="flex items-center gap-2 bg-gray-50 px-3 rounded-lg border border-gray-200">
<Filter size={18} className="text-gray-500" />
<select
value={filterStatus}
onChange={(e) => setFilterStatus(e.target.value)}
className="bg-transparent py-2 outline-none text-sm font-medium text-gray-700 cursor-pointer"
>
<option value="All">Semua Status</option>
<option value="Available">Tersedia (Available)</option>
<option value="In Use">Sedang Dipakai (In Use)</option>
<option value="Maintenance">Perbaikan</option>
</select>
</div>
</div>
</div>
{/* --- ROOM GRID --- */}
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
{filteredRooms.map((room) => (
<div
key={room.id}
className={`relative overflow-hidden rounded-xl border bg-white p-6 shadow-sm hover:shadow-md transition-shadow duration-300
${room.status === "In Use" ? "border-blue-200" :
room.status === "Available" ? "border-green-200" : "border-gray-200"}`}
>
{/* Status Badge di Pojok Kanan Atas */}
<span
className={`absolute top-4 right-4 px-3 py-1 rounded-full text-xs font-semibold
${
room.status === "Available"
? "bg-green-100 text-green-700"
: room.status === "In Use"
? "bg-blue-100 text-blue-700"
: "bg-gray-100 text-gray-600"
}`}
>
{room.status}
</span>
{/* Info Utama Ruangan */}
<div className="mb-4">
<h3 className="text-lg font-bold text-gray-800">{room.name}</h3>
<p className="text-xs text-gray-500 uppercase tracking-wider mt-1">
{room.category} {room.floor}
</p>
</div>
<div className="flex items-center gap-2 mb-6">
<span className="text-sm text-gray-600 bg-gray-100 px-2 py-1 rounded">
Kapasitas: {room.capacity} Org
</span>
</div>
{/* Status Perangkat IoT (Visualisasi) */}
<div className="pt-4 border-t border-gray-100">
<p className="text-xs text-gray-400 font-medium mb-3">STATUS PERANGKAT</p>
<div className="flex justify-between gap-2">
{/* AC Status */}
<div className={`flex flex-1 flex-col items-center p-2 rounded-lg text-xs font-medium transition-colors
${room.devices.ac ? "bg-blue-50 text-blue-600" : "bg-gray-50 text-gray-400"}`}>
<Wind size={20} className="mb-1" />
AC {room.devices.ac ? "ON" : "OFF"}
</div>
{/* Lampu Status */}
<div className={`flex flex-1 flex-col items-center p-2 rounded-lg text-xs font-medium transition-colors
${room.devices.lamp ? "bg-yellow-50 text-yellow-600" : "bg-gray-50 text-gray-400"}`}>
<Lightbulb size={20} className="mb-1" />
Light {room.devices.lamp ? "ON" : "OFF"}
</div>
{/* Proyektor Status */}
<div className={`flex flex-1 flex-col items-center p-2 rounded-lg text-xs font-medium transition-colors
${room.devices.projector ? "bg-purple-50 text-purple-600" : "bg-gray-50 text-gray-400"}`}>
<Projector size={20} className="mb-1" />
LCD {room.devices.projector ? "ON" : "OFF"}
</div>
</div>
</div>
</div>
))}
</div>
{/* Empty State jika filter tidak menemukan hasil */}
{filteredRooms.length === 0 && (
<div className="text-center py-20 bg-gray-50 rounded-xl border-dashed border-2 border-gray-200">
<p className="text-gray-500">Tidak ada ruangan yang cocok dengan filter Anda.</p>
</div>
)}
</div>
);
}