From 1d748042214c4e686b1c7ec280223099284a364c Mon Sep 17 00:00:00 2001 From: Haylie Tan Date: Wed, 11 Mar 2026 22:56:40 -0700 Subject: [PATCH 01/15] added init files --- app/(pages)/(hackers)/(hub)/page.tsx | 2 +- .../_components/AuthForms/RegisterForm.tsx | 6 +- app/(pages)/(hackers)/register/page.tsx | 22 +++-- app/(pages)/_components/RegisterFlow.tsx | 85 +++++++++++++++++++ .../_components/slides/ChooseLevel.tsx | 44 ++++++++++ app/(pages)/_components/slides/ChooseRole.tsx | 44 ++++++++++ 6 files changed, 189 insertions(+), 14 deletions(-) create mode 100644 app/(pages)/_components/RegisterFlow.tsx create mode 100644 app/(pages)/_components/slides/ChooseLevel.tsx create mode 100644 app/(pages)/_components/slides/ChooseRole.tsx diff --git a/app/(pages)/(hackers)/(hub)/page.tsx b/app/(pages)/(hackers)/(hub)/page.tsx index bf6ae3c6..fb312cc5 100644 --- a/app/(pages)/(hackers)/(hub)/page.tsx +++ b/app/(pages)/(hackers)/(hub)/page.tsx @@ -31,7 +31,7 @@ export default function Page() { {/* temporarilty set featureId below to "hero-hacking" to test */} - + diff --git a/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx b/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx index 83ed3d3f..23b30718 100644 --- a/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx +++ b/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx @@ -5,7 +5,7 @@ import { useRouter } from 'next/navigation'; import AuthForm from '@components/AuthForm/AuthForm'; import RegisterAction from '@actions/auth/register'; -export default function RegisterForm({ data }: any) { +export default function RegisterForm({ data, onSuccess: onSuccessProp }: { data: any; onSuccess?: () => void }) { const router = useRouter(); const name = data?.name ?? 'HackDavis Admin'; @@ -24,6 +24,10 @@ export default function RegisterForm({ data }: any) { const onSuccess = () => { if (role === 'admin') { router.push('/'); + return; + } + if (onSuccessProp) { + onSuccessProp(); } else { router.push('/register/details'); } diff --git a/app/(pages)/(hackers)/register/page.tsx b/app/(pages)/(hackers)/register/page.tsx index b421fe5c..2691048d 100644 --- a/app/(pages)/(hackers)/register/page.tsx +++ b/app/(pages)/(hackers)/register/page.tsx @@ -2,9 +2,9 @@ import { redirect } from 'next/navigation'; import { auth } from '@/auth'; import { getInviteData } from '@actions/invite/getInviteData'; -import RegisterForm from '../_components/AuthForms/RegisterForm'; + +import RegisterFlow from '@pages/_components/RegisterFlow'; import AuthFormBackground from '../_components/AuthFormBackground/AuthFormBackground'; -import InviteOnlyRoute from '@components/InviteOnlyRoute/InviteOnlyRoute'; export default async function RegisterPage() { const session = await auth(); @@ -17,14 +17,12 @@ export default async function RegisterPage() { } return ( - - - - - + + + ); -} +} \ No newline at end of file diff --git a/app/(pages)/_components/RegisterFlow.tsx b/app/(pages)/_components/RegisterFlow.tsx new file mode 100644 index 00000000..f01211a6 --- /dev/null +++ b/app/(pages)/_components/RegisterFlow.tsx @@ -0,0 +1,85 @@ +'use client'; + +import { useState } from 'react'; +import { useRouter } from 'next/navigation'; + +import RegisterForm from '@pages/(hackers)/_components/AuthForms/RegisterForm'; +import ChooseRole from './slides/ChooseRole'; +import ChooseLevel from './slides/ChooseLevel'; + +type RegisterFlowProps = { + data?: any; +}; + +type OnboardingFormData = { + role?: string; + level?: string; +}; + +export default function RegisterFlow({ data }: RegisterFlowProps) { + const router = useRouter(); + + const [stage, setStage] = useState<0 | 1 | 2>(0); + const [formData, setFormData] = useState({}); + + return ( +
+ {stage === 0 && ( + <> + setStage(1)} + /> + + + + )} + + {stage === 1 && ( + <> + { + setFormData((prev) => ({ ...prev, role: value })); + setStage(2); + }} + /> + + + + )} + + {stage === 2 && ( + <> + { + setFormData((prev) => ({ ...prev, level: value })); + router.push('/register/details'); + }} + /> + + + + )} +
+ ); +} \ No newline at end of file diff --git a/app/(pages)/_components/slides/ChooseLevel.tsx b/app/(pages)/_components/slides/ChooseLevel.tsx new file mode 100644 index 00000000..cb4d752a --- /dev/null +++ b/app/(pages)/_components/slides/ChooseLevel.tsx @@ -0,0 +1,44 @@ +'use client'; + +type ChooseLevelProps = { + value?: string; + onSelect: (value: string) => void; +}; + +const LEVELS = ['Beginner', 'Intermediate', 'Advanced'] as const; + +export default function ChooseLevel({ value, onSelect }: ChooseLevelProps) { + return ( +
+
+

+ How experienced are you? +

+

+ We'll use this to suggest the right resources. +

+
+ +
+ {LEVELS.map((level) => { + const selected = value === level; + return ( + + ); + })} +
+
+ ); +} + diff --git a/app/(pages)/_components/slides/ChooseRole.tsx b/app/(pages)/_components/slides/ChooseRole.tsx new file mode 100644 index 00000000..3ff934e0 --- /dev/null +++ b/app/(pages)/_components/slides/ChooseRole.tsx @@ -0,0 +1,44 @@ +'use client'; + +type ChooseRoleProps = { + value?: string; + onSelect: (value: string) => void; +}; + +const ROLES = ['Developer', 'Designer', 'Product', 'Explorer'] as const; + +export default function ChooseRole({ value, onSelect }: ChooseRoleProps) { + return ( +
+
+

+ Tell us about your role +

+

+ This helps us tailor your HackDavis experience. +

+
+ +
+ {ROLES.map((role) => { + const selected = value === role; + return ( + + ); + })} +
+
+ ); +} + From 2dbac5ea1a0548e37fe9ab40f9f115b22f388848 Mon Sep 17 00:00:00 2001 From: Haylie Tan Date: Wed, 11 Mar 2026 23:16:02 -0700 Subject: [PATCH 02/15] carousel impl --- app/(pages)/(hackers)/register/page.tsx | 5 +- app/(pages)/_components/RegisterFlow.tsx | 95 +++++++------------ .../register-flow/stages/LevelStage.tsx | 42 ++++++++ .../register-flow/stages/PasswordStage.tsx | 30 ++++++ .../register-flow/stages/RoleStage.tsx | 42 ++++++++ 5 files changed, 151 insertions(+), 63 deletions(-) create mode 100644 app/(pages)/_components/register-flow/stages/LevelStage.tsx create mode 100644 app/(pages)/_components/register-flow/stages/PasswordStage.tsx create mode 100644 app/(pages)/_components/register-flow/stages/RoleStage.tsx diff --git a/app/(pages)/(hackers)/register/page.tsx b/app/(pages)/(hackers)/register/page.tsx index 2691048d..4232c4d9 100644 --- a/app/(pages)/(hackers)/register/page.tsx +++ b/app/(pages)/(hackers)/register/page.tsx @@ -18,9 +18,8 @@ export default async function RegisterPage() { return ( diff --git a/app/(pages)/_components/RegisterFlow.tsx b/app/(pages)/_components/RegisterFlow.tsx index f01211a6..b999dcbb 100644 --- a/app/(pages)/_components/RegisterFlow.tsx +++ b/app/(pages)/_components/RegisterFlow.tsx @@ -3,9 +3,9 @@ import { useState } from 'react'; import { useRouter } from 'next/navigation'; -import RegisterForm from '@pages/(hackers)/_components/AuthForms/RegisterForm'; -import ChooseRole from './slides/ChooseRole'; -import ChooseLevel from './slides/ChooseLevel'; +import PasswordStage from './register-flow/stages/PasswordStage'; +import RoleStage from './register-flow/stages/RoleStage'; +import LevelStage from './register-flow/stages/LevelStage'; type RegisterFlowProps = { data?: any; @@ -22,64 +22,39 @@ export default function RegisterFlow({ data }: RegisterFlowProps) { const [stage, setStage] = useState<0 | 1 | 2>(0); const [formData, setFormData] = useState({}); - return ( -
- {stage === 0 && ( - <> - setStage(1)} - /> - - - - )} - - {stage === 1 && ( - <> - { - setFormData((prev) => ({ ...prev, role: value })); - setStage(2); - }} - /> + const goNext = () => setStage((s) => (s === 2 ? s : ((s + 1) as 0 | 1 | 2))); + const goBack = () => setStage((s) => (s === 0 ? s : ((s - 1) as 0 | 1 | 2))); - - - )} - - {stage === 2 && ( - <> - { - setFormData((prev) => ({ ...prev, level: value })); - router.push('/register/details'); - }} - /> - - - - )} + return ( +
+
+
+
+ setStage(1)} /> +
+ +
+ setFormData((prev) => ({ ...prev, role: value }))} + onBack={goBack} + onNext={goNext} + /> +
+ +
+ setFormData((prev) => ({ ...prev, level: value }))} + onBack={goBack} + onNext={() => router.push('/register/details')} + /> +
+
+
); } \ No newline at end of file diff --git a/app/(pages)/_components/register-flow/stages/LevelStage.tsx b/app/(pages)/_components/register-flow/stages/LevelStage.tsx new file mode 100644 index 00000000..7c6b302b --- /dev/null +++ b/app/(pages)/_components/register-flow/stages/LevelStage.tsx @@ -0,0 +1,42 @@ +'use client'; + +import ChooseLevel from '../../slides/ChooseLevel'; + +type LevelStageProps = { + value?: string; + onSelect: (value: string) => void; + onBack: () => void; + onNext: () => void; +}; + +export default function LevelStage({ + value, + onSelect, + onBack, + onNext, +}: LevelStageProps) { + return ( +
+ + +
+ + +
+
+ ); +} + diff --git a/app/(pages)/_components/register-flow/stages/PasswordStage.tsx b/app/(pages)/_components/register-flow/stages/PasswordStage.tsx new file mode 100644 index 00000000..d4cc5a13 --- /dev/null +++ b/app/(pages)/_components/register-flow/stages/PasswordStage.tsx @@ -0,0 +1,30 @@ +'use client'; + +import RegisterForm from '@pages/(hackers)/_components/AuthForms/RegisterForm'; + +type PasswordStageProps = { + data?: any; + onNext: () => void; +}; + +export default function PasswordStage({ data, onNext }: PasswordStageProps) { + return ( + <> +
+

+ Hi {data?.name ?? 'HackDavis Admin'}! +

+

+ Welcome to the HackerHub! The HackDavis team made this for all your hacking needs + {' <3'} + {'\n'}Let's get you started. +

+
+ + + ); +} + diff --git a/app/(pages)/_components/register-flow/stages/RoleStage.tsx b/app/(pages)/_components/register-flow/stages/RoleStage.tsx new file mode 100644 index 00000000..1d3d307b --- /dev/null +++ b/app/(pages)/_components/register-flow/stages/RoleStage.tsx @@ -0,0 +1,42 @@ +'use client'; + +import ChooseRole from '../../slides/ChooseRole'; + +type RoleStageProps = { + value?: string; + onSelect: (value: string) => void; + onBack: () => void; + onNext: () => void; +}; + +export default function RoleStage({ + value, + onSelect, + onBack, + onNext, +}: RoleStageProps) { + return ( +
+ + +
+ + +
+
+ ); +} + From 6a4dacbd66b7762a5158b2fdcc40a36e4690fea3 Mon Sep 17 00:00:00 2001 From: Haylie Tan Date: Wed, 11 Mar 2026 23:24:14 -0700 Subject: [PATCH 03/15] role stage upadte --- .../register-flow/stages/PasswordStage.tsx | 3 +- .../register-flow/stages/RoleStage.tsx | 110 +++++++++++++----- 2 files changed, 81 insertions(+), 32 deletions(-) diff --git a/app/(pages)/_components/register-flow/stages/PasswordStage.tsx b/app/(pages)/_components/register-flow/stages/PasswordStage.tsx index d4cc5a13..c53dfd78 100644 --- a/app/(pages)/_components/register-flow/stages/PasswordStage.tsx +++ b/app/(pages)/_components/register-flow/stages/PasswordStage.tsx @@ -1,5 +1,4 @@ 'use client'; - import RegisterForm from '@pages/(hackers)/_components/AuthForms/RegisterForm'; type PasswordStageProps = { @@ -24,6 +23,8 @@ export default function PasswordStage({ data, onNext }: PasswordStageProps) {

+ + {/* DEV BUTTON */} ); } diff --git a/app/(pages)/_components/register-flow/stages/RoleStage.tsx b/app/(pages)/_components/register-flow/stages/RoleStage.tsx index 1d3d307b..d34ab91d 100644 --- a/app/(pages)/_components/register-flow/stages/RoleStage.tsx +++ b/app/(pages)/_components/register-flow/stages/RoleStage.tsx @@ -1,42 +1,90 @@ 'use client'; -import ChooseRole from '../../slides/ChooseRole'; +import Image from 'next/image'; -type RoleStageProps = { +type ChooseRoleProps = { value?: string; onSelect: (value: string) => void; - onBack: () => void; - onNext: () => void; }; -export default function RoleStage({ - value, - onSelect, - onBack, - onNext, -}: RoleStageProps) { - return ( -
- +const roles = [ + { + id: 'developer', + label: 'Developer', + image: '/characters/developer.png', + }, + { + id: 'designer', + label: 'Designer', + image: '/characters/designer.png', + }, + { + id: 'product', + label: 'Product', + image: '/characters/product.png', + }, + { + id: 'explorer', + label: 'Explorer', + image: '/characters/explorer.png', + }, +]; -
- - +export default function ChooseRole({ value, onSelect }: ChooseRoleProps) { + return ( + <> + {/* header */} +
+

+ Choose what suits you the most: +

+

+ This will help us recommend workshops to you! +

+ +
+ {roles.map((role) => { + const selected = value === role.id; + + return ( + + ); + })}
+ ); -} - +} \ No newline at end of file From 4a7388e15cf5558223edcaef6810fee454627c21 Mon Sep 17 00:00:00 2001 From: Haylie Tan Date: Wed, 11 Mar 2026 23:35:57 -0700 Subject: [PATCH 04/15] add svsgs --- public/hackers/register/designer-bunny.svg | 42 ++++++++++++++++++++ public/hackers/register/dev-cow.svg | 41 ++++++++++++++++++++ public/hackers/register/explorer-duck.svg | 45 ++++++++++++++++++++++ public/hackers/register/product-frog.svg | 29 ++++++++++++++ 4 files changed, 157 insertions(+) create mode 100644 public/hackers/register/designer-bunny.svg create mode 100644 public/hackers/register/dev-cow.svg create mode 100644 public/hackers/register/explorer-duck.svg create mode 100644 public/hackers/register/product-frog.svg diff --git a/public/hackers/register/designer-bunny.svg b/public/hackers/register/designer-bunny.svg new file mode 100644 index 00000000..228c44a5 --- /dev/null +++ b/public/hackers/register/designer-bunny.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/hackers/register/dev-cow.svg b/public/hackers/register/dev-cow.svg new file mode 100644 index 00000000..221e7061 --- /dev/null +++ b/public/hackers/register/dev-cow.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/hackers/register/explorer-duck.svg b/public/hackers/register/explorer-duck.svg new file mode 100644 index 00000000..a01f6056 --- /dev/null +++ b/public/hackers/register/explorer-duck.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/hackers/register/product-frog.svg b/public/hackers/register/product-frog.svg new file mode 100644 index 00000000..637a53f8 --- /dev/null +++ b/public/hackers/register/product-frog.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 8232d4466301aa08803ef645b180ec8074603404 Mon Sep 17 00:00:00 2001 From: Haylie Tan Date: Wed, 11 Mar 2026 23:52:22 -0700 Subject: [PATCH 05/15] Updated UI For RoleStage --- .../register-flow/stages/RoleStage.tsx | 135 ++++++++++++------ 1 file changed, 90 insertions(+), 45 deletions(-) diff --git a/app/(pages)/_components/register-flow/stages/RoleStage.tsx b/app/(pages)/_components/register-flow/stages/RoleStage.tsx index d34ab91d..753132ec 100644 --- a/app/(pages)/_components/register-flow/stages/RoleStage.tsx +++ b/app/(pages)/_components/register-flow/stages/RoleStage.tsx @@ -5,36 +5,43 @@ import Image from 'next/image'; type ChooseRoleProps = { value?: string; onSelect: (value: string) => void; + onBack: () => void; + onNext: () => void; }; const roles = [ { id: 'developer', label: 'Developer', - image: '/characters/developer.png', + image: '/hackers/register/dev-cow.svg', }, { id: 'designer', label: 'Designer', - image: '/characters/designer.png', + image: '/hackers/register/designer-bunny.svg', }, { id: 'product', label: 'Product', - image: '/characters/product.png', + image: '/hackers/register/product-frog.svg', }, { id: 'explorer', label: 'Explorer', - image: '/characters/explorer.png', + image: '/hackers/register/explorer-duck.svg', }, ]; -export default function ChooseRole({ value, onSelect }: ChooseRoleProps) { +export default function ChooseRole({ + value, + onSelect, + onBack, + onNext, +}: ChooseRoleProps) { return ( <> - {/* header */} -
+ {/* header */} +

Choose what suits you the most:

@@ -42,49 +49,87 @@ export default function ChooseRole({ value, onSelect }: ChooseRoleProps) { This will help us recommend workshops to you!

- -
- {roles.map((role) => { - const selected = value === role.id; - return ( + {/* cards */} +
+ {roles.map((role) => { + const selected = value === role.id; + + return ( + + ); + })} +
+ + {/* Bottom navigation */} +
+ {/* indicators */} +
+
+
+
+ + {/* nav buttons */} +
- {/* Role label */} -
- {role.label.toUpperCase()} -
+ - ); - })} -
+
+
); } \ No newline at end of file From 04c97e45bd4aac5974a5d7df544b3c0de06b4d6f Mon Sep 17 00:00:00 2001 From: Haylie Tan Date: Thu, 12 Mar 2026 00:02:19 -0700 Subject: [PATCH 06/15] Added level stage --- .../register-flow/stages/LevelStage.tsx | 143 +++++++++++++++--- public/hackers/register/beginner-frog.svg | 19 +++ public/hackers/register/experienced-frog.svg | 22 +++ 3 files changed, 163 insertions(+), 21 deletions(-) create mode 100644 public/hackers/register/beginner-frog.svg create mode 100644 public/hackers/register/experienced-frog.svg diff --git a/app/(pages)/_components/register-flow/stages/LevelStage.tsx b/app/(pages)/_components/register-flow/stages/LevelStage.tsx index 7c6b302b..e740af3c 100644 --- a/app/(pages)/_components/register-flow/stages/LevelStage.tsx +++ b/app/(pages)/_components/register-flow/stages/LevelStage.tsx @@ -1,6 +1,6 @@ 'use client'; -import ChooseLevel from '../../slides/ChooseLevel'; +import Image from 'next/image'; type LevelStageProps = { value?: string; @@ -9,6 +9,25 @@ type LevelStageProps = { onNext: () => void; }; +const levels = [ + { + id: 'beginner', + title: 'Beginner', + tag: 'NEW TO THE SCENE', + description: + "You're here to build your foundation, explore new tools, and ship your first few projects.", + image: '/hackers/register/beginner-frog.svg', + }, + { + id: 'experienced', + title: 'Experienced', + tag: 'A SEASONED HACKER', + description: + "You're comfortable with the 36-hour grind and ready to push the boundaries of your projects.", + image: '/hackers/register/experienced-frog.svg', + }, +]; + export default function LevelStage({ value, onSelect, @@ -17,26 +36,108 @@ export default function LevelStage({ }: LevelStageProps) { return (
- - -
- - + {/* header */} +
+

+ Tell us your skill level: +

+

+ This will help us recommend workshops to you! +

+
+ + {/* cards */} +
+ {levels.map((level) => { + const selected = value === level.id; + + return ( + + ); + })} +
+ + {/* footer */} +
+ + {/* indicators */} +
+
+
+
+ + {/* nav buttons */} +
+ + + +
); -} - +} \ No newline at end of file diff --git a/public/hackers/register/beginner-frog.svg b/public/hackers/register/beginner-frog.svg new file mode 100644 index 00000000..65d3130c --- /dev/null +++ b/public/hackers/register/beginner-frog.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/hackers/register/experienced-frog.svg b/public/hackers/register/experienced-frog.svg new file mode 100644 index 00000000..6d58185c --- /dev/null +++ b/public/hackers/register/experienced-frog.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + From ff5012f0566056daeee7de476c2a0dbb91bd3721 Mon Sep 17 00:00:00 2001 From: Haylie Tan Date: Thu, 12 Mar 2026 00:14:45 -0700 Subject: [PATCH 07/15] Fixed angelic cow --- .../AuthFormBackground/AuthFormBackground.tsx | 18 +++-- app/(pages)/(hackers)/register/page.tsx | 10 +-- app/(pages)/_components/RegisterFlow.tsx | 72 ++++++++++++------- .../register-flow/stages/RoleStage.tsx | 6 +- 4 files changed, 62 insertions(+), 44 deletions(-) diff --git a/app/(pages)/(hackers)/_components/AuthFormBackground/AuthFormBackground.tsx b/app/(pages)/(hackers)/_components/AuthFormBackground/AuthFormBackground.tsx index ecab3ae4..822f0f62 100644 --- a/app/(pages)/(hackers)/_components/AuthFormBackground/AuthFormBackground.tsx +++ b/app/(pages)/(hackers)/_components/AuthFormBackground/AuthFormBackground.tsx @@ -14,10 +14,12 @@ export default function AuthFormBackground({ title, subtitle, children, + showAngelCow = true, }: { title: string; subtitle: string; children: React.ReactNode; + showAngelCow?: boolean; }) { const [mascotsVisibility, setMascotsVisibility] = useState(true); const pathname = usePathname(); @@ -35,13 +37,15 @@ export default function AuthFormBackground({
- Angel Cow + {showAngelCow && ( + Angel Cow + )}

{title}

diff --git a/app/(pages)/(hackers)/register/page.tsx b/app/(pages)/(hackers)/register/page.tsx index 4232c4d9..62d0ad7f 100644 --- a/app/(pages)/(hackers)/register/page.tsx +++ b/app/(pages)/(hackers)/register/page.tsx @@ -4,7 +4,6 @@ import { auth } from '@/auth'; import { getInviteData } from '@actions/invite/getInviteData'; import RegisterFlow from '@pages/_components/RegisterFlow'; -import AuthFormBackground from '../_components/AuthFormBackground/AuthFormBackground'; export default async function RegisterPage() { const session = await auth(); @@ -16,12 +15,5 @@ export default async function RegisterPage() { redirect('/judges/register'); } - return ( - - - - ); + return ; } \ No newline at end of file diff --git a/app/(pages)/_components/RegisterFlow.tsx b/app/(pages)/_components/RegisterFlow.tsx index b999dcbb..024832a0 100644 --- a/app/(pages)/_components/RegisterFlow.tsx +++ b/app/(pages)/_components/RegisterFlow.tsx @@ -7,6 +7,8 @@ import PasswordStage from './register-flow/stages/PasswordStage'; import RoleStage from './register-flow/stages/RoleStage'; import LevelStage from './register-flow/stages/LevelStage'; +import AuthFormBackground from '@pages/(hackers)/_components/AuthFormBackground/AuthFormBackground'; + type RegisterFlowProps = { data?: any; }; @@ -22,39 +24,55 @@ export default function RegisterFlow({ data }: RegisterFlowProps) { const [stage, setStage] = useState<0 | 1 | 2>(0); const [formData, setFormData] = useState({}); - const goNext = () => setStage((s) => (s === 2 ? s : ((s + 1) as 0 | 1 | 2))); - const goBack = () => setStage((s) => (s === 0 ? s : ((s - 1) as 0 | 1 | 2))); + const goNext = () => + setStage((s) => (s === 2 ? s : ((s + 1) as 0 | 1 | 2))); + + const goBack = () => + setStage((s) => (s === 0 ? s : ((s - 1) as 0 | 1 | 2))); return ( -
-
-
-
- setStage(1)} /> -
+ +
+
+
+ {/* PASSWORD */} +
+ setStage(1)} /> +
-
- setFormData((prev) => ({ ...prev, role: value }))} - onBack={goBack} - onNext={goNext} - /> -
+ {/* ROLE */} +
+ + setFormData((prev) => ({ ...prev, role: value })) + } + onBack={goBack} + onNext={goNext} + /> +
-
- setFormData((prev) => ({ ...prev, level: value }))} - onBack={goBack} - onNext={() => router.push('/register/details')} - /> + {/* LEVEL */} +
+ + setFormData((prev) => ({ ...prev, level: value })) + } + onBack={goBack} + onNext={() => router.push('/register/details')} + /> +
-
+
); } \ No newline at end of file diff --git a/app/(pages)/_components/register-flow/stages/RoleStage.tsx b/app/(pages)/_components/register-flow/stages/RoleStage.tsx index 753132ec..8062de1d 100644 --- a/app/(pages)/_components/register-flow/stages/RoleStage.tsx +++ b/app/(pages)/_components/register-flow/stages/RoleStage.tsx @@ -83,7 +83,11 @@ export default function ChooseRole({ className="pointer-events-none drop-shadow" /> -
+
{role.label.toUpperCase()}
From aef3d787e615cf7352a909ab0cea1f33b443a4da Mon Sep 17 00:00:00 2001 From: Haylie Tan Date: Thu, 12 Mar 2026 00:20:55 -0700 Subject: [PATCH 08/15] Updated mobile --- .../_components/AuthForms/RegisterForm.tsx | 8 +++- app/(pages)/(hackers)/register/page.tsx | 2 +- app/(pages)/_components/RegisterFlow.tsx | 14 ++---- .../register-flow/stages/LevelStage.tsx | 44 +++++++++++-------- .../register-flow/stages/PasswordStage.tsx | 17 ++++--- .../register-flow/stages/RoleStage.tsx | 41 ++++++++++------- .../_components/slides/ChooseLevel.tsx | 1 - app/(pages)/_components/slides/ChooseRole.tsx | 1 - 8 files changed, 75 insertions(+), 53 deletions(-) diff --git a/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx b/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx index 23b30718..92137b36 100644 --- a/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx +++ b/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx @@ -5,7 +5,13 @@ import { useRouter } from 'next/navigation'; import AuthForm from '@components/AuthForm/AuthForm'; import RegisterAction from '@actions/auth/register'; -export default function RegisterForm({ data, onSuccess: onSuccessProp }: { data: any; onSuccess?: () => void }) { +export default function RegisterForm({ + data, + onSuccess: onSuccessProp, +}: { + data: any; + onSuccess?: () => void; +}) { const router = useRouter(); const name = data?.name ?? 'HackDavis Admin'; diff --git a/app/(pages)/(hackers)/register/page.tsx b/app/(pages)/(hackers)/register/page.tsx index 62d0ad7f..7da5f5f4 100644 --- a/app/(pages)/(hackers)/register/page.tsx +++ b/app/(pages)/(hackers)/register/page.tsx @@ -16,4 +16,4 @@ export default async function RegisterPage() { } return ; -} \ No newline at end of file +} diff --git a/app/(pages)/_components/RegisterFlow.tsx b/app/(pages)/_components/RegisterFlow.tsx index 024832a0..5534f889 100644 --- a/app/(pages)/_components/RegisterFlow.tsx +++ b/app/(pages)/_components/RegisterFlow.tsx @@ -24,18 +24,12 @@ export default function RegisterFlow({ data }: RegisterFlowProps) { const [stage, setStage] = useState<0 | 1 | 2>(0); const [formData, setFormData] = useState({}); - const goNext = () => - setStage((s) => (s === 2 ? s : ((s + 1) as 0 | 1 | 2))); + const goNext = () => setStage((s) => (s === 2 ? s : ((s + 1) as 0 | 1 | 2))); - const goBack = () => - setStage((s) => (s === 0 ? s : ((s - 1) as 0 | 1 | 2))); + const goBack = () => setStage((s) => (s === 0 ? s : ((s - 1) as 0 | 1 | 2))); return ( - +
); -} \ No newline at end of file +} diff --git a/app/(pages)/_components/register-flow/stages/LevelStage.tsx b/app/(pages)/_components/register-flow/stages/LevelStage.tsx index e740af3c..4c059655 100644 --- a/app/(pages)/_components/register-flow/stages/LevelStage.tsx +++ b/app/(pages)/_components/register-flow/stages/LevelStage.tsx @@ -46,8 +46,8 @@ export default function LevelStage({

- {/* cards */} -
+ {/* cards (ALWAYS SIDE BY SIDE) */} +
{levels.map((level) => { const selected = value === level.id; @@ -58,7 +58,7 @@ export default function LevelStage({ className={` flex flex-col items-start rounded-2xl - p-8 + p-6 md:p-8 text-left border transition @@ -74,10 +74,10 @@ export default function LevelStage({ alt={level.title} width={110} height={110} - className="mb-6 self-center drop-shadow" + className="mb-6 self-center drop-shadow-[0_10px_18px_rgba(0,0,0,0.18)]" /> -

+

{level.title}

@@ -90,7 +90,7 @@ export default function LevelStage({ {level.tag}
-

+

{level.description}

@@ -100,7 +100,6 @@ export default function LevelStage({ {/* footer */}
- {/* indicators */}
@@ -108,21 +107,16 @@ export default function LevelStage({
{/* nav buttons */} -
- - +
+ {/* NEXT (top on mobile) */}
); -} \ No newline at end of file +} diff --git a/app/(pages)/_components/register-flow/stages/PasswordStage.tsx b/app/(pages)/_components/register-flow/stages/PasswordStage.tsx index c53dfd78..6a06f141 100644 --- a/app/(pages)/_components/register-flow/stages/PasswordStage.tsx +++ b/app/(pages)/_components/register-flow/stages/PasswordStage.tsx @@ -17,15 +17,22 @@ export default function PasswordStage({ data, onNext }: PasswordStageProps) { className="text-[14px] md:text-[16px] text-[#5E5E65]" style={{ whiteSpace: 'pre-line' }} > - Welcome to the HackerHub! The HackDavis team made this for all your hacking needs + Welcome to the HackerHub! The HackDavis team made this for all your + hacking needs {' <3'} {'\n'}Let's get you started.

-
+
- - {/* DEV BUTTON */} + {/* DEV BUTTON */}{' '} + ); } - diff --git a/app/(pages)/_components/register-flow/stages/RoleStage.tsx b/app/(pages)/_components/register-flow/stages/RoleStage.tsx index 8062de1d..c62d748a 100644 --- a/app/(pages)/_components/register-flow/stages/RoleStage.tsx +++ b/app/(pages)/_components/register-flow/stages/RoleStage.tsx @@ -27,7 +27,7 @@ const roles = [ }, { id: 'explorer', - label: 'Explorer', + label: 'Other', image: '/hackers/register/explorer-duck.svg', }, ]; @@ -51,7 +51,7 @@ export default function ChooseRole({
{/* cards */} -
+
{roles.map((role) => { const selected = value === role.id; @@ -61,7 +61,7 @@ export default function ChooseRole({ onClick={() => onSelect(role.id)} className={` relative - h-[210px] + h-[190px] md:h-[210px] rounded-2xl border transition @@ -80,11 +80,11 @@ export default function ChooseRole({ alt={role.label} width={120} height={120} - className="pointer-events-none drop-shadow" + className="pointer-events-none drop-shadow-[0_8px_14px_rgba(0,0,0,0.15)]" />
@@ -104,21 +104,16 @@ export default function ChooseRole({
{/* nav buttons */} -
- - +
+ {/* NEXT (top on mobile) */}
); -} \ No newline at end of file +} diff --git a/app/(pages)/_components/slides/ChooseLevel.tsx b/app/(pages)/_components/slides/ChooseLevel.tsx index cb4d752a..ebd3a2dd 100644 --- a/app/(pages)/_components/slides/ChooseLevel.tsx +++ b/app/(pages)/_components/slides/ChooseLevel.tsx @@ -41,4 +41,3 @@ export default function ChooseLevel({ value, onSelect }: ChooseLevelProps) {
); } - diff --git a/app/(pages)/_components/slides/ChooseRole.tsx b/app/(pages)/_components/slides/ChooseRole.tsx index 3ff934e0..cc7c9b6d 100644 --- a/app/(pages)/_components/slides/ChooseRole.tsx +++ b/app/(pages)/_components/slides/ChooseRole.tsx @@ -41,4 +41,3 @@ export default function ChooseRole({ value, onSelect }: ChooseRoleProps) {
); } - From 997581e3fffbf5fa0ffefb2845db7df578e9bf8b Mon Sep 17 00:00:00 2001 From: michelleyeoh Date: Thu, 12 Mar 2026 20:03:33 -0700 Subject: [PATCH 09/15] register cleaned up --- app/(pages)/(hackers)/(hub)/page.tsx | 2 +- .../AuthForms/DetailForm.module.scss | 249 ------------------ .../_components/AuthForms/DetailForm.tsx | 149 ----------- .../AuthForms/register/DetailForm.tsx | 72 +++++ .../AuthForms/register/LevelStage.tsx | 163 ++++++++++++ .../AuthForms/{ => register}/RegisterForm.tsx | 12 +- .../AuthForms/register}/RoleStage.tsx | 27 +- .../(hackers)/register/details/page.tsx | 13 +- app/(pages)/(hackers)/register/page.tsx | 16 +- app/(pages)/_components/RegisterFlow.tsx | 72 ----- .../register-flow/stages/LevelStage.tsx | 151 ----------- .../register-flow/stages/PasswordStage.tsx | 38 --- .../_components/slides/ChooseLevel.tsx | 43 --- app/(pages)/_components/slides/ChooseRole.tsx | 43 --- public/hackers/login/designer_bunny.svg | 40 --- public/hackers/login/developer_cow.svg | 44 ---- public/hackers/login/other_ducky.svg | 50 ---- public/hackers/login/pm_froggy.svg | 27 -- 18 files changed, 263 insertions(+), 948 deletions(-) delete mode 100644 app/(pages)/(hackers)/_components/AuthForms/DetailForm.module.scss delete mode 100644 app/(pages)/(hackers)/_components/AuthForms/DetailForm.tsx create mode 100644 app/(pages)/(hackers)/_components/AuthForms/register/DetailForm.tsx create mode 100644 app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx rename app/(pages)/(hackers)/_components/AuthForms/{ => register}/RegisterForm.tsx (88%) rename app/(pages)/{_components/register-flow/stages => (hackers)/_components/AuthForms/register}/RoleStage.tsx (86%) delete mode 100644 app/(pages)/_components/RegisterFlow.tsx delete mode 100644 app/(pages)/_components/register-flow/stages/LevelStage.tsx delete mode 100644 app/(pages)/_components/register-flow/stages/PasswordStage.tsx delete mode 100644 app/(pages)/_components/slides/ChooseLevel.tsx delete mode 100644 app/(pages)/_components/slides/ChooseRole.tsx delete mode 100644 public/hackers/login/designer_bunny.svg delete mode 100644 public/hackers/login/developer_cow.svg delete mode 100644 public/hackers/login/other_ducky.svg delete mode 100644 public/hackers/login/pm_froggy.svg diff --git a/app/(pages)/(hackers)/(hub)/page.tsx b/app/(pages)/(hackers)/(hub)/page.tsx index fb312cc5..bf6ae3c6 100644 --- a/app/(pages)/(hackers)/(hub)/page.tsx +++ b/app/(pages)/(hackers)/(hub)/page.tsx @@ -31,7 +31,7 @@ export default function Page() { {/* temporarilty set featureId below to "hero-hacking" to test */} - + diff --git a/app/(pages)/(hackers)/_components/AuthForms/DetailForm.module.scss b/app/(pages)/(hackers)/_components/AuthForms/DetailForm.module.scss deleted file mode 100644 index 4b589984..00000000 --- a/app/(pages)/(hackers)/_components/AuthForms/DetailForm.module.scss +++ /dev/null @@ -1,249 +0,0 @@ -@import 'app/(pages)/_globals/mixins'; - -.container { - display: flex; - flex-direction: column; - width: 100%; - - @include tablet-l { - margin-top: 5%; - } -} - -.header { - display: flex; - flex-direction: row; - gap: 26px; - margin-left: 5%; - margin-right: 5%; - margin-top: max(114px, 6%); - - .header_text { - display: flex; - flex-direction: column; - gap: 16px; - - h1 { - font-size: 1.75rem; - font-style: normal; - font-weight: 600; - line-height: normal; - letter-spacing: 0.56px; - - @include tablet-s { - font-size: 1.25rem; - } - - @include mobile-l { - font-size: 1rem; - } - } - - p { - font-size: 1.125rem; - font-style: normal; - font-weight: 400; - line-height: 145%; - letter-spacing: 0.36px; - - @include tablet-s { - font-size: 0.875rem; - } - - @include mobile-l { - font-size: 0.75rem; - } - } - } -} - -.form { - display: flex; - flex-direction: column; - align-self: center; - align-items: center; - width: 70%; - margin-top: 5%; - - @include desktop-m { - width: 80%; - } - - @include tablet-l { - padding-bottom: 32px; - } -} - -.characterGrid { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 40px; - height: 100%; - width: 100%; - - @include desktop-m { - gap: 20px; - } - - @include tablet-l { - display: grid; - grid-template-columns: repeat(2, 1fr); - justify-content: space-between; - gap: 0; - width: 50%; - } - - @include tablet-s { - width: 75%; - } - - @include mobile-l { - width: 85%; - } -} - -.characterOption { - display: flex; - align-self: flex-end; - height: 100%; - - - &.selected { - border-radius: 20px; - border: 1px dashed #005271; - } -} - -.radioInput { - position: absolute; - opacity: 0; - width: 0; - height: 0; -} - -.character { - display: flex; - flex-direction: column; - align-items: center; - height: 100%; - width: 100%; - cursor: pointer; -} - -.characterImage { - width: 100%; - height: 100%; - display: flex; - margin-bottom: 16px; - transition: transform 0.2s; - - &.selected { - filter: drop-shadow(32px 32px 2rem rgba(255, 243, 216, 0.60)); - } -} - -.characterImage:hover { - filter: drop-shadow(32px 32px 2rem rgba(255, 243, 216, 0.60)); -} - -.characterLabel { - text-align: center; - font-size: 1.5rem; - font-style: normal; - font-weight: 700; - line-height: normal; - padding-bottom: 32px; - - @include desktop-l { - font-size: 1rem; - } - - @include desktop-m { - font-size: 0.875rem; - padding-bottom: 16px; - } - - &.selected { - color: #005271; - } -} - -.bottom { - display: flex; - flex-direction: row; - justify-content: space-between; - width: 100%; - margin-top: 28px; - - @include tablet-l { - flex-direction: column; - align-items: end; - gap: 20px; - } -} - -.beginnerOption { - display: flex; - align-items: center; - gap: 16px; - margin-left: 40px; -} - -.checkboxInput { - appearance: none; - width: 23px; - height: 23px; - border: 1px solid #000; - border-radius: 4px; - position: relative; - cursor: pointer; - - &:checked { - background-color: #4a90e2; - border-color: #4a90e2; - - &:after { - content: "✓"; - color: white; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - } - } -} - -.beginnerLabel { - font-size: 1.125rem; -} - -.submit_button { - padding: 12px 24px; - font-size: 1.125rem; - font-weight: 600; - line-height: normal; - font-style: normal; - line-height: 100%; - letter-spacing: 0.36px; - color: var(--text-light); - background: var(--background-secondary); - border: none; - cursor: not-allowed; - border-radius: 20px; - opacity: 0.3; - - @include tablet-l { - padding: 8px 16px; - font-size: 1rem; - letter-spacing: 0.24px; - } -} - -.valid { - opacity: 1; - cursor: pointer; -} - -.error_msg { - color: var(--text-error); -} diff --git a/app/(pages)/(hackers)/_components/AuthForms/DetailForm.tsx b/app/(pages)/(hackers)/_components/AuthForms/DetailForm.tsx deleted file mode 100644 index d00d7d0c..00000000 --- a/app/(pages)/(hackers)/_components/AuthForms/DetailForm.tsx +++ /dev/null @@ -1,149 +0,0 @@ -'use client'; - -import { useEffect, useState, FormEvent } from 'react'; -import { useRouter } from 'next/navigation'; -import Image from 'next/image'; - -import { updateUser } from '@actions/users/updateUser'; -import Loader from '@components/Loader/Loader'; -import DeveloperCow from 'public/hackers/login/developer_cow.svg'; -import DesignerBunny from 'public/hackers/login/designer_bunny.svg'; -import PmFroggy from 'public/hackers/login/pm_froggy.svg'; -import OtherDucky from 'public/hackers/login/other_ducky.svg'; -import styles from './DetailForm.module.scss'; - -const characters = [ - { - label: 'DEVELOPER', - role: 'developer', - image: DeveloperCow, - alt: 'Developer Cow', - }, - { - label: 'DESIGNER', - role: 'designer', - image: DesignerBunny, - alt: 'Designer Bunny', - }, - { - label: 'PROJECT MANAGER', - role: 'pm', - image: PmFroggy, - alt: 'PM Froggy', - }, - { - label: 'OTHER', - role: 'other', - image: OtherDucky, - alt: 'Other Ducky', - }, -]; - -export default function DetailForm({ id }: any) { - const router = useRouter(); - - const [loading, setLoading] = useState(false); - const [error, setError] = useState(''); - const [valid, setValid] = useState(false); - const [selectedPosition, setSelectedPosition] = useState(''); - - const handleRegister = async (e: FormEvent) => { - e.preventDefault(); - - setLoading(true); - setError(''); - - const formData = new FormData(e.currentTarget); - - const position = formData.get('position') as string; - const is_beginner = formData.get('beginner') !== null; - - const userRes = await updateUser(id, { - $set: { - position, - is_beginner, - }, - }); - - if (userRes.ok) { - router.push('/'); - } else { - setError(userRes.error ?? 'Error updating details'); - } - - setLoading(false); - }; - - useEffect(() => { - setValid(selectedPosition !== ''); - }, [selectedPosition]); - - return ( -
-
- {error &&

{error}

} - -
- {characters.map(({ label, role, image, alt }) => ( -
- setSelectedPosition(role)} - className={styles.radioInput} - /> - -
- ))} -
- -
-
- - -
- - -
-
- - {loading && } -
- ); -} diff --git a/app/(pages)/(hackers)/_components/AuthForms/register/DetailForm.tsx b/app/(pages)/(hackers)/_components/AuthForms/register/DetailForm.tsx new file mode 100644 index 00000000..7daff7a6 --- /dev/null +++ b/app/(pages)/(hackers)/_components/AuthForms/register/DetailForm.tsx @@ -0,0 +1,72 @@ +'use client'; + +import { useState } from 'react'; +import { useRouter } from 'next/navigation'; + +import { updateUser } from '@actions/users/updateUser'; +import RoleStage from './RoleStage'; +import LevelStage from './LevelStage'; + +type DetailFormProps = { + id: string; +}; + +export default function DetailForm({ id }: DetailFormProps) { + const router = useRouter(); + + const [stage, setStage] = useState<0 | 1>(0); + const [role, setRole] = useState(); + const [level, setLevel] = useState(); + const [loading, setLoading] = useState(false); + + const [error, setError] = useState(''); + + const handleRegister = async () => { + if (!role || !level) return; + + setLoading(true); + setError(''); + + const is_beginner = level === 'beginner'; + + const userRes = await updateUser(id, { + $set: { + position: role, + is_beginner, + }, + }); + + if (userRes.ok) { + router.push('/'); + } else { + setError(userRes.error ?? 'Error updating details'); + } + + setLoading(false); + }; + + return ( +
+ {stage === 0 ? ( + router.push('/register')} + onNext={() => { + if (!role) return; + setStage(1); + }} + /> + ) : ( + setStage(0)} + onNext={handleRegister} + loading={loading} + error={error} + /> + )} +
+ ); +} diff --git a/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx b/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx new file mode 100644 index 00000000..08c8e236 --- /dev/null +++ b/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx @@ -0,0 +1,163 @@ +'use client'; + +import Image from 'next/image'; +import AuthFormBackground from '../../AuthFormBackground/AuthFormBackground'; + +type LevelStageProps = { + value?: string; + onSelect: (value: string) => void; + onBack: () => void; + onNext: () => void; + loading?: boolean; + error?: string; +}; + +const levels = [ + { + id: 'beginner', + title: 'Beginner', + tag: 'NEW TO THE SCENE', + description: + "You're here to build your foundation, explore new tools, and ship your first few projects.", + image: '/hackers/register/beginner-frog.svg', + }, + { + id: 'experienced', + title: 'Experienced', + tag: 'A SEASONED HACKER', + description: + "You're comfortable with the 36-hour grind and ready to push the boundaries of your projects.", + image: '/hackers/register/experienced-frog.svg', + }, +]; + +export default function LevelStage({ + value, + onSelect, + onBack, + onNext, + loading = false, + error = '', +}: LevelStageProps) { + return ( + +
+ {/* cards (ALWAYS SIDE BY SIDE) */} +
+ {levels.map((level) => { + const selected = value === level.id; + return ( + + ); + })} +
+ + {/* footer */} +
+ {/* indicators */} +
+
+
+
+ {/* nav buttons */} +
+ {/* error message - takes up vertical space*/} +

+ {error} +

+
+ {/* NEXT (top on mobile) */} + + + {/* BACK */} + +
+
+
+
+ + ); +} diff --git a/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx b/app/(pages)/(hackers)/_components/AuthForms/register/RegisterForm.tsx similarity index 88% rename from app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx rename to app/(pages)/(hackers)/_components/AuthForms/register/RegisterForm.tsx index 92137b36..83ed3d3f 100644 --- a/app/(pages)/(hackers)/_components/AuthForms/RegisterForm.tsx +++ b/app/(pages)/(hackers)/_components/AuthForms/register/RegisterForm.tsx @@ -5,13 +5,7 @@ import { useRouter } from 'next/navigation'; import AuthForm from '@components/AuthForm/AuthForm'; import RegisterAction from '@actions/auth/register'; -export default function RegisterForm({ - data, - onSuccess: onSuccessProp, -}: { - data: any; - onSuccess?: () => void; -}) { +export default function RegisterForm({ data }: any) { const router = useRouter(); const name = data?.name ?? 'HackDavis Admin'; @@ -30,10 +24,6 @@ export default function RegisterForm({ const onSuccess = () => { if (role === 'admin') { router.push('/'); - return; - } - if (onSuccessProp) { - onSuccessProp(); } else { router.push('/register/details'); } diff --git a/app/(pages)/_components/register-flow/stages/RoleStage.tsx b/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx similarity index 86% rename from app/(pages)/_components/register-flow/stages/RoleStage.tsx rename to app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx index c62d748a..26151660 100644 --- a/app/(pages)/_components/register-flow/stages/RoleStage.tsx +++ b/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx @@ -1,6 +1,7 @@ 'use client'; import Image from 'next/image'; +import AuthFormBackground from '../../AuthFormBackground/AuthFormBackground'; type ChooseRoleProps = { value?: string; @@ -39,22 +40,15 @@ export default function ChooseRole({ onNext, }: ChooseRoleProps) { return ( - <> - {/* header */} -
-

- Choose what suits you the most: -

-

- This will help us recommend workshops to you! -

-
- + {/* cards */} -
+
{roles.map((role) => { const selected = value === role.id; - return (
{/* Bottom navigation */} -
+
{/* indicators */}
@@ -143,6 +138,6 @@ export default function ChooseRole({
- + ); } diff --git a/app/(pages)/(hackers)/register/details/page.tsx b/app/(pages)/(hackers)/register/details/page.tsx index e35aad4c..4f7a45d8 100644 --- a/app/(pages)/(hackers)/register/details/page.tsx +++ b/app/(pages)/(hackers)/register/details/page.tsx @@ -1,7 +1,6 @@ import { redirect } from 'next/navigation'; -import DetailForm from '@pages/(hackers)/_components/AuthForms/DetailForm'; -import AuthFormBackground from '../../_components/AuthFormBackground/AuthFormBackground'; +import DetailForm from '@pages/(hackers)/_components/AuthForms/register/DetailForm'; import getActiveUser from 'app/(pages)/_utils/getActiveUser'; export default async function DetailPage() { @@ -9,13 +8,5 @@ export default async function DetailPage() { if (user.role === 'judge') redirect('/judges/register'); - return ( - - - - ); + return ; } diff --git a/app/(pages)/(hackers)/register/page.tsx b/app/(pages)/(hackers)/register/page.tsx index 7da5f5f4..bcd8d9b8 100644 --- a/app/(pages)/(hackers)/register/page.tsx +++ b/app/(pages)/(hackers)/register/page.tsx @@ -2,8 +2,9 @@ import { redirect } from 'next/navigation'; import { auth } from '@/auth'; import { getInviteData } from '@actions/invite/getInviteData'; - -import RegisterFlow from '@pages/_components/RegisterFlow'; +import InviteOnlyRoute from '@components/InviteOnlyRoute/InviteOnlyRoute'; +import AuthFormBackground from '@pages/(hackers)/_components/AuthFormBackground/AuthFormBackground'; +import RegisterForm from '../_components/AuthForms/register/RegisterForm'; export default async function RegisterPage() { const session = await auth(); @@ -15,5 +16,14 @@ export default async function RegisterPage() { redirect('/judges/register'); } - return ; + return ( + + + + + + ); } diff --git a/app/(pages)/_components/RegisterFlow.tsx b/app/(pages)/_components/RegisterFlow.tsx deleted file mode 100644 index 5534f889..00000000 --- a/app/(pages)/_components/RegisterFlow.tsx +++ /dev/null @@ -1,72 +0,0 @@ -'use client'; - -import { useState } from 'react'; -import { useRouter } from 'next/navigation'; - -import PasswordStage from './register-flow/stages/PasswordStage'; -import RoleStage from './register-flow/stages/RoleStage'; -import LevelStage from './register-flow/stages/LevelStage'; - -import AuthFormBackground from '@pages/(hackers)/_components/AuthFormBackground/AuthFormBackground'; - -type RegisterFlowProps = { - data?: any; -}; - -type OnboardingFormData = { - role?: string; - level?: string; -}; - -export default function RegisterFlow({ data }: RegisterFlowProps) { - const router = useRouter(); - - const [stage, setStage] = useState<0 | 1 | 2>(0); - const [formData, setFormData] = useState({}); - - const goNext = () => setStage((s) => (s === 2 ? s : ((s + 1) as 0 | 1 | 2))); - - const goBack = () => setStage((s) => (s === 0 ? s : ((s - 1) as 0 | 1 | 2))); - - return ( - -
-
-
- {/* PASSWORD */} -
- setStage(1)} /> -
- - {/* ROLE */} -
- - setFormData((prev) => ({ ...prev, role: value })) - } - onBack={goBack} - onNext={goNext} - /> -
- - {/* LEVEL */} -
- - setFormData((prev) => ({ ...prev, level: value })) - } - onBack={goBack} - onNext={() => router.push('/register/details')} - /> -
-
-
-
-
- ); -} diff --git a/app/(pages)/_components/register-flow/stages/LevelStage.tsx b/app/(pages)/_components/register-flow/stages/LevelStage.tsx deleted file mode 100644 index 4c059655..00000000 --- a/app/(pages)/_components/register-flow/stages/LevelStage.tsx +++ /dev/null @@ -1,151 +0,0 @@ -'use client'; - -import Image from 'next/image'; - -type LevelStageProps = { - value?: string; - onSelect: (value: string) => void; - onBack: () => void; - onNext: () => void; -}; - -const levels = [ - { - id: 'beginner', - title: 'Beginner', - tag: 'NEW TO THE SCENE', - description: - "You're here to build your foundation, explore new tools, and ship your first few projects.", - image: '/hackers/register/beginner-frog.svg', - }, - { - id: 'experienced', - title: 'Experienced', - tag: 'A SEASONED HACKER', - description: - "You're comfortable with the 36-hour grind and ready to push the boundaries of your projects.", - image: '/hackers/register/experienced-frog.svg', - }, -]; - -export default function LevelStage({ - value, - onSelect, - onBack, - onNext, -}: LevelStageProps) { - return ( -
- {/* header */} -
-

- Tell us your skill level: -

-

- This will help us recommend workshops to you! -

-
- - {/* cards (ALWAYS SIDE BY SIDE) */} -
- {levels.map((level) => { - const selected = value === level.id; - - return ( - - ); - })} -
- - {/* footer */} -
- {/* indicators */} -
-
-
-
- - {/* nav buttons */} -
- {/* NEXT (top on mobile) */} - - - {/* BACK */} - -
-
-
- ); -} diff --git a/app/(pages)/_components/register-flow/stages/PasswordStage.tsx b/app/(pages)/_components/register-flow/stages/PasswordStage.tsx deleted file mode 100644 index 6a06f141..00000000 --- a/app/(pages)/_components/register-flow/stages/PasswordStage.tsx +++ /dev/null @@ -1,38 +0,0 @@ -'use client'; -import RegisterForm from '@pages/(hackers)/_components/AuthForms/RegisterForm'; - -type PasswordStageProps = { - data?: any; - onNext: () => void; -}; - -export default function PasswordStage({ data, onNext }: PasswordStageProps) { - return ( - <> -
-

- Hi {data?.name ?? 'HackDavis Admin'}! -

-

- Welcome to the HackerHub! The HackDavis team made this for all your - hacking needs - {' <3'} - {'\n'}Let's get you started. -

-
- - {/* DEV BUTTON */}{' '} - - - ); -} diff --git a/app/(pages)/_components/slides/ChooseLevel.tsx b/app/(pages)/_components/slides/ChooseLevel.tsx deleted file mode 100644 index ebd3a2dd..00000000 --- a/app/(pages)/_components/slides/ChooseLevel.tsx +++ /dev/null @@ -1,43 +0,0 @@ -'use client'; - -type ChooseLevelProps = { - value?: string; - onSelect: (value: string) => void; -}; - -const LEVELS = ['Beginner', 'Intermediate', 'Advanced'] as const; - -export default function ChooseLevel({ value, onSelect }: ChooseLevelProps) { - return ( -
-
-

- How experienced are you? -

-

- We'll use this to suggest the right resources. -

-
- -
- {LEVELS.map((level) => { - const selected = value === level; - return ( - - ); - })} -
-
- ); -} diff --git a/app/(pages)/_components/slides/ChooseRole.tsx b/app/(pages)/_components/slides/ChooseRole.tsx deleted file mode 100644 index cc7c9b6d..00000000 --- a/app/(pages)/_components/slides/ChooseRole.tsx +++ /dev/null @@ -1,43 +0,0 @@ -'use client'; - -type ChooseRoleProps = { - value?: string; - onSelect: (value: string) => void; -}; - -const ROLES = ['Developer', 'Designer', 'Product', 'Explorer'] as const; - -export default function ChooseRole({ value, onSelect }: ChooseRoleProps) { - return ( -
-
-

- Tell us about your role -

-

- This helps us tailor your HackDavis experience. -

-
- -
- {ROLES.map((role) => { - const selected = value === role; - return ( - - ); - })} -
-
- ); -} diff --git a/public/hackers/login/designer_bunny.svg b/public/hackers/login/designer_bunny.svg deleted file mode 100644 index eb23fe1e..00000000 --- a/public/hackers/login/designer_bunny.svg +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/hackers/login/developer_cow.svg b/public/hackers/login/developer_cow.svg deleted file mode 100644 index a3ca0f45..00000000 --- a/public/hackers/login/developer_cow.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/hackers/login/other_ducky.svg b/public/hackers/login/other_ducky.svg deleted file mode 100644 index ab11d59e..00000000 --- a/public/hackers/login/other_ducky.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/public/hackers/login/pm_froggy.svg b/public/hackers/login/pm_froggy.svg deleted file mode 100644 index 8b9790e7..00000000 --- a/public/hackers/login/pm_froggy.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - From 8928375d1b77794b7b108fd2a7fd42e0ac04ce56 Mon Sep 17 00:00:00 2001 From: michelleyeoh <74385095+michelleyeoh@users.noreply.github.com> Date: Thu, 12 Mar 2026 21:05:24 -0700 Subject: [PATCH 10/15] font fix Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../(hackers)/_components/AuthForms/register/RoleStage.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx b/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx index 26151660..c53af42c 100644 --- a/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx +++ b/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx @@ -78,10 +78,9 @@ export default function ChooseRole({ />
{role.label.toUpperCase()}
From 9cbcc4047bb0ac4922366e14ef5e884463dbb3e3 Mon Sep 17 00:00:00 2001 From: michelleyeoh <74385095+michelleyeoh@users.noreply.github.com> Date: Thu, 12 Mar 2026 21:05:45 -0700 Subject: [PATCH 11/15] user id fix Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../(hackers)/_components/AuthForms/register/RoleStage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx b/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx index c53af42c..8a57b03d 100644 --- a/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx +++ b/app/(pages)/(hackers)/_components/AuthForms/register/RoleStage.tsx @@ -22,12 +22,12 @@ const roles = [ image: '/hackers/register/designer-bunny.svg', }, { - id: 'product', + id: 'pm', label: 'Product', image: '/hackers/register/product-frog.svg', }, { - id: 'explorer', + id: 'other', label: 'Other', image: '/hackers/register/explorer-duck.svg', }, From 36eb43d18ed4c7a382b8a64e1922a5e452b1d477 Mon Sep 17 00:00:00 2001 From: michelleyeoh <74385095+michelleyeoh@users.noreply.github.com> Date: Thu, 12 Mar 2026 21:05:59 -0700 Subject: [PATCH 12/15] font fix Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../(hackers)/_components/AuthForms/register/LevelStage.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx b/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx index 08c8e236..0ccf613a 100644 --- a/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx +++ b/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx @@ -83,10 +83,9 @@ export default function LevelStage({
{level.tag}
From 70848e3b2840088982c6025fab389509672d51a8 Mon Sep 17 00:00:00 2001 From: michelleyeoh <74385095+michelleyeoh@users.noreply.github.com> Date: Thu, 12 Mar 2026 22:17:53 -0700 Subject: [PATCH 13/15] define button type Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../(hackers)/_components/AuthForms/register/LevelStage.tsx | 1 + .../(hackers)/_components/AuthForms/register/RoleStage.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx b/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx index 0ccf613a..b5177fd7 100644 --- a/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx +++ b/app/(pages)/(hackers)/_components/AuthForms/register/LevelStage.tsx @@ -53,6 +53,7 @@ export default function LevelStage({ return (