diff --git a/frontend/src/pages/AccountPage.tsx b/frontend/src/pages/AccountPage.tsx
new file mode 100644
index 0000000..9896e4e
--- /dev/null
+++ b/frontend/src/pages/AccountPage.tsx
@@ -0,0 +1,455 @@
+import { useState, useRef } from 'react'
+import { useAuth } from '@/context/AuthContext'
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
+import { Label } from '@/components/ui/label'
+import { Alert, AlertDescription } from '@/components/ui/alert'
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
+import { Separator } from '@/components/ui/separator'
+import { UserCog, Shield, Smartphone, Upload, Trash2, Check, Loader2 } from 'lucide-react'
+import * as authService from '@/services/authService'
+import type { ProfileUpdatePayload } from '@/types'
+
+
+export function AccountPage() {
+ return (
+
+
+
Kontoverwaltung
+
+ Verwalten Sie Ihr Profil, Ihre Sicherheitseinstellungen und die Zwei-Faktor-Authentifizierung.
+
+
+
+
+
+
+
+ Profil
+
+
+
+ Sicherheit
+
+
+
+ Zwei-Faktor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+
+function ProfileTab() {
+ const { user, refreshUser } = useAuth()
+ const [saving, setSaving] = useState(false)
+ const [success, setSuccess] = useState('')
+ const [error, setError] = useState('')
+ const fileInputRef = useRef(null)
+ const [avatarUploading, setAvatarUploading] = useState(false)
+
+ const [form, setForm] = useState({
+ first_name: user?.first_name ?? '',
+ last_name: user?.last_name ?? '',
+ display_name: user?.display_name ?? '',
+ username: user?.username ?? '',
+ email: user?.email ?? '',
+ })
+
+ const handleSave = async () => {
+ setSaving(true)
+ setError('')
+ setSuccess('')
+ try {
+ await authService.updateProfile(form)
+ await refreshUser()
+ setSuccess('Profil erfolgreich gespeichert.')
+ } catch (err: any) {
+ setError(err.response?.data?.detail ?? 'Fehler beim Speichern.')
+ } finally {
+ setSaving(false)
+ }
+ }
+
+ const handleAvatarUpload = async (e: React.ChangeEvent) => {
+ const file = e.target.files?.[0]
+ if (!file) return
+ setAvatarUploading(true)
+ setError('')
+ try {
+ await authService.uploadAvatar(file)
+ await refreshUser()
+ } catch (err: any) {
+ setError(err.response?.data?.detail ?? 'Fehler beim Hochladen.')
+ } finally {
+ setAvatarUploading(false)
+ }
+ }
+
+ const handleAvatarDelete = async () => {
+ setAvatarUploading(true)
+ try {
+ await authService.deleteAvatar()
+ await refreshUser()
+ } catch (err: any) {
+ setError(err.response?.data?.detail ?? 'Fehler beim Löschen.')
+ } finally {
+ setAvatarUploading(false)
+ }
+ }
+
+ const initials = user?.username
+ ?.split(/[\s._-]/)
+ .map((p) => p[0])
+ .join('')
+ .toUpperCase()
+ .slice(0, 2) ?? '??'
+
+ const avatarSrc = user?.avatar_url ?? undefined
+
+ return (
+
+
+ Profildaten
+ Aktualisieren Sie Ihre persönlichen Informationen.
+
+
+ {error && {error}}
+ {success && {success}}
+
+ {/* Avatar */}
+
+
+ {avatarSrc && }
+ {initials}
+
+
+
+
+ {user?.avatar_url && (
+
+ )}
+
+
+
+
+
+ {/* Form fields */}
+
+
+
+ setForm({ ...form, display_name: e.target.value })} placeholder="Wird automatisch aus Vor-/Nachname generiert, wenn leer" />
+
+
+
+
+
+
+ )
+}
+
+
+function SecurityTab() {
+ const { user } = useAuth()
+ const [saving, setSaving] = useState(false)
+ const [success, setSuccess] = useState('')
+ const [error, setError] = useState('')
+ const [form, setForm] = useState({
+ old_password: '',
+ new_password: '',
+ confirm_password: '',
+ })
+
+ const handleChangePassword = async () => {
+ setError('')
+ setSuccess('')
+ if (form.new_password !== form.confirm_password) {
+ setError('Die Passwörter stimmen nicht überein.')
+ return
+ }
+ if (form.new_password.length < 8) {
+ setError('Das neue Passwort muss mindestens 8 Zeichen lang sein.')
+ return
+ }
+ setSaving(true)
+ try {
+ await authService.changePassword({
+ old_password: form.old_password,
+ new_password: form.new_password,
+ })
+ setSuccess('Passwort erfolgreich geändert.')
+ setForm({ old_password: '', new_password: '', confirm_password: '' })
+ } catch (err: any) {
+ setError(err.response?.data?.detail ?? 'Fehler beim Ändern des Passworts.')
+ } finally {
+ setSaving(false)
+ }
+ }
+
+ return (
+
+ )
+}
+
+
+function MFATab() {
+ const { user, refreshUser } = useAuth()
+ const [step, setStep] = useState<'idle' | 'setup' | 'verify'>('idle')
+ const [secret, setSecret] = useState('')
+ const [qrUri, setQrUri] = useState('')
+ const [code, setCode] = useState('')
+ const [password, setPassword] = useState('')
+ const [loading, setLoading] = useState(false)
+ const [error, setError] = useState('')
+ const [success, setSuccess] = useState('')
+ const [showDisableDialog, setShowDisableDialog] = useState(false)
+
+ const handleStartSetup = async () => {
+ setLoading(true)
+ setError('')
+ try {
+ const result = await authService.setupMFA()
+ setSecret(result.secret)
+ setQrUri(result.qr_uri)
+ setStep('verify')
+ } catch (err: any) {
+ setError(err.response?.data?.detail ?? 'Fehler beim MFA-Setup.')
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ const handleVerify = async () => {
+ setLoading(true)
+ setError('')
+ try {
+ await authService.verifyMFA({ secret, code })
+ await refreshUser()
+ setSuccess('Zwei-Faktor-Authentifizierung erfolgreich aktiviert!')
+ setStep('idle')
+ setCode('')
+ } catch (err: any) {
+ setError(err.response?.data?.detail ?? 'Ungültiger Code. Bitte erneut versuchen.')
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ const handleDisable = async () => {
+ setLoading(true)
+ setError('')
+ try {
+ await authService.disableMFA(password)
+ await refreshUser()
+ setSuccess('Zwei-Faktor-Authentifizierung deaktiviert.')
+ setShowDisableDialog(false)
+ setPassword('')
+ } catch (err: any) {
+ setError(err.response?.data?.detail ?? 'Fehler beim Deaktivieren.')
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ return (
+
+
+
+ Zwei-Faktor-Authentifizierung
+ {user?.mfa_enabled && (
+
+ Aktiv
+
+ )}
+
+
+ Schützen Sie Ihr Konto mit einem zusätzlichen Sicherheitsfaktor über eine Authenticator-App.
+
+
+
+ {error && {error}}
+ {success && {success}}
+
+ {!user?.mfa_enabled && step === 'idle' && (
+
+
+ Die Zwei-Faktor-Authentifizierung ist derzeit nicht aktiviert. Aktivieren Sie diese Funktion,
+ um Ihr Konto zusätzlich zu schützen.
+
+
+
+ )}
+
+ {step === 'verify' && (
+
+
+ Scannen Sie den folgenden QR-Code mit Ihrer Authenticator-App (z.B. Google Authenticator, Authy):
+
+
+
}`})
+
+
+ Manueller Schlüssel: {secret}
+
+
+
+ setCode(e.target.value)}
+ placeholder="6-stelliger Code"
+ maxLength={6}
+ />
+
+
+
+
+
+
+ )}
+
+ {user?.mfa_enabled && step === 'idle' && !showDisableDialog && (
+
+
+ Ihr Konto ist durch Zwei-Faktor-Authentifizierung geschützt.
+
+
+
+ )}
+
+ {showDisableDialog && (
+
+
+ Bitte bestätigen Sie mit Ihrem Passwort, um 2FA zu deaktivieren.
+
+
+
+ setPassword(e.target.value)}
+ />
+
+
+
+
+
+
+ )}
+
+
+ )
+}