diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx index a490632..63d4fdc 100644 --- a/src/app/profile/page.tsx +++ b/src/app/profile/page.tsx @@ -15,6 +15,7 @@ import { getProfileCompletion } from './hooks/getProfileCompletion' import { useProfileData } from './hooks/getProfileData' import { useMedia } from './hooks/getMedia' import { editProfileBasic } from './hooks/editProfile' +import { authFetch } from '../utils/authFetch' // Helper to display missing fields in subtle gray italic (no yellow highlight) function HighlightIfMissing({ value, children }: { value: any, children: React.ReactNode }) { @@ -65,6 +66,8 @@ const bankFields = [ { key: 'iban', label: 'IBAN', type: 'text' }, ]; +const BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:3001' + export default function ProfilePage() { const router = useRouter() const user = useAuthStore(state => state.user) @@ -91,6 +94,8 @@ export default function ProfilePage() { const [editModalType, setEditModalType] = React.useState<'basic' | 'bank'>('basic') const [editModalValues, setEditModalValues] = React.useState>({}) const [editModalError, setEditModalError] = React.useState(null) + const [downloadLoading, setDownloadLoading] = React.useState(false) + const [downloadError, setDownloadError] = React.useState(null) useEffect(() => { setHasHydrated(true) }, []) @@ -221,6 +226,65 @@ export default function ProfilePage() { setEditModalValues(prev => ({ ...prev, [key]: value })) } + async function handleDownloadAccountData() { + if (!userId) return + setDownloadError(null) + setDownloadLoading(true) + + try { + const fullRes = await authFetch(`${BASE_URL}/api/users/${userId}/full`, { method: 'GET' }) + + if (fullRes.status === 401) { + router.push('/login') + return + } + + if (!fullRes.ok) { + throw new Error('Failed to fetch account data') + } + + const fullData = await fullRes.json() + const statusOnly = fullData?.userStatus?.status ?? null + const cleanedUser = fullData?.user && typeof fullData.user === 'object' + ? (() => { + const { id, user_id, ...rest } = fullData.user as Record + return rest + })() + : fullData?.user + const cleanedProfile = fullData?.profile && typeof fullData.profile === 'object' + ? (() => { + const { id, user_id, ...rest } = fullData.profile as Record + return rest + })() + : fullData?.profile + + const exportPayload = { + exportedAt: new Date().toISOString(), + userType: user?.userType || null, + account: { + success: fullData?.success ?? true, + user: cleanedUser, + profile: cleanedProfile, + userStatus: statusOnly + } + } + + const blob = new Blob([JSON.stringify(exportPayload, null, 2)], { type: 'application/json' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = `profit-planet-account-data-${userId}-${new Date().toISOString().slice(0, 10)}.json` + document.body.appendChild(a) + a.click() + a.remove() + URL.revokeObjectURL(url) + } catch (error: any) { + setDownloadError(error?.message || 'Failed to download account data.') + } finally { + setDownloadLoading(false) + } + } + // --- EARLY RETURN AFTER ALL HOOKS --- if (!hasHydrated || !isAuthReady || !user) { return ( @@ -309,13 +373,20 @@ export default function ProfilePage() { > Go to Dashboard - + {downloadError && ( +

{downloadError}

+ )}