"use client"; import { useEffect, useState } from "react"; import Link from "next/link"; import { RefreshCwIcon } from "lucide-react"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"; import { FuzzyCombobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList } from "@/components/ui/combobox"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Empty, EmptyHeader, EmptyTitle, EmptyDescription } from "@/components/ui/empty"; import { Table, TableBody, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import type { CommentPage } from "@/lib/comments/types"; import { characterRarityGradientClass } from "@/lib/catalog/rarity"; import { cn } from "@/lib/utils"; import { useMarkCommentsRead } from "./admin-unread-comments"; import { CommentCard, CommentThread } from "./comment-card"; import { AdminCommentRowsSkeleton } from "./comment-skeleton"; import { useCommentEvents } from "./use-comment-events"; import { useCommentFeed } from "./use-comment-feed"; type TargetOption = { value: string; label: string; image: string | null; rarity: number | null; characterKey: string | null }; export function AdminCommentInbox({ initial, targets, initialTarget, initialComment }: { initial: CommentPage; targets: TargetOption[]; initialTarget?: string; initialComment?: string }) { const [target, setTarget] = useState(targets.find((item) => item.value === initialTarget) ?? null); const [status, setStatus] = useState("all"); const [answered, setAnswered] = useState("all"); const query = new URLSearchParams({ view: "inbox", grouped: "true", status, unanswered: String(answered === "unanswered") }); if (target) query.set("target", target.value); const feed = useCommentFeed(`/api/admin/comments?${query}`, initial); useCommentEvents({ admin: true }, () => feed.refresh({ silent: true, forceRevision: true })); const markRead = useMarkCommentsRead(); useEffect(() => { void markRead(target?.value ?? "all"); }, [markRead, target, feed.revision]); return
{initialComment && initialTarget &&

การสนทนาจากการแจ้งเตือน

feed.refresh({ silent: true })} />
} ไกด์หรือรอบ Stygian item.label} itemToStringValue={(item) => item.value} searchNames={(item) => [item.label]} autoHighlight> ไม่พบไกด์ที่ตรงกัน{(item: TargetOption) => {item.label.slice(0, 2)}{item.label}} การแสดงผล { if (values[0]) setStatus(values[0]); }} variant="outline" aria-label="กรองการแสดงผลความคิดเห็น"> ทั้งหมดแสดงอยู่ซ่อนอยู่ การตอบกลับจากผู้ดูแล { if (values[0]) setAnswered(values[0]); }} variant="outline" aria-label="กรองการตอบกลับจากผู้ดูแล"> ทุกความคิดเห็นยังไม่ได้ตอบ {feed.error && {feed.error}} {feed.page.items.length > 0 &&
ความคิดเห็น เนื้อหา {feed.page.items.map((item) => feed.refresh({ silent: true, forceRevision: true })} revision={feed.revision} overview={item.target.startsWith("stygian:") ? {item.targetName} : item.targetImage && {/* eslint-disable-next-line @next/next/no-img-element */} {`ภาพ } />)}
} {!feed.page.items.length && !feed.busy && !feed.error && ไม่พบความคิดเห็นที่ตรงกันความคิดเห็นจากทุกไกด์และทุกรอบ Stygian จะแสดงที่นี่} {feed.busy && } {feed.page.nextCursor && }
; }