Add Theme Settings tool + polish remaining radio detail pages
- New /admin/theme: recolour the whole site from housekeeping. 6 atom- faithful presets (Atom/Midnight/Ocean/Forest/Sunset/Candy) + per-colour pickers for the 12 settings ThemeVars injects + border radius. Writes to website_settings, busts the siteSettings cache, and revalidates the layout so the new palette applies live with no rebuild. Constants live in src/lib/theme-presets.ts (a "use server" file can't export objects). Added to the admin sidebar (System). - radio/contests/[id] + giveaways/[id] wrapped in ContentCard to match the public design system. - Skipped a separate VPN page: /admin/ip already manages the IP white/blacklist, so it would only duplicate it. Verified live (prod, amx_test): applied the Ocean preset → home renders --color-primary #0ea5e9 site-wide; reverted the test rows. tsc 0, vitest 49/49, next build 0.
This commit is contained in:
1 parent
6f15e0c8a3
commit
1199176883
6 files changed
+322
-10
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { notFound } from "next/navigation";
|
||||
import { ContentCard } from "@/components/public/ui";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
@@ -33,13 +34,12 @@ export default async function RadioContestDetailPage({
|
||||
const contestIdStr = contest.id.toString();
|
||||
|
||||
return (
|
||||
<main>
|
||||
<p className="muted" style={{ margin: "0 0 0.5rem" }}>
|
||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
||||
<p className="muted" style={{ margin: 0 }}>
|
||||
<Link href="/radio/contests">← Back to contests</Link>
|
||||
</p>
|
||||
|
||||
<div className="card">
|
||||
<h1 style={{ margin: "0 0 0.5rem" }}>Contest #{contestIdStr}</h1>
|
||||
<ContentCard icon="🎉" title={`Contest #${contestIdStr}`} subtitle="Radio contest details">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
@@ -52,7 +52,7 @@ export default async function RadioContestDetailPage({
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</ContentCard>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { notFound } from "next/navigation";
|
||||
import { ContentCard } from "@/components/public/ui";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
@@ -33,13 +34,12 @@ export default async function RadioGiveawayDetailPage({
|
||||
const giveawayIdStr = giveaway.id.toString();
|
||||
|
||||
return (
|
||||
<main>
|
||||
<p className="muted" style={{ margin: "0 0 0.5rem" }}>
|
||||
<main style={{ display: "grid", gap: "1.5rem" }}>
|
||||
<p className="muted" style={{ margin: 0 }}>
|
||||
<Link href="/radio/giveaways">← Back to giveaways</Link>
|
||||
</p>
|
||||
|
||||
<div className="card">
|
||||
<h1 style={{ margin: "0 0 0.5rem" }}>Giveaway #{giveawayIdStr}</h1>
|
||||
<ContentCard icon="🎁" title={`Giveaway #${giveawayIdStr}`} subtitle="Radio giveaway details">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
@@ -52,7 +52,7 @@ export default async function RadioGiveawayDetailPage({
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</ContentCard>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user