feat: shop buy, forum replies, tickets, messages, sessions, and UX hardening

Complete remaining product gaps: credit-based shop purchases, guild thread replies, help ticket detail/reply/close, offline message compose, sign-out-everywhere via JWT version, ads delete confirm, soft-fail feedback, rate limits, loading states, and single auth() in site layout.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-07-21 21:21:02 +02:00
1 parent ed7db6e048
commit 803e8f36c1
47 files changed
+2793 -358

No files matched your search

+10 -35
View File
@@ -4,6 +4,7 @@ import { StatusCard } from "@/components/admin/dashboard";
import { prisma } from "@/lib/prisma";
import { redirect } from "next/navigation";
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
import { AdsTable } from "./ads-table";
export const dynamic = "force-dynamic";
@@ -51,41 +52,15 @@ export default async function AdminAds() {
{ads.length === 0 ? (
<div className="admin-empty">{t("noAds")}</div>
) : (
<table>
<thead>
<tr>
<th>{t("colPreview")}</th>
<th>{t("colImage")}</th>
<th>{t("colCreated")}</th>
<th />
</tr>
</thead>
<tbody>
{ads.map((ad) => (
<tr key={String(ad.id)}>
<td>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={ad.image}
alt=""
style={{ maxHeight: 40, maxWidth: 120 }}
/>
</td>
<td className="text-sm theme-text-muted dark:theme-text-muted whitespace-nowrap">
<code>{ad.image}</code>
</td>
<td className="text-sm theme-text-muted dark:theme-text-muted whitespace-nowrap">
{ad.createdAt
? ad.createdAt.toISOString().slice(0, 10)
: "—"}
</td>
<td>
<Link href={`/admin/ads/${ad.id}`}>{t("edit")}</Link>
</td>
</tr>
))}
</tbody>
</table>
<AdsTable
ads={ads.map((ad) => ({
id: String(ad.id),
image: ad.image,
createdAt: ad.createdAt
? ad.createdAt.toISOString().slice(0, 10)
: null,
}))}
/>
)}
</section>
</main>