From 9c7ae39ee46354143216a15179d1fc0bc16cf5a4 Mon Sep 17 00:00:00 2001 From: gavinlin24 Date: Wed, 6 May 2026 22:29:16 -0700 Subject: [PATCH 1/3] feat(admin): redesign login page with split-panel layout Replace the inline-styled centered card on /admin/login with a Tailwind split-panel that matches the Figma. Left panel renders the BSL branding, headline, and three stat blocks; right panel hosts the sign-in surface. Email/password fields are visual-only (login is out of scope) and the Google SSO button drops into the "Continue with SSO" Figma slot, keeping the existing signIn("google") + useSession() redirect untouched. --- app/admin/login/page.tsx | 264 +++++++++++++++++++++++++++------------ 1 file changed, 186 insertions(+), 78 deletions(-) diff --git a/app/admin/login/page.tsx b/app/admin/login/page.tsx index 0e68d59..899a648 100644 --- a/app/admin/login/page.tsx +++ b/app/admin/login/page.tsx @@ -1,78 +1,186 @@ -"use client"; - -import { useSession, signIn } from "next-auth/react"; -import { useRouter } from "next/navigation"; -import { useEffect } from "react"; - -export default function AdminLoginPage() { - const { data: session, status } = useSession(); - const router = useRouter(); - - useEffect(() => { - if (session) { - router.push("/admin"); - } - }, [session, router]); - - if (status === "loading" || status === "authenticated") { - return ( -
- Loading... -
- ); - } - - return ( -
-
-

- Admin Login -

- -

- Sign in to access the dashboard -

- - -
-
- ); -} +// Renders outside the admin sidebar — see BSL-51 +"use client"; + +import { useSession, signIn } from "next-auth/react"; +import { useRouter } from "next/navigation"; +import { useEffect } from "react"; +import Image from "next/image"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; + +export default function AdminLoginPage() { + const { data: session, status } = useSession(); + const router = useRouter(); + + useEffect(() => { + if (session) { + router.push("/admin"); + } + }, [session, router]); + + if (status === "loading" || status === "authenticated") { + return ( +
+

Loading…

+
+ ); + } + + return ( +
+ {/* Left panel — marketing / branded surface */} + + + {/* Right panel — sign-in surface */} +
+
+
+

Admin Sign In

+

+ Use your BSL corporate credentials. All access is logged and + audited. +

+
+ + {/* TODO: email/password login is out of scope — fields are visual only */} +
e.preventDefault()} + className="space-y-4" + > +
+ + +
+ +
+ + +
+ + + + +
+ + {/* Divider */} +
+
+ + or + +
+
+ + {/* Google SSO — replaces the "Continue with SSO" Figma slot */} + + + {/* Restricted-system warning */} +
+

+ This is a restricted system for authorised BSL personnel only. + Unauthorised access attempts are logged and may be subject to + disciplinary or legal action. +

+
+
+
+
+ ); +} From 336b959a48c5e7115f6efa9ac8479d931bd63dda Mon Sep 17 00:00:00 2001 From: gavinlin24 Date: Wed, 6 May 2026 22:29:20 -0700 Subject: [PATCH 2/3] docs(readme): document admin access via seed script Add a brief "Accessing the Admin Section" section so a dev with the project already running can grant themselves admin access in three steps: edit prisma/seed.ts, run npm run seed, sign in at /admin/login. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index ae6fb6a..934824f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ # BSL Platform +## Accessing the Admin Section + +To grant yourself admin access locally: + +1. Edit `prisma/seed.ts` and add your Google email to `SEED_USERS` with a role (`USER`, `REVIEWER`, `AMBASSADOR`, or `SUPER_ADMIN` — use `SUPER_ADMIN` for full access). +2. Run `npm run seed`. The script is idempotent, so it's safe to re-run. +3. Visit `/admin/login` and sign in with Google. + ## How to Seed Roles To assign roles to users for testing RBAC/admin features: From 19d515c151167bdc794469224aac55cbf9bb251c Mon Sep 17 00:00:00 2001 From: gavinlin24 Date: Wed, 6 May 2026 23:12:33 -0700 Subject: [PATCH 3/3] refactor(admin/login): polish styling and copy - Switch to pink palette and transparent logo - Extract STATS, INPUT_CLASSES, PINK_BUTTON_CLASSES - Use raw HTML inputs/buttons (shared Button/Input lock to sky-400/rounded-full) - Make form copy generic (drop BSL-specific placeholder, label, subtitle) - Remove section comments and simplify TODOs --- app/admin/login/page.tsx | 160 +++++++++++++++----------------- public/bsl-logo-transparent.png | Bin 0 -> 122602 bytes 2 files changed, 77 insertions(+), 83 deletions(-) create mode 100644 public/bsl-logo-transparent.png diff --git a/app/admin/login/page.tsx b/app/admin/login/page.tsx index 899a648..e60a44d 100644 --- a/app/admin/login/page.tsx +++ b/app/admin/login/page.tsx @@ -1,13 +1,22 @@ -// Renders outside the admin sidebar — see BSL-51 "use client"; import { useSession, signIn } from "next-auth/react"; import { useRouter } from "next/navigation"; import { useEffect } from "react"; import Image from "next/image"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; + +// TODO: confirm stats values and labels +const STATS = [ + { value: "2,418", label: "Startups Onboarded" }, + { value: "$847M", label: "Startups Onboarded" }, + { value: "326", label: "Startups Onboarded" }, +]; + +const INPUT_CLASSES = + "block w-full rounded-md border border-stone-300 bg-white px-4 py-2.5 text-sm text-stone-900 placeholder:text-stone-400 focus:outline-none focus:ring-2 focus:ring-stone-500/30"; + +const PINK_BUTTON_CLASSES = + "w-full rounded-md border border-[#D9A8A8] bg-[#F5C3C399] px-4 py-2.5 text-sm font-medium text-stone-900 transition-colors hover:bg-[#F5C3C3]"; export default function AdminLoginPage() { const { data: session, status } = useSession(); @@ -21,160 +30,145 @@ export default function AdminLoginPage() { if (status === "loading" || status === "authenticated") { return ( -
-

Loading…

+
+

Loading…

); } return (
- {/* Left panel — marketing / branded surface */} -