'use client' import React, { useEffect } from 'react' import { useRouter } from 'next/navigation' import useAuthStore from '../store/authStore' import Header from '../components/nav/Header' import Footer from '../components/Footer' import ProfileCompletion from './components/profileCompletion' import BasicInformation from './components/basicInformation' import MediaSection from './components/mediaSection' import BankInformation from './components/bankInformation' import EditModal from './components/editModal' import { UserCircleIcon, EnvelopeIcon, PhoneIcon, MapPinIcon, PencilIcon, CheckCircleIcon } from '@heroicons/react/24/outline' import { getProfileCompletion } from './hooks/getProfileCompletion'; import { useProfileData } from './hooks/getProfileData'; import { useMedia } from './hooks/getMedia'; import { editProfileBasic, editProfileBank } from './hooks/editProfile'; // Helper to display missing fields in subtle gray italic (no yellow highlight) function HighlightIfMissing({ value, children }: { value: any, children: React.ReactNode }) { if (value === null || value === undefined || value === '') { return ( Not provided ); } return <>{children}; } // Helper for safe access to profileData fields function getProfileField( obj: typeof defaultProfileData, key: T ) { return obj[key]; } // Default profile data for typing const defaultProfileData = { firstName: '', lastName: '', email: '', phone: '', address: '', joinDate: '', memberStatus: '', profileComplete: 0, accountHolder: '', iban: '', contactPersonName: '', userType: '', }; export default function ProfilePage() { const router = useRouter() const user = useAuthStore(state => state.user) const [userId, setUserId] = React.useState(undefined); // Update userId when user changes useEffect(() => { if (user?.id) setUserId(user.id); }, [user]); // Add refresh key and UI states for smooth refresh const [refreshKey, setRefreshKey] = React.useState(0); const [showRefreshing, setShowRefreshing] = React.useState(false); const [completionLoading, setCompletionLoading] = React.useState(false); // Fetch profile data on page load/navigation, now with refreshKey const { data: profileDataApi, loading: profileLoading, error: profileError } = useProfileData(userId, refreshKey); // Fetch media/documents for user, now with refreshKey const { data: mediaData, loading: mediaLoading, error: mediaError } = useMedia(userId, refreshKey); // Redirect if not logged in useEffect(() => { if (!user) { router.push('/login') } }, [user, router]) // Don't render if no user if (!user) { return (

Loading...

) } // Progress bar state const [progressPercent, setProgressPercent] = React.useState(0); const [completedSteps, setCompletedSteps] = React.useState([]); const [allSteps, setAllSteps] = React.useState([]); useEffect(() => { if (!user) { router.push('/login'); return; } async function fetchCompletion() { setCompletionLoading(true); const progress = await getProfileCompletion(); // progress can be percent or object if (progress && typeof progress === 'object') { // If not admin-verified, cap progress below 100 to reflect pending verification const pct = progress.progressPercent ?? 0; // Try to read admin verification from profileDataApi if available; otherwise assume false until data loads const isAdminVerified = Boolean(profileDataApi?.userStatus?.is_admin_verified); setProgressPercent(isAdminVerified ? pct : Math.min(pct, 95)); setCompletedSteps(progress.completedSteps ?? []); setAllSteps(progress.steps?.map((s: any) => s.name || s.title || '') ?? []); } else if (typeof progress === 'number') { setProgressPercent(progress); } setCompletionLoading(false); } fetchCompletion(); }, [user, router, refreshKey]); // If admin verification flips to true, ensure progress shows 100% useEffect(() => { const verified = Boolean(profileDataApi?.userStatus?.is_admin_verified); if (verified) { setProgressPercent(prev => (prev < 100 ? 100 : prev)); } }, [profileDataApi?.userStatus?.is_admin_verified]); // Use API profile data if available, fallback to mock const profileData = React.useMemo(() => { if (!profileDataApi) { return { firstName: 'Admin', lastName: 'User', email: user?.email || 'office@profit-planet.com', phone: '+49 123 456 789', address: 'Musterstraße 123, 12345 Berlin', joinDate: 'Oktober 2024', memberStatus: 'Gold Member', profileComplete: progressPercent, accountHolder: '', // Always empty string if not provided iban: '', contactPersonName: '', userType: user?.userType || '', }; } const { user: apiUser = {}, profile: apiProfile = {}, userStatus = {} } = profileDataApi; return { firstName: apiUser.firstName ?? apiProfile.first_name ?? '', lastName: apiUser.lastName ?? apiProfile.last_name ?? '', email: apiUser.email ?? '', phone: apiUser.phone ?? apiProfile.phone ?? '', address: apiProfile.address ?? '', joinDate: apiUser.createdAt ? new Date(apiUser.createdAt).toLocaleDateString('de-DE', { year: 'numeric', month: 'long' }) : '', memberStatus: userStatus.status ?? '', profileComplete: progressPercent, accountHolder: apiProfile.account_holder_name ?? '', // Only use account_holder_name iban: apiUser.iban ?? '', contactPersonName: apiProfile.contact_person_name ?? '', userType: apiUser.userType ?? '', }; }, [profileDataApi, user, progressPercent]); // Dummy data for new sections const documents = Array.isArray(mediaData?.documents) ? mediaData.documents : []; // Adjusted bankInfo state to only have accountHolder and iban, always strings const [bankInfo, setBankInfo] = React.useState({ accountHolder: '', iban: '', }); const [editingBank, setEditingBank] = React.useState(false); const [bankDraft, setBankDraft] = React.useState(bankInfo) // Modal state const [editModalOpen, setEditModalOpen] = React.useState(false); const [editModalType, setEditModalType] = React.useState<'basic' | 'bank'>('basic'); const [editModalValues, setEditModalValues] = React.useState>({}); // Modal error state const [editModalError, setEditModalError] = React.useState(null); // Modal field definitions const basicFields = [ { key: 'firstName', label: 'First Name' }, { key: 'lastName', label: 'Last Name' }, { key: 'email', label: 'Email Address', type: 'email' }, { key: 'phone', label: 'Phone Number' }, { key: 'address', label: 'Address' }, ]; const bankFields = [ { key: 'accountHolder', label: 'Account Holder' }, { key: 'iban', label: 'IBAN' }, ]; // Modal open handlers function openEditModal(type: 'basic' | 'bank', values: Record) { setEditModalType(type); setEditModalValues(values); setEditModalOpen(true); } // Modal save handler (calls API) async function handleEditModalSave() { setEditModalError(null); if (editModalType === 'basic') { const payload: Partial = {}; (['firstName', 'lastName', 'email', 'phone', 'address'] as const).forEach(key => { if (editModalValues[key] !== getProfileField(profileData, key)) { payload[key] = editModalValues[key]?.trim(); } }); const res = await editProfileBasic(payload); if (res.success) { setEditModalOpen(false); // Start smooth refresh with overlay spinner setShowRefreshing(true); setRefreshKey(k => k + 1); } else if (res.status === 409) { setEditModalError('Email already in use.'); } else if (res.status === 401) { router.push('/login'); } else { setEditModalError(res.error || 'Failed to update profile.'); } } else { const payload: Partial = {}; (['accountHolder', 'iban'] as const).forEach(key => { if (editModalValues[key] !== getProfileField(profileData, key)) { payload[key] = editModalValues[key]?.trim(); } }); const res = await editProfileBank(payload); if (res.success) { setBankInfo({ accountHolder: res.data?.profile?.account_holder_name ?? '', iban: res.data?.user?.iban ?? '', }); setEditModalOpen(false); // Start smooth refresh with overlay spinner setShowRefreshing(true); setRefreshKey(k => k + 1); } else if (res.status === 400 && res.error?.toLowerCase().includes('iban')) { setEditModalError('Invalid IBAN.'); } else if (res.status === 401) { router.push('/login'); } else { setEditModalError(res.error || 'Failed to update bank info.'); } } } // Modal change handler function handleEditModalChange(key: string, value: string) { setEditModalValues(prev => ({ ...prev, [key]: value })); } // Hide overlay when all data re-fetches complete useEffect(() => { if (showRefreshing && !profileLoading && !mediaLoading && !completionLoading) { const t = setTimeout(() => setShowRefreshing(false), 200); // small delay for smoothness return () => clearTimeout(t); } }, [showRefreshing, profileLoading, mediaLoading, completionLoading]); const loadingUser = !user; return (
{loadingUser && (

Loading...

)} {!loadingUser && ( <> {/* Page Header */}

Profile Settings

Manage your account information and preferences

{/* Pending admin verification notice (above progress) */} {profileDataApi?.userStatus && profileDataApi.userStatus.is_admin_verified === 0 && (
Your account is fully submitted. Our team will verify your account shortly.
)} {/* Profile Completion Progress Bar */} {/* Basic Info + Sidebar */}
{/* Basic Information */}
openEditModal('basic', { firstName: profileData.firstName, lastName: profileData.lastName, email: profileData.email, phone: profileData.phone, address: profileData.address, })} />
{/* Sidebar: Account Status + Quick Actions */}
{/* Account Status */}

Account Status

Member Since {profileData.joinDate}
Status {profileData.memberStatus}
Profile Verified
{/* Quick Actions */}

Quick Actions

{/* Bank Info, Media */}
{/* --- Edit Bank Information Section --- */} openEditModal('bank', { accountHolder: profileData.accountHolder, iban: profileData.iban, })} /> {/* --- Media Section --- */}
{/* Account Settings */}

Account Settings

Email Notifications

Receive updates about orders and promotions

SMS Notifications

Get text messages for important updates

Two-Factor Authentication

Add extra security to your account

)}
) }