Spaces:
Paused
Paused
import { useFetchUserInfo, useSaveSetting } from '@/hooks/user-setting-hooks'; | |
import { | |
getBase64FromUploadFileList, | |
getUploadFileListFromBase64, | |
normFile, | |
} from '@/utils/file-util'; | |
import { PlusOutlined } from '@ant-design/icons'; | |
import { | |
Button, | |
Divider, | |
Form, | |
Input, | |
Select, | |
Space, | |
Spin, | |
Upload, | |
UploadFile, | |
} from 'antd'; | |
import camelCase from 'lodash/camelCase'; | |
import { useEffect } from 'react'; | |
import SettingTitle from '../components/setting-title'; | |
import { TimezoneList } from '../constants'; | |
import { useValidateSubmittable } from '../hooks'; | |
import { LanguageList } from '@/constants/common'; | |
import { useTranslate } from '@/hooks/common-hooks'; | |
import { useChangeLanguage } from '@/hooks/logic-hooks'; | |
import parentStyles from '../index.less'; | |
import styles from './index.less'; | |
const { Option } = Select; | |
type FieldType = { | |
nickname?: string; | |
language?: string; | |
email?: string; | |
color_schema?: string; | |
timezone?: string; | |
avatar?: string; | |
}; | |
const tailLayout = { | |
wrapperCol: { offset: 20, span: 4 }, | |
}; | |
const UserSettingProfile = () => { | |
const { data: userInfo, loading } = useFetchUserInfo(); | |
const { saveSetting, loading: submitLoading } = useSaveSetting(); | |
const { form, submittable } = useValidateSubmittable(); | |
const { t } = useTranslate('setting'); | |
const changeLanguage = useChangeLanguage(); | |
const onFinish = async (values: any) => { | |
const avatar = await getBase64FromUploadFileList(values.avatar); | |
saveSetting({ ...values, avatar }); | |
}; | |
const onFinishFailed = (errorInfo: any) => { | |
console.log('Failed:', errorInfo); | |
}; | |
useEffect(() => { | |
const fileList: UploadFile[] = getUploadFileListFromBase64(userInfo.avatar); | |
form.setFieldsValue({ ...userInfo, avatar: fileList }); | |
}, [form, userInfo]); | |
return ( | |
<section className={styles.profileWrapper}> | |
<SettingTitle | |
title={t('profile')} | |
description={t('profileDescription')} | |
></SettingTitle> | |
<Divider /> | |
<Spin spinning={loading}> | |
<Form | |
colon={false} | |
name="basic" | |
labelAlign={'left'} | |
labelCol={{ span: 8 }} | |
wrapperCol={{ span: 16 }} | |
style={{ width: '100%' }} | |
initialValues={{ remember: true }} | |
onFinish={onFinish} | |
onFinishFailed={onFinishFailed} | |
form={form} | |
autoComplete="off" | |
> | |
<Form.Item<FieldType> | |
label={t('username')} | |
name="nickname" | |
rules={[ | |
{ | |
required: true, | |
message: t('usernameMessage'), | |
whitespace: true, | |
}, | |
]} | |
> | |
<Input /> | |
</Form.Item> | |
<Divider /> | |
<Form.Item<FieldType> | |
label={ | |
<div> | |
<Space>{t('photo')}</Space> | |
<div>{t('photoDescription')}</div> | |
</div> | |
} | |
name="avatar" | |
valuePropName="fileList" | |
getValueFromEvent={normFile} | |
> | |
<Upload | |
listType="picture-card" | |
maxCount={1} | |
accept="image/*" | |
beforeUpload={() => { | |
return false; | |
}} | |
showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }} | |
> | |
<button style={{ border: 0, background: 'none' }} type="button"> | |
<PlusOutlined /> | |
<div style={{ marginTop: 8 }}> | |
{t('upload', { keyPrefix: 'common' })} | |
</div> | |
</button> | |
</Upload> | |
</Form.Item> | |
<Divider /> | |
<Form.Item<FieldType> | |
label={t('colorSchema')} | |
name="color_schema" | |
rules={[{ required: true, message: t('colorSchemaMessage') }]} | |
> | |
<Select placeholder={t('colorSchemaPlaceholder')}> | |
<Option value="Bright">{t('bright')}</Option> | |
<Option value="Dark">{t('dark')}</Option> | |
</Select> | |
</Form.Item> | |
<Divider /> | |
<Form.Item<FieldType> | |
label={t('language', { keyPrefix: 'common' })} | |
name="language" | |
rules={[ | |
{ | |
required: true, | |
message: t('languageMessage', { keyPrefix: 'common' }), | |
}, | |
]} | |
> | |
<Select | |
placeholder={t('languagePlaceholder', { keyPrefix: 'common' })} | |
onChange={changeLanguage} | |
> | |
{LanguageList.map((x) => ( | |
<Option value={x} key={x}> | |
{t(camelCase(x), { keyPrefix: 'common' })} | |
</Option> | |
))} | |
</Select> | |
</Form.Item> | |
<Divider /> | |
<Form.Item<FieldType> | |
label={t('timezone')} | |
name="timezone" | |
rules={[{ required: true, message: t('timezoneMessage') }]} | |
> | |
<Select placeholder={t('timezonePlaceholder')} showSearch> | |
{TimezoneList.map((x) => ( | |
<Option value={x} key={x}> | |
{x} | |
</Option> | |
))} | |
</Select> | |
</Form.Item> | |
<Divider /> | |
<Form.Item label={t('email')}> | |
<Form.Item<FieldType> name="email" noStyle> | |
<Input disabled /> | |
</Form.Item> | |
<p className={parentStyles.itemDescription}> | |
{t('emailDescription')} | |
</p> | |
</Form.Item> | |
<Form.Item | |
{...tailLayout} | |
shouldUpdate={(prevValues, curValues) => | |
prevValues.additional !== curValues.additional | |
} | |
> | |
<Space> | |
<Button htmlType="button">{t('cancel')}</Button> | |
<Button | |
type="primary" | |
htmlType="submit" | |
disabled={!submittable} | |
loading={submitLoading} | |
> | |
{t('save', { keyPrefix: 'common' })} | |
</Button> | |
</Space> | |
</Form.Item> | |
</Form> | |
</Spin> | |
</section> | |
); | |
}; | |
export default UserSettingProfile; | |