From 08035ede7460ed98c93af0ef5631003d0c659446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20S=C3=A1nchez?= Date: Tue, 20 Feb 2024 16:11:45 +0100 Subject: [PATCH] My grants page (#23) --- .../builders/[builderAddress]/grants/route.ts | 17 ++++++++ .../nextjs/app/api/grants/review/route.tsx | 14 +++++-- packages/nextjs/app/my-grants/page.tsx | 41 +++++++++++++++++++ packages/nextjs/components/Header.tsx | 8 ++-- packages/nextjs/services/database/grants.ts | 14 +++++++ 5 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 packages/nextjs/app/api/builders/[builderAddress]/grants/route.ts create mode 100644 packages/nextjs/app/my-grants/page.tsx 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..1738a9e --- /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( + { error: "Internal Server Error" }, + { + status: 500, + }, + ); + } +} diff --git a/packages/nextjs/app/api/grants/review/route.tsx b/packages/nextjs/app/api/grants/review/route.tsx index 78546cd..7872c93 100644 --- a/packages/nextjs/app/api/grants/review/route.tsx +++ b/packages/nextjs/app/api/grants/review/route.tsx @@ -2,7 +2,15 @@ import { NextResponse } from "next/server"; import { getAllGrantsForReview } from "~~/services/database/grants"; export async function GET() { - const grants = await getAllGrantsForReview(); - - return NextResponse.json({ data: grants }); + try { + const grants = await getAllGrantsForReview(); + return NextResponse.json({ data: grants }); + } catch (error) { + return NextResponse.json( + { error: "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..ddc3e8c --- /dev/null +++ b/packages/nextjs/app/my-grants/page.tsx @@ -0,0 +1,41 @@ +"use client"; + +import { NextPage } from "next"; +import useSWR from "swr"; +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) +const MyGrants: NextPage = () => { + const { address } = useAccount(); + const { data: builderGrants, isLoading } = useSWR(address ? `/api/builders/${address}/grants` : null); + + return ( +
+

My grants

+ {isLoading && } + {builderGrants?.length === 0 &&

No grants found

} + {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 b11e97c..ed9551d 100644 --- a/packages/nextjs/components/Header.tsx +++ b/packages/nextjs/components/Header.tsx @@ -4,7 +4,7 @@ import Link from "next/link"; import { usePathname } from "next/navigation"; import { RainbowKitCustomConnectButton } from "./scaffold-eth"; import { useAccount } from "wagmi"; -import { LockClosedIcon } from "@heroicons/react/24/outline"; +import { AcademicCapIcon, LockClosedIcon } from "@heroicons/react/24/outline"; import { useBGBuilderData } from "~~/hooks/useBGBuilderData"; type HeaderMenuLink = { @@ -15,8 +15,9 @@ type HeaderMenuLink = { export const menuLinks: HeaderMenuLink[] = [ { - label: "Home", - href: "/", + label: "My Grants", + href: "/my-grants", + icon: , }, { label: "Admin", @@ -35,6 +36,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