151 lines
4.4 KiB
TypeScript
151 lines
4.4 KiB
TypeScript
'use client'
|
|
|
|
import { ProfileForm, ProfileFormData } from '@/components/ProfileForm'
|
|
import { AvatarUpload } from '@/components/AvatarUpload'
|
|
import { useState, useEffect } from 'react'
|
|
|
|
export default function ProfilePage() {
|
|
const [user, setUser] = useState<any>(null)
|
|
const [loading, setLoading] = useState(true)
|
|
const [isUpdatingProfile, setIsUpdatingProfile] = useState(false)
|
|
const [isUploadingAvatar, setIsUploadingAvatar] = useState(false)
|
|
|
|
useEffect(() => {
|
|
fetchCurrentUser()
|
|
}, [])
|
|
|
|
const fetchCurrentUser = async () => {
|
|
try {
|
|
const res = await fetch('/api/users/me')
|
|
if (res.ok) {
|
|
const data = await res.json()
|
|
setUser(data.user)
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to fetch user:', error)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
const handleAvatarUpload = async (file: File) => {
|
|
setIsUploadingAvatar(true)
|
|
try {
|
|
// In a real app, upload to cloud storage and get URL
|
|
// For now, create a local blob URL as placeholder
|
|
const avatarUrl = URL.createObjectURL(file)
|
|
|
|
const res = await fetch('/api/users/me', {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ avatarUrl }),
|
|
})
|
|
|
|
if (res.ok) {
|
|
const data = await res.json()
|
|
setUser(data.user)
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to upload avatar:', error)
|
|
} finally {
|
|
setIsUploadingAvatar(false)
|
|
}
|
|
}
|
|
|
|
const handleProfileSubmit = async (data: ProfileFormData) => {
|
|
setIsUpdatingProfile(true)
|
|
try {
|
|
const res = await fetch('/api/users/me', {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
displayName: data.username,
|
|
bio: data.bio,
|
|
}),
|
|
})
|
|
|
|
if (res.ok) {
|
|
const result = await res.json()
|
|
setUser(result.user)
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to update profile:', error)
|
|
} finally {
|
|
setIsUpdatingProfile(false)
|
|
}
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<main className="min-h-screen bg-zinc-950 flex items-center justify-center">
|
|
<p className="text-zinc-400">Loading profile...</p>
|
|
</main>
|
|
)
|
|
}
|
|
|
|
if (!user) {
|
|
return (
|
|
<main className="min-h-screen bg-zinc-950 flex items-center justify-center">
|
|
<div className="text-center">
|
|
<p className="text-xl text-zinc-400 mb-4">Please log in to view your profile</p>
|
|
<a
|
|
href="/login"
|
|
className="px-6 py-3 bg-purple-600 hover:bg-purple-700 text-white font-semibold rounded-lg inline-block"
|
|
>
|
|
Log In
|
|
</a>
|
|
</div>
|
|
</main>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<main className="min-h-screen bg-zinc-950">
|
|
<div className="max-w-4xl mx-auto px-4 py-8">
|
|
{/* Header */}
|
|
<div className="mb-8">
|
|
<h1 className="text-4xl font-bold text-white mb-4">Profile Settings</h1>
|
|
<p className="text-xl text-zinc-400">
|
|
Manage your account and preferences
|
|
</p>
|
|
</div>
|
|
|
|
{/* Avatar Section */}
|
|
<div className="bg-zinc-900 rounded-lg p-8 mb-6">
|
|
<h2 className="text-2xl font-semibold text-white mb-6">Profile Picture</h2>
|
|
<AvatarUpload
|
|
currentAvatarUrl={user.avatarUrl}
|
|
onUpload={handleAvatarUpload}
|
|
isLoading={isUploadingAvatar}
|
|
/>
|
|
</div>
|
|
|
|
{/* Profile Form */}
|
|
<div className="bg-zinc-900 rounded-lg p-8">
|
|
<h2 className="text-2xl font-semibold text-white mb-6">Account Information</h2>
|
|
<ProfileForm
|
|
initialData={{
|
|
username: user.displayName || user.username || '',
|
|
email: user.email || '',
|
|
bio: user.bio || '',
|
|
}}
|
|
onSubmit={handleProfileSubmit}
|
|
isLoading={isUpdatingProfile}
|
|
/>
|
|
</div>
|
|
|
|
{/* Danger Zone */}
|
|
<div className="bg-zinc-900 rounded-lg p-8 mt-6 border border-red-900/50">
|
|
<h2 className="text-2xl font-semibold text-white mb-4">Danger Zone</h2>
|
|
<p className="text-zinc-400 mb-4">
|
|
Once you delete your account, there is no going back. Please be certain.
|
|
</p>
|
|
<button className="px-6 py-3 bg-red-600 hover:bg-red-700 text-white font-semibold rounded-lg transition-colors">
|
|
Delete Account
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
)
|
|
}
|