diff --git a/packages/nextjs/app/admin/page.tsx b/packages/nextjs/app/admin/page.tsx new file mode 100644 index 0000000..c7d1efe --- /dev/null +++ b/packages/nextjs/app/admin/page.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { GrantData } from "~~/services/database/schema"; +import { notification } from "~~/utils/scaffold-eth"; + +// ToDo. "Protect" with address header or PROTECT with signing the read. +const AdminPage = () => { + const [grants, setGrants] = useState([]); + + useEffect(() => { + const getGrants = async () => { + try { + const response = await fetch("/api/grants/review"); + const grants: GrantData[] = (await response.json()).data; + setGrants(grants); + } catch (error) { + notification.error("Error getting grants for review"); + } + }; + + getGrants(); + }, []); + + return ( +
+

Admin page

+ {grants && ( + <> +

All grants that need review:

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

{grant.title}

+

{grant.description}

+
+ ))} + + )} +
+ ); +}; + +export default AdminPage; diff --git a/packages/nextjs/app/api/grants/review/route.tsx b/packages/nextjs/app/api/grants/review/route.tsx new file mode 100644 index 0000000..78546cd --- /dev/null +++ b/packages/nextjs/app/api/grants/review/route.tsx @@ -0,0 +1,8 @@ +import { NextResponse } from "next/server"; +import { getAllGrantsForReview } from "~~/services/database/grants"; + +export async function GET() { + const grants = await getAllGrantsForReview(); + + return NextResponse.json({ data: grants }); +} diff --git a/packages/nextjs/components/Header.tsx b/packages/nextjs/components/Header.tsx index e4770b1..b927560 100644 --- a/packages/nextjs/components/Header.tsx +++ b/packages/nextjs/components/Header.tsx @@ -1,7 +1,54 @@ import React from "react"; 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"; + +type HeaderMenuLink = { + label: string; + href: string; + icon?: React.ReactNode; +}; + +export const menuLinks: HeaderMenuLink[] = [ + { + label: "Home", + href: "/", + }, + // ToDo. Show only on admins + { + label: "Admin", + href: "/admin", + icon: , + }, +]; + +export const HeaderMenuLinks = () => { + const pathname = usePathname(); + + return ( + <> + {menuLinks.map(({ label, href, icon }) => { + const isActive = pathname === href; + return ( +
  • + + {icon} + {label} + +
  • + ); + })} + + ); +}; /** * Site header @@ -9,13 +56,17 @@ import { RainbowKitCustomConnectButton } from "./scaffold-eth"; export const Header = () => { return (
    -
    +
    SE2 logo
    +
      + +
    +
    diff --git a/packages/nextjs/services/database/grants.ts b/packages/nextjs/services/database/grants.ts index 4325c8e..cf24ab2 100644 --- a/packages/nextjs/services/database/grants.ts +++ b/packages/nextjs/services/database/grants.ts @@ -43,6 +43,22 @@ export const getAllGrants = async () => { } }; +export const getAllGrantsForReview = async () => { + try { + const grantsSnapshot = await grantsCollection + .where("status", "in", [PROPOSAL_STATUS.PROPOSED, PROPOSAL_STATUS.SUBMITTED]) + .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 completed grants:", error); + throw error; + } +}; + export const getAllCompletedGrants = async () => { try { const grantsSnapshot = await grantsCollection.where("status", "==", PROPOSAL_STATUS.COMPLETED).get();