diff --git a/apps/hackathon/src/app/auth/login/page-original.tsx b/apps/hackathon/src/app/auth/login/page-original.tsx deleted file mode 100644 index c615f92..0000000 --- a/apps/hackathon/src/app/auth/login/page-original.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { FC, ReactElement, useEffect, useState } from 'react'; -import { Button } from '@imphnen-frontend-service/ui/atoms'; -import { useNavigate } from 'react-router'; -import { useGitHubAuth } from '@imphnen-frontend-service/service'; -import { useSession } from '@imphnen-frontend-service/utils'; -import { GithubOutlined } from '@ant-design/icons'; - -const LoginPage: FC = (): ReactElement => { - console.log('[LoginPage] Rendering...'); - - const navigate = useNavigate(); - const { signInWithGitHub } = useGitHubAuth(); - const [isGithubLoading, setIsGithubLoading] = useState(false); - const { isAuthenticated } = useSession(); - - console.log('[LoginPage] isAuthenticated:', isAuthenticated); - - useEffect(() => { - console.log('[LoginPage] useEffect - isAuthenticated:', isAuthenticated); - if (isAuthenticated) { - console.log('[LoginPage] Redirecting to dashboard...'); - navigate('/dashboard'); - } - }, [isAuthenticated, navigate]); - - const handleGithubLogin = async () => { - try { - setIsGithubLoading(true); - console.log('[Login] Initiating GitHub OAuth...'); - - const result = await signInWithGitHub(); - console.log('[Login] OAuth result:', result); - - // Check if we got a redirect URL - if (result?.url) { - console.log('[Login] Redirecting to GitHub OAuth:', result.url); - // Supabase should handle the redirect automatically - // If we're still here after 2 seconds, manually redirect - setTimeout(() => { - if (result.url) { - globalThis.location.href = result.url; - } - }, 2000); - } else { - console.error('[Login] No OAuth URL returned'); - setIsGithubLoading(false); - } - } catch (error) { - console.error('[Login] GitHub login failed:', error); - setIsGithubLoading(false); - } - }; - - return ( -
-
-
-

- Welcome to Hackathon -

-

- Sign in with your GitHub account to join or create your hackathon team -

-
- - - -
-

- By signing in, you agree to our Terms of Service and Privacy Policy -

-
-
-
- ); -}; - -export default LoginPage; diff --git a/apps/hackathon/src/app/layout.tsx b/apps/hackathon/src/app/layout.tsx index 24da90e..cb034c0 100644 --- a/apps/hackathon/src/app/layout.tsx +++ b/apps/hackathon/src/app/layout.tsx @@ -14,18 +14,14 @@ export default function RootLayout() { const checkAuth = async () => { const pathname = location.pathname; - console.log('[Layout] Checking auth for route:', pathname); - // Allow hackathon pages without checks if (pathname.startsWith('/hackathons')) { - console.log('[Layout] Public route, allowing access'); setIsChecking(false); return; } // Allow auth callback without checks if (pathname === '/auth/callback') { - console.log('[Layout] Auth callback, allowing access'); setIsChecking(false); return; } @@ -43,27 +39,23 @@ export default function RootLayout() { if (isPublicAuthPage) { // If already authenticated and not on password reset pages, redirect to dashboard if (session && pathname !== '/auth/reset-password') { - console.log('[Layout] Already authenticated, redirecting to dashboard'); navigate('/dashboard', { replace: true }); setIsChecking(false); return; } // Allow unauthenticated access - console.log('[Layout] Public auth page, allowing access'); setIsChecking(false); return; } // Home page - allow everyone to view the landing page if (pathname === '/') { - console.log('[Layout] Landing page, allowing access'); setIsChecking(false); return; } // Require authentication for all other routes if (!session) { - console.log('[Layout] No session, redirecting to login'); navigate('/auth/login', { replace: true }); setIsChecking(false); return; @@ -87,17 +79,15 @@ export default function RootLayout() { const hasLocation = !!userData?.location; if (!hasLocation) { - console.log('[Layout] User needs onboarding, redirecting'); navigate('/onboarding/user', { replace: true }); setIsChecking(false); return; } } catch (error) { - console.error('[Layout] Unexpected error checking onboarding:', error); + // Silently handle error } } - console.log('[Layout] Auth check passed'); setIsChecking(false); }; diff --git a/apps/hackathon/src/app/onboarding/user/page.tsx b/apps/hackathon/src/app/onboarding/user/page.tsx index 2fd7ab1..4f0b6c0 100644 --- a/apps/hackathon/src/app/onboarding/user/page.tsx +++ b/apps/hackathon/src/app/onboarding/user/page.tsx @@ -12,6 +12,7 @@ import { useAuthStore, } from '@imphnen-frontend-service/service'; import { zodResolver } from '@hookform/resolvers/zod'; +import { toast } from 'sonner'; import { CitySelect } from '../../../components/city-select'; import { Icon } from '@iconify/react'; @@ -70,41 +71,34 @@ const UserOnboardingPage: FC = (): ReactElement => { const onSubmit = form.handleSubmit(async (data) => { try { - // console.log('[Onboarding] Starting submission...', data); let avatarUrl = session?.user?.avatar || null; // Upload avatar if a new file was selected if (avatarFile) { - // console.log('[Onboarding] Uploading avatar...'); const uploadResult = await uploadAvatar(avatarFile); avatarUrl = uploadResult.data.url; - // console.log('[Onboarding] Avatar uploaded:', avatarUrl); } // Update user in Supabase - // console.log('[Onboarding] Updating user in Supabase...'); - const result = await updateUser({ + await updateUser({ fullname: data.fullname, avatar: avatarUrl, location: data.location, bio: data.bio, skills: data.skills, }); - // console.log('[Onboarding] User updated successfully:', result); // Wait a bit for the onSuccess handler to update localStorage // The updateUser mutation's onSuccess handler updates the Zustand store and localStorage await new Promise((resolve) => setTimeout(resolve, 100)); - // console.log('[Onboarding] Navigating to dashboard...'); // Use window.location for a full page reload to ensure middleware sees updated localStorage globalThis.location.href = '/dashboard'; } catch (error) { - // console.error('[Onboarding] Onboarding failed:', error); - alert( - `Onboarding failed: ${ - error instanceof Error ? error.message : 'Unknown error' - }` + toast.error( + error instanceof Error + ? error.message + : 'Onboarding failed. Please try again.' ); } }); diff --git a/apps/hackathon/src/app/profile/page.tsx b/apps/hackathon/src/app/profile/page.tsx index 93a3b27..2e22689 100644 --- a/apps/hackathon/src/app/profile/page.tsx +++ b/apps/hackathon/src/app/profile/page.tsx @@ -138,8 +138,8 @@ const ProfilePage: FC = (): ReactElement => { const isLoading = isUpdating || isUploading; return ( -
-
+
+

diff --git a/apps/hackathon/src/app/teams/[teamId]/edit/page.tsx b/apps/hackathon/src/app/teams/[teamId]/edit/page.tsx index edde57a..92cb574 100644 --- a/apps/hackathon/src/app/teams/[teamId]/edit/page.tsx +++ b/apps/hackathon/src/app/teams/[teamId]/edit/page.tsx @@ -5,7 +5,8 @@ import { useNavigate, useParams } from 'react-router'; import { useForm, Controller } from 'react-hook-form'; import { teamUpdateSchema, TTeamUpdateForm, useUpdateTeam, useTeamById, ETeamVisibility, useUploadFile, useAuthStore } from '@imphnen-frontend-service/service'; import { zodResolver } from '@hookform/resolvers/zod'; -import INDONESIAN_CITIES from '../../../../constants/cities'; + +import { CitySelect } from '../../../../components/city-select'; const EditTeamPage: FC = (): ReactElement => { const { teamId } = useParams<{ teamId: string }>(); @@ -229,22 +230,12 @@ const EditTeamPage: FC = (): ReactElement => { control={form.control} name="city" render={({ field, fieldState }) => ( -
- - {fieldState.error && ( -

{fieldState.error.message}

- )} -
+ )} />

diff --git a/apps/hackathon/src/app/teams/[teamId]/page.tsx b/apps/hackathon/src/app/teams/[teamId]/page.tsx index 7532996..a123a6e 100644 --- a/apps/hackathon/src/app/teams/[teamId]/page.tsx +++ b/apps/hackathon/src/app/teams/[teamId]/page.tsx @@ -85,54 +85,6 @@ const TeamDashboardPage: FC = (): ReactElement => { ); const canInvite = isLeader && members.length < MAX_TEAM_MEMBERS; - // Calculate total images to load - const totalImagesToLoad = - (team?.banner ? 1 : 0) + - (team?.logo ? 1 : 0) + - members.filter((m: any) => m.user?.avatar).length; - - // Track image loading with timeout fallback - useEffect(() => { - if (!isLoadingTeam && !isLoadingMembers && team) { - if (totalImagesToLoad === 0) { - setImagesLoaded(true); - } else if (imageLoadCount >= totalImagesToLoad) { - setImagesLoaded(true); - } - } - }, [ - isLoadingTeam, - isLoadingMembers, - team, - imageLoadCount, - totalImagesToLoad, - ]); - - // Fallback timeout - if images take too long, show content anyway - useEffect(() => { - if (!isLoadingTeam && !isLoadingMembers && team && !imagesLoaded) { - const timeout = setTimeout(() => { - setImagesLoaded(true); - }, 3000); // 3 second timeout - return () => clearTimeout(timeout); - } - }, [isLoadingTeam, isLoadingMembers, team, imagesLoaded]); - - const handleImageLoad = () => { - setImageLoadCount((prev) => prev + 1); - }; - - // Also count error as loaded to prevent stuck - const handleImageError = () => { - setImageLoadCount((prev) => prev + 1); - }; - - console.log('Leader check:', { - currentUserId, - leaderId: team?.leader_id, - isLeader, - }); - const handleInviteMember = async (e: React.FormEvent) => { e.preventDefault(); if (!inviteEmail.trim() || isInviting) return; diff --git a/apps/hackathon/src/middleware.ts b/apps/hackathon/src/middleware.ts index 28ed9e0..d5001ae 100644 --- a/apps/hackathon/src/middleware.ts +++ b/apps/hackathon/src/middleware.ts @@ -37,8 +37,6 @@ export const middleware = async ({ request }: LoaderFunctionArgs) => { const url = new URL(request.url); const pathname = url.pathname; - console.log('[Middleware] Checking route:', pathname); - // Get session from Supabase (authoritative source) const { data: { session: supabaseSession }, error: sessionError } = await supabase.auth.getSession(); @@ -86,10 +84,8 @@ export const middleware = async ({ request }: LoaderFunctionArgs) => { let hasLocation = false; if (cached && (now - cached.timestamp) < CACHE_DURATION) { - console.log('[Middleware] Using cached onboarding status'); hasLocation = cached.hasLocation; } else { - console.log('[Middleware] Fetching fresh onboarding status'); const { data: userData, error: userError } = await supabase .from('users') .select('location') diff --git a/libs/ui/src/atoms/input/input.tsx b/libs/ui/src/atoms/input/input.tsx index 85e9b18..cc730e9 100644 --- a/libs/ui/src/atoms/input/input.tsx +++ b/libs/ui/src/atoms/input/input.tsx @@ -56,7 +56,7 @@ export const Input: FC = ({ }; const mergedClassName = cn( - `px-[12px] py-[8px] text-neutral-800 bg-white placeholder:text-neutral-300 border border-neutral-200 hover:border-blue-300 focus:outline-1 focus:outline-blue-500 rounded-md font-bai-jamjuree w-full ${ + `px-[12px] py-[8px] text-neutral-800 dark:text-white bg-white dark:bg-neutral-800 placeholder:text-neutral-300 dark:placeholder:text-neutral-500 border border-neutral-200 dark:border-neutral-600 hover:border-blue-300 dark:hover:border-blue-500 focus:outline-1 focus:outline-blue-500 dark:focus:outline-primary-500 rounded-md font-bai-jamjuree w-full ${ widthform === 'standard' ? 'min-w-70' : '' }`, sizeClasses[size].textSize, diff --git a/libs/ui/src/atoms/textarea/textarea.tsx b/libs/ui/src/atoms/textarea/textarea.tsx index 1c31100..eaab380 100644 --- a/libs/ui/src/atoms/textarea/textarea.tsx +++ b/libs/ui/src/atoms/textarea/textarea.tsx @@ -38,7 +38,7 @@ export const Textarea: FC = ({ ...rest }): ReactElement => { const mergedClassName = cn( - 'rounded-md border border-neutral-200 hover:border-blue-300 focus:outline-1 focus:outline-blue-500 px-[12px] py-[8px] invalid:border-danger-500 invalid:text-danger-500', + 'rounded-md border border-neutral-200 dark:border-neutral-600 hover:border-blue-300 dark:hover:border-blue-500 focus:outline-1 focus:outline-blue-500 dark:focus:outline-primary-500 px-[12px] py-[8px] bg-white dark:bg-neutral-800 text-neutral-800 dark:text-white placeholder:text-neutral-300 dark:placeholder:text-neutral-500 invalid:border-danger-500 invalid:text-danger-500', sizeClasses[size], disabled && disabledClass, error && errorClass,