"use client" import * as React from "react" import { formatDistanceToNow, format, parseISO } from "date-fns" import { IconPin, IconPinnedOff, IconLoader2 } from "@tabler/icons-react" import { Sheet, SheetContent, SheetHeader, SheetTitle, } from "@/components/ui/sheet" import { Button } from "@/components/ui/button" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { ScrollArea } from "@/components/ui/scroll-area" import { getPinnedMessages, unpinMessage } from "@/app/actions/message-search" type PinnedMessage = { id: string channelId: string threadId: string | null content: string contentHtml: string | null editedAt: string | null isPinned: boolean replyCount: number lastReplyAt: string | null createdAt: string user: { id: string displayName: string | null email: string avatarUrl: string | null } | null } type PinnedMessagesPanelProps = { channelId: string isOpen: boolean onClose: () => void onJumpToMessage?: (messageId: string) => void } export function PinnedMessagesPanel({ channelId, isOpen, onClose, onJumpToMessage, }: PinnedMessagesPanelProps) { const [messages, setMessages] = React.useState([]) const [isLoading, setIsLoading] = React.useState(false) const [error, setError] = React.useState(null) const [unpinningId, setUnpinningId] = React.useState(null) // fetch pinned messages when panel opens React.useEffect(() => { async function fetchPinned() { if (!isOpen || !channelId) return setIsLoading(true) setError(null) const result = await getPinnedMessages(channelId) if (result.success) { setMessages(result.data as PinnedMessage[]) } else { setError(result.error) setMessages([]) } setIsLoading(false) } fetchPinned() }, [channelId, isOpen]) const handleUnpin = async (messageId: string) => { setUnpinningId(messageId) const result = await unpinMessage(messageId) setUnpinningId(null) if (result.success) { setMessages((prev) => prev.filter((m) => m.id !== messageId)) } else { // show error briefly - could use toast here console.error("Failed to unpin:", result.error) } } const handleMessageClick = (message: PinnedMessage) => { if (onJumpToMessage) { onJumpToMessage(message.id) onClose() } } return ( !open && onClose()}> Pinned Messages {isLoading && (
)} {error && (
{error}
)} {!isLoading && !error && messages.length === 0 && (

No pinned messages in this channel

Important messages can be pinned for easy reference

)} {!isLoading && !error && messages.length > 0 && (
{messages.map((message) => { const displayName = message.user?.displayName ?? message.user?.email?.split("@")[0] ?? "Unknown User" const avatarFallback = displayName.substring(0, 2).toUpperCase() const timestamp = parseISO(message.createdAt) const isRecent = Date.now() - timestamp.getTime() < 24 * 60 * 60 * 1000 const timeDisplay = isRecent ? formatDistanceToNow(timestamp, { addSuffix: true }) : format(timestamp, "MMM d, yyyy 'at' h:mm a") return (
{message.user?.avatarUrl && ( )} {avatarFallback}
{displayName}
{timeDisplay} {message.editedAt && ( (edited) )}
) })}
)}
) }