diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 2485128..095a695 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -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() { + {/* Separator */} +
+
+ Control Center +
+
+ + + {/* Separator */}

diff --git a/src/app/api/admin/can-submit/route.ts b/src/app/api/admin/can-submit/route.ts new file mode 100644 index 0000000..6623dc7 --- /dev/null +++ b/src/app/api/admin/can-submit/route.ts @@ -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 }); +} diff --git a/src/app/api/submit/route.ts b/src/app/api/submit/route.ts index 8bdf4d2..6266402 100644 --- a/src/app/api/submit/route.ts +++ b/src/app/api/submit/route.ts @@ -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[]; diff --git a/src/app/submit/page.tsx b/src/app/submit/page.tsx index 9e4b838..7490f2f 100644 --- a/src/app/submit/page.tsx +++ b/src/app/submit/page.tsx @@ -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 ( +
+
+

Sorry

+

Submissions are disabled

+ + + Return Home + +
+
+ ); + return ; } diff --git a/src/components/admin/control-center.tsx b/src/components/admin/control-center.tsx new file mode 100644 index 0000000..258b0bf --- /dev/null +++ b/src/components/admin/control-center.tsx @@ -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 ( +
+
+ + setCanSubmit(e.target.checked)} + /> +
+ +
+ +
+
+ ); +}