import type { Metadata } from "next"; import Link from "next/link"; import { redirect } from "next/navigation"; import { caseKinds } from "@/components/cases"; import { ActionForm, SubmitButton } from "@/components/forms"; import { PageHeader } from "@/components/status"; import { DateTime } from "@/components/time"; import { buttonVariants } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { api, getMe, unwrap, type NotificationEntry } from "@/lib/api"; import { cn } from "@/lib/utils"; import { markAllRead } from "../console/cases/actions"; export const metadata: Metadata = { title: "Notifications" }; export default async function Notifications({ searchParams }: { searchParams: Promise<{ before?: string | string[] }> }) { const me = await getMe(); if (!me) redirect("/signin?next=/notifications"); const raw = (await searchParams).before; const before = typeof raw === "string" && /^\d+$/.test(raw) ? Number(raw) : undefined; const data = unwrap(await api.notifications.get({ query: before ? { before } : {} })); return ( <>
{data.unread > 0 ? `${data.unread} unread.` : "You're up to date."} {data.unread > 0 && ( Mark all as read )}
{data.notifications.length === 0 ? (

Nothing yet.

) : ( )}
{data.before && (
Older
)} ); } /** A notification in words, and where it leads. */ function describe(n: NotificationEntry): { text: string; href?: string } { const d = n.data as Record; const s = (k: string) => (typeof d[k] === "string" ? (d[k] as string) : ""); const why = s("reason") ? `: “${s("reason")}”` : ""; switch (n.type) { case "product_edited": { const what = s("kind") === "lock" ? "changed the locks on" : s("kind") === "revert" ? "undid a change to" : `changed the ${(d.fields as string[] | undefined)?.join(", ") ?? "info"} of`; return { text: `${s("by") || "A moderator"} ${what} ${s("name")}${why}`, href: `/products/${s("product")}/edit` }; } case "product_removed": return { text: `Moderation removed ${s("name")}${why}. You can appeal it from your audit log.`, href: `/console/audit?product=${s("product")}` }; case "product_restored": return { text: `Moderation restored ${s("name")}${why}`, href: `/products/${s("product")}` }; case "case_decided": { const status = s("status") === "resolved" ? "resolved" : "declined"; const res = s("resolution") ? `: “${s("resolution")}”` : ""; return { text: `Your ${caseKinds[s("kind")]?.toLowerCase() ?? "case"} was ${status}${res}`, href: `/console/cases/${d.case}` }; } case "case_note": return { text: `${s("by") || "Someone"} replied on your ${caseKinds[s("kind")]?.toLowerCase() ?? "case"}`, href: `/console/cases/${d.case}` }; case "membership_decided": { const status = s("status"); const text = status === "member" ? `You're a member of ${s("name")}` : status === "banned" ? `${s("name")} banned you` : `${s("name")} declined your request to join`; return { text, href: `/catalogs/${s("catalog")}` }; } default: return { text: n.type }; } }