feat: allow admins to disable submissions
This commit is contained in:
parent
769dd0b863
commit
c5437ed3e7
5 changed files with 104 additions and 0 deletions
|
|
@ -10,6 +10,7 @@ import { auth } from "@/lib/auth";
|
|||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
import BannerForm from "@/components/admin/banner-form";
|
||||
import ControlCenter from "@/components/admin/control-center";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Admin - TomodachiShare",
|
||||
|
|
@ -56,6 +57,15 @@ export default async function AdminPage() {
|
|||
|
||||
<BannerForm />
|
||||
|
||||
{/* Separator */}
|
||||
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium my-1">
|
||||
<hr className="flex-grow border-zinc-300" />
|
||||
<span>Control Center</span>
|
||||
<hr className="flex-grow border-zinc-300" />
|
||||
</div>
|
||||
|
||||
<ControlCenter />
|
||||
|
||||
{/* Separator */}
|
||||
<div className="flex items-center gap-4 text-zinc-500 text-sm font-medium my-1">
|
||||
<hr className="flex-grow border-zinc-300" />
|
||||
|
|
|
|||
23
src/app/api/admin/can-submit/route.ts
Normal file
23
src/app/api/admin/can-submit/route.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { auth } from "@/lib/auth";
|
||||
|
||||
let canSubmit = true;
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.json({ success: true, value: canSubmit });
|
||||
}
|
||||
|
||||
export async function PATCH(request: NextRequest) {
|
||||
const session = await auth();
|
||||
if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
|
||||
if (Number(session.user.id) !== Number(process.env.NEXT_PUBLIC_ADMIN_USER_ID)) return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||||
|
||||
const body = await request.json();
|
||||
const validatedCanSubmit = z.boolean().safeParse(body);
|
||||
if (!validatedCanSubmit.success) return NextResponse.json({ error: "Failed to validate body" }, { status: 400 });
|
||||
|
||||
canSubmit = validatedCanSubmit.data;
|
||||
return NextResponse.json({ success: true });
|
||||
}
|
||||
|
|
@ -41,6 +41,11 @@ export async function POST(request: NextRequest) {
|
|||
const check = await rateLimit.handle();
|
||||
if (check) return check;
|
||||
|
||||
const response = await fetch(`${process.env.BASE_URL}/api/admin/can-submit`);
|
||||
const { value } = await response.json();
|
||||
if (!value) return rateLimit.sendResponse({ error: "Submissions are disabled" }, 409);
|
||||
|
||||
// Parse data
|
||||
const formData = await request.formData();
|
||||
|
||||
let rawTags: string[];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { Metadata } from "next";
|
||||
import { redirect } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
|
||||
import { Icon } from "@iconify/react";
|
||||
|
||||
import { auth } from "@/lib/auth";
|
||||
import SubmitForm from "@/components/submit-form";
|
||||
|
||||
|
|
@ -18,5 +22,23 @@ export default async function SubmitPage() {
|
|||
if (!session) redirect("/login");
|
||||
if (!session.user.username) redirect("/create-username");
|
||||
|
||||
// Check if submissions are disabled
|
||||
const response = await fetch(`${process.env.BASE_URL}/api/admin/can-submit`);
|
||||
const { value } = await response.json();
|
||||
|
||||
if (!value)
|
||||
return (
|
||||
<div className="flex-grow flex items-center justify-center">
|
||||
<div className="bg-amber-50 border-2 border-amber-500 rounded-2xl shadow-lg p-8 max-w-xs w-full text-center flex flex-col">
|
||||
<h2 className="text-5xl font-black">Sorry</h2>
|
||||
<p className="mt-1">Submissions are disabled</p>
|
||||
<Link href="/" className="pill button gap-2 mt-8 w-fit self-center">
|
||||
<Icon icon="ic:round-home" fontSize={24} />
|
||||
Return Home
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return <SubmitForm />;
|
||||
}
|
||||
|
|
|
|||
44
src/components/admin/control-center.tsx
Normal file
44
src/components/admin/control-center.tsx
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function ControlCenter() {
|
||||
const [canSubmit, setCanSubmit] = useState(true);
|
||||
|
||||
const onClickSet = async () => {
|
||||
await fetch("/api/admin/can-submit", { method: "PATCH", body: JSON.stringify(canSubmit) });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const check = async () => {
|
||||
const response = await fetch("/api/admin/can-submit");
|
||||
const { value } = await response.json();
|
||||
|
||||
setCanSubmit(value);
|
||||
};
|
||||
|
||||
check();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="bg-orange-100 rounded-xl border-2 border-orange-400 p-2 flex flex-col gap-2">
|
||||
<div className="flex items-center gap-4">
|
||||
<label htmlFor="submit">Submissions</label>
|
||||
<input
|
||||
name="submit"
|
||||
type="checkbox"
|
||||
className="checkbox !size-6"
|
||||
placeholder="Enter banner text"
|
||||
checked={canSubmit}
|
||||
onChange={(e) => setCanSubmit(e.target.checked)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 self-end">
|
||||
<button type="submit" className="pill button" onClick={onClickSet}>
|
||||
Set
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue