import { useState, useCallback, useEffect } from 'react'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { cn } from '@/lib/utils'; import { SmilePlus } from 'lucide-react'; import { client } from '@/client/client.gen'; interface ReactionGroup { emoji: string; count: number; reacted_by_me: boolean; users: string[]; } interface RoomMessageReactionsProps { roomId: string; messageId: string; className?: string; } const COMMON_EMOJIS = [ '👍', '👎', '❤️', '😂', '😮', '😢', '🎉', '🚀', '✅', '⭐', '🔥', '💯', '👀', '🙏', '💪', '🤔', ]; export function RoomMessageReactions({ roomId, messageId, className, }: RoomMessageReactionsProps) { const [reactions, setReactions] = useState([]); const [isOpen, setIsOpen] = useState(false); useEffect(() => { loadReactions(); }, [messageId]); const loadReactions = useCallback(async () => { try { const resp = await client.get({ url: `/api/rooms/${roomId}/messages/${messageId}/reactions`, }); const data = (resp.data as any)?.data as { reactions: ReactionGroup[] } | undefined; if (data) { setReactions(data.reactions); } } catch (err) { console.error('Failed to load reactions:', err); } }, [roomId, messageId]); const handleReaction = useCallback(async (emoji: string) => { try { const existingReaction = reactions.find(r => r.emoji === emoji); if (existingReaction?.reacted_by_me) { await client.delete({ url: `/api/rooms/${roomId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}`, }); } else { await client.post({ url: `/api/rooms/${roomId}/messages/${messageId}/reactions`, body: { emoji }, }); } await loadReactions(); } catch (err) { console.error('Failed to update reaction:', err); } finally { setIsOpen(false); } }, [roomId, messageId, reactions, loadReactions]); // Compact inline reaction bar return (
{reactions.map((reaction) => ( ))}
); } interface EmojiPickerProps { onEmojiSelect: (emoji: string) => void; } function EmojiPicker({ onEmojiSelect }: EmojiPickerProps) { return (
{COMMON_EMOJIS.map((emoji) => ( ))}
); }