From bc5b072ad8b977da058efefc3b0e15c2869184af Mon Sep 17 00:00:00 2001 From: Hafid Nur <73023445+hafidnrzs@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:12:45 +0700 Subject: [PATCH] feat(hackathon): Improve dark mode and UI/UX in Hackathon website (#64) * feat: update landing page * feat: Add favicon and SEO (JSON-LD schema, meta tags) - Add favicon image - Add JSON-LD schema for Hackathon event - Add react-helmet-async for managing meta tags * chore: remove react-helmet-async * chore: update landing page * chore: update UI for signup and login - add back button for better UX * feat: add image loading state and skeleton UI for team dashboard * fix: landing navbar not sticky to top, fix onboarding UI * feat(hackathon): update UI - Update dashboard, onboarding user, edit profile, and team layout to make it more consistent * fix: optimize placeholder banner image & minor fix dark mode * feat(hackathon): update landing page dark mode color scheme * feat(hackathon): update auth page dark mode color scheme * feat(hackathon): dashboard UI improvement and dark mode adjustment * feat(hackathon): browse team page - update dark mode color scheme - add some border style to give outline and depth - change emoji to icon * feat(hackathon): update team page - update dark mode color scheme for team page: view, team edit, and submit project page - fix bug in chat where messages are displayed double - make the form field size consistent * feat(hackathon): update dark mode onboarding and edit profile --------- Co-authored-by: Maulana Sodiqin Co-authored-by: Muhammad Zakir Ramadhan <61570975+zakirkun@users.noreply.github.com> --- apps/hackathon/src/app/404.tsx | 6 +- .../src/app/auth/forgot-password/page.tsx | 33 +-- apps/hackathon/src/app/auth/login/page.tsx | 30 +-- .../src/app/auth/reset-password/page.tsx | 62 ++--- apps/hackathon/src/app/auth/signup/page.tsx | 40 ++-- apps/hackathon/src/app/dashboard/layout.tsx | 8 +- apps/hackathon/src/app/dashboard/page.tsx | 88 ++++--- .../src/app/onboarding/user/page.tsx | 26 +- apps/hackathon/src/app/page.tsx | 124 +++++----- apps/hackathon/src/app/profile/page.tsx | 12 +- .../src/app/teams/[teamId]/chat/page.tsx | 174 +++++++++++--- .../src/app/teams/[teamId]/edit/page.tsx | 117 ++++++--- .../src/app/teams/[teamId]/layout.tsx | 26 +- .../src/app/teams/[teamId]/members/page.tsx | 136 +++++++---- .../hackathon/src/app/teams/[teamId]/page.tsx | 224 ++++++++++-------- .../src/app/teams/[teamId]/submit/page.tsx | 112 ++++++--- apps/hackathon/src/app/teams/browse/page.tsx | 63 ++--- apps/hackathon/src/app/teams/layout.tsx | 8 +- apps/hackathon/src/components/city-select.tsx | 12 +- apps/hackathon/src/components/sidebar.tsx | 26 +- .../hackathon/src/components/theme-toggle.tsx | 44 +++- libs/ui/src/atoms/button/button.tsx | 9 +- libs/ui/src/atoms/input/input.tsx | 2 +- libs/ui/src/atoms/textarea/textarea.tsx | 2 +- .../src/molecules/input-field/input-field.tsx | 2 +- 25 files changed, 864 insertions(+), 522 deletions(-) diff --git a/apps/hackathon/src/app/404.tsx b/apps/hackathon/src/app/404.tsx index 2db4df6..3a2e703 100644 --- a/apps/hackathon/src/app/404.tsx +++ b/apps/hackathon/src/app/404.tsx @@ -2,13 +2,13 @@ import { Link } from 'react-router-dom'; export default function NotFoundPage() { return ( -
+

404

-

+

Page Not Found

-

+

The page you are looking for doesn't exist or has been moved.

-
+
+
+
+ + +
-

+

Forgot Password?

-

+

No worries, we'll send you reset instructions

@@ -95,7 +106,7 @@ export default function ForgotPasswordPage() {
@@ -106,7 +117,7 @@ export default function ForgotPasswordPage() { onChange={(e) => setEmail(e.target.value)} placeholder="your@email.com" disabled={isLoading} - className="w-full px-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed" + className="bg-white dark:bg-gray-800 w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed" required />
@@ -119,16 +130,6 @@ export default function ForgotPasswordPage() { {isLoading ? 'Sending...' : 'Send Reset Link'} - -
- - - Back to Login - -
); diff --git a/apps/hackathon/src/app/auth/login/page.tsx b/apps/hackathon/src/app/auth/login/page.tsx index 4d6bfdd..87f4ca3 100644 --- a/apps/hackathon/src/app/auth/login/page.tsx +++ b/apps/hackathon/src/app/auth/login/page.tsx @@ -115,8 +115,8 @@ export default function LoginPage() { }; return ( -
-
+
+
@@ -147,7 +147,7 @@ export default function LoginPage() {
@@ -158,7 +158,7 @@ export default function LoginPage() { onChange={(e) => setEmail(e.target.value)} placeholder="your@email.com" disabled={isEmailLoading} - className="w-full px-4 py-2.5 border border-gray-300 dark:border-neutral-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-neutral-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-neutral-500 disabled:bg-gray-100 dark:disabled:bg-neutral-700 disabled:cursor-not-allowed" + className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500 disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed" required />
@@ -167,7 +167,7 @@ export default function LoginPage() {
@@ -185,7 +185,7 @@ export default function LoginPage() { onChange={(e) => setPassword(e.target.value)} placeholder="••••••••" disabled={isEmailLoading} - className="w-full px-4 py-2.5 border border-gray-300 dark:border-neutral-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-neutral-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-neutral-500 disabled:bg-gray-100 dark:disabled:bg-neutral-700 disabled:cursor-not-allowed" + className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500 disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed" required />
@@ -193,23 +193,25 @@ export default function LoginPage() {
-
- OR -
+
+ + OR + +
-

+

Don't have an account?{' '}

diff --git a/apps/hackathon/src/app/auth/reset-password/page.tsx b/apps/hackathon/src/app/auth/reset-password/page.tsx index 11a882d..905917b 100644 --- a/apps/hackathon/src/app/auth/reset-password/page.tsx +++ b/apps/hackathon/src/app/auth/reset-password/page.tsx @@ -10,17 +10,17 @@ export default function ResetPasswordPage() { const [isLoading, setIsLoading] = useState(false); const [isValidToken, setIsValidToken] = useState(false); - useEffect(() => { - // Check if we have a valid session (from the reset link) - supabase.auth.getSession().then(({ data: { session } }) => { - if (session) { - setIsValidToken(true); - } else { - toast.error('Invalid or expired reset link'); - setTimeout(() => navigate('/auth/forgot-password'), 2000); - } - }); - }, [navigate]); + // useEffect(() => { + // // Check if we have a valid session (from the reset link) + // supabase.auth.getSession().then(({ data: { session } }) => { + // if (session) { + // setIsValidToken(true); + // } else { + // toast.error('Invalid or expired reset link'); + // setTimeout(() => navigate('/auth/forgot-password'), 2000); + // } + // }); + // }, [navigate]); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); @@ -59,32 +59,36 @@ export default function ResetPasswordPage() { } }; - if (!isValidToken) { - return ( -
-
-
-

Verifying reset link...

-
-
- ); - } + // if (!isValidToken) { + // return ( + //
+ //
+ //
+ //

+ // Verifying reset link... + //

+ //
+ //
+ // ); + // } return ( -
-
+
+
-

+

Set New Password

-

Enter your new password below

+

+ Enter your new password below +

@@ -95,7 +99,7 @@ export default function ResetPasswordPage() { onChange={(e) => setPassword(e.target.value)} placeholder="••••••••" disabled={isLoading} - className="w-full px-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed" + className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed bg-white dark:bg-gray-800 text-gray-900 dark:text-white" required minLength={6} /> @@ -104,7 +108,7 @@ export default function ResetPasswordPage() {
@@ -115,7 +119,7 @@ export default function ResetPasswordPage() { onChange={(e) => setConfirmPassword(e.target.value)} placeholder="••••••••" disabled={isLoading} - className="w-full px-4 py-2.5 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed" + className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed bg-white dark:bg-gray-800 text-gray-900 dark:text-white" required minLength={6} /> diff --git a/apps/hackathon/src/app/auth/signup/page.tsx b/apps/hackathon/src/app/auth/signup/page.tsx index 0b4bdc2..4fcee88 100644 --- a/apps/hackathon/src/app/auth/signup/page.tsx +++ b/apps/hackathon/src/app/auth/signup/page.tsx @@ -138,8 +138,8 @@ export default function SignupPage() { }; return ( -
-
+
+
{error && ( @@ -168,7 +170,7 @@ export default function SignupPage() {
@@ -179,7 +181,7 @@ export default function SignupPage() { onChange={(e) => setFullname(e.target.value)} placeholder="John Doe" disabled={isEmailLoading} - className="w-full px-4 py-2.5 border border-gray-300 dark:border-neutral-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-neutral-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-neutral-500 disabled:bg-gray-100 dark:disabled:bg-neutral-700 disabled:cursor-not-allowed" + className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500 disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed" required />
@@ -187,7 +189,7 @@ export default function SignupPage() {
@@ -198,7 +200,7 @@ export default function SignupPage() { onChange={(e) => setEmail(e.target.value)} placeholder="your@email.com" disabled={isEmailLoading} - className="w-full px-4 py-2.5 border border-gray-300 dark:border-neutral-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-neutral-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-neutral-500 disabled:bg-gray-100 dark:disabled:bg-neutral-700 disabled:cursor-not-allowed" + className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500 disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed" required />
@@ -206,7 +208,7 @@ export default function SignupPage() {
@@ -217,7 +219,7 @@ export default function SignupPage() { onChange={(e) => setPassword(e.target.value)} placeholder="••••••••" disabled={isEmailLoading} - className="w-full px-4 py-2.5 border border-gray-300 dark:border-neutral-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-neutral-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-neutral-500 disabled:bg-gray-100 dark:disabled:bg-neutral-700 disabled:cursor-not-allowed" + className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500 disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed" required />
@@ -225,7 +227,7 @@ export default function SignupPage() {
@@ -236,7 +238,7 @@ export default function SignupPage() { onChange={(e) => setConfirmPassword(e.target.value)} placeholder="••••••••" disabled={isEmailLoading} - className="w-full px-4 py-2.5 border border-gray-300 dark:border-neutral-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-neutral-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-neutral-500 disabled:bg-gray-100 dark:disabled:bg-neutral-700 disabled:cursor-not-allowed" + className="w-full px-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-white placeholder:text-gray-400 dark:placeholder:text-gray-500 disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed" required />
@@ -244,23 +246,25 @@ export default function SignupPage() {
-
- OR -
+
+ + OR + +
-

+

Already have an account?{' '}

diff --git a/apps/hackathon/src/app/dashboard/layout.tsx b/apps/hackathon/src/app/dashboard/layout.tsx index 7bd34ef..5360727 100644 --- a/apps/hackathon/src/app/dashboard/layout.tsx +++ b/apps/hackathon/src/app/dashboard/layout.tsx @@ -6,18 +6,18 @@ const DashboardLayout: FC = (): ReactElement => { const [sidebarOpen, setSidebarOpen] = useState(false); return ( -
+
setSidebarOpen(false)} />
{/* Mobile Header with Hamburger */} -
+
@@ -158,23 +158,23 @@ export default function HomePage() { {/* Mobile Menu */} {mobileMenuOpen && ( -