+ {Number(session?.user.id) != id && (
+
+
+
Report
+
+ )}
{Number(session?.user.id) == id && Number(session?.user.id) === Number(process.env.NEXT_PUBLIC_ADMIN_USER_ID) && (
diff --git a/src/components/report/mii-form.tsx b/src/components/report/mii-form.tsx
new file mode 100644
index 0000000..0379050
--- /dev/null
+++ b/src/components/report/mii-form.tsx
@@ -0,0 +1,83 @@
+"use client";
+
+import Image from "next/image";
+import { redirect } from "next/navigation";
+
+import { useState } from "react";
+import { Mii, ReportReason } from "@prisma/client";
+
+import ReasonSelector from "./reason-selector";
+import SubmitButton from "../submit-button";
+import LikeButton from "../like-button";
+
+interface Props {
+ mii: Mii;
+ likes: number;
+}
+
+export default function ReportMiiForm({ mii, likes }: Props) {
+ const [reason, setReason] = useState
();
+ const [notes, setNotes] = useState();
+ const [error, setError] = useState(undefined);
+
+ const handleSubmit = async () => {
+ const response = await fetch(`/api/report`, {
+ method: "POST",
+ body: JSON.stringify({ id: mii.id, type: "mii", reason: reason?.toLowerCase(), notes }),
+ });
+ const { error } = await response.json();
+
+ if (!response.ok) {
+ setError(error);
+ return;
+ }
+
+ redirect(`/`);
+ };
+
+ return (
+
+
+
Report a Mii
+
If you encounter a rule-breaking Mii, please report it here
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {error && Error: {error}}
+
+
+
+
+ );
+}
diff --git a/src/components/report/reason-selector.tsx b/src/components/report/reason-selector.tsx
new file mode 100644
index 0000000..b9f1f38
--- /dev/null
+++ b/src/components/report/reason-selector.tsx
@@ -0,0 +1,64 @@
+"use client";
+
+import { Icon } from "@iconify/react";
+import { ReportReason } from "@prisma/client";
+import { useSelect } from "downshift";
+
+interface Props {
+ reason: ReportReason | undefined;
+ setReason: React.Dispatch>;
+}
+
+const reasonMap: Record = {
+ INAPPROPRIATE: "Inappropriate content",
+ SPAM: "Spam",
+ COPYRIGHT: "Copyrighted content",
+ OTHER: "Other...",
+};
+
+const reasonOptions = Object.entries(reasonMap).map(([value, label]) => ({
+ value: value as ReportReason,
+ label,
+}));
+
+export default function ReasonSelector({ reason, setReason }: Props) {
+ const { isOpen, getToggleButtonProps, getMenuProps, getItemProps, highlightedIndex, selectedItem } = useSelect({
+ items: reasonOptions,
+ selectedItem: reason ? reasonOptions.find((option) => option.value === reason) : null,
+ itemToString: (item) => (item ? item.label : ""),
+ onSelectedItemChange: ({ selectedItem }) => {
+ if (selectedItem) {
+ setReason(selectedItem.value);
+ }
+ },
+ });
+
+ return (
+
+ {/* Toggle button to open the dropdown */}
+
+
+ {/* Dropdown menu */}
+
+ {isOpen &&
+ reasonOptions.map((item, index) => (
+ -
+ {item.label}
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/report/user-form.tsx b/src/components/report/user-form.tsx
new file mode 100644
index 0000000..a514711
--- /dev/null
+++ b/src/components/report/user-form.tsx
@@ -0,0 +1,87 @@
+"use client";
+
+import Image from "next/image";
+import { redirect } from "next/navigation";
+
+import { useState } from "react";
+import { ReportReason, User } from "@prisma/client";
+
+import ReasonSelector from "./reason-selector";
+import SubmitButton from "../submit-button";
+
+interface Props {
+ user: User;
+}
+
+export default function ReportUserForm({ user }: Props) {
+ const [reason, setReason] = useState();
+ const [notes, setNotes] = useState();
+ const [error, setError] = useState(undefined);
+
+ const handleSubmit = async () => {
+ const response = await fetch(`/api/report`, {
+ method: "POST",
+ body: JSON.stringify({ id: user.id, type: "user", reason: reason?.toLowerCase(), notes }),
+ });
+ const { error } = await response.json();
+
+ if (!response.ok) {
+ setError(error);
+ return;
+ }
+
+ redirect(`/`);
+ };
+
+ return (
+
+
+
Report a User
+
If you encounter a user causing issues, please report them here
+
+
+
+
+
+
+
+
{user.name}
+
@{user.username}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {error && Error: {error}}
+
+
+
+
+ );
+}
diff --git a/src/lib/rate-limit.ts b/src/lib/rate-limit.ts
index 3072e5a..47aef3b 100644
--- a/src/lib/rate-limit.ts
+++ b/src/lib/rate-limit.ts
@@ -80,7 +80,7 @@ export class RateLimit {
this.data = await this.check(identifier);
- if (!this.data.success) return this.sendResponse({ success: false, error: "Rate limit exceeded. Please try again later." }, 429);
+ if (!this.data.success) return this.sendResponse({ error: "Rate limit exceeded. Please try again later." }, 429);
return;
}
}