diff --git a/backend/social/chat/consumers.py b/backend/social/chat/consumers.py index 077faf0..be15191 100644 --- a/backend/social/chat/consumers.py +++ b/backend/social/chat/consumers.py @@ -84,7 +84,8 @@ class ChatConsumer(AsyncWebsocketConsumer): "message_id": data["message_id"], "emoji": data["emoji"], "user": user.username, - "action": action, # 'added' | 'removed' | 'switched' + "user_id": user.id, + "action": action, }) elif msg_type == "typing": @@ -158,6 +159,7 @@ class ChatConsumer(AsyncWebsocketConsumer): "message_id": event["message_id"], "emoji": event["emoji"], "user": event["user"], + "user_id": event["user_id"], "action": event["action"], })) diff --git a/frontend/src/components/social/EmojiPicker.tsx b/frontend/src/components/social/EmojiPicker.tsx new file mode 100644 index 0000000..2574682 --- /dev/null +++ b/frontend/src/components/social/EmojiPicker.tsx @@ -0,0 +1,42 @@ +import { useEffect, useRef } from "react"; + +const EMOJIS = ["๐Ÿ‘", "โค๏ธ", "๐Ÿ˜‚", "๐Ÿ˜ฎ", "๐Ÿ˜ข", "๐Ÿ”ฅ", "๐Ÿ‘", "๐ŸŽ‰"]; + +interface Props { + onSelect: (emoji: string) => void; + onClose: () => void; + className?: string; +} + +export default function EmojiPicker({ onSelect, onClose, className }: Props) { + const ref = useRef(null); + + useEffect(() => { + function handleOutside(e: MouseEvent) { + if (ref.current && !ref.current.contains(e.target as Node)) onClose(); + } + document.addEventListener("mousedown", handleOutside); + return () => document.removeEventListener("mousedown", handleOutside); + }, [onClose]); + + return ( +
+ {EMOJIS.map((e) => ( + + ))} +
+ ); +} diff --git a/frontend/src/components/social/chat/ChatMediaGallery.tsx b/frontend/src/components/social/chat/ChatMediaGallery.tsx index 86a5e0f..7ea5371 100644 --- a/frontend/src/components/social/chat/ChatMediaGallery.tsx +++ b/frontend/src/components/social/chat/ChatMediaGallery.tsx @@ -122,6 +122,7 @@ function ChatLightboxContent({ file }: { file: MessageFile }) {