feat(admin): ban appeals, photos polish, economy adjust, staff smoke
Deploy / release (push) Skipped
Deploy / deploy (push) Successful in 1m17s
CI / check (push) Successful in 25s
CI / deploy (push) Failing after 11s

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-07-30 20:23:03 +02:00
1 parent fe46bd0544
commit 3ad3f9512c
36 files changed
+1185 -293

No files matched your search

@@ -6,6 +6,7 @@ import { useTranslations } from "next-intl";
import { useEffect, useRef, useState } from "react";
import {
closeHelpCenterTicket,
liftBanFromHelpTicket,
reopenHelpCenterTicket,
replyHelpCenterTicket,
} from "@/actions/admin-help-tickets";
@@ -30,6 +31,7 @@ interface HelpTicketInfo {
open: boolean;
createdAt: string;
updatedAt: string;
categoryName?: string | null;
creator: {
id: number;
username: string;
@@ -42,12 +44,17 @@ export function AdminHelpTicketDetail({
ticket,
messages: initialMessages,
canEdit,
canLiftBan = false,
hasActiveBan = false,
listHref = "/admin/help-tickets",
hideRequesterContact = false,
}: {
ticket: HelpTicketInfo;
messages: ThreadMessage[];
canEdit: boolean;
/** Staff may lift requester bans (USERS_BAN). */
canLiftBan?: boolean;
hasActiveBan?: boolean;
listHref?: string;
/** Hide email/IP-style contact for mod-lite surfaces. */
hideRequesterContact?: boolean;
@@ -94,6 +101,13 @@ export function AdminHelpTicketDetail({
});
}
function handleLiftBan() {
if (!ticket.creator || isPending) return;
run(() => liftBanFromHelpTicket({ ticketId: ticket.id }), {
successMessage: t("success.banLifted"),
});
}
return (
<div className="space-y-6">
<div className="flex items-start gap-4">
@@ -110,6 +124,12 @@ export function AdminHelpTicketDetail({
<Badge variant={ticket.open ? "default" : "secondary"}>
{ticket.open ? t("statusOpen") : t("statusClosed")}
</Badge>
{ticket.categoryName ? (
<Badge variant="outline">{ticket.categoryName}</Badge>
) : null}
{hasActiveBan ? (
<Badge variant="destructive">{t("requesterBanned")}</Badge>
) : null}
</div>
<h1 className="text-2xl font-bold">{ticket.title}</h1>
</div>
@@ -208,13 +228,24 @@ export function AdminHelpTicketDetail({
</div>
<div className="space-y-4">
{canEdit && (
{(canEdit || (canLiftBan && hasActiveBan)) && (
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm">{t("actionsTitle")}</CardTitle>
</CardHeader>
<CardContent className="space-y-2">
{ticket.open ? (
{canLiftBan && hasActiveBan && ticket.creator ? (
<Button
variant="destructive"
size="sm"
className="w-full"
disabled={isPending}
onClick={handleLiftBan}
>
{t("liftBanSubmit")}
</Button>
) : null}
{canEdit && ticket.open ? (
<Button
variant="outline"
size="sm"
@@ -224,7 +255,8 @@ export function AdminHelpTicketDetail({
>
{t("closeSubmit")}
</Button>
) : (
) : null}
{canEdit && !ticket.open ? (
<Button
variant="outline"
size="sm"
@@ -234,7 +266,7 @@ export function AdminHelpTicketDetail({
>
{t("reopenSubmit")}
</Button>
)}
) : null}
</CardContent>
</Card>
)}