import { asc } from "drizzle-orm"; import type { Metadata } from "next"; import { getTranslations } from "next-intl/server"; import Link from "@/components/link"; export async function generateMetadata(): Promise { const t = await getTranslations("pages.help"); return { title: t("title"), description: t("subtitle"), openGraph: { title: t("title"), description: t("subtitle"), type: "website", }, }; } import { ContentCard, EmptyState } from "@/components/public/ui"; import { db, WebsiteHelpCenterCategories, WebsiteRuleCategories, WebsiteRules, } from "@/lib/db"; type HelpCategory = { id: bigint; name: string; content: string; imageUrl: string | null; buttonText: string | null; buttonUrl: string | null; buttonColor: string; buttonBorderColor: string; smallBox: boolean; }; type RuleCategory = { id: bigint; name: string; description: string; badge: string; }; type Rule = { id: bigint; categoryId: bigint | null; paragraph: string; rule: string; }; function isExternal(url: string): boolean { return /^https?:\/\//i.test(url); } export default async function HelpCenterPage() { const t = await getTranslations("pages.help"); let categories: HelpCategory[] = []; try { categories = await db .select({ id: WebsiteHelpCenterCategories.id, name: WebsiteHelpCenterCategories.name, content: WebsiteHelpCenterCategories.content, imageUrl: WebsiteHelpCenterCategories.imageUrl, buttonText: WebsiteHelpCenterCategories.buttonText, buttonUrl: WebsiteHelpCenterCategories.buttonUrl, buttonColor: WebsiteHelpCenterCategories.buttonColor, buttonBorderColor: WebsiteHelpCenterCategories.buttonBorderColor, smallBox: WebsiteHelpCenterCategories.smallBox, }) .from(WebsiteHelpCenterCategories) .orderBy( asc(WebsiteHelpCenterCategories.position), asc(WebsiteHelpCenterCategories.id), ); } catch { // DB unavailable — render the shell without help categories. } let ruleCategories: RuleCategory[] = []; try { ruleCategories = await db .select({ id: WebsiteRuleCategories.id, name: WebsiteRuleCategories.name, description: WebsiteRuleCategories.description, badge: WebsiteRuleCategories.badge, }) .from(WebsiteRuleCategories) .orderBy(asc(WebsiteRuleCategories.id)); } catch { // DB unavailable — render the shell without rule categories. } let rules: Rule[] = []; try { rules = await db .select({ id: WebsiteRules.id, categoryId: WebsiteRules.categoryId, paragraph: WebsiteRules.paragraph, rule: WebsiteRules.rule, }) .from(WebsiteRules) .orderBy( asc(WebsiteRules.categoryId), asc(WebsiteRules.paragraph), asc(WebsiteRules.id), ); } catch { // DB unavailable — render the shell without rules. } // Group the rules under their categories. const rulesByCategory = new Map(); for (const r of rules) { const key = r.categoryId === null ? "" : String(r.categoryId); const list = rulesByCategory.get(key); if (list) { list.push(r); } else { rulesByCategory.set(key, [r]); } } return (
{t("myTickets")} } /> {categories.length === 0 ? ( {t("topicsEmpty")} ) : (
{categories.map((c) => (
{c.imageUrl ? ( // eslint-disable-next-line @next/next/no-img-element ) : null}

{c.name}

{c.content}

{c.buttonUrl && c.buttonText ? (
{isExternal(c.buttonUrl) ? ( {c.buttonText} ) : ( {c.buttonText} )}
) : null}
))}
)}
{ruleCategories.length === 0 ? ( {t("rulesEmpty")} ) : (
{ruleCategories.map((cat) => { const catRules = rulesByCategory.get(String(cat.id)) ?? []; return (

{cat.name}

{cat.badge ? ( {cat.badge} ) : null}
{cat.description ? (

{cat.description}

) : null} {catRules.length === 0 ? (

{t("categoryEmpty")}

) : (
    {catRules.map((r) => (
  • {r.paragraph ? ( {r.paragraph} ) : null} {r.rule}
  • ))}
)}
); })}
)}
); }