diff --git a/app/[locale]/profile/page.tsx b/app/[locale]/profile/page.tsx index b3e7b5e..4201ed1 100644 --- a/app/[locale]/profile/page.tsx +++ b/app/[locale]/profile/page.tsx @@ -28,7 +28,7 @@ import { } from '@mui/icons-material' export default function ProfilePage() { - const { user } = useAuth() + const { user, refreshUser } = useAuth() const t = useTranslations('profile') const [isEditing, setIsEditing] = useState(false) const [name, setName] = useState(user?.name || '') @@ -40,10 +40,31 @@ export default function ProfilePage() { setMessage('') try { - // TODO: Implement profile update API - await new Promise(resolve => setTimeout(resolve, 1000)) // Placeholder - setMessage(t('profileUpdated')) - setIsEditing(false) + const token = localStorage.getItem('authToken') + if (!token) { + setMessage(t('updateError')) + return + } + + const response = await fetch(`/api/user/profile?locale=${navigator.language.split('-')[0]}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify({ name }) + }) + + const data = await response.json() + + if (response.ok) { + setMessage(t('profileUpdated')) + setIsEditing(false) + // Refresh user data in context to show updated name + await refreshUser() + } else { + setMessage(data.error || t('updateError')) + } } catch (error) { setMessage(t('updateError')) } finally { diff --git a/app/api/user/profile/route.ts b/app/api/user/profile/route.ts new file mode 100644 index 0000000..4bf5e0d --- /dev/null +++ b/app/api/user/profile/route.ts @@ -0,0 +1,82 @@ +import { NextResponse } from 'next/server' +import { getUserFromToken } from '@/lib/auth' +import { prisma } from '@/lib/db' + +export const runtime = 'nodejs' + +function getErrorMessages(locale: string = 'ro') { + const messages = { + ro: { + unauthorized: 'Nu esti autentificat', + nameRequired: 'Numele este obligatoriu', + updateFailed: 'Actualizarea a eșuat', + success: 'Profil actualizat cu succes' + }, + en: { + unauthorized: 'Unauthorized', + nameRequired: 'Name is required', + updateFailed: 'Update failed', + success: 'Profile updated successfully' + } + } + return messages[locale as keyof typeof messages] || messages.ro +} + +export async function PUT(request: Request) { + try { + const url = new URL(request.url) + const locale = url.searchParams.get('locale') || 'ro' + const messages = getErrorMessages(locale) + + // Get token from authorization header + const authHeader = request.headers.get('authorization') + const token = authHeader?.replace('Bearer ', '') + + if (!token) { + return NextResponse.json({ error: messages.unauthorized }, { status: 401 }) + } + + // Verify token and get user + const user = await getUserFromToken(token) + + if (!user) { + return NextResponse.json({ error: messages.unauthorized }, { status: 401 }) + } + + // Parse request body + const { name } = await request.json() + + // Validate input + if (!name || typeof name !== 'string' || name.trim().length === 0) { + return NextResponse.json({ error: messages.nameRequired }, { status: 400 }) + } + + // Update user profile using raw query + await prisma.$executeRaw` + UPDATE "User" + SET name = ${name.trim()}, "updatedAt" = CURRENT_TIMESTAMP + WHERE id = ${user.id} + ` + + // Get updated user data + const updatedUsers = await prisma.$queryRaw` + SELECT id, email, name, role, theme, "fontSize", "createdAt", "updatedAt", "lastLoginAt" + FROM "User" + WHERE id = ${user.id} + ` + const updatedUser = Array.isArray(updatedUsers) && updatedUsers.length > 0 ? updatedUsers[0] : null + + return NextResponse.json({ + message: messages.success, + user: updatedUser + }) + + } catch (error) { + console.error('Profile update error:', error) + const url = new URL(request.url) + const locale = url.searchParams.get('locale') || 'ro' + const messages = getErrorMessages(locale) + + return NextResponse.json({ error: messages.updateFailed }, { status: 500 }) + } +} \ No newline at end of file