From 14d92bf2770b775d4c4211ef24e482464d550389 Mon Sep 17 00:00:00 2001 From: Z8MB1E Date: Sun, 16 Aug 2026 18:12:40 -0400 Subject: [PATCH] feat(helpdesk): add helpdesk pages Add the helpdesk list page and ticket detail page routes. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/app/(frontend)/helpdesk/[id]/page.tsx | 83 +++++++++++++++++++++++ src/app/(frontend)/helpdesk/page.tsx | 47 +++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 src/app/(frontend)/helpdesk/[id]/page.tsx create mode 100644 src/app/(frontend)/helpdesk/page.tsx diff --git a/src/app/(frontend)/helpdesk/[id]/page.tsx b/src/app/(frontend)/helpdesk/[id]/page.tsx new file mode 100644 index 0000000..a50dbb2 --- /dev/null +++ b/src/app/(frontend)/helpdesk/[id]/page.tsx @@ -0,0 +1,83 @@ +import config from "@payload-config"; +import { headers as nextHeaders } from "next/headers"; +import { notFound, redirect } from "next/navigation"; +import { getPayload } from "payload"; +import type { Ticket } from "@/payload-types"; +import { TicketDetail } from "@/components/frontend/helpdesk/TicketDetail"; +import hasRoles from "@/utils/access-control/hasRoles"; +import { ArrowLeftIcon, LifeBuoyIcon } from "lucide-react"; +import Link from "next/link"; + +export const metadata = { + title: "Ticket — Polaris Task Force", +}; + +interface TicketPageProps { + params: Promise<{ id: string }>; +} + +export default async function TicketPage({ params }: TicketPageProps) { + const { id } = await params; + const payload = await getPayload({ config }); + const { user } = await payload.auth({ + headers: await nextHeaders(), + canSetHeaders: false, + }); + + if (!user) { + redirect("/login"); + } + + const ticket = await payload + .findByID({ + collection: "tickets", + id: Number(id), + depth: 2, + }) + .catch(() => null); + + if (!ticket) { + notFound(); + } + + const typedTicket = ticket as unknown as Ticket; + const isStaff = hasRoles(["admin", "developer"], user); + const assigneeOptions = isStaff + ? ( + await payload.find({ + collection: "users", + sort: "username", + limit: 100, + depth: 0, + }) + ).docs.map((staffUser) => ({ + id: staffUser.id, + label: staffUser.payloadDisplayName || staffUser.username, + })) + : []; + + return ( +
+
+ + + Helpdesk + +
+ +

Ticket #{typedTicket.id}

+
+
+ + +
+ ); +} diff --git a/src/app/(frontend)/helpdesk/page.tsx b/src/app/(frontend)/helpdesk/page.tsx new file mode 100644 index 0000000..75ce25c --- /dev/null +++ b/src/app/(frontend)/helpdesk/page.tsx @@ -0,0 +1,47 @@ +import config from "@payload-config"; +import { headers as nextHeaders } from "next/headers"; +import { redirect } from "next/navigation"; +import { getPayload } from "payload"; +import type { Ticket } from "@/payload-types"; +import { TicketsView } from "@/components/frontend/helpdesk/TicketsView"; +import hasRoles from "@/utils/access-control/hasRoles"; +import { LifeBuoyIcon } from "lucide-react"; + +export const metadata = { + title: "Helpdesk — Polaris Task Force", +}; + +export default async function HelpdeskPage() { + const payload = await getPayload({ config }); + const { user } = await payload.auth({ + headers: await nextHeaders(), + canSetHeaders: false, + }); + + if (!user) { + redirect("/login"); + } + + const ticketsRes = await payload.find({ + collection: "tickets", + sort: "-updatedAt", + limit: 200, + depth: 2, + }); + const tickets = ticketsRes.docs as unknown as Ticket[]; + const isStaff = hasRoles(["admin", "developer"], user); + + return ( +
+
+
+ +

Helpdesk

+
+

Submit and track support requests.

+
+ + +
+ ); +}