import { FC, ReactElement, useState, useEffect } from 'react'; import { ControlledInputField } from '@imphnen-frontend-service/ui/organisms'; import { Button, Textarea } from '@imphnen-frontend-service/ui/atoms'; import { useNavigate } from 'react-router'; import { useForm, Controller } from 'react-hook-form'; import { userOnboardingSchema, TUserOnboardingForm, useUpdateUserMe, useUploadAvatar } from '@imphnen-frontend-service/service'; import { zodResolver } from '@hookform/resolvers/zod'; import { useUserMe } from '@imphnen-frontend-service/service'; import { useAuthStore } from '@imphnen-frontend-service/utils'; const ROLE_OPTIONS = [ 'Frontend Developer', 'Backend Developer', 'Full Stack Developer', 'DevOps Engineer', 'UI/UX Designer', 'Product Manager', 'Data Scientist', 'Mobile Developer', ]; const INDONESIAN_CITIES = [ 'Jakarta', 'Surabaya', 'Bandung', 'Medan', 'Semarang', 'Makassar', 'Palembang', 'Tangerang', 'Depok', 'Bekasi', 'Yogyakarta', 'Malang', 'Bogor', 'Batam', 'Pekanbaru', ]; const UserOnboardingPage: FC = (): ReactElement => { const navigate = useNavigate(); const [avatarFile, setAvatarFile] = useState(null); const [avatarPreview, setAvatarPreview] = useState(''); const { data: userData } = useUserMe(); const { mutateAsync: updateUser, isPending: isUpdating } = useUpdateUserMe(); const { mutateAsync: uploadAvatar, isPending: isUploading } = useUploadAvatar(); const { session } = useAuthStore(); const form = useForm({ resolver: zodResolver(userOnboardingSchema), mode: 'all', defaultValues: { fullname: session?.user?.fullname || userData?.data?.fullname || '', location: session?.user?.location || '', bio: session?.user?.bio || '', skills: session?.user?.skills || [], }, }); // Set initial avatar preview from GitHub avatar if available useEffect(() => { if (session?.user?.avatar && !avatarPreview) { setAvatarPreview(session.user.avatar); } }, [session?.user?.avatar, avatarPreview]); const handleAvatarChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { setAvatarFile(file); const reader = new FileReader(); reader.onloadend = () => { setAvatarPreview(reader.result as string); }; reader.readAsDataURL(file); } }; 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({ 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'}`); } }); return (

Complete Your Profile

Tell us more about yourself to get started

{/* Avatar Upload */}
{avatarPreview ? ( Avatar preview ) : (
👤
)}

Optional, but highly recommended

{/* Full Name */} {/* City */}
(
{fieldState.error && (

{fieldState.error.message}

)}
)} />
{/* Role/Skills */}
(
{ROLE_OPTIONS.map((role) => ( ))}
)} />
{/* Bio */}
(