From 6d5f6ea4aa9b3ca06e8ca22925b2ffce3978ec55 Mon Sep 17 00:00:00 2001 From: DaStormer Date: Sun, 30 Aug 2026 19:04:50 -0400 Subject: [PATCH 1/7] revamp auth pages & dashboard for improved styling and mobile responsiveness --- app/(pre-dashboard)/(entry)/forgot/page.tsx | 103 ++-- app/(pre-dashboard)/(entry)/layout.tsx | 42 +- app/(pre-dashboard)/(entry)/login/page.tsx | 160 +++--- .../(entry)/magic/[forgot]/page.tsx | 183 +++---- app/(pre-dashboard)/(entry)/signup/page.tsx | 246 ++++----- .../(entry)/verify/[code]/page.tsx | 79 +-- app/(pre-dashboard)/layout.tsx | 25 +- app/dashboard/components/StatusBar.tsx | 132 ++--- app/dashboard/components/button.tsx | 10 +- app/dashboard/components/card.tsx | 12 +- app/dashboard/components/discord.tsx | 30 +- app/dashboard/components/input.tsx | 12 +- app/dashboard/components/profileHeader.tsx | 466 ++++++++++++------ app/dashboard/layout.tsx | 5 +- app/dashboard/page.tsx | 196 ++++---- app/dashboard/views/organizerView.tsx | 4 +- app/lib/actions.ts | 115 +++-- app/lib/teamactions.ts | 12 +- app/ui/button.tsx | 2 +- app/ui/global.css | 16 +- app/ui/skeletons.tsx | 21 +- 21 files changed, 1086 insertions(+), 785 deletions(-) diff --git a/app/(pre-dashboard)/(entry)/forgot/page.tsx b/app/(pre-dashboard)/(entry)/forgot/page.tsx index c3b8fd5d..ec6257bd 100644 --- a/app/(pre-dashboard)/(entry)/forgot/page.tsx +++ b/app/(pre-dashboard)/(entry)/forgot/page.tsx @@ -1,19 +1,17 @@ 'use client'; import { Button } from '@/app/ui/button'; -import Image from 'next/image'; - import { Forgot } from '../../../lib/actions'; - import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; - import { useState } from 'react'; +import Image from 'next/image'; +import { useRouter } from 'next/navigation'; export default function SignupPage() { const SignUpSchema = z.object({ - email: z.string().email(), + email: z.string().email('Please enter a valid email address'), }); type SignUp = z.infer; @@ -21,66 +19,91 @@ export default function SignupPage() { const { register, handleSubmit, - reset, formState: { errors }, } = useForm({ resolver: zodResolver(SignUpSchema) }); const [message, setMessage] = useState(''); const [buttonDisabled, setButtonDisabled] = useState(false); + const router = useRouter(); const onSubmit = async (data: SignUp) => { setButtonDisabled(true); + setMessage(''); + const resp = await Forgot(data.email); setMessage(resp); setTimeout(() => { - // wait 1 minutes between requests setButtonDisabled(false); }, 60000); }; return ( -
-
-
- { -

+

+
+ +
+ +
+
+

+ Reset password +

+

+ Forgot your password? +

+
+ + + {message && ( +

{message}

- } + )} +
-
- - {errors.email && ( -

- {errors.email?.message} -

- )} -
+ + {errors.email && ( +

+ {errors.email?.message} +

+ )}
-
- - + + + +
); } diff --git a/app/(pre-dashboard)/(entry)/layout.tsx b/app/(pre-dashboard)/(entry)/layout.tsx index e4327e65..4efd3bd1 100644 --- a/app/(pre-dashboard)/(entry)/layout.tsx +++ b/app/(pre-dashboard)/(entry)/layout.tsx @@ -3,27 +3,27 @@ import { inter } from '@/app/ui/fonts'; export default function Layout({ children }: { children: React.ReactNode }) { return ( - <> -
+
+
+
{children} - -
-
- + +
); } diff --git a/app/(pre-dashboard)/(entry)/login/page.tsx b/app/(pre-dashboard)/(entry)/login/page.tsx index e00fe552..54a4cc1d 100644 --- a/app/(pre-dashboard)/(entry)/login/page.tsx +++ b/app/(pre-dashboard)/(entry)/login/page.tsx @@ -1,24 +1,18 @@ 'use client'; import { Button } from '@/app/ui/button'; - -import { authenticate, authUser } from '../../../lib/actions'; - +import { authenticate } from '../../../lib/actions'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; - -import { Suspense, useState } from 'react'; - -import Image from 'next/image'; +import { useState } from 'react'; import { useRouter } from 'next/navigation'; -import Cursor from '../../../ui/cursor'; +import Image from 'next/image'; export default function LoginPage() { const LoginSchema = z.object({ - email: z.string().email(), - //email :z.string(), - password: z.string(), + email: z.string().email('Please enter a valid email address'), + password: z.string().min(1, 'Please enter your password'), }); type Login = z.infer; @@ -30,97 +24,131 @@ export default function LoginPage() { const { register, handleSubmit, - reset, formState: { errors }, } = useForm({ resolver: zodResolver(LoginSchema) }); const onSubmit = async (data: Login) => { setLoading(true); + setErrors(''); + const resp = await authenticate(data.email, data.password); setLoading(false); + + if (resp === 'success') { + router.push('/dashboard'); + router.refresh(); + return; + } + setErrors(resp); }; return ( -
-
-
- { -

+

+
+ +
+ +
+
+

+ Welcome back +

+

+ Log in +

+
+ + + {submit_errors && ( +

{submit_errors}

- } + )} +
-

- Login to your HackRU account below -

-
- -
+ {errors.email && ( -

+

{errors.email?.message}

)}
-
+ +
-
- - {errors.password && ( -

- {errors.password?.message} -

- )} -
+ + {errors.password && ( +

+ {errors.password?.message} +

+ )}
- -

+ +

+
- +
); } diff --git a/app/(pre-dashboard)/(entry)/magic/[forgot]/page.tsx b/app/(pre-dashboard)/(entry)/magic/[forgot]/page.tsx index 93b0cac5..637efab2 100644 --- a/app/(pre-dashboard)/(entry)/magic/[forgot]/page.tsx +++ b/app/(pre-dashboard)/(entry)/magic/[forgot]/page.tsx @@ -1,29 +1,24 @@ 'use client'; import { Button } from '@/app/ui/button'; - import { Reset } from '../../../../lib/actions'; - import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; - import { useState } from 'react'; +import { usePathname, useRouter } from 'next/navigation'; import Image from 'next/image'; -import { usePathname } from 'next/navigation'; - export default function SignupPage() { const SignUpSchema = z .object({ - email: z.string().email(), - - password: z.string(), - confirm_password: z.string(), + email: z.string().email('Please enter a valid email address'), + password: z.string().min(1, 'Please enter a password'), + confirm_password: z.string().min(1, 'Please confirm your password'), }) .refine((data) => data.password === data.confirm_password, { message: "Passwords don't match", - path: ['confirm_password'], // path of error + path: ['confirm_password'], }); type SignUp = z.infer; @@ -31,22 +26,17 @@ export default function SignupPage() { const { register, handleSubmit, - reset, formState: { errors }, } = useForm({ resolver: zodResolver(SignUpSchema) }); const [submit_errors, setErrors] = useState(''); const [success, setSuccess] = useState(''); + const router = useRouter(); const pathname = usePathname(); const arr = pathname.split('magic/'); - console.log(arr[1]); - const onSubmit = async (data: SignUp) => { - console.log('SENDING Reset'); - console.log(data); - console.log(arr[1]); const resp = await Reset( data.email, data.password, @@ -54,7 +44,6 @@ export default function SignupPage() { arr[1], ); - console.log(resp); if (resp.error) { setErrors(resp.error); setSuccess(''); @@ -64,105 +53,123 @@ export default function SignupPage() { } if (resp.error == 'Password reset successful') { - // for some reason this was showing up as an error setSuccess(resp.error); setErrors(''); } }; return ( -
-
-
- { -

+

+
+ +
+ +
+
+

+ Security +

+

+ Set a new password +

+
+ + + {submit_errors && ( +

{submit_errors}

- } - { -

+ )} + {success && ( +

{success}

- } + )} +
-
- - {errors.email && ( -

- {errors.email?.message} -

- )} -
+ + {errors.email && ( +

+ {errors.email?.message} +

+ )}
-
+
-
- - {errors.password && ( -

- {errors.password?.message} -

- )} -
+ + {errors.password && ( +

+ {errors.password?.message} +

+ )}
-
+ +
-
- - {errors.confirm_password && ( -

- {errors.confirm_password?.message} -

- )} -
+ + {errors.confirm_password && ( +

+ {errors.confirm_password?.message} +

+ )}
-
- - + + + +
); } diff --git a/app/(pre-dashboard)/(entry)/signup/page.tsx b/app/(pre-dashboard)/(entry)/signup/page.tsx index ae2844c7..2d195a3f 100644 --- a/app/(pre-dashboard)/(entry)/signup/page.tsx +++ b/app/(pre-dashboard)/(entry)/signup/page.tsx @@ -6,8 +6,8 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { useState } from 'react'; -import Image from 'next/image'; import { useRouter } from 'next/navigation'; +import Image from 'next/image'; export default function SignupPage() { const SignUpSchema = z @@ -41,11 +41,12 @@ export default function SignupPage() { const [submit_errors, setErrors] = useState(''); const [loading, setLoading] = useState(false); - const [submitErrors, setSubmitErrors] = useState([]); const router = useRouter(); const onSubmit = async (data: SignUp) => { setLoading(true); + setErrors(''); + const resp = await SignUp( data.first_name, data.last_name, @@ -54,170 +55,187 @@ export default function SignupPage() { data.confirm_password, ); setLoading(false); + + if (resp.response === '200') { + router.push('/dashboard'); + router.refresh(); + return; + } + if (resp) { - setErrors(resp.error); + setErrors(resp.error || 'Something went wrong while creating your account.'); } }; - const onError = (errorList: any) => { - const errorMessages: string[] = Object.keys(errors).map((field) => { - type FieldKey = keyof SignUp; // Defining possible keys from the SignUp type - - const typedField = field as FieldKey; // Casting field to the specific known type - if (errors[typedField]?.message) { - return `${typedField.replace('_', ' ')}: ${errors[typedField]?.message}`; - } - return `${typedField.replace('_', ' ')} is required`; - }); + return ( +
+
+ +
- setSubmitErrors(errorMessages); - }; +
+
+

+ Get started +

+

+ Create your account +

+
- return ( -
-
-
+ {submit_errors && ( -

+

{submit_errors}

)} -

- Create a HackRU Account by signing up below -

-
- -
- - {errors.email && ( -

- {errors.email.message} -

- )} -
-
-
- -
+
+
+ {errors.first_name && ( -

+

{errors.first_name.message}

)}
-
-
- -
+
+ {errors.last_name && ( -

+

{errors.last_name.message}

)}
-
+
+ + {errors.email && ( +

+ {errors.email.message} +

+ )} +
+ +
+ -
- - {errors.password && ( -

- {errors.password.message} -

- )} -
+ + {errors.password && ( +

+ {errors.password.message} +

+ )}
-
+
-
- - {errors.confirm_password && ( -

- {errors.confirm_password.message} -

- )} -
+ + {errors.confirm_password && ( +

+ {errors.confirm_password.message} +

+ )}
-
-
- -
-

+ + +

); } diff --git a/app/(pre-dashboard)/(entry)/verify/[code]/page.tsx b/app/(pre-dashboard)/(entry)/verify/[code]/page.tsx index 33402077..8f92a9b1 100644 --- a/app/(pre-dashboard)/(entry)/verify/[code]/page.tsx +++ b/app/(pre-dashboard)/(entry)/verify/[code]/page.tsx @@ -1,45 +1,31 @@ 'use client'; import { Button } from '@/app/ui/button'; - import { Verify } from '../../../../lib/actions'; - import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; - import { useState } from 'react'; +import { usePathname, useRouter } from 'next/navigation'; import Image from 'next/image'; -import { usePathname } from 'next/navigation'; - export default function SignupPage() { const SignUpSchema = z.object({}); type SignUp = z.infer; - const { - register, - handleSubmit, - reset, - formState: { errors }, - } = useForm({ resolver: zodResolver(SignUpSchema) }); + const { handleSubmit } = useForm({ resolver: zodResolver(SignUpSchema) }); const [submit_errors, setErrors] = useState(''); const [success, setSuccess] = useState(''); + const router = useRouter(); const pathname = usePathname(); const arr = pathname.split('verify/'); - console.log(arr[1]); - - const onSubmit = async (data: SignUp) => { - console.log('SENDING Verify'); - console.log(data); - console.log(arr[1]); + const onSubmit = async () => { const resp = await Verify(arr[1]); - console.log(resp); if (resp.error) { setErrors(resp.error); setSuccess(''); @@ -49,32 +35,57 @@ export default function SignupPage() { } if (resp.error == 'Password reset successful') { - // for some reason this was showing up as an error setSuccess(resp.error); setErrors(''); } }; return ( -
-
-
- { -

+

+
+ +
+ +
+
+

+ Verify email +

+

+ Finish account setup +

+
+ + + {submit_errors && ( +

{submit_errors}

- } - { -

+ )} + {success && ( +

{success}

- } -
- - + )} + + + +
); } diff --git a/app/(pre-dashboard)/layout.tsx b/app/(pre-dashboard)/layout.tsx index 49da8788..c4483ce8 100644 --- a/app/(pre-dashboard)/layout.tsx +++ b/app/(pre-dashboard)/layout.tsx @@ -1,18 +1,31 @@ +'use client'; + import { Suspense } from 'react'; +import { usePathname } from 'next/navigation'; import Cursor from '../ui/cursor'; import Navbar from './(landing)/sections/Hero/Navbar'; export default function Layout({ children }: { children: React.ReactNode }) { + const pathname = usePathname(); + const isAuthRoute = + pathname === '/login' || + pathname === '/signup' || + pathname === '/forgot' || + pathname.startsWith('/verify/') || + pathname.startsWith('/magic/'); + return ( <> {/* f2026-cursor: see cursor.css. Here rather than on so it stops at the dashboard. */} -
- - - {/* mounts the Luge trail only - the pocket-watch image is gone */} - - +
+ {!isAuthRoute && } + {!isAuthRoute && ( + + {/* mounts the Luge trail only - the pocket-watch image is gone */} + + + )} {children}
diff --git a/app/dashboard/components/StatusBar.tsx b/app/dashboard/components/StatusBar.tsx index e41117a9..9c099787 100644 --- a/app/dashboard/components/StatusBar.tsx +++ b/app/dashboard/components/StatusBar.tsx @@ -57,77 +57,77 @@ export default function StatusBar({ status }: { status: Status }) { } return ( -
- {STAGES.map((stage, index) => { - const isCompleted = index <= currentIndex; - const isCurrent = index === currentIndex; - const isFuture = index > currentIndex; - const isWaitlistMarker = isWaitlist && stage === 'confirmed'; +
+
+
+ {STAGES.map((stage, index) => { + const isCompleted = index <= currentIndex; + const isCurrent = index === currentIndex; + const isWaitlistMarker = isWaitlist && stage === 'confirmed'; - return ( -
- {/* Connector Line */} - {/* Left Line */} - {index !== 0 && ( + return (
- )} + key={stage} + className="relative flex min-w-0 flex-1 flex-col items-center" + > + {index !== 0 && ( +
+ )} - {/* Right Line */} - {index !== STAGES.length - 1 && ( -
- )} + {index !== STAGES.length - 1 && ( +
+ )} - {/* Status Dot */} -
- {isWaitlistMarker && ( -
- )} -
+
+ {isWaitlistMarker && ( +
+ )} +
- {/* Label */} -
- {isWaitlist && STAGE_LABELS[stage] == "Confirmed" ? "Waitlist" : STAGE_LABELS[stage]} -
-
- ); - })} +
+ {isWaitlist && STAGE_LABELS[stage] == 'Confirmed' + ? 'Waitlist' + : STAGE_LABELS[stage]} +
+
+ ); + })} +
+
); } diff --git a/app/dashboard/components/button.tsx b/app/dashboard/components/button.tsx index 30c8ffd9..f73b4e4b 100644 --- a/app/dashboard/components/button.tsx +++ b/app/dashboard/components/button.tsx @@ -10,21 +10,21 @@ const buttonVariants = cva( variants: { variant: { default: - 'bg-gray-900 text-gray-50 hover:bg-gray-900/90 dark:bg-gray-50 dark:text-gray-900 dark:hover:bg-gray-50/90', + 'bg-[#cddaf5] text-slate-950 hover:bg-[#dfe9ff] shadow-[0_8px_24px_rgba(205,218,245,0.2)]', destructive: 'bg-red-500 text-gray-50 hover:bg-red-500/90 dark:bg-red-900 dark:text-gray-50 dark:hover:bg-red-900/90', outline: - 'border border-gray-200 bg-white hover:bg-gray-100 hover:text-gray-900 dark:border-gray-800 dark:bg-gray-950 dark:hover:bg-gray-800 dark:hover:text-gray-50', + 'border border-white/20 bg-transparent text-white hover:bg-white/5 hover:text-white', secondary: - 'bg-gray-100 text-gray-900 hover:bg-gray-100/80 dark:bg-gray-800 dark:text-gray-50 dark:hover:bg-gray-800/80', + 'bg-slate-700 text-white hover:bg-slate-600', ghost: 'hover:bg-gray-100 hover:text-gray-900 dark:hover:bg-gray-800 dark:hover:text-gray-50', link: 'text-gray-900 underline-offset-4 hover:underline dark:text-gray-50', }, size: { - default: 'h-10 px-4 py-2', + default: 'h-11 px-4 py-2 text-sm sm:text-base', sm: 'h-9 rounded-md px-3', - lg: 'h-11 rounded-md px-8', + lg: 'h-12 rounded-md px-8', icon: 'h-10 w-10', }, }, diff --git a/app/dashboard/components/card.tsx b/app/dashboard/components/card.tsx index abe5f171..0221dbf8 100644 --- a/app/dashboard/components/card.tsx +++ b/app/dashboard/components/card.tsx @@ -9,7 +9,7 @@ const Card = React.forwardRef<
(({ className, ...props }, ref) => (
)); @@ -36,7 +36,7 @@ const CardTitle = React.forwardRef<

(({ className, ...props }, ref) => (

)); @@ -60,7 +60,7 @@ const CardContent = React.forwardRef< HTMLDivElement, React.HTMLAttributes >(({ className, ...props }, ref) => ( -

+
)); CardContent.displayName = 'CardContent'; @@ -70,7 +70,7 @@ const CardFooter = React.forwardRef< >(({ className, ...props }, ref) => (
)); diff --git a/app/dashboard/components/discord.tsx b/app/dashboard/components/discord.tsx index 3ab77331..8c38302b 100644 --- a/app/dashboard/components/discord.tsx +++ b/app/dashboard/components/discord.tsx @@ -1,14 +1,9 @@ 'use client'; -import { Button } from '@/app/ui/button'; - +import { Button } from '@/app/dashboard/components/button'; import { getOAuthUrl, setDiscord } from '@/app/lib/actions'; - -import { UpdateSelf } from '@/app/lib/data'; - import { useState, useEffect } from 'react'; import { redirect } from 'next/navigation'; - import { useRouter } from 'next/navigation'; export default function DiscordAuth(props: { @@ -36,7 +31,6 @@ export default function DiscordAuth(props: { const setHackRU = async () => { if (code != null) { console.log('SEND REQUEST'); - //setdiscordAuth(true); const resp = await setDiscord(code); if (resp != null) { setErrors(resp.error); @@ -53,21 +47,27 @@ export default function DiscordAuth(props: { }, []); return ( -
- {

{submit_errors}

} - { -

- {userData.discord != undefined ? userData.discord.username : ''} +

+ {submit_errors && ( +

{submit_errors}

+ )} + {userData.discord != undefined && userData.discord.username && ( +

+ Connected as {userData.discord.username}

- } + )} Join Here! https://discord.gg/yt65RGgN4x
- {/*
- - - -
*/}
- +
{ setLoading(true); @@ -105,114 +140,243 @@ export default function ProfileHeader(props: { )} */} {userData.registration_status == 'unregistered' && ( <> - {waiverState && ( -

- {'Waiver Uploaded'} -

- )} -
-

- Click - +

+
+

+ Step 1: Profile +

+

+ Complete your HackRU profile first +

+
+ - {' '} - HERE{' '} -
- for waiver -

- { - handleChangingFile(e, 'application/pdf', 'WAIVER'); - }} - required - > + {profileReady ? 'Profile complete' : 'Required'} + +
+ + {!profileReady && ( +
+

+ You need to finish and save your profile before you can + upload a waiver or register for HackRU. +

+ +
+ )} + + {profileReady && ( +

+ Your profile is complete. You can continue to the waiver. +

+ )}
-
- -

- I have read and agree to the - +

+
+

+ Step 2: Waiver +

+

+ Upload your waiver +

+
+ - {' '} - MLH Code of Conduct -
-

+ {waiverState + ? 'Waiver complete' + : profileReady + ? 'Required' + : 'Profile required'} + +
+ + {!waiverState && ( +
+ {!profileReady && ( +

+ Complete and save your profile first before uploading a + waiver. +

+ )} + + {profileReady && ( +

+ Please review and upload the HackRU waiver. You cannot + complete registration until it's submitted. +

+ )} + +
+

+ Click + + {' '} + here{' '} + + to open the waiver +

+
+ { + const file = e.target.files?.[0]; + setSelectedWaiverName(file ? file.name : ''); + handleChangingFile(e, 'application/pdf', 'WAIVER'); + }} + required + > + {selectedWaiverName && ( +

+ Selected file:{' '} + + {selectedWaiverName} + +

+ )} +
+
+ +
+
+ +

+ I have read and agree to the + + {' '} + MLH Code of Conduct + +

+
+ +
+ +

+ I authorize you to share my application/registration + information for event administration, ranking, MLH + administration, pre- and post-event informational + emails, and occasional messages about hackathons in + line with the{' '} + + MLH Privacy Policy + + . Further, I agree to the terms of both the{' '} + + MLH Contest Terms and Conditions + {' '} + and the{' '} + + MLH Privacy Policy + +

+
+
+ +
+ +
+
+ )} + + {waiverState && ( +

+ Your waiver has been submitted. You may continue to + registration. +

+ )}
-
- -

- I authorize you to share my application/registration - information for event administration, ranking, MLH - administration, pre- and post-event informational e-mails, - and occasional messages about hackathons in-line with the{' '} - - MLH Privacy Policy - - . Further, I agree to the terms of both the{' '} - - MLH Contest Terms and Conditions - {' '} - and the{' '} - +

-
- (userData.opt_in = e.target.checked)} - /> -

- I authorize MLH to send me occasional emails about relevant - events, career opportunities, and community announcements. - (optional) -

-
-
- Unregistered - + {registrationReady ? 'Register' : 'Complete profile + waiver'} + +
+ {!registrationReady && ( +

+ Finish your profile and upload the waiver before registering. +

+ )}
)} @@ -263,19 +427,19 @@ export default function ProfileHeader(props: { userData.registration_status == 'coming' || userData.registration_status == 'not_coming') && ( <> -
+
{uploadingNewConfirmationStatus && ( -

Loading confirmation status...

+

Loading confirmation status...

)} {errorMessage && ( -

{errorMessage}

+

{errorMessage}

)} {!uploadingNewConfirmationStatus && ( <> {userData.registration_status == 'confirmation' && ( <> - + RSVP: We're ready to begin moving hackers to acceptance! Please confirm your availability and let us know if you're "Coming." We will @@ -285,47 +449,41 @@ export default function ProfileHeader(props: { individual hackers based on FCFS priority and use team formations to keep your friends with you! - - +
+ + +
)} {userData.registration_status == 'coming' && ( <> - + Thanks for letting us know you can make it! We're slowly moving hackers into the final confirmation stage based on first-come first-serve responses. - +
+ +
)} {userData.registration_status == 'not_coming' && ( <> - + You are not coming. Thanks for letting us know. - +
+ +
)} diff --git a/app/dashboard/layout.tsx b/app/dashboard/layout.tsx index 5d2f6ffe..b77f3a39 100644 --- a/app/dashboard/layout.tsx +++ b/app/dashboard/layout.tsx @@ -7,7 +7,10 @@ import { inter } from '@/app/ui/fonts'; export default function Layout({ children }: { children: React.ReactNode }) { return ( <> -
+
diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx index 1e45bb8b..40c9780e 100644 --- a/app/dashboard/page.tsx +++ b/app/dashboard/page.tsx @@ -252,7 +252,6 @@ export default function Dashboard() { } const resp = await UploadTeamSubmission(current_email, data); - console.log(resp); const team_id = resp.team_id; if (resp.error.length > 0 || team_id === undefined || team_id === 0) { @@ -413,21 +412,35 @@ export default function Dashboard() { }; async function fetchTeam() { + if (!userData?.email) { + return; + } + try { setpendingteam(userData?.team_info?.pending_invites[0]?.team_id); + const resp = await ReadConfirmed(); - console.log('TEAM'); - setTeamInfo(resp.response); - console.log(teamInfo); - const l = await isLeaderCheck(teamInfo?.leader_email); - setTeamStatus({ - ...teamStatus, - isLeader: l, - }); + if (resp?.error && String(resp.error).includes('not in an active team')) { + setTeamInfo(null); + setpendingTeamInvites(null); + setTeamStatus((prev: any) => ({ ...prev, isLeader: false, team_id: '' })); + return; + } + + const teamInfoResponse = (resp?.response as any) || null; + setTeamInfo(teamInfoResponse); + const leaderEmail = teamInfoResponse?.leader_email; + const l = leaderEmail ? await isLeaderCheck(leaderEmail) : false; + setTeamStatus((prev: any) => ({ ...prev, isLeader: !!l })); + const resp2 = await ReadPendingOnTeam(); - setpendingTeamInvites(resp2.response); + if (resp2?.error && String(resp2.error).includes('not in an active team')) { + setpendingTeamInvites(null); + return; + } + setpendingTeamInvites(resp2.response || null); } catch (error) { - console.error('Error fetching or parsing schools data:', error); + console.error('Error fetching team data:', error); } } @@ -471,8 +484,10 @@ export default function Dashboard() { }; useEffect(() => { - fetchTeam(); - }, [userData]); + if (userData?.email) { + fetchTeam(); + } + }, [userData?.email]); // First useEffect to fetch and set schools data useEffect(() => { @@ -549,6 +564,18 @@ export default function Dashboard() { async function fetchUser() { try { const data = await getSelf(); + + if (data?.error && typeof data.error === 'string') { + if ( + data.error.includes('Something went wrong') || + data.error.includes('not authenticated') || + data.error.includes('Unauthorized') + ) { + window.location.href = '/login'; + return; + } + } + const points = await GetPoints(); const pointsResponseBody = @@ -634,82 +661,65 @@ export default function Dashboard() { //REMOVE ONCE OPTIN WORKING AS EXPECTED if (userData?.opt_in == null) { return ( -
- - - - - Would you like to opt-in to Major League Hacking emails? You - must choose before you can proceed to registration profile. - - - - - - - +
+
+

+ Before you continue +

+

+ MLH communications preference +

+

+ Please choose whether you'd like to receive occasional MLH + emails about events, career opportunities, and community updates. + This must be answered before you can continue to your HackRU + profile and registration. +

+ +
+ + +
+
); } return ( -
+
{/* */} -
+
- {!(userData?.registration_status === 'unregistered') && ( - - -
-
- {`QR Code - Shirt Size ${userData?.shirt_size}`} - - Use this QR code to check-in or scan-in for events! - -
-
-
- -
- -
-
-
- )} {/*Getting ride of house info as well */} {userData?.registration_status === 'checked_in' && false && ( @@ -1214,25 +1224,34 @@ export default function Dashboard() { /> - + -
+
Profile Update your profile information. * fields are required
-
- +
- +
- + */}
- + {majors.map((major, index) => (