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