193 lines
7.7 KiB
TypeScript
193 lines
7.7 KiB
TypeScript
'use client';
|
||
|
||
import React, { FC, useEffect, useState } from 'react';
|
||
import { Button, Form, message, Upload } from 'antd';
|
||
import type { GetProp, UploadFile, UploadProps } from 'antd';
|
||
import ImgCrop from 'antd-img-crop';
|
||
import { CameraOutlined, DeleteOutlined } from '@ant-design/icons';
|
||
import { useRouter } from '../../navigation';
|
||
import { i18nText } from '../../i18nKeys';
|
||
import { ProfileRequest } from '../../types/profile';
|
||
import { validateImage } from '../../utils/account';
|
||
import { useProfileSettings } from '../../actions/hooks/useProfileSettings';
|
||
import { CustomInput } from '../view/CustomInput';
|
||
import { OutlinedButton } from '../view/OutlinedButton';
|
||
import {FilledButton, FilledSquareButton, FilledYellowButton} from '../view/FilledButton';
|
||
import { DeleteAccountModal } from '../Modals/DeleteAccountModal';
|
||
import { Loader } from '../view/Loader';
|
||
|
||
type ProfileSettingsProps = {
|
||
locale: string;
|
||
};
|
||
|
||
type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];
|
||
|
||
export const ProfileSettings: FC<ProfileSettingsProps> = ({ locale }) => {
|
||
const [form] = Form.useForm<ProfileRequest>();
|
||
const { profileSettings, fetchProfileSettings, save, fetchLoading } = useProfileSettings(locale);
|
||
const [showDeleteModal, setShowDeleteModal] = useState<boolean>(false);
|
||
const [saveLoading, setSaveLoading] = useState<boolean>(false);
|
||
const [photo, setPhoto] = useState<UploadFile | undefined>();
|
||
const router = useRouter();
|
||
|
||
useEffect(() => {
|
||
fetchProfileSettings()
|
||
}, []);
|
||
|
||
useEffect(() => {
|
||
if (profileSettings) {
|
||
form.setFieldsValue(profileSettings);
|
||
}
|
||
}, [profileSettings]);
|
||
|
||
const onSaveProfile = () => {
|
||
form.validateFields()
|
||
.then(({ login, surname, username }) => {
|
||
const { phone, role, languagesLinks } = profileSettings;
|
||
const newProfile: ProfileRequest = {
|
||
phone,
|
||
role,
|
||
login,
|
||
surname,
|
||
username,
|
||
isPasswordKeepExisting: true,
|
||
isFaceImageKeepExisting: true,
|
||
languagesLinks: languagesLinks?.map(({ languageId }) => ({ languageId })) || []
|
||
};
|
||
|
||
if (photo) {
|
||
console.log(photo);
|
||
const formData = new FormData();
|
||
formData.append('file', photo as FileType);
|
||
|
||
newProfile.faceImage = `[${(photo as File).arrayBuffer()}]`;
|
||
newProfile.isFaceImageKeepExisting = false;
|
||
}
|
||
|
||
console.log(newProfile);
|
||
|
||
setSaveLoading(true);
|
||
save(newProfile)
|
||
.then(() => {
|
||
fetchProfileSettings();
|
||
})
|
||
.catch(() => {
|
||
message.error('Не удалось сохранить изменения');
|
||
})
|
||
.finally(() => {
|
||
setSaveLoading(false);
|
||
})
|
||
})
|
||
}
|
||
|
||
const beforeCrop = (file: UploadFile) => {
|
||
return validateImage(file, true);
|
||
}
|
||
|
||
const beforeUpload = (file: UploadFile) => {
|
||
const isValid = validateImage(file);
|
||
|
||
if (isValid) {
|
||
setPhoto(file);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
const onDeleteAccount = () => setShowDeleteModal(true);
|
||
|
||
return (
|
||
<Loader isLoading={fetchLoading} refresh={fetchProfileSettings}>
|
||
<Form form={form} className="form-settings">
|
||
<ImgCrop
|
||
modalTitle="Редактировать"
|
||
modalOk="Сохранить"
|
||
modalCancel="Отмена"
|
||
beforeCrop={beforeCrop}
|
||
>
|
||
<Upload
|
||
fileList={photo ? [photo] : profileSettings?.faceImageUrl ? [
|
||
{
|
||
uid: profileSettings.faceImageUrl,
|
||
name: profileSettings.faceImageUrl,
|
||
status: 'done',
|
||
url: profileSettings.faceImageUrl
|
||
}
|
||
] : undefined}
|
||
accept=".jpg,.jpeg,.png,.gif"
|
||
beforeUpload={beforeUpload}
|
||
multiple={false}
|
||
showUploadList={false}
|
||
>
|
||
<div className="user-avatar">
|
||
<div className="user-avatar__edit" style={photo
|
||
? { backgroundImage: `url(${URL.createObjectURL(photo)})` }
|
||
: profileSettings?.faceImageUrl ? { backgroundImage: `url(${profileSettings.faceImageUrl})`} : undefined }>
|
||
<FilledSquareButton
|
||
type="primary"
|
||
icon={<CameraOutlined style={{ fontSize: 28 }} />}
|
||
/>
|
||
</div>
|
||
<div className="user-avatar__text">{i18nText('photoDesc', locale)}</div>
|
||
</div>
|
||
</Upload>
|
||
</ImgCrop>
|
||
<div className="form-fieldset">
|
||
<div className="form-field">
|
||
<Form.Item name="username" rules={[
|
||
{
|
||
required: true,
|
||
message: 'Поле не должно быть пустым'
|
||
}
|
||
]}>
|
||
<CustomInput placeholder={i18nText('name', locale)} />
|
||
</Form.Item>
|
||
</div>
|
||
<div className="form-field">
|
||
<Form.Item name="surname">
|
||
<CustomInput placeholder={i18nText('surname', locale)} />
|
||
</Form.Item>
|
||
</div>
|
||
{/* <div className="form-field">
|
||
<Form.Item name="birthday">
|
||
<CustomInput placeholder={i18nText('birthday', locale)} />
|
||
</Form.Item>
|
||
</div> */}
|
||
<div className="form-field">
|
||
<Form.Item name="login" rules={[
|
||
{
|
||
required: true,
|
||
message: 'Поле не должно быть пустым'
|
||
}
|
||
]}>
|
||
<CustomInput type="email" placeholder="E-mail" />
|
||
</Form.Item>
|
||
</div>
|
||
</div>
|
||
<div className="form-actions">
|
||
<FilledYellowButton
|
||
onClick={onSaveProfile}
|
||
loading={saveLoading}
|
||
>
|
||
{i18nText('save', locale)}
|
||
</FilledYellowButton>
|
||
<OutlinedButton onClick={() => router.push('change-password')}>
|
||
{i18nText('changePass', locale)}
|
||
</OutlinedButton>
|
||
<OutlinedButton
|
||
onClick={onDeleteAccount}
|
||
icon={<DeleteOutlined />}
|
||
danger
|
||
>
|
||
{i18nText('deleteAcc', locale)}
|
||
</OutlinedButton>
|
||
</div>
|
||
<DeleteAccountModal
|
||
open={showDeleteModal}
|
||
handleCancel={() => setShowDeleteModal(false)}
|
||
/>
|
||
</Form>
|
||
</Loader>
|
||
);
|
||
};
|