138 lines
5.0 KiB
JavaScript
138 lines
5.0 KiB
JavaScript
import { useEffect, useState } from 'react'
|
|
import { Container, Form, Row, Col } from 'react-bootstrap'
|
|
import { getCurrentUser, uploadAvatar } from '../api/client'
|
|
import { useAuth } from '../context/AuthContext'
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
export default function Ucp({ theme, setTheme, accentOverride, setAccentOverride }) {
|
|
const { t, i18n } = useTranslation()
|
|
const { token } = useAuth()
|
|
const accentMode = accentOverride ? 'custom' : 'system'
|
|
const [avatarError, setAvatarError] = useState('')
|
|
const [avatarUploading, setAvatarUploading] = useState(false)
|
|
const [avatarPreview, setAvatarPreview] = useState('')
|
|
|
|
useEffect(() => {
|
|
if (!token) return
|
|
let active = true
|
|
|
|
getCurrentUser()
|
|
.then((data) => {
|
|
if (!active) return
|
|
setAvatarPreview(data?.avatar_url || '')
|
|
})
|
|
.catch(() => {
|
|
if (active) setAvatarPreview('')
|
|
})
|
|
|
|
return () => {
|
|
active = false
|
|
}
|
|
}, [token])
|
|
|
|
const handleLanguageChange = (event) => {
|
|
const locale = event.target.value
|
|
i18n.changeLanguage(locale)
|
|
localStorage.setItem('speedbb_lang', locale)
|
|
}
|
|
|
|
return (
|
|
<Container fluid className="py-5 bb-portal-shell">
|
|
<div className="bb-portal-card mb-4">
|
|
<div className="bb-portal-card-title">{t('ucp.profile')}</div>
|
|
<p className="bb-muted mb-4">{t('ucp.profile_hint')}</p>
|
|
<Row className="g-3 align-items-center">
|
|
<Col md="auto">
|
|
<div className="bb-avatar-preview">
|
|
{avatarPreview ? (
|
|
<img src={avatarPreview} alt="" />
|
|
) : (
|
|
<i className="bi bi-person" aria-hidden="true" />
|
|
)}
|
|
</div>
|
|
</Col>
|
|
<Col>
|
|
{avatarError && <p className="text-danger mb-2">{avatarError}</p>}
|
|
<Form.Group>
|
|
<Form.Label>{t('ucp.avatar_label')}</Form.Label>
|
|
<Form.Control
|
|
type="file"
|
|
accept="image/png,image/jpeg,image/jpg,image/gif,image/webp"
|
|
disabled={!token || avatarUploading}
|
|
onChange={async (event) => {
|
|
const file = event.target.files?.[0]
|
|
if (!file) return
|
|
setAvatarError('')
|
|
setAvatarUploading(true)
|
|
try {
|
|
const response = await uploadAvatar(file)
|
|
setAvatarPreview(response.url)
|
|
} catch (err) {
|
|
setAvatarError(err.message)
|
|
} finally {
|
|
setAvatarUploading(false)
|
|
}
|
|
}}
|
|
/>
|
|
<Form.Text className="bb-muted">{t('ucp.avatar_hint')}</Form.Text>
|
|
</Form.Group>
|
|
</Col>
|
|
</Row>
|
|
</div>
|
|
<div className="bb-portal-card">
|
|
<div className="bb-portal-card-title">{t('portal.user_control_panel')}</div>
|
|
<p className="bb-muted mb-4">{t('ucp.intro')}</p>
|
|
<Row className="g-3">
|
|
<Col xs={12}>
|
|
<Form.Group>
|
|
<Form.Label>{t('nav.language')}</Form.Label>
|
|
<Form.Select value={i18n.language} onChange={handleLanguageChange}>
|
|
<option value="en">English</option>
|
|
<option value="de">Deutsch</option>
|
|
</Form.Select>
|
|
</Form.Group>
|
|
</Col>
|
|
<Col md={6}>
|
|
<Form.Group>
|
|
<Form.Label>{t('nav.theme')}</Form.Label>
|
|
<Form.Select value={theme} onChange={(event) => setTheme(event.target.value)}>
|
|
<option value="auto">{t('ucp.system_default')}</option>
|
|
<option value="dark">{t('nav.theme_dark')}</option>
|
|
<option value="light">{t('nav.theme_light')}</option>
|
|
</Form.Select>
|
|
</Form.Group>
|
|
</Col>
|
|
<Col md={6}>
|
|
<Form.Group>
|
|
<Form.Label>{t('ucp.accent_override')}</Form.Label>
|
|
<div className="d-flex align-items-center gap-2">
|
|
<Form.Select
|
|
value={accentMode}
|
|
onChange={(event) => {
|
|
const mode = event.target.value
|
|
if (mode === 'system') {
|
|
setAccentOverride('')
|
|
} else if (!accentOverride) {
|
|
setAccentOverride('#f29b3f')
|
|
}
|
|
}}
|
|
>
|
|
<option value="system">{t('ucp.system_default')}</option>
|
|
<option value="custom">{t('ucp.custom_color')}</option>
|
|
</Form.Select>
|
|
<Form.Control
|
|
type="color"
|
|
value={accentOverride || '#f29b3f'}
|
|
onChange={(event) => setAccentOverride(event.target.value)}
|
|
disabled={accentMode !== 'custom'}
|
|
/>
|
|
</div>
|
|
<Form.Text className="bb-muted">{t('ucp.accent_override_hint')}</Form.Text>
|
|
</Form.Group>
|
|
</Col>
|
|
</Row>
|
|
</div>
|
|
</Container>
|
|
)
|
|
}
|