mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 10:19:22 +03:00
refactor: update user contacts form
This commit is contained in:
parent
d997f99239
commit
b2541ff3e5
@ -38,13 +38,13 @@ const App = () => {
|
||||
<Router history={history}>
|
||||
<Switch>
|
||||
<PrivateRoute exact path='/' component={MainPage} title='Home' />
|
||||
<PrivateRoute exact path='/courses' component={CoursesPage} title='Courses' />
|
||||
<PrivateRoute
|
||||
path='/courses/create'
|
||||
component={CreateCoursePage}
|
||||
title='Create new course'
|
||||
roles={[UserRoleEnum.ADMIN, UserRoleEnum.TEACHER]}
|
||||
/>
|
||||
<PrivateRoute path='/courses' component={CoursesPage} title='Courses' />
|
||||
<PrivateRoute path='/messages' component={MessagesPage} title='Messages' />
|
||||
<PrivateRoute path='/profile' component={ProfilePage} title='Profile' />
|
||||
<PrivateRoute
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
import { IApiRespose, IUserContacts } from '@educt/interfaces';
|
||||
import { useState } from 'react';
|
||||
import { useErrorHandler } from 'react-error-boundary';
|
||||
import useIsMountedRef from './useIsMountedRef';
|
||||
import { useRootStore } from './useRootStore';
|
||||
|
||||
type UpdateContactsStateType = {
|
||||
result: IApiRespose<{}> | null;
|
||||
error: any;
|
||||
loading: boolean;
|
||||
fetched: boolean;
|
||||
};
|
||||
|
||||
const useUpdateUserContactsQuery = () => {
|
||||
const isMountedRef = useIsMountedRef();
|
||||
const [state, setState] = useState<UpdateContactsStateType>({
|
||||
result: null,
|
||||
error: null,
|
||||
loading: false,
|
||||
fetched: false,
|
||||
});
|
||||
const { userStore } = useRootStore();
|
||||
const toast = useToast();
|
||||
const handleError = useErrorHandler();
|
||||
|
||||
const updateContacts = async (data: IUserContacts) => {
|
||||
try {
|
||||
setState(s => ({ ...s, loading: true }));
|
||||
const result = await userStore.updateCurrentUserContacts(data);
|
||||
toast({ title: `Contacts saved!`, isClosable: true, status: 'info' });
|
||||
|
||||
if (isMountedRef.current) {
|
||||
setState(s => ({ ...s, result }));
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (isMountedRef.current) {
|
||||
setState(s => ({ ...s, error }));
|
||||
}
|
||||
if (error.response) {
|
||||
/**
|
||||
* Catch response error
|
||||
*/
|
||||
switch (error.response.status) {
|
||||
case 422:
|
||||
toast({ title: 'Validation error.', status: 'error', duration: 2000 });
|
||||
break;
|
||||
default:
|
||||
handleError(error);
|
||||
}
|
||||
} else {
|
||||
console.error(error);
|
||||
handleError(error);
|
||||
}
|
||||
} finally {
|
||||
if (isMountedRef.current) {
|
||||
setState(s => ({ ...s, loading: false, fetched: true }));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return { ...state, updateContacts };
|
||||
};
|
||||
|
||||
export default useUpdateUserContactsQuery;
|
||||
@ -31,7 +31,6 @@ import { useRootStore } from '@educt/hooks/useRootStore';
|
||||
import CourseStatusBadge from '@educt/components/CourseStatusBadge';
|
||||
import { CourseStatusEnum } from '@educt/enums';
|
||||
import { observer } from 'mobx-react';
|
||||
import { API_BASE_URL } from '@educt/constants';
|
||||
|
||||
type CourseItemPropsType = {
|
||||
course: Omit<ICourse, 'teacher' | 'students' | 'lessons'>;
|
||||
@ -63,16 +62,27 @@ const CourseItem: React.FC<CourseItemPropsType> = ({ course, onDelete, onSetStat
|
||||
/>
|
||||
<MenuList>
|
||||
<MenuItem icon={<EditIcon />}>Edit course</MenuItem>
|
||||
{course.status === CourseStatusEnum.DRAFT && (
|
||||
<MenuItem onClick={() => onSetStatus(course.id, CourseStatusEnum.PUBLISHED)} icon={<CheckIcon />}>
|
||||
Publish
|
||||
</MenuItem>
|
||||
)}
|
||||
{course.status === CourseStatusEnum.PUBLISHED && (
|
||||
<MenuItem onClick={() => onSetStatus(course.id, CourseStatusEnum.DRAFT)} icon={<MdNote />}>
|
||||
Mark as Draft
|
||||
</MenuItem>
|
||||
)}
|
||||
{(() => {
|
||||
switch (course.status) {
|
||||
case CourseStatusEnum.DRAFT:
|
||||
return (
|
||||
<MenuItem
|
||||
onClick={() => onSetStatus(course.id, CourseStatusEnum.PUBLISHED)}
|
||||
icon={<CheckIcon />}
|
||||
>
|
||||
Publish
|
||||
</MenuItem>
|
||||
);
|
||||
case CourseStatusEnum.PUBLISHED:
|
||||
return (
|
||||
<MenuItem onClick={() => onSetStatus(course.id, CourseStatusEnum.DRAFT)} icon={<MdNote />}>
|
||||
Mark as Draft
|
||||
</MenuItem>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})()}
|
||||
<MenuItem
|
||||
onClick={() => onDelete({ id: course.id, title: course.title })}
|
||||
icon={<DeleteIcon />}
|
||||
@ -101,19 +111,21 @@ const CourseItem: React.FC<CourseItemPropsType> = ({ course, onDelete, onSetStat
|
||||
borderTopRightRadius='lg'
|
||||
p='10px'
|
||||
>
|
||||
<Image
|
||||
position='absolute'
|
||||
top='0'
|
||||
bottom='0'
|
||||
right='0'
|
||||
left='0'
|
||||
fit='cover'
|
||||
h='100%'
|
||||
w='100%'
|
||||
borderTopLeftRadius='lg'
|
||||
borderTopRightRadius='lg'
|
||||
src={course.image ? `/api/assets/images/courses/${course.image.name}` : ''}
|
||||
/>
|
||||
{course.image && (
|
||||
<Image
|
||||
position='absolute'
|
||||
top='0'
|
||||
bottom='0'
|
||||
right='0'
|
||||
left='0'
|
||||
fit='cover'
|
||||
h='100%'
|
||||
w='100%'
|
||||
borderTopLeftRadius='lg'
|
||||
borderTopRightRadius='lg'
|
||||
src={`/api/assets/images/courses/${course.image.name}`}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
<Box p='0 10px' mt='10px' pb='20px'>
|
||||
<Flex justifyContent='space-between'>
|
||||
|
||||
@ -1,13 +1,27 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { SubmitHandler, useForm } from 'react-hook-form';
|
||||
import { MdSave } from 'react-icons/md';
|
||||
import { IUserContacts } from '@educt/interfaces';
|
||||
import { Box, Heading, Stack } from '@chakra-ui/layout';
|
||||
import { Text, Input, Button } from '@chakra-ui/react';
|
||||
import { Box, Heading, Stack } from '@chakra-ui/layout';
|
||||
import { FormControl, FormHelperText } from '@chakra-ui/form-control';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import useUpdateUserContactsQuery from '@educt/hooks/useUpdateUserContactsQuery';
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
import { IUserContacts } from '@educt/interfaces';
|
||||
|
||||
/**
|
||||
* Hooks
|
||||
*/
|
||||
import { useToast } from '@chakra-ui/toast';
|
||||
import { useRootStore } from '@educt/hooks/useRootStore';
|
||||
import { useErrorHandler } from 'react-error-boundary';
|
||||
|
||||
/**
|
||||
* Schema
|
||||
*/
|
||||
import UpdateUserContactsSchema from './UpdateUserContactsForm.validator';
|
||||
|
||||
type UpdateUserContactsInputType = {
|
||||
@ -17,11 +31,11 @@ type UpdateUserContactsInputType = {
|
||||
vk_id: string | null;
|
||||
};
|
||||
|
||||
type UpdateUserContactsFormProps = {
|
||||
type UpdateUserContactsFormPropsType = {
|
||||
contacts: IUserContacts | null;
|
||||
};
|
||||
|
||||
const UpdateUserContactsForm: React.FC<UpdateUserContactsFormProps> = ({ contacts }) => {
|
||||
const UpdateUserContactsForm: React.FC<UpdateUserContactsFormPropsType> = ({ contacts }) => {
|
||||
const {
|
||||
register,
|
||||
formState: { errors, isDirty },
|
||||
@ -36,17 +50,41 @@ const UpdateUserContactsForm: React.FC<UpdateUserContactsFormProps> = ({ contact
|
||||
vk_id: contacts && (contacts.vk_id ?? ''),
|
||||
},
|
||||
});
|
||||
const { updateContacts, loading } = useUpdateUserContactsQuery();
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const { userStore } = useRootStore();
|
||||
const toast = useToast();
|
||||
const handleError = useErrorHandler();
|
||||
|
||||
const onSubmit: SubmitHandler<UpdateUserContactsInputType> = data => {
|
||||
updateContacts(data).finally(() =>
|
||||
/**
|
||||
* Sumbit form handler
|
||||
*/
|
||||
const onSubmit: SubmitHandler<UpdateUserContactsInputType> = async data => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
await userStore.updateCurrentUserContacts(data);
|
||||
toast({ title: 'Contacts saved!', status: 'info' });
|
||||
reset({
|
||||
phone_number: data.phone_number ?? '',
|
||||
twitter_id: data.twitter_id ?? '',
|
||||
telegram_id: data.telegram_id ?? '',
|
||||
vk_id: data.vk_id ?? '',
|
||||
})
|
||||
);
|
||||
});
|
||||
setIsLoading(false);
|
||||
} catch (error: any) {
|
||||
if (error.response) {
|
||||
switch (error.response.status) {
|
||||
case 422:
|
||||
toast({ title: error.response.data.errors[0].message, status: 'error', duration: 2000 });
|
||||
break;
|
||||
default:
|
||||
handleError(error);
|
||||
}
|
||||
} else {
|
||||
handleError(error);
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@ -121,7 +159,7 @@ const UpdateUserContactsForm: React.FC<UpdateUserContactsFormProps> = ({ contact
|
||||
type='submit'
|
||||
size='md'
|
||||
variant='outline'
|
||||
isLoading={loading}
|
||||
isLoading={isLoading}
|
||||
loadingText='Saving...'
|
||||
rightIcon={<MdSave />}
|
||||
isDisabled={!isDirty}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user