diff --git a/prisma/migrations/20260224165250_nonbinary_gender/migration.sql b/prisma/migrations/20260224165250_nonbinary_gender/migration.sql new file mode 100644 index 0000000..46a344c --- /dev/null +++ b/prisma/migrations/20260224165250_nonbinary_gender/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "MiiGender" ADD VALUE 'NONBINARY'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2f4f5a6..b5a5c4b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -164,6 +164,7 @@ enum MiiPlatform { enum MiiGender { MALE FEMALE + NONBINARY } enum ReportType { diff --git a/src/app/api/submit/route.ts b/src/app/api/submit/route.ts index 29e657b..c7da211 100644 --- a/src/app/api/submit/route.ts +++ b/src/app/api/submit/route.ts @@ -67,7 +67,6 @@ export async function POST(request: NextRequest) { const check = await rateLimit.handle(); if (check) return check; - const response = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/admin/can-submit`); const response = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/admin/can-submit`); const { value } = await response.json(); if (!value) return rateLimit.sendResponse({ error: "Submissions are temporarily disabled" }, 503); @@ -239,6 +238,14 @@ export async function POST(request: NextRequest) { return rateLimit.sendResponse({ error: "Failed to process and store Mii files" }, 500); } + try { + await generateMetadataImage(miiRecord, session.user.name!); + } catch (error) { + console.error(error); + Sentry.captureException(error, { extra: { miiId: miiRecord.id, stage: "metadata-image" } }); + return rateLimit.sendResponse({ error: `Failed to generate 'metadata' type image for mii ${miiRecord.id}` }, 500); + } + // Compress and store user images try { await Promise.all( diff --git a/src/app/mii/[id]/page.tsx b/src/app/mii/[id]/page.tsx index ca784c4..0b7d8b2 100644 --- a/src/app/mii/[id]/page.tsx +++ b/src/app/mii/[id]/page.tsx @@ -178,7 +178,7 @@ export default async function MiiPage({ params }: Props) {
@@ -186,7 +186,7 @@ export default async function MiiPage({ params }: Props) {
@@ -201,17 +201,21 @@ export default async function MiiPage({ params }: Props) {
-
+
- {mii.gender === "MALE" ? "Male" : "Female"} + {mii.gender === "MALE" ? "Male" : mii.gender === "FEMALE" ? "Female" : "Nonbinary"}
@@ -219,12 +223,20 @@ export default async function MiiPage({ params }: Props) {
+ +
+ +
diff --git a/src/app/submit/page.tsx b/src/app/submit/page.tsx index faceed8..f2c63dd 100644 --- a/src/app/submit/page.tsx +++ b/src/app/submit/page.tsx @@ -19,26 +19,26 @@ export const metadata: Metadata = { }; export default async function SubmitPage() { - // const session = await auth(); + const session = await auth(); - // if (!session) redirect("/login"); - // if (!session.user.username) redirect("/create-username"); - // const activePunishment = await prisma.punishment.findFirst({ - // where: { - // userId: Number(session?.user.id), - // returned: false, - // }, - // }); - // if (activePunishment) redirect("/off-the-island"); + if (!session) redirect("/login"); + if (!session.user.username) redirect("/create-username"); + const activePunishment = await prisma.punishment.findFirst({ + where: { + userId: Number(session?.user.id), + returned: false, + }, + }); + if (activePunishment) redirect("/off-the-island"); // Check if submissions are disabled let value: boolean | null = true; - // try { - // const response = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/admin/can-submit`); - // value = await response.json(); - // } catch (error) { - // return

An error occurred!

; - // } + try { + const response = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/admin/can-submit`); + value = await response.json(); + } catch (error) { + return

An error occurred!

; + } if (!value) return ( diff --git a/src/components/mii-list/filter-menu.tsx b/src/components/mii-list/filter-menu.tsx index 848e607..e1cbe69 100644 --- a/src/components/mii-list/filter-menu.tsx +++ b/src/components/mii-list/filter-menu.tsx @@ -4,8 +4,9 @@ import { useSearchParams } from "next/navigation"; import { useEffect, useMemo, useState } from "react"; import { Icon } from "@iconify/react"; -import { MiiGender } from "@prisma/client"; +import { MiiGender, MiiPlatform } from "@prisma/client"; +import PlatformSelect from "./platform-select"; import TagFilter from "./tag-filter"; import GenderSelect from "./gender-select"; import OtherFilters from "./other-filters"; @@ -16,9 +17,10 @@ export default function FilterMenu() { const [isOpen, setIsOpen] = useState(false); const [isVisible, setIsVisible] = useState(false); + const platform = (searchParams.get("platform") as MiiPlatform) || undefined; + const gender = (searchParams.get("gender") as MiiGender) || undefined; const rawTags = searchParams.get("tags") || ""; const rawExclude = searchParams.get("exclude") || ""; - const gender = (searchParams.get("gender") as MiiGender) || undefined; const allowCopying = (searchParams.get("allowCopying") as unknown as boolean) || false; const tags = useMemo( @@ -61,11 +63,12 @@ export default function FilterMenu() { // Count all active filters useEffect(() => { let count = tags.length + exclude.length; + if (platform) count++; if (gender) count++; if (allowCopying) count++; setFilterCount(count); - }, [tags, exclude, gender, allowCopying]); + }, [tags, exclude, platform, gender, allowCopying]); return (
@@ -84,6 +87,20 @@ export default function FilterMenu() {
+
+ Platform +
+
+ + +
+
+ Gender +
+
+ + +

Tags Include
@@ -97,19 +114,16 @@ export default function FilterMenu() {
-
-
- Gender -
-
- - -
-
- Other -
-
- + {platform !== "SWITCH" && ( + <> +
+
+ Other +
+
+ + + )}
)} diff --git a/src/components/mii-list/gender-select.tsx b/src/components/mii-list/gender-select.tsx index 147c645..936b213 100644 --- a/src/components/mii-list/gender-select.tsx +++ b/src/components/mii-list/gender-select.tsx @@ -3,16 +3,15 @@ import { useRouter, useSearchParams } from "next/navigation"; import { useState, useTransition } from "react"; import { Icon } from "@iconify/react"; -import { MiiGender } from "@prisma/client"; +import { MiiGender, MiiPlatform } from "@prisma/client"; export default function GenderSelect() { const router = useRouter(); const searchParams = useSearchParams(); const [, startTransition] = useTransition(); - const [selected, setSelected] = useState( - (searchParams.get("gender") as MiiGender) ?? null - ); + const [selected, setSelected] = useState((searchParams.get("gender") as MiiGender) ?? null); + const platform = (searchParams.get("platform") as MiiPlatform) || undefined; const handleClick = (gender: MiiGender) => { const filter = selected === gender ? null : gender; @@ -33,20 +32,16 @@ export default function GenderSelect() { }; return ( -
+
@@ -55,16 +50,26 @@ export default function GenderSelect() { aria-label="Filter for Female Miis" data-tooltip-span className={`cursor-pointer rounded-xl flex justify-center items-center size-13 text-5xl border-2 transition-all ${ - selected === "FEMALE" - ? "bg-pink-100 border-pink-400 shadow-md" - : "bg-white border-gray-300 hover:border-gray-400" + selected === "FEMALE" ? "bg-pink-100 border-pink-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400" }`} > -
- Female -
+
Female
+ + {platform !== "THREE_DS" && ( + + )}
); } diff --git a/src/components/mii-list/platform-select.tsx b/src/components/mii-list/platform-select.tsx index 8915d8e..0327c62 100644 --- a/src/components/mii-list/platform-select.tsx +++ b/src/components/mii-list/platform-select.tsx @@ -38,7 +38,7 @@ export default function PlatformSelect() { selected === "THREE_DS" ? "bg-sky-100 border-sky-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400" }`} > -
3DS
+
3DS
@@ -50,7 +50,7 @@ export default function PlatformSelect() { selected === "SWITCH" ? "bg-red-100 border-red-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400" }`} > -
Switch
+
Switch
diff --git a/src/components/submit-form/index.tsx b/src/components/submit-form/index.tsx index 2b46938..88fa963 100644 --- a/src/components/submit-form/index.tsx +++ b/src/components/submit-form/index.tsx @@ -279,7 +279,8 @@ export default function SubmitForm() { type="button" onClick={() => setGender("MALE")} aria-label="Filter for Male Miis" - className={`cursor-pointer rounded-xl flex justify-center items-center size-11 text-4xl border-2 transition-all ${ + data-tooltip="Male" + className={`cursor-pointer rounded-xl flex justify-center items-center size-11 text-4xl border-2 transition-all after:bg-blue-400! after:border-blue-400! before:border-b-blue-400! ${ gender === "MALE" ? "bg-blue-100 border-blue-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400" }`} > @@ -290,12 +291,25 @@ export default function SubmitForm() { type="button" onClick={() => setGender("FEMALE")} aria-label="Filter for Female Miis" - className={`cursor-pointer rounded-xl flex justify-center items-center size-11 text-4xl border-2 transition-all ${ + data-tooltip="Female" + className={`cursor-pointer rounded-xl flex justify-center items-center size-11 text-4xl border-2 transition-all after:bg-pink-400! after:border-pink-400! before:border-b-pink-400! ${ gender === "FEMALE" ? "bg-pink-100 border-pink-400 shadow-md" : "bg-white border-gray-300 hover:border-gray-400" }`} > + + )} diff --git a/src/lib/schemas.ts b/src/lib/schemas.ts index a4713f4..50a3df9 100644 --- a/src/lib/schemas.ts +++ b/src/lib/schemas.ts @@ -59,7 +59,7 @@ export const searchSchema = z.object({ .filter((tag) => tag.length > 0), ), platform: z.enum(MiiPlatform, { error: "Platform must be either 'THREE_DS', or 'SWITCH'" }).optional(), - gender: z.enum(MiiGender, { error: "Gender must be either 'MALE', or 'FEMALE'" }).optional(), + gender: z.enum(MiiGender, { error: "Gender must be either 'MALE', 'FEMALE', or 'NONBINARY' if on Switch platform" }).optional(), allowCopying: z.coerce.boolean({ error: "Allow Copying must be either true or false" }).optional(), // todo: incorporate tagsSchema // Pages