feat: add account data download functionality to profile page
This commit is contained in:
parent
51cffc0ad5
commit
e01dbb6405
@ -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<Record<string, string>>({})
|
||||
const [editModalError, setEditModalError] = React.useState<string | null>(null)
|
||||
const [downloadLoading, setDownloadLoading] = React.useState(false)
|
||||
const [downloadError, setDownloadError] = React.useState<string | null>(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<string, any>
|
||||
return rest
|
||||
})()
|
||||
: fullData?.user
|
||||
const cleanedProfile = fullData?.profile && typeof fullData.profile === 'object'
|
||||
? (() => {
|
||||
const { id, user_id, ...rest } = fullData.profile as Record<string, any>
|
||||
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
|
||||
</button>
|
||||
<button className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 rounded-lg transition-colors">
|
||||
Download Account Data
|
||||
<button
|
||||
onClick={handleDownloadAccountData}
|
||||
disabled={downloadLoading}
|
||||
className="w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 rounded-lg transition-colors disabled:opacity-60 disabled:cursor-not-allowed"
|
||||
>
|
||||
{downloadLoading ? 'Preparing download...' : 'Download Account Data'}
|
||||
</button>
|
||||
<button className="w-full text-left px-4 py-2 text-sm text-red-600 hover:bg-red-50 rounded-lg transition-colors">
|
||||
Delete Account
|
||||
</button>
|
||||
</div>
|
||||
{downloadError && (
|
||||
<p className="mt-2 text-xs text-red-600">{downloadError}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user