refactor: refactored dialog

This commit is contained in:
Sergey Yarkov 2021-12-03 22:10:41 +03:00
parent 3db6174b8b
commit ba514954e6
11 changed files with 54 additions and 124 deletions

View File

@ -14,26 +14,20 @@ import ConfirmDialog from '@educt/components/ConfirmDialog/ConfirmDialog';
* Hooks
*/
import { useDeleteLesson } from '@educt/hooks/queries';
import { useRootStore } from '@educt/hooks/useRootStore';
type DeleteLessonDialogPropsType = {
lesson: Pick<ILesson, 'id' | 'title'>;
isOpen: boolean;
onClose: () => void;
};
//TODO pass lesson by prop
const DeleteLessonDialog: React.FC<DeleteLessonDialogPropsType> = ({ isOpen, onClose }) => {
const {
pageStore: {
editCourseStore: { deletingLesson },
},
} = useRootStore();
const DeleteLessonDialog: React.FC<DeleteLessonDialogPropsType> = ({ lesson, isOpen, onClose }) => {
const { deleteLesson, isLoading } = useDeleteLesson();
const handleDelete = async (isConfirmed: boolean) => {
if (isConfirmed && deletingLesson) {
if (isConfirmed) {
try {
await deleteLesson(deletingLesson.id);
await deleteLesson(lesson.id);
} catch (error: any) {
console.error(error);
}

View File

@ -23,14 +23,14 @@ import { useRootStore } from '@educt/hooks/useRootStore';
import { useDeleteUser } from '@educt/hooks/queries';
type DeleteUserDialogPropsType = {
user: IUser;
user: Pick<IUser, 'id' | 'fullname'>;
isOpen: boolean;
onClose: () => void;
};
const DeleteUserDialog: React.FC<DeleteUserDialogPropsType> = ({ isOpen, onClose, user }) => {
const { userStore } = useRootStore();
const { setDeletingUser, searchingRole, searchingPage, search } = useContext(UsersPageContext);
const { searchingRole, searchingPage, search } = useContext(UsersPageContext);
const { deleteUser, isLoading } = useDeleteUser();
const { pagination } = userStore;
@ -52,8 +52,6 @@ const DeleteUserDialog: React.FC<DeleteUserDialogPropsType> = ({ isOpen, onClose
});
} catch (error: any) {
console.error(error);
} finally {
setDeletingUser(undefined);
}
}

View File

@ -18,10 +18,6 @@ export const UsersPageContext = createContext<UsersPageContextType>({
setSearchingPage: () => {},
search: undefined,
setSearch: () => {},
editingUser: undefined,
setEditingUser: () => {},
deletingUser: undefined,
setDeletingUser: () => {},
});
export const CoursesPageContext = createContext<CoursesPageContextType>({
@ -29,8 +25,4 @@ export const CoursesPageContext = createContext<CoursesPageContextType>({
setSelectedCategory: () => {},
courseStatus: undefined,
setCourseStatus: () => {},
//TODO: remove
deletingCourse: undefined,
setDeletingCourse: () => {},
});

View File

@ -43,7 +43,7 @@ const CourseList: React.FC<CourseListPropsType> = ({ render: Item }) => {
const { setCourseStatus } = useSetCourseStatus();
const { courses, isLoading } = courseStore;
const deleteHandler = (course: Pick<ICourse, 'id' | 'title'>) => {
const handleDeleteCourse = (course: Pick<ICourse, 'id' | 'title'>) => {
setDeleting(course);
onOpenDeleteDialog();
};
@ -71,7 +71,7 @@ const CourseList: React.FC<CourseListPropsType> = ({ render: Item }) => {
<Item
key={course.id}
course={course}
onDelete={() => deleteHandler({ id: course.id, title: course.title })}
onDelete={() => handleDeleteCourse({ id: course.id, title: course.title })}
onSetStatus={setCourseStatus}
/>
))}

View File

@ -1,10 +1,10 @@
import React from 'react';
import React, { useState } from 'react';
import { observer } from 'mobx-react';
import { ItemProps, Virtuoso } from 'react-virtuoso';
import { DragDropContext, Draggable, DraggableProvided, Droppable, DropResult } from 'react-beautiful-dnd';
import moment from 'moment';
import { Flex, Box, Text, IconButton, Icon, Button } from '@chakra-ui/react';
import { DeleteIcon, DragHandleIcon } from '@chakra-ui/icons';
import moment from 'moment';
/**
* Types
@ -58,13 +58,14 @@ const LessonList: React.FC<LessonListPropsType> = ({ course }) => {
pageStore: { editCourseStore },
} = useRootStore();
const { onOpen: onOpenDeleteDialog, onClose: onCloseDeleteDialog, isOpen: isOpenDeleteDialog } = useDisclosure();
const [deleting, setDeleting] = useState<Pick<ILesson, 'id' | 'title'> | null>(null);
const handleError = useErrorHandler();
const lessons = course.lessons;
const handleCreateLesson = (): void => history.push('/lessons/create');
const handleEditLesson = (id: string): void => history.push(`/lessons/edit/${id}`);
const handleDeleteLesson = (lesson: ILesson): void => {
editCourseStore.setDeletingLesson(lesson);
setDeleting({ id: lesson.id, title: lesson.title });
onOpenDeleteDialog();
};
@ -143,7 +144,7 @@ const LessonList: React.FC<LessonListPropsType> = ({ course }) => {
<Box>
<Flex flexDirection='column' alignItems={{ base: 'center' }} mt={{ base: '4' }}>
<Flex flexDirection={{ base: 'column', md: 'row' }}>
<Button size='md' p='0 60px' mr='1'>
<Button onClick={() => handleEditLesson(lesson.id)} size='md' p='0 60px' mr='1'>
Edit
</Button>
<IconButton
@ -200,7 +201,9 @@ const LessonList: React.FC<LessonListPropsType> = ({ course }) => {
<Box style={{ overflow: 'auto' }}>
{lessons.length !== 0 ? (
<>
<DeleteLessonDialog isOpen={isOpenDeleteDialog} onClose={onCloseDeleteDialog} />
{deleting && (
<DeleteLessonDialog lesson={deleting} isOpen={isOpenDeleteDialog} onClose={onCloseDeleteDialog} />
)}
<Flex mt='2' mb='3' padding='0 20px' alignItems='center' justifyContent='space-between'>
<Text fontWeight='medium'>Total: ({lessons.length})</Text>
<Button onClick={handleCreateLesson}>Create new</Button>

View File

@ -1,4 +1,4 @@
import React, { useContext } from 'react';
import React from 'react';
import * as helpers from '@educt/helpers';
import {
Modal,
@ -33,19 +33,15 @@ import { SubmitHandler } from 'react-hook-form';
/**
* Hooks
*/
import { useEffect, useMemo } from 'react';
import { useForm } from 'react-hook-form';
import { useRootStore } from '@educt/hooks/useRootStore';
/**
* Contexts
*/
import { UsersPageContext } from '@educt/contexts';
import { useUpdateUser } from '@educt/hooks/queries';
/**
* Schema
*/
import UpdateUserSchema from './EditUserForm.validator';
import { useUpdateUser } from '@educt/hooks/queries';
type UpdateUserFormPropsType = {
user: IUser;
@ -62,9 +58,11 @@ type UpdateUserInputType = {
password: string | null;
};
const UpdateUserForm: React.FC<UpdateUserFormPropsType> = ({ user, onClose, isOpen }) => {
const { userStore } = useRootStore();
const { setEditingUser } = useContext(UsersPageContext);
const UpdateUserForm: React.FC<UpdateUserFormPropsType> = props => {
const { user, onClose, isOpen } = props;
const {
userStore: { me },
} = useRootStore();
const { updateUser, isLoading } = useUpdateUser();
const {
register,
@ -73,18 +71,11 @@ const UpdateUserForm: React.FC<UpdateUserFormPropsType> = ({ user, onClose, isOp
formState: { errors, isDirty, dirtyFields },
} = useForm<UpdateUserInputType>({
resolver: yupResolver(UpdateUserSchema),
defaultValues: {
first_name: user.first_name,
last_name: user.last_name,
email: user.email,
role: user.roles[0].slug,
login: '',
password: '',
},
defaultValues: useMemo(() => {
return props.user;
}, [props]),
});
const { me } = userStore;
if (me === null) return null;
/**
@ -94,20 +85,18 @@ const UpdateUserForm: React.FC<UpdateUserFormPropsType> = ({ user, onClose, isOp
try {
const params = helpers.getDirtyFields<UpdateUserInputType>(dirtyFields, data);
await updateUser(user.id, params);
onCloseModal();
onClose();
} catch (error: any) {
console.error(error);
}
};
const onCloseModal = () => {
reset({});
setEditingUser(undefined);
onClose();
};
useEffect(() => {
reset(props.user);
}, [props.user]);
return (
<Modal isOpen={isOpen} onClose={onCloseModal}>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<form onSubmit={handleSubmit(onSubmit)}>
@ -187,7 +176,7 @@ const UpdateUserForm: React.FC<UpdateUserFormPropsType> = ({ user, onClose, isOp
>
Save
</Button>
<Button onClick={onCloseModal}>Cancel</Button>
<Button onClick={onClose}>Cancel</Button>
</ModalFooter>
</form>
</ModalContent>

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { observer } from 'mobx-react';
import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons';
import { Flex, Box, Stack, Text } from '@chakra-ui/layout';
@ -9,7 +9,7 @@ import { Button } from '@chakra-ui/button';
*/
import LoadingList from '@educt/components/LoadingList';
import EditUserForm from '../EditUserForm';
import DeleteUserDialog from '../DeleteUserDialog';
import DeleteUserDialog from '@educt/components/Dialogs/DeleteUserDialog';
/**
* Types
@ -29,26 +29,29 @@ import { useEffect, useContext } from 'react';
import { useErrorHandler } from 'react-error-boundary';
import { useRootStore } from '@educt/hooks/useRootStore';
import { useDisclosure } from '@chakra-ui/hooks';
import { IUser } from '@educt/interfaces';
type UserListPropsType = { render: React.FC<UserItemPropsType>; limit?: number };
const UserList: React.FC<UserListPropsType> = ({ render: Item, limit }) => {
const { userStore } = useRootStore();
const {
searchingRole,
search,
searchingPage,
setSearchingPage,
editingUser,
setEditingUser,
deletingUser,
setDeletingUser,
} = useContext<UsersPageContextType>(UsersPageContext);
const { searchingRole, search, searchingPage, setSearchingPage } = useContext<UsersPageContextType>(UsersPageContext);
const handleError = useErrorHandler();
const [deleting, setDeleting] = useState<Pick<IUser, 'id' | 'fullname'> | null>(null);
const [editing, setEditing] = useState<IUser | null>(null);
const { onOpen: onOpenEditModal, onClose: onCloseEditModal, isOpen: isOpenEditModal } = useDisclosure();
const { onOpen: onOpenDeleteDialog, onClose: onCloseDeleteDialog, isOpen: isOpenDeleteDialog } = useDisclosure();
const { users, pagination, me, isLoading } = userStore;
const handleEditUser = (user: IUser) => {
setEditing(user);
onOpenEditModal();
};
const handleDeleteUser = (user: Pick<IUser, 'id' | 'fullname'>) => {
setDeleting(user);
onOpenDeleteDialog();
};
/**
* Fetch users handler
*/
@ -69,10 +72,8 @@ const UserList: React.FC<UserListPropsType> = ({ render: Item, limit }) => {
return (
<Box>
{editingUser && <EditUserForm user={editingUser} isOpen={isOpenEditModal} onClose={onCloseEditModal} />}
{deletingUser && (
<DeleteUserDialog user={deletingUser} isOpen={isOpenDeleteDialog} onClose={onCloseDeleteDialog} />
)}
{editing && <EditUserForm user={editing} isOpen={isOpenEditModal} onClose={onCloseEditModal} />}
{deleting && <DeleteUserDialog user={deleting} isOpen={isOpenDeleteDialog} onClose={onCloseDeleteDialog} />}
{users.length !== 0 ? (
<>
<Box>
@ -86,14 +87,8 @@ const UserList: React.FC<UserListPropsType> = ({ render: Item, limit }) => {
<Item
key={user.id}
user={user}
onEdit={user => {
setEditingUser(user);
onOpenEditModal();
}}
onDelete={user => {
setDeletingUser(user);
onOpenDeleteDialog();
}}
onEdit={user => handleEditUser(user)}
onDelete={user => handleDeleteUser({ id: user.id, fullname: user.fullname })}
/>
))}
</Stack>

View File

@ -35,8 +35,6 @@ export const UsersPageContextProvider: React.FC = ({ children }) => {
const [searchingRole, setSearchingRole] = useState<SearchingRoleStateType>(undefined);
const [searchingPage, setSearchingPage] = useState<number>(1);
const [search, setSearch] = useState<string | undefined>(undefined);
const [editingUser, setEditingUser] = useState<IUser | undefined>(undefined);
const [deletingUser, setDeletingUser] = useState<IUser | undefined>(undefined);
return (
<UsersPageContext.Provider
@ -47,10 +45,6 @@ export const UsersPageContextProvider: React.FC = ({ children }) => {
setSearchingPage,
search,
setSearch,
editingUser,
setEditingUser,
deletingUser,
setDeletingUser,
}}
>
{children}
@ -64,7 +58,6 @@ export const UsersPageContextProvider: React.FC = ({ children }) => {
export const CoursesPageContextProvider: React.FC = ({ children }) => {
const [selectedCategory, setSelectedCategory] = useState<ICategory | undefined>(undefined);
const [courseStatus, setCourseStatus] = useState<CourseStatusEnum | undefined>(undefined);
const [deletingCourse, setDeletingCourse] = useState<Pick<ICourse, 'id' | 'title'> | undefined>(undefined);
const context = React.useMemo(
() => ({
@ -72,10 +65,8 @@ export const CoursesPageContextProvider: React.FC = ({ children }) => {
setCourseStatus,
selectedCategory,
setSelectedCategory,
deletingCourse,
setDeletingCourse,
}),
[courseStatus, setCourseStatus, selectedCategory, setSelectedCategory, deletingCourse, setDeletingCourse]
[courseStatus, setCourseStatus, selectedCategory, setSelectedCategory]
);
return <CoursesPageContext.Provider value={context}>{children}</CoursesPageContext.Provider>;

View File

@ -1,6 +1,6 @@
import { makeAutoObservable, runInAction } from 'mobx';
import * as helpers from '@educt/helpers';
import { ICourse, ILesson } from '@educt/interfaces';
import { ICourse } from '@educt/interfaces';
import PageStore from '../PageStore';
import { CourseServiceInstance, LessonServiceInstance } from '@educt/services';
@ -10,12 +10,6 @@ export default class EditCourseStore {
public course: Omit<ICourse, 'students_count' | 'likes_count' | 'lessons_count'> | null = null;
public isDeleting: boolean = false;
public deletingCourse: Pick<ICourse, 'id' | 'title'> | undefined;
public deletingLesson: ILesson | undefined;
constructor(pageStore: PageStore) {
this.pageStore = pageStore;
@ -75,12 +69,4 @@ export default class EditCourseStore {
this.course.lessons = helpers.arrayMove(this.course.lessons, oldIndex, newIndex);
}
}
public setDeletingLesson(lesson: ILesson) {
this.deletingLesson = lesson;
}
public setDeletingCourse(course: Pick<ICourse, 'id' | 'title'> | undefined) {
this.deletingCourse = course;
}
}

18
src/types/index.d.ts vendored
View File

@ -71,23 +71,11 @@ export type UsersPageContextType = {
search: string | undefined;
setSearch: React.Dispatch<React.SetStateAction<string | undefined>>;
/**
* Set editing user state when press on edit button
*/
editingUser: IUser | undefined;
setEditingUser: React.Dispatch<React.SetStateAction<IUser | undefined>>;
/**
* Search users by page
*/
searchingPage: number;
setSearchingPage: React.Dispatch<React.SetStateAction<number>>;
/**
* Set deleting user state when press on delete button
*/
deletingUser: IUser | undefined;
setDeletingUser: React.Dispatch<React.SetStateAction<IUser | undefined>>;
};
export type CoursesPageContextType = {
@ -102,12 +90,6 @@ export type CoursesPageContextType = {
*/
courseStatus: CourseStatusEnum | undefined;
setCourseStatus: React.Dispatch<React.SetStateAction<CourseStatusEnum | undefined>>;
/**
* Set deleting course state when press on delete button
*/
deletingCourse: Pick<ICourse, 'id' | 'title'> | undefined;
setDeletingCourse: React.Dispatch<React.SetStateAction<Pick<ICourse, 'id' | 'title'> | undefined>>;
};
export type FetchCoursesParams = {
/**