diff --git a/packages/nextjs/app/api/users/[address]/submissions/route.ts b/packages/nextjs/app/api/users/[address]/submissions/route.ts
new file mode 100644
index 0000000..89566fa
--- /dev/null
+++ b/packages/nextjs/app/api/users/[address]/submissions/route.ts
@@ -0,0 +1,18 @@
+import { NextResponse } from "next/server";
+import { getSubmissionsByBuilder } from "~~/services/database/repositories/submissions";
+
+export async function GET(request: Request, { params }: { params: { address: string } }) {
+ try {
+ const { address } = params;
+
+ if (!address) {
+ return NextResponse.json({ error: "Address not provided" }, { status: 400 });
+ }
+
+ const submissions = await getSubmissionsByBuilder(address);
+ return NextResponse.json(submissions);
+ } catch (error) {
+ console.error(error);
+ return NextResponse.json({ error: "Error fetching submissions" }, { status: 500 });
+ }
+}
diff --git a/packages/nextjs/app/my-submissions/page.tsx b/packages/nextjs/app/my-submissions/page.tsx
new file mode 100644
index 0000000..433037e
--- /dev/null
+++ b/packages/nextjs/app/my-submissions/page.tsx
@@ -0,0 +1,74 @@
+"use client";
+
+import { useRouter } from "next/navigation";
+import { SubmissionCard } from "../submissions/_components/SubmissionCard";
+import { useQuery } from "@tanstack/react-query";
+import { useAccount } from "wagmi";
+import { RainbowKitCustomConnectButton } from "~~/components/scaffold-eth";
+import scaffoldConfig from "~~/scaffold.config";
+import { SubmissionWithWinnerTag } from "~~/services/database/repositories/submissions";
+
+const MySubmissions = () => {
+ const { address: connectedAddress, isConnecting } = useAccount();
+ const router = useRouter();
+ const { submissionsEnabled } = scaffoldConfig;
+
+ const {
+ isPending,
+ error,
+ data: submissions,
+ } = useQuery({
+ queryKey: ["my-submissions", connectedAddress],
+ queryFn: () => fetch(`/api/users/${connectedAddress}/submissions`).then(res => res.json()),
+ });
+
+ if (isConnecting || isPending) {
+ return
Loading...
;
+ }
+
+ if (error) {
+ return Error loading submissions.
;
+ }
+
+ return (
+
+ {!connectedAddress ? (
+
+ Connect Wallet to see your submissions
+
+
+ ) : (
+
+
My Submissions
+ {submissions.length === 0 ? (
+
+ {submissionsEnabled ? (
+ <>
+
You haven't made any submissions yet.
+
+ >
+ ) : (
+ <>
+
You haven't made any submissions.
+
+ >
+ )}
+
+ ) : (
+
+ {submissions.map((submission: SubmissionWithWinnerTag) => (
+
+ ))}
+
+ )}
+
+ )}
+
+ );
+};
+
+export default MySubmissions;
diff --git a/packages/nextjs/components/Header.tsx b/packages/nextjs/components/Header.tsx
index 7d14d29..52d7b42 100644
--- a/packages/nextjs/components/Header.tsx
+++ b/packages/nextjs/components/Header.tsx
@@ -3,7 +3,14 @@
import React, { useCallback, useRef, useState } from "react";
import Image from "next/image";
import Link from "next/link";
-import { Bars3Icon, ChatBubbleLeftEllipsisIcon, DocumentTextIcon, LockClosedIcon } from "@heroicons/react/24/outline";
+import { useAccount } from "wagmi";
+import {
+ Bars3Icon,
+ ChatBubbleLeftEllipsisIcon,
+ ClipboardDocumentListIcon,
+ DocumentTextIcon,
+ LockClosedIcon,
+} from "@heroicons/react/24/outline";
import { RainbowKitCustomConnectButton } from "~~/components/scaffold-eth";
import { useOutsideClick } from "~~/hooks/scaffold-eth";
import { useAuthSession } from "~~/hooks/useAuthSession";
@@ -14,26 +21,38 @@ type HeaderMenuLink = {
icon?: React.ReactNode;
};
-export const menuLinks: HeaderMenuLink[] = [
- {
- label: "Submissions",
- href: "/submissions",
- icon: ,
- },
- {
- label: "Admin",
- href: "/admin",
- icon: ,
- },
- {
- label: "Join Telegram",
- href: "https://t.me/+jgKFHjb9B_cyNmMx",
- icon: ,
- },
-];
-
export const HeaderMenuLinks = () => {
const { isAdmin } = useAuthSession();
+ const { address: connectedAddress } = useAccount();
+
+ const menuLinks: HeaderMenuLink[] = [
+ {
+ label: "Submissions",
+ href: "/submissions",
+ icon: ,
+ },
+ ];
+
+ if (connectedAddress) {
+ menuLinks.push({
+ label: "My Submissions",
+ href: "/my-submissions",
+ icon: ,
+ });
+ }
+
+ menuLinks.concat([
+ {
+ label: "Admin",
+ href: "/admin",
+ icon: ,
+ },
+ {
+ label: "Join Telegram",
+ href: "https://t.me/+jgKFHjb9B_cyNmMx",
+ icon: ,
+ },
+ ]);
return (
<>
@@ -49,7 +68,7 @@ export const HeaderMenuLinks = () => {
href={href}
target="_blank"
rel="noreferrer noopener"
- className="hover:underline flex items-center align-center active:!text-neutral py-1.5 px-3 text-lg gap-2"
+ className="hover:underline flex items-center active:!text-neutral py-1.5 px-3 text-lg gap-2 whitespace-nowrap"
>
{icon}
{label}
@@ -58,7 +77,7 @@ export const HeaderMenuLinks = () => {
{icon}
{label}
diff --git a/packages/nextjs/services/database/repositories/submissions.ts b/packages/nextjs/services/database/repositories/submissions.ts
index 117fa26..77f05bf 100644
--- a/packages/nextjs/services/database/repositories/submissions.ts
+++ b/packages/nextjs/services/database/repositories/submissions.ts
@@ -37,3 +37,11 @@ export async function clearEligible(submissionId: number) {
.set({ eligible: null, eligibleAdmin: null, eligibleTimestamp: null })
.where(eq(submissions.id, submissionId));
}
+
+export async function getSubmissionsByBuilder(builderId: string) {
+ return await db.query.submissions.findMany({
+ where: eq(submissions.builder, builderId),
+ with: { comments: true, votes: true },
+ orderBy: [desc(submissions.id)],
+ });
+}