From 92b63435f2226ea1d73fb7219cf91f0b5067d730 Mon Sep 17 00:00:00 2001
From: Dao Ho <84757503+Dao-Ho@users.noreply.github.com>
Date: Sun, 14 Jun 2026 19:08:54 -0700
Subject: [PATCH 1/4] feat: page skeletons
---
frontend/package-lock.json | 10 ++
frontend/package.json | 1 +
.../src/app/(portal)/admin/builder/page.tsx | 7 ++
.../src/app/(portal)/admin/cycles/page.tsx | 7 ++
.../src/app/(portal)/admin/roles/page.tsx | 7 ++
.../(portal)/applicant/applications/page.tsx | 7 ++
frontend/src/app/(portal)/layout.tsx | 21 +++++
.../app/(portal)/reviewer/applicants/page.tsx | 7 ++
.../app/(portal)/reviewer/dashboard/page.tsx | 7 ++
frontend/src/app/globals.css | 2 +
frontend/src/app/layout.tsx | 4 +-
frontend/src/app/page.tsx | 66 +------------
frontend/src/components/nav/NavItem.tsx | 33 +++++++
frontend/src/components/nav/Sidebar.tsx | 92 +++++++++++++++++++
frontend/src/lib/mock-user.ts | 7 ++
frontend/src/types/roles.ts | 10 ++
frontend/src/types/user.ts | 5 +
17 files changed, 228 insertions(+), 65 deletions(-)
create mode 100644 frontend/src/app/(portal)/admin/builder/page.tsx
create mode 100644 frontend/src/app/(portal)/admin/cycles/page.tsx
create mode 100644 frontend/src/app/(portal)/admin/roles/page.tsx
create mode 100644 frontend/src/app/(portal)/applicant/applications/page.tsx
create mode 100644 frontend/src/app/(portal)/layout.tsx
create mode 100644 frontend/src/app/(portal)/reviewer/applicants/page.tsx
create mode 100644 frontend/src/app/(portal)/reviewer/dashboard/page.tsx
create mode 100644 frontend/src/components/nav/NavItem.tsx
create mode 100644 frontend/src/components/nav/Sidebar.tsx
create mode 100644 frontend/src/lib/mock-user.ts
create mode 100644 frontend/src/types/roles.ts
create mode 100644 frontend/src/types/user.ts
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index e565acd..f61b4d6 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -8,6 +8,7 @@
"name": "frontend",
"version": "0.1.0",
"dependencies": {
+ "lucide-react": "^1.18.0",
"next": "16.2.9",
"react": "19.2.4",
"react-dom": "19.2.4"
@@ -4961,6 +4962,15 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/lucide-react": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.18.0.tgz",
+ "integrity": "sha512-LZDb7H/0YfM+RJncD0hDQRCAu+vSGODqpe35TuVI8EuXaRjkczbsx7p8dY4J87F/MUSj6bpYqeI8nw8qXaAdmA==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/magic-string": {
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 826911c..8e83e30 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -9,6 +9,7 @@
"lint": "eslint"
},
"dependencies": {
+ "lucide-react": "^1.18.0",
"next": "16.2.9",
"react": "19.2.4",
"react-dom": "19.2.4"
diff --git a/frontend/src/app/(portal)/admin/builder/page.tsx b/frontend/src/app/(portal)/admin/builder/page.tsx
new file mode 100644
index 0000000..769e70b
--- /dev/null
+++ b/frontend/src/app/(portal)/admin/builder/page.tsx
@@ -0,0 +1,7 @@
+export default function BuilderPage() {
+ return (
+
+
App Builder
+
+ );
+}
diff --git a/frontend/src/app/(portal)/admin/cycles/page.tsx b/frontend/src/app/(portal)/admin/cycles/page.tsx
new file mode 100644
index 0000000..ca084eb
--- /dev/null
+++ b/frontend/src/app/(portal)/admin/cycles/page.tsx
@@ -0,0 +1,7 @@
+export default function CyclesPage() {
+ return (
+
+
Cycles
+
+ );
+}
diff --git a/frontend/src/app/(portal)/admin/roles/page.tsx b/frontend/src/app/(portal)/admin/roles/page.tsx
new file mode 100644
index 0000000..9fb33bb
--- /dev/null
+++ b/frontend/src/app/(portal)/admin/roles/page.tsx
@@ -0,0 +1,7 @@
+export default function RolesPage() {
+ return (
+
+
Roles
+
+ );
+}
diff --git a/frontend/src/app/(portal)/applicant/applications/page.tsx b/frontend/src/app/(portal)/applicant/applications/page.tsx
new file mode 100644
index 0000000..713e545
--- /dev/null
+++ b/frontend/src/app/(portal)/applicant/applications/page.tsx
@@ -0,0 +1,7 @@
+export default function ApplicationsPage() {
+ return (
+
+
My Applications
+
+ );
+}
diff --git a/frontend/src/app/(portal)/layout.tsx b/frontend/src/app/(portal)/layout.tsx
new file mode 100644
index 0000000..a2708a9
--- /dev/null
+++ b/frontend/src/app/(portal)/layout.tsx
@@ -0,0 +1,21 @@
+import Sidebar from "@/components/nav/Sidebar";
+import { mockUser } from "@/lib/mock-user";
+import { getRoles } from "@/types/roles";
+
+export default function PortalLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ // TODO: replace mockUser with session user from auth
+ const roles = getRoles(mockUser);
+
+ return (
+
+
+
+ {children}
+
+
+ );
+}
diff --git a/frontend/src/app/(portal)/reviewer/applicants/page.tsx b/frontend/src/app/(portal)/reviewer/applicants/page.tsx
new file mode 100644
index 0000000..6905fed
--- /dev/null
+++ b/frontend/src/app/(portal)/reviewer/applicants/page.tsx
@@ -0,0 +1,7 @@
+export default function ApplicantsPage() {
+ return (
+
+
Applicants
+
+ );
+}
diff --git a/frontend/src/app/(portal)/reviewer/dashboard/page.tsx b/frontend/src/app/(portal)/reviewer/dashboard/page.tsx
new file mode 100644
index 0000000..f6722e0
--- /dev/null
+++ b/frontend/src/app/(portal)/reviewer/dashboard/page.tsx
@@ -0,0 +1,7 @@
+export default function DashboardPage() {
+ return (
+
+
Dashboard
+
+ );
+}
diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css
index a2dc41e..a7af88f 100644
--- a/frontend/src/app/globals.css
+++ b/frontend/src/app/globals.css
@@ -8,6 +8,8 @@
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
+ --color-brand-blue: #1477f8;
+ --color-brand-white: #ffffff;
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index 976eb90..461a21d 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -13,8 +13,8 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: "Generate Portal",
+ description: "Application portal for Generate NU",
};
export default function RootLayout({
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index 3f36f7c..107f3e5 100644
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -1,65 +1,5 @@
-import Image from "next/image";
+import { redirect } from "next/navigation";
-export default function Home() {
- return (
-
-
-
-
-
- To get started, edit the page.tsx file.
-
-
- Looking for a starting point or more instructions? Head over to{" "}
-
- Templates
- {" "}
- or the{" "}
-
- Learning
- {" "}
- center.
-
-
-
-
-
- );
+export default function RootPage() {
+ redirect("/reviewer/dashboard");
}
diff --git a/frontend/src/components/nav/NavItem.tsx b/frontend/src/components/nav/NavItem.tsx
new file mode 100644
index 0000000..60483d5
--- /dev/null
+++ b/frontend/src/components/nav/NavItem.tsx
@@ -0,0 +1,33 @@
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+import type { LucideIcon } from "lucide-react";
+
+interface NavItemProps {
+ href: string;
+ label: string;
+ icon: LucideIcon;
+}
+
+export default function NavItem({ href, label, icon: Icon }: NavItemProps) {
+ const pathname = usePathname();
+ const isActive = pathname === href || pathname.startsWith(href + "/");
+
+ return (
+
+
+ {label}
+
+ );
+}
diff --git a/frontend/src/components/nav/Sidebar.tsx b/frontend/src/components/nav/Sidebar.tsx
new file mode 100644
index 0000000..dd8ce02
--- /dev/null
+++ b/frontend/src/components/nav/Sidebar.tsx
@@ -0,0 +1,92 @@
+"use client";
+
+import {
+ LayoutDashboard,
+ Users,
+ FileText,
+ RefreshCw,
+ Settings,
+ Layers,
+} from "lucide-react";
+import NavItem from "./NavItem";
+import type { Role } from "@/types/roles";
+
+interface SidebarProps {
+ roles: Role[];
+ nuid?: string;
+}
+
+type NavSection = { label: string; items: { href: string; label: string; icon: typeof FileText }[] };
+
+const sectionsByRole: Record = {
+ applicant: {
+ label: "Applications",
+ items: [
+ { href: "/applicant/applications", label: "My Applications", icon: FileText },
+ ],
+ },
+ reviewer: {
+ label: "Review",
+ items: [
+ { href: "/reviewer/dashboard", label: "Dashboard", icon: LayoutDashboard },
+ { href: "/reviewer/applicants", label: "Applicants", icon: Users },
+ ],
+ },
+ admin: {
+ label: "Admin",
+ items: [
+ { href: "/admin/cycles", label: "Cycles", icon: RefreshCw },
+ { href: "/admin/builder", label: "App Builder", icon: Layers },
+ { href: "/admin/roles", label: "Roles", icon: Settings },
+ ],
+ },
+};
+
+// Display order: reviewer sections before applicant, admin last
+const roleOrder: Role[] = ["reviewer", "applicant", "admin"];
+
+export default function Sidebar({ roles, nuid }: SidebarProps) {
+ const sections = roleOrder
+ .filter((role) => roles.includes(role))
+ .map((role) => sectionsByRole[role]);
+
+ return (
+
+ );
+}
diff --git a/frontend/src/lib/mock-user.ts b/frontend/src/lib/mock-user.ts
new file mode 100644
index 0000000..49607ae
--- /dev/null
+++ b/frontend/src/lib/mock-user.ts
@@ -0,0 +1,7 @@
+import type { User } from "@/types/user";
+
+export const mockUser: User = {
+ nuid: "002139999",
+ is_reviewer: true,
+ is_admin: false,
+};
diff --git a/frontend/src/types/roles.ts b/frontend/src/types/roles.ts
new file mode 100644
index 0000000..3f99ea2
--- /dev/null
+++ b/frontend/src/types/roles.ts
@@ -0,0 +1,10 @@
+import type { User } from "./user";
+
+export type Role = "applicant" | "reviewer" | "admin";
+
+export function getRoles(user: User): Role[] {
+ const roles: Role[] = ["applicant"];
+ if (user.is_reviewer) roles.push("reviewer");
+ if (user.is_admin) roles.push("admin");
+ return roles;
+}
diff --git a/frontend/src/types/user.ts b/frontend/src/types/user.ts
new file mode 100644
index 0000000..6eca3df
--- /dev/null
+++ b/frontend/src/types/user.ts
@@ -0,0 +1,5 @@
+export interface User {
+ nuid: string;
+ is_reviewer: boolean;
+ is_admin: boolean;
+}
From 234f8edcbaddc5780c5025bfe633bf7b3c3ebf95 Mon Sep 17 00:00:00 2001
From: Dao Ho <84757503+Dao-Ho@users.noreply.github.com>
Date: Sun, 14 Jun 2026 19:09:06 -0700
Subject: [PATCH 2/4] format
---
frontend/AGENTS.md | 2 +
frontend/eslint.config.mjs | 18 +++---
frontend/next.config.ts | 6 +-
frontend/postcss.config.mjs | 6 +-
.../src/app/(portal)/admin/builder/page.tsx | 2 +-
.../src/app/(portal)/admin/cycles/page.tsx | 2 +-
.../src/app/(portal)/admin/roles/page.tsx | 2 +-
.../(portal)/applicant/applications/page.tsx | 2 +-
frontend/src/app/(portal)/layout.tsx | 12 ++--
.../app/(portal)/reviewer/applicants/page.tsx | 2 +-
.../app/(portal)/reviewer/dashboard/page.tsx | 2 +-
frontend/src/app/globals.css | 2 +-
frontend/src/app/layout.tsx | 30 ++++-----
frontend/src/app/page.tsx | 4 +-
frontend/src/components/nav/NavItem.tsx | 26 ++++----
frontend/src/components/nav/Sidebar.tsx | 61 +++++++++++--------
frontend/src/lib/mock-user.ts | 6 +-
frontend/src/types/roles.ts | 12 ++--
frontend/src/types/user.ts | 6 +-
19 files changed, 108 insertions(+), 95 deletions(-)
diff --git a/frontend/AGENTS.md b/frontend/AGENTS.md
index 8bd0e39..c153a9b 100644
--- a/frontend/AGENTS.md
+++ b/frontend/AGENTS.md
@@ -1,5 +1,7 @@
+
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
+
diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs
index 05e726d..7fef4d3 100644
--- a/frontend/eslint.config.mjs
+++ b/frontend/eslint.config.mjs
@@ -1,6 +1,6 @@
-import { defineConfig, globalIgnores } from "eslint/config";
-import nextVitals from "eslint-config-next/core-web-vitals";
-import nextTs from "eslint-config-next/typescript";
+import { defineConfig, globalIgnores } from 'eslint/config'
+import nextVitals from 'eslint-config-next/core-web-vitals'
+import nextTs from 'eslint-config-next/typescript'
const eslintConfig = defineConfig([
...nextVitals,
@@ -8,11 +8,11 @@ const eslintConfig = defineConfig([
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
- ".next/**",
- "out/**",
- "build/**",
- "next-env.d.ts",
+ '.next/**',
+ 'out/**',
+ 'build/**',
+ 'next-env.d.ts',
]),
-]);
+])
-export default eslintConfig;
+export default eslintConfig
diff --git a/frontend/next.config.ts b/frontend/next.config.ts
index 66e1566..b0d9a6a 100644
--- a/frontend/next.config.ts
+++ b/frontend/next.config.ts
@@ -1,8 +1,8 @@
-import type { NextConfig } from "next";
+import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
/* config options here */
reactCompiler: true,
-};
+}
-export default nextConfig;
+export default nextConfig
diff --git a/frontend/postcss.config.mjs b/frontend/postcss.config.mjs
index 61e3684..ae85b2f 100644
--- a/frontend/postcss.config.mjs
+++ b/frontend/postcss.config.mjs
@@ -1,7 +1,7 @@
const config = {
plugins: {
- "@tailwindcss/postcss": {},
+ '@tailwindcss/postcss': {},
},
-};
+}
-export default config;
+export default config
diff --git a/frontend/src/app/(portal)/admin/builder/page.tsx b/frontend/src/app/(portal)/admin/builder/page.tsx
index 769e70b..a537585 100644
--- a/frontend/src/app/(portal)/admin/builder/page.tsx
+++ b/frontend/src/app/(portal)/admin/builder/page.tsx
@@ -3,5 +3,5 @@ export default function BuilderPage() {
App Builder
- );
+ )
}
diff --git a/frontend/src/app/(portal)/admin/cycles/page.tsx b/frontend/src/app/(portal)/admin/cycles/page.tsx
index ca084eb..702bf28 100644
--- a/frontend/src/app/(portal)/admin/cycles/page.tsx
+++ b/frontend/src/app/(portal)/admin/cycles/page.tsx
@@ -3,5 +3,5 @@ export default function CyclesPage() {
Cycles
- );
+ )
}
diff --git a/frontend/src/app/(portal)/admin/roles/page.tsx b/frontend/src/app/(portal)/admin/roles/page.tsx
index 9fb33bb..1c4a3e1 100644
--- a/frontend/src/app/(portal)/admin/roles/page.tsx
+++ b/frontend/src/app/(portal)/admin/roles/page.tsx
@@ -3,5 +3,5 @@ export default function RolesPage() {
Roles
- );
+ )
}
diff --git a/frontend/src/app/(portal)/applicant/applications/page.tsx b/frontend/src/app/(portal)/applicant/applications/page.tsx
index 713e545..143adc7 100644
--- a/frontend/src/app/(portal)/applicant/applications/page.tsx
+++ b/frontend/src/app/(portal)/applicant/applications/page.tsx
@@ -3,5 +3,5 @@ export default function ApplicationsPage() {
My Applications
- );
+ )
}
diff --git a/frontend/src/app/(portal)/layout.tsx b/frontend/src/app/(portal)/layout.tsx
index a2708a9..d6c4384 100644
--- a/frontend/src/app/(portal)/layout.tsx
+++ b/frontend/src/app/(portal)/layout.tsx
@@ -1,14 +1,14 @@
-import Sidebar from "@/components/nav/Sidebar";
-import { mockUser } from "@/lib/mock-user";
-import { getRoles } from "@/types/roles";
+import Sidebar from '@/components/nav/Sidebar'
+import { mockUser } from '@/lib/mock-user'
+import { getRoles } from '@/types/roles'
export default function PortalLayout({
children,
}: {
- children: React.ReactNode;
+ children: React.ReactNode
}) {
// TODO: replace mockUser with session user from auth
- const roles = getRoles(mockUser);
+ const roles = getRoles(mockUser)
return (
@@ -17,5 +17,5 @@ export default function PortalLayout({
{children}
- );
+ )
}
diff --git a/frontend/src/app/(portal)/reviewer/applicants/page.tsx b/frontend/src/app/(portal)/reviewer/applicants/page.tsx
index 6905fed..b0d91ff 100644
--- a/frontend/src/app/(portal)/reviewer/applicants/page.tsx
+++ b/frontend/src/app/(portal)/reviewer/applicants/page.tsx
@@ -3,5 +3,5 @@ export default function ApplicantsPage() {
Applicants
- );
+ )
}
diff --git a/frontend/src/app/(portal)/reviewer/dashboard/page.tsx b/frontend/src/app/(portal)/reviewer/dashboard/page.tsx
index f6722e0..7a594d1 100644
--- a/frontend/src/app/(portal)/reviewer/dashboard/page.tsx
+++ b/frontend/src/app/(portal)/reviewer/dashboard/page.tsx
@@ -3,5 +3,5 @@ export default function DashboardPage() {
Dashboard
- );
+ )
}
diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css
index a7af88f..5628d86 100644
--- a/frontend/src/app/globals.css
+++ b/frontend/src/app/globals.css
@@ -1,4 +1,4 @@
-@import "tailwindcss";
+@import 'tailwindcss';
:root {
--background: #ffffff;
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index 461a21d..03ed81d 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -1,33 +1,33 @@
-import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
-import "./globals.css";
+import type { Metadata } from 'next'
+import { Geist, Geist_Mono } from 'next/font/google'
+import './globals.css'
const geistSans = Geist({
- variable: "--font-geist-sans",
- subsets: ["latin"],
-});
+ variable: '--font-geist-sans',
+ subsets: ['latin'],
+})
const geistMono = Geist_Mono({
- variable: "--font-geist-mono",
- subsets: ["latin"],
-});
+ variable: '--font-geist-mono',
+ subsets: ['latin'],
+})
export const metadata: Metadata = {
- title: "Generate Portal",
- description: "Application portal for Generate NU",
-};
+ title: 'Generate Portal',
+ description: 'Application portal for Generate NU',
+}
export default function RootLayout({
children,
}: Readonly<{
- children: React.ReactNode;
+ children: React.ReactNode
}>) {
return (
- {children}
+ {children}
- );
+ )
}
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index 107f3e5..d65b2c3 100644
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -1,5 +1,5 @@
-import { redirect } from "next/navigation";
+import { redirect } from 'next/navigation'
export default function RootPage() {
- redirect("/reviewer/dashboard");
+ redirect('/reviewer/dashboard')
}
diff --git a/frontend/src/components/nav/NavItem.tsx b/frontend/src/components/nav/NavItem.tsx
index 60483d5..0b6652c 100644
--- a/frontend/src/components/nav/NavItem.tsx
+++ b/frontend/src/components/nav/NavItem.tsx
@@ -1,33 +1,33 @@
-"use client";
+'use client'
-import Link from "next/link";
-import { usePathname } from "next/navigation";
-import type { LucideIcon } from "lucide-react";
+import Link from 'next/link'
+import { usePathname } from 'next/navigation'
+import type { LucideIcon } from 'lucide-react'
interface NavItemProps {
- href: string;
- label: string;
- icon: LucideIcon;
+ href: string
+ label: string
+ icon: LucideIcon
}
export default function NavItem({ href, label, icon: Icon }: NavItemProps) {
- const pathname = usePathname();
- const isActive = pathname === href || pathname.startsWith(href + "/");
+ const pathname = usePathname()
+ const isActive = pathname === href || pathname.startsWith(href + '/')
return (
{label}
- );
+ )
}
diff --git a/frontend/src/components/nav/Sidebar.tsx b/frontend/src/components/nav/Sidebar.tsx
index dd8ce02..6601ca7 100644
--- a/frontend/src/components/nav/Sidebar.tsx
+++ b/frontend/src/components/nav/Sidebar.tsx
@@ -1,4 +1,4 @@
-"use client";
+'use client'
import {
LayoutDashboard,
@@ -7,54 +7,65 @@ import {
RefreshCw,
Settings,
Layers,
-} from "lucide-react";
-import NavItem from "./NavItem";
-import type { Role } from "@/types/roles";
+} from 'lucide-react'
+import NavItem from './NavItem'
+import type { Role } from '@/types/roles'
interface SidebarProps {
- roles: Role[];
- nuid?: string;
+ roles: Role[]
+ nuid?: string
}
-type NavSection = { label: string; items: { href: string; label: string; icon: typeof FileText }[] };
+type NavSection = {
+ label: string
+ items: { href: string; label: string; icon: typeof FileText }[]
+}
const sectionsByRole: Record = {
applicant: {
- label: "Applications",
+ label: 'Applications',
items: [
- { href: "/applicant/applications", label: "My Applications", icon: FileText },
+ {
+ href: '/applicant/applications',
+ label: 'My Applications',
+ icon: FileText,
+ },
],
},
reviewer: {
- label: "Review",
+ label: 'Review',
items: [
- { href: "/reviewer/dashboard", label: "Dashboard", icon: LayoutDashboard },
- { href: "/reviewer/applicants", label: "Applicants", icon: Users },
+ {
+ href: '/reviewer/dashboard',
+ label: 'Dashboard',
+ icon: LayoutDashboard,
+ },
+ { href: '/reviewer/applicants', label: 'Applicants', icon: Users },
],
},
admin: {
- label: "Admin",
+ label: 'Admin',
items: [
- { href: "/admin/cycles", label: "Cycles", icon: RefreshCw },
- { href: "/admin/builder", label: "App Builder", icon: Layers },
- { href: "/admin/roles", label: "Roles", icon: Settings },
+ { href: '/admin/cycles', label: 'Cycles', icon: RefreshCw },
+ { href: '/admin/builder', label: 'App Builder', icon: Layers },
+ { href: '/admin/roles', label: 'Roles', icon: Settings },
],
},
-};
+}
// Display order: reviewer sections before applicant, admin last
-const roleOrder: Role[] = ["reviewer", "applicant", "admin"];
+const roleOrder: Role[] = ['reviewer', 'applicant', 'admin']
export default function Sidebar({ roles, nuid }: SidebarProps) {
const sections = roleOrder
.filter((role) => roles.includes(role))
- .map((role) => sectionsByRole[role]);
+ .map((role) => sectionsByRole[role])
return (