import { useState, useMemo } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Building2, Monitor, ChevronDown, ChevronRight, Loader2 } from "lucide-react"; import type { Room } from "@/types/room"; import type { DeviceHealthCheck } from "@/types/device"; interface DeviceSearchDialogProps { open: boolean; onClose: () => void; rooms: Room[]; onSelect: (deviceIds: string[]) => void; fetchDevices: (roomName: string) => Promise; // API fetch } export function DeviceSearchDialog({ open, onClose, rooms, onSelect, fetchDevices, }: DeviceSearchDialogProps) { const [selected, setSelected] = useState([]); const [expandedRoom, setExpandedRoom] = useState(null); const [roomDevices, setRoomDevices] = useState>({}); const [loadingRoom, setLoadingRoom] = useState(null); const [searchQuery, setSearchQuery] = useState(""); const sortedRooms = useMemo(() => { return [...rooms].sort((a, b) => { const nameA = typeof a.name === "string" ? a.name : ""; const nameB = typeof b.name === "string" ? b.name : ""; return nameA.localeCompare(nameB); }); }, [rooms]); const filteredRooms = useMemo(() => { if (!searchQuery) return sortedRooms; return sortedRooms.filter(room => room.name.toLowerCase().includes(searchQuery.toLowerCase()) ); }, [sortedRooms, searchQuery]); const handleRoomClick = async (roomName: string) => { // Nếu đang mở thì đóng lại if (expandedRoom === roomName) { setExpandedRoom(null); return; } // Nếu chưa fetch devices của room này thì gọi API if (!roomDevices[roomName]) { setLoadingRoom(roomName); try { const devices = await fetchDevices(roomName); setRoomDevices(prev => ({ ...prev, [roomName]: devices })); setExpandedRoom(roomName); } catch (error) { console.error("Failed to fetch devices:", error); // Có thể thêm toast notification ở đây } finally { setLoadingRoom(null); } } else { // Đã có data rồi thì chỉ toggle setExpandedRoom(roomName); } }; const toggleDevice = (deviceId: string) => { setSelected((prev) => prev.includes(deviceId) ? prev.filter((id) => id !== deviceId) : [...prev, deviceId] ); }; const toggleAllInRoom = (roomName: string) => { const devices = roomDevices[roomName] || []; const deviceIds = devices.map(d => d.id); const allSelected = deviceIds.every(id => selected.includes(id)); if (allSelected) { setSelected(prev => prev.filter(id => !deviceIds.includes(id))); } else { setSelected(prev => [...new Set([...prev, ...deviceIds])]); } }; const handleConfirm = () => { onSelect(selected); setSelected([]); setExpandedRoom(null); setRoomDevices({}); setSearchQuery(""); onClose(); }; const handleClose = () => { setSelected([]); setExpandedRoom(null); setRoomDevices({}); setSearchQuery(""); onClose(); }; return ( Chọn thiết bị {/* Search bar */} setSearchQuery(e.target.value)} className="my-2" /> {/* Room list */}
{filteredRooms.length === 0 && (

Không tìm thấy phòng

)} {filteredRooms.map((room) => { const isExpanded = expandedRoom === room.name; const isLoading = loadingRoom === room.name; const devices = roomDevices[room.name] || []; const allSelected = devices.length > 0 && devices.every(d => selected.includes(d.id)); const someSelected = devices.some(d => selected.includes(d.id)); const selectedCount = devices.filter(d => selected.includes(d.id)).length; return (
{/* Room header - clickable */}
handleRoomClick(room.name)} > {/* Expand icon or loading */} {isLoading ? ( ) : isExpanded ? ( ) : ( )} {/* Select all checkbox - chỉ hiện khi đã load devices */} {devices.length > 0 && ( { toggleAllInRoom(room.name); }} onClick={(e) => e.stopPropagation()} className={someSelected && !allSelected ? "opacity-50" : ""} /> )} {room.name}
{selectedCount > 0 && ( {selectedCount}/ )} {room.numberOfDevices} thiết bị {room.numberOfOfflineDevices > 0 && ( {room.numberOfOfflineDevices} offline )}
{/* Device table - collapsible */} {isExpanded && devices.length > 0 && (
{devices.map((device) => ( ))}
Thiết bị IP Address MAC Address Version Trạng thái
toggleDevice(device.id)} />
{device.id}
{device.networkInfos[0]?.ipAddress || "-"} {device.networkInfos[0]?.macAddress || "-"} {device.version ? ( v{device.version} ) : ( "-" )} {device.isOffline ? ( Offline ) : ( Online )}
)}
); })}
{/* Selected count */} {selected.length > 0 && (
Đã chọn: {selected.length} thiết bị
)} {/* Actions */}
); }