"use client"; import type { MessagePage, SuggestionDetail, SuggestionMessage } from "@/lib/discord/suggestion-types"; import { SuggestionBadges, SuggestionFailure, SuggestionLoading, SuggestionPagination, suggestionControl, useSuggestionRead, useSuggestionPages, type SuggestionPaging } from "./suggestion-shared"; export function SuggestionReader({ id }: { id: string }) { const { data, error, retry } = useSuggestionRead(`/api/suggestions/${id}`); if (error) return ; if (!data) return Loading suggestion…; return <>

Community proposal / Read-only

{data.title}

Thread / {data.id}

Open in Discord

Original suggestion

{data.originalPost ? :

The original post was deleted or is unavailable.

}

Discord remains the source of truth. Open Discord for attachments, formatting, replies, and reactions. Message text may be unavailable if the bot lacks Message Content access.

; } function Discussion({ id }: { id: string }) { const paging = useSuggestionPages(); const query = new URLSearchParams({ limit: "25" }); if (paging.cursor) query.set("cursor", paging.cursor); const url = `/api/suggestions/${id}/messages?${query}`; return

Discussion

Newest messages first / Read-only

; } function DiscussionPage({ id, url, paging }: { id: string; url: string; paging: SuggestionPaging }) { const { data, error, retry } = useSuggestionRead(url); if (error) return ; if (!data) return Loading discussion…; const replies = data.items.filter((message) => message.id !== id); return <>
{replies.map((message) => )} {!replies.length &&

No replies on this page.

}
; } function MessageCard({ message }: { message: SuggestionMessage }) { return

{message.author.name}

{message.content || "No text was returned. View this message in Discord."}

{message.editedAt &&

Edited

} {!!message.reactions.length &&
    {message.reactions.map((reaction, index) =>
  • {reaction.emoji} {reaction.count}
  • )}
}
; }