diff --git a/frontend/src/components/ChatHeader.jsx b/frontend/src/components/ChatHeader.jsx index 46a810a..9688dff 100644 --- a/frontend/src/components/ChatHeader.jsx +++ b/frontend/src/components/ChatHeader.jsx @@ -10,6 +10,7 @@ import { Image, Trash, Search, + Users, } from "lucide-react"; import { useState, useRef, useEffect } from "react"; import { motion, AnimatePresence } from "framer-motion"; @@ -18,6 +19,16 @@ import { useChatStore } from "../store/useChatStore"; import GroupMembersModal from "./GroupMembersModal"; import { useCallStore } from "../store/useCallStore"; +const IconBtn = ({ children, onClick, ...props }) => ( + +); + const ChatHeader = () => { const { selectedUser, @@ -39,21 +50,41 @@ const ChatHeader = () => { const { authUser } = useAuthStore(); const { startCall, startGroupCall } = useCallStore(); + const [showInfoPanel, setShowInfoPanel] = useState(false); + const infoRef = useRef(null); const [showMembers, setShowMembers] = useState(false); const [openMenu, setOpenMenu] = useState(false); const [showSearch, setShowSearch] = useState(false); const menuRef = useRef(null); - useEffect(() => { - const handleClickOutside = (e) => { - if (menuRef.current && !menuRef.current.contains(e.target)) { - setOpenMenu(false); - } - }; - document.addEventListener("mousedown", handleClickOutside); - return () => document.removeEventListener("mousedown", handleClickOutside); - }, []); + +useEffect(() => { + const handleClickOutside = (e) => { + if (menuRef.current && !menuRef.current.contains(e.target)) { + setOpenMenu(false); + } + if (infoRef.current && !infoRef.current.contains(e.target)) { + setShowInfoPanel(false); + } + }; + + const handleKeyDown = (e) => { + if (e.key === "Escape") { + setShowInfoPanel(false); + setOpenMenu(false); + setShowSearch(false); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + document.addEventListener("keydown", handleKeyDown); + + return () => { + document.removeEventListener("mousedown", handleClickOutside); + document.removeEventListener("keydown", handleKeyDown); + }; +}, []); if (!selectedUser && !selectedGroup) return null; const isGroup = selectedChatType === "group"; @@ -110,6 +141,7 @@ const ChatHeader = () => { await removeChatWallpaper(chatId); setOpenMenu(false); }; + return (
@@ -215,61 +247,117 @@ const ChatHeader = () => {
-
- {isGroup ? ( - <> - setShowMembers(true)}> - - - - startGroupCall({ - groupId: selectedGroup._id, - callType: "voice", - }) - } - > - - - - startGroupCall({ - groupId: selectedGroup._id, - callType: "video", - }) - } - > - - - ) : ( - !isAI && ( - <> - - startCall({ - receiver: selectedUser, - callType: "voice", - }) - } - > - - - - startCall({ - receiver: selectedUser, - callType: "video", - }) - } - > - - - ) - )} + + {!isAI && ( +
+ + setShowInfoPanel(v => !v)} aria-label="Open chat info"> + + + + + {showInfoPanel && ( + <> +
setShowInfoPanel(false)} + /> + + {/* Header info */} +
+ {isGroup ? ( +
+ + {selectedGroup.name[0]?.toUpperCase()} + +
+ ) : ( +
+ + {onlineUsers.includes(selectedUser?._id) && ( + + )} +
+ )} +
+

+ {isGroup ? selectedGroup.name : selectedUser.fullName} +

+

+ {isGroup + ? `${selectedGroup.members?.length || 0} members` + : onlineUsers.includes(selectedUser?._id) + ? "Active now" + : "Offline"} +

+
+ + {/* Action buttons */} +
+ + + + {isGroup && ( + + )} +
+
+ + )} + +
+ )} {/*SEARCH */}
setShowSearch((s) => !s)}> @@ -315,8 +403,7 @@ const ChatHeader = () => { > - - + {openMenu && ( { Change Wallpaper -
); }; -const IconBtn = ({ children, onClick }) => ( - -); + + export default ChatHeader;