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)], + }); +}