import { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { FiSearch, FiPlus, FiSliders } from "react-icons/fi";
import { createRoom } from "../../store/slices/spaceSlice";
import { setActiveRoom } from "../../store/slices/appSlice";
import { getSpaceIconComponent } from "../../constants/spaceIcons";
function RoomItem({
room,
isActive,
onClick,
lastMessage,
lastMessageTime,
unreadCount,
}) {
const [isHovered, setIsHovered] = useState(false);
return (
setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onClick={onClick}
>
{/* Room info */}
{room.name}
{room.is_private && (
Private
)}
{/* Last message time */}
{lastMessageTime && (
{lastMessageTime}
)}
{/* Last message */}
0 ? "var(--text-primary)" : "var(--text-secondary)",
fontWeight: unreadCount > 0 ? 500 : 400,
}}
>
{lastMessage || "Bắt đầu trò chuyện"}
{/* Unread badge */}
{unreadCount > 0 && (
{unreadCount > 99 ? "99+" : unreadCount}
)}
);
}
function LoadingDots() {
return (
);
}
function EmptyState({ isDark, onCreateRoomClick }) {
return (
Chưa có room nào
Tạo room đầu tiên để bắt đầu thảo luận
);
}
function CreateRoomModal({ isOpen, onClose, onCreate, isDark }) {
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [isPrivate, setIsPrivate] = useState(false);
if (!isOpen) return null;
const handleSubmit = (e) => {
e.preventDefault();
if (name.trim()) {
onCreate({
name: name.trim(),
description: description.trim(),
isPrivate,
});
setName("");
setDescription("");
setIsPrivate(false);
onClose();
}
};
return (
);
}
function SpaceRoomList({
activeSpace,
activeRoom,
setActiveRoom,
searchQuery,
setSearchQuery,
onCreateRoomClick,
}) {
const { isDark } = useSelector((state) => state.theme);
const dispatch = useDispatch();
const [isSearching, setIsSearching] = useState(false);
const {
spaces,
roomsMap,
roomsLoading,
fetchedRooms,
roomUnreadCounts,
} = useSelector((state) => state.space);
const currentUser = useSelector((state) => state.auth.user);
const spaceRooms = roomsMap[activeSpace] || [];
const isFetched = fetchedRooms[activeSpace];
// Helper to format last message from API
const getRoomLastMessage = (room) => {
const lastMsg = room.last_message;
if (!lastMsg) return null;
const isOwn =
lastMsg.sender_id &&
currentUser?.id &&
String(lastMsg.sender_id) === String(currentUser.id);
const senderName = isOwn
? "Bạn"
: lastMsg.sender_display_name || lastMsg.username || "Unknown";
return {
content: lastMsg.content,
senderName,
};
};
// Rooms are already fetched globally in App.jsx
// This component only reads from Redux store, no need to fetch here
const filteredRooms = spaceRooms.filter((room) =>
room.name.toLowerCase().includes(searchQuery.toLowerCase()),
);
const handleSearchChange = (e) => {
setSearchQuery(e.target.value);
if (e.target.value.trim()) {
setIsSearching(true);
setTimeout(() => setIsSearching(false), 300);
} else {
setIsSearching(false);
}
};
const handleCreateRoom = (roomData) => {
if (activeSpace) {
dispatch(createRoom({ spaceId: activeSpace, data: roomData }));
}
};
const currentSpace = spaces.find((s) => s.id === activeSpace);
return (
{/* Header */}
{/* Room list */}
{/* Header with create button — always visible */}
Rooms
{(roomsLoading || isSearching) &&
}
{!roomsLoading && !isSearching && filteredRooms.length === 0 && (
)}
{!isSearching && filteredRooms.length > 0 && (
{filteredRooms.map((room) => {
const lastMsg = getRoomLastMessage(room);
return (
setActiveRoom(room.id)}
lastMessage={
lastMsg ? `${lastMsg.senderName}: ${lastMsg.content}` : null
}
unreadCount={roomUnreadCounts[room.id] || 0}
/>
);
})}
)}
);
}
export default SpaceRoomList;