mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 18:29:15 +03:00
refactor: refactored dialog
This commit is contained in:
parent
3db6174b8b
commit
ba514954e6
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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: () => {},
|
||||
});
|
||||
|
||||
@ -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}
|
||||
/>
|
||||
))}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>;
|
||||
|
||||
@ -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
18
src/types/index.d.ts
vendored
@ -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 = {
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user