diff --git a/packages/nextjs/app/api/builders/[builderAddress]/grants/route.ts b/packages/nextjs/app/api/builders/[builderAddress]/grants/route.ts new file mode 100644 index 0000000..41d72f7 --- /dev/null +++ b/packages/nextjs/app/api/builders/[builderAddress]/grants/route.ts @@ -0,0 +1,17 @@ +import { NextResponse } from "next/server"; +import { getAllGrantsForUser } from "~~/services/database/grants"; + +export async function GET(_request: Request, { params }: { params: { builderAddress: string } }) { + try { + const builderAddress = params.builderAddress; + const grants = await getAllGrantsForUser(builderAddress); + return NextResponse.json(grants); + } catch (error) { + return NextResponse.json( + { message: "Internal Server Error" }, + { + status: 500, + }, + ); + } +} diff --git a/packages/nextjs/app/my-grants/page.tsx b/packages/nextjs/app/my-grants/page.tsx new file mode 100644 index 0000000..ecff4f0 --- /dev/null +++ b/packages/nextjs/app/my-grants/page.tsx @@ -0,0 +1,56 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { NextPage } from "next"; +import { useAccount } from "wagmi"; +import { GrantData } from "~~/services/database/schema"; +import { PROPOSAL_STATUS } from "~~/utils/grants"; + +const badgeBgColor = { + [PROPOSAL_STATUS.PROPOSED]: "bg-warning", + [PROPOSAL_STATUS.APPROVED]: "bg-success", + [PROPOSAL_STATUS.SUBMITTED]: "bg-warning", + [PROPOSAL_STATUS.COMPLETED]: "bg-success", + [PROPOSAL_STATUS.REJECTED]: "bg-error", +}; + +// ToDo. Action (v1.0 = submit grant after completion) +// ToDo. Loading states +const MyGrants: NextPage = () => { + const { address } = useAccount(); + const [builderGrants, setBuilderGrants] = useState([]); + + useEffect(() => { + const fetchBuilderGrants = async () => { + try { + const response = await fetch(`/api/builders/${address}/grants`); + const data = await response.json(); + setBuilderGrants(data); + } catch (error) { + console.error("Failed to fetch builder grants", error); + } + }; + + if (address) { + fetchBuilderGrants(); + } + }, [address]); + + return ( +
+

My grants

+ {builderGrants.map(grant => ( +
+

+ {grant.title} + ({grant.id}) +

+

{grant.description}

+

{grant.status}

+
+ ))} +
+ ); +}; + +export default MyGrants; diff --git a/packages/nextjs/components/Header.tsx b/packages/nextjs/components/Header.tsx index 3ceb161..3420d87 100644 --- a/packages/nextjs/components/Header.tsx +++ b/packages/nextjs/components/Header.tsx @@ -3,7 +3,7 @@ import Image from "next/image"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { RainbowKitCustomConnectButton } from "./scaffold-eth"; -import { LockClosedIcon } from "@heroicons/react/24/outline"; +import { AcademicCapIcon, LockClosedIcon } from "@heroicons/react/24/outline"; import { useGlobalState } from "~~/services/store/store"; type HeaderMenuLink = { @@ -14,8 +14,9 @@ type HeaderMenuLink = { export const menuLinks: HeaderMenuLink[] = [ { - label: "Home", - href: "/", + label: "My Grants", + href: "/my-grants", + icon: , }, { label: "Admin", @@ -33,6 +34,7 @@ export const HeaderMenuLinks = () => { {menuLinks.map(({ label, href, icon }) => { const isActive = pathname === href; if (href === "/admin" && builderData?.role !== "admin") return null; + if (href === "/my-grants" && !builderData) return null; return (
  • { } }; +export const getAllGrantsForUser = async (userAddress: string) => { + try { + const grantsSnapshot = await grantsCollection.where("builder", "==", userAddress).get(); + const grants: GrantData[] = []; + grantsSnapshot.forEach(doc => { + grants.push({ id: doc.id, ...doc.data() } as GrantData); + }); + return grants; + } catch (error) { + console.error("Error getting all grants for user:", error); + throw error; + } +}; + export const getAllGrantsForReview = async () => { try { const grantsSnapshot = await grantsCollection