mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-22 20:01:59 +00:00
Apply modal instead of dialog in user pages
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
import { MutableRefObject, ReactNode, forwardRef } from 'react';
|
||||
|
||||
// Styled
|
||||
import { StyledBody, StyledDialog, StyledTitle } from './styled';
|
||||
|
||||
// Type
|
||||
import { Nullable } from '../../types/common';
|
||||
|
||||
export interface IDialogProps {
|
||||
title?: string;
|
||||
children?: ReactNode;
|
||||
onClose?: () => void;
|
||||
ref?: MutableRefObject<Nullable<HTMLDialogElement>>;
|
||||
}
|
||||
|
||||
const Dialog = forwardRef<HTMLDialogElement, IDialogProps>(
|
||||
(props: IDialogProps, ref) => {
|
||||
const { title, children, onClose } = props;
|
||||
|
||||
return (
|
||||
<StyledDialog ref={ref} onClose={onClose}>
|
||||
<StyledTitle>{title}</StyledTitle>
|
||||
<StyledBody>{children}</StyledBody>
|
||||
</StyledDialog>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default Dialog;
|
||||
@@ -1,23 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledDialog = styled.dialog`
|
||||
border-radius: var(--radius-sm);
|
||||
border-color: var(--border-color);
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.p`
|
||||
font-size: var(--fs-md);
|
||||
text-transform: capitalize;
|
||||
font-weight: 600;
|
||||
|
||||
padding: 20px 40px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const StyledBody = styled.div`
|
||||
padding: 10px 20px;
|
||||
`;
|
||||
|
||||
export { StyledDialog, StyledTitle, StyledBody };
|
||||
@@ -2,6 +2,6 @@ export const DASHBOARD = '/dashboard';
|
||||
export const USER = '/user';
|
||||
export const ROOM = '/room';
|
||||
export const OTHER_PATH = '*';
|
||||
export const BASE_URL = 'http://localhost:3000/';
|
||||
export const BASE_URL = 'https://hotel-management-api.loiphan.com/';
|
||||
export const USER_PATH = 'users';
|
||||
export const ROOM_PATH = 'rooms';
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import {
|
||||
Dispatch,
|
||||
MutableRefObject,
|
||||
SetStateAction,
|
||||
forwardRef,
|
||||
useEffect,
|
||||
} from 'react';
|
||||
|
||||
// Components
|
||||
import Dialog from '../../components/Dialog';
|
||||
import RoomForm from './Form';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { IRoom } from '../../types/rooms';
|
||||
|
||||
// Hooks
|
||||
import { useForwardRef } from '../../hooks/useForwardRef';
|
||||
|
||||
interface IRoomDialog {
|
||||
onClose?: () => void;
|
||||
reload?: boolean;
|
||||
setReload?: Dispatch<SetStateAction<boolean>>;
|
||||
ref?: MutableRefObject<Nullable<HTMLDialogElement>>;
|
||||
room?: Nullable<IRoom>;
|
||||
isAdd?: boolean;
|
||||
}
|
||||
|
||||
const RoomDialog = forwardRef<HTMLDialogElement, IRoomDialog>(
|
||||
(props: IRoomDialog, ref) => {
|
||||
const dialogRef = useForwardRef(ref);
|
||||
const {
|
||||
onClose,
|
||||
setReload,
|
||||
reload,
|
||||
room,
|
||||
isAdd
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
if (dialogRef.current) {
|
||||
dialogRef.current.addEventListener('click', (e: MouseEvent) => {
|
||||
const dialogDimensions = dialogRef.current!.getBoundingClientRect();
|
||||
if (
|
||||
e.clientX < dialogDimensions.left ||
|
||||
e.clientX > dialogDimensions.right ||
|
||||
e.clientY < dialogDimensions.top ||
|
||||
e.clientY > dialogDimensions.bottom
|
||||
) {
|
||||
dialogRef.current!.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [dialogRef]);
|
||||
|
||||
return (
|
||||
<Dialog title={'Add room'} onClose={onClose} ref={dialogRef}>
|
||||
<RoomForm
|
||||
onClose={onClose!}
|
||||
reload={reload!}
|
||||
setReload={setReload!}
|
||||
room={room}
|
||||
isAdd={isAdd!}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default RoomDialog;
|
||||
+1
-71
@@ -1,10 +1,7 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
// Components
|
||||
import { RiEditBoxFill } from 'react-icons/ri';
|
||||
import { HiTrash } from 'react-icons/hi';
|
||||
import { StyledOperationTable } from './styled';
|
||||
import Menus from '../../components/Menus';
|
||||
import Table from '../../components/Table';
|
||||
@@ -19,78 +16,11 @@ import { IRoom } from '../../types/rooms';
|
||||
|
||||
// Constants
|
||||
import { useFetch } from '../../hooks/useFetch';
|
||||
import { ROOM_PATH } from '../../constants/path';
|
||||
import { STATUS_CODE } from '../../constants/responseStatus';
|
||||
import { CONFIRM_DELETE, DELETE_SUCCESS } from '../../constants/messages';
|
||||
import { ORDERBY_OPTIONS, ROOM_PAGE } from '../../constants/variables';
|
||||
|
||||
// Styled
|
||||
import Spinner from '../../commons/styles/Spinner';
|
||||
|
||||
// Helpers
|
||||
import { sendRequest } from '../../helpers/sendRequest';
|
||||
import { formatCurrency } from '../../helpers/helper';
|
||||
import Modal from '../../components/Modal';
|
||||
import RoomForm from './Form';
|
||||
|
||||
interface IRoomRow {
|
||||
room: IRoom;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const RoomRow = ({ room, reload, setReload }: IRoomRow) => {
|
||||
const handleDelete = async (room: IRoom) => {
|
||||
if (confirm(CONFIRM_DELETE)) {
|
||||
const response = await sendRequest(ROOM_PATH + `/${room.id}`, 'DELETE');
|
||||
|
||||
if (response.statusCode === STATUS_CODE.OK) {
|
||||
toast.success(DELETE_SUCCESS);
|
||||
|
||||
// Reload table
|
||||
setReload(!reload);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const { id, name, finalPrice, status } = room;
|
||||
|
||||
const statusText = status ? 'Unavailable' : 'Available';
|
||||
|
||||
return (
|
||||
<Table.Row>
|
||||
<div>{id}</div>
|
||||
<div>{name}</div>
|
||||
<div>{formatCurrency(finalPrice)}</div>
|
||||
<div>{statusText}</div>
|
||||
|
||||
<div>
|
||||
<Modal>
|
||||
<Menus.Menu>
|
||||
<Menus.Toggle id={id.toString()} />
|
||||
|
||||
<Menus.List id={id.toString()}>
|
||||
<Modal.Open modalName="edit">
|
||||
<Menus.Button icon={<RiEditBoxFill />}>Edit</Menus.Button>
|
||||
</Modal.Open>
|
||||
|
||||
<Menus.Button
|
||||
icon={<HiTrash />}
|
||||
onClick={() => handleDelete(room)}
|
||||
>
|
||||
Delete
|
||||
</Menus.Button>
|
||||
</Menus.List>
|
||||
|
||||
<Modal.Window name="edit" title="Edit Room">
|
||||
<RoomForm room={room} />
|
||||
</Modal.Window>
|
||||
</Menus.Menu>
|
||||
</Modal>
|
||||
</div>
|
||||
</Table.Row>
|
||||
);
|
||||
};
|
||||
import RoomRow from './RoomRow';
|
||||
|
||||
interface IRoomTable {
|
||||
reload: boolean;
|
||||
+15
-17
@@ -10,8 +10,8 @@ import Button from '../../commons/styles/Button.ts';
|
||||
import Input from '../../commons/styles/Input.ts';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { IRoom } from '../../types/rooms';
|
||||
import { Nullable } from '../../types/common.ts';
|
||||
import { IRoom } from '../../types/rooms.ts';
|
||||
|
||||
// Constants
|
||||
import {
|
||||
@@ -51,33 +51,31 @@ interface IRoomFormProp {
|
||||
onCloseModal?: () => void;
|
||||
reload?: boolean;
|
||||
setReload?: Dispatch<SetStateAction<boolean>>;
|
||||
room?: Nullable<IRoom>;
|
||||
isAdd?: boolean;
|
||||
roomEdit?: Nullable<IRoom>;
|
||||
}
|
||||
|
||||
const RoomForm = ({
|
||||
onCloseModal,
|
||||
reload,
|
||||
setReload,
|
||||
room,
|
||||
isAdd,
|
||||
roomEdit,
|
||||
}: IRoomFormProp) => {
|
||||
const formMethods = useForm<IRoom>();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { errors, isDirty, isValid },
|
||||
formState: { errors, isDirty, isValid, isSubmitting },
|
||||
trigger,
|
||||
} = formMethods;
|
||||
|
||||
useEffect(() => {
|
||||
if (room && !isAdd) {
|
||||
reset(room);
|
||||
if (roomEdit) {
|
||||
reset(roomEdit);
|
||||
} else {
|
||||
reset(INIT_VALUE_ROOM_FORM);
|
||||
}
|
||||
}, [room, reset, isAdd]);
|
||||
}, [roomEdit, reset]);
|
||||
|
||||
// Submit form
|
||||
const onSubmit = async (room: IRoom) => {
|
||||
@@ -85,7 +83,7 @@ const RoomForm = ({
|
||||
room.finalPrice = room.price - (room.price * room.discount) / 100;
|
||||
|
||||
try {
|
||||
if (isAdd) {
|
||||
if (!roomEdit) {
|
||||
// Add request
|
||||
const response = await addRoom(room);
|
||||
|
||||
@@ -101,7 +99,7 @@ const RoomForm = ({
|
||||
}
|
||||
}
|
||||
// Reload table data
|
||||
// setReload(!reload);
|
||||
setReload!(!reload);
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
toast.error(error.message);
|
||||
@@ -109,7 +107,7 @@ const RoomForm = ({
|
||||
}
|
||||
|
||||
reset();
|
||||
// onClose();
|
||||
onCloseModal!();
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -161,11 +159,11 @@ const RoomForm = ({
|
||||
</FormRow>
|
||||
|
||||
<Form.Action>
|
||||
<FormBtn type="submit" name="submit" disabled={!isDirty || !isValid}>
|
||||
<FormBtn type="submit" name="submit" disabled={!isDirty || !isValid || isSubmitting}>
|
||||
{
|
||||
isAdd
|
||||
? 'Add'
|
||||
: 'Save'
|
||||
!roomEdit
|
||||
? 'Add'
|
||||
: 'Save'
|
||||
}
|
||||
</FormBtn>
|
||||
<FormBtn type="button" styled="secondary" onClick={onCloseModal}>
|
||||
@@ -0,0 +1,83 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
// Constants
|
||||
import { ROOM_PATH } from '../../constants/path';
|
||||
import { STATUS_CODE } from '../../constants/responseStatus';
|
||||
import { CONFIRM_DELETE, DELETE_SUCCESS } from '../../constants/messages';
|
||||
|
||||
// Helpers
|
||||
import { sendRequest } from '../../helpers/sendRequest';
|
||||
import { formatCurrency } from '../../helpers/helper';
|
||||
import Modal from '../../components/Modal';
|
||||
import RoomForm from './RoomForm';
|
||||
|
||||
// Types
|
||||
import { IRoom } from '../../types/rooms';
|
||||
|
||||
// Components
|
||||
import Table from '../../components/Table';
|
||||
import Menus from '../../components/Menus';
|
||||
import { RiEditBoxFill } from 'react-icons/ri';
|
||||
import { HiTrash } from 'react-icons/hi';
|
||||
|
||||
interface IRoomRow {
|
||||
room: IRoom;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const RoomRow = ({ room, reload, setReload }: IRoomRow) => {
|
||||
const handleDelete = async (room: IRoom) => {
|
||||
if (confirm(CONFIRM_DELETE)) {
|
||||
const response = await sendRequest(ROOM_PATH + `/${room.id}`, 'DELETE');
|
||||
|
||||
if (response.statusCode === STATUS_CODE.OK) {
|
||||
toast.success(DELETE_SUCCESS);
|
||||
|
||||
// Reload table
|
||||
setReload(!reload);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const { id, name, finalPrice, status } = room;
|
||||
|
||||
const statusText = status ? 'Unavailable' : 'Available';
|
||||
|
||||
return (
|
||||
<Table.Row>
|
||||
<div>{id}</div>
|
||||
<div>{name}</div>
|
||||
<div>{formatCurrency(finalPrice)}</div>
|
||||
<div>{statusText}</div>
|
||||
|
||||
<div>
|
||||
<Modal>
|
||||
<Menus.Menu>
|
||||
<Menus.Toggle id={id.toString()} />
|
||||
|
||||
<Menus.List id={id.toString()}>
|
||||
<Modal.Open modalName="edit">
|
||||
<Menus.Button icon={<RiEditBoxFill />}>Edit</Menus.Button>
|
||||
</Modal.Open>
|
||||
|
||||
<Menus.Button
|
||||
icon={<HiTrash />}
|
||||
onClick={() => handleDelete(room)}
|
||||
>
|
||||
Delete
|
||||
</Menus.Button>
|
||||
</Menus.List>
|
||||
|
||||
<Modal.Window name="edit" title="Edit Room">
|
||||
<RoomForm roomEdit={room} setReload={setReload} reload={reload} />
|
||||
</Modal.Window>
|
||||
</Menus.Menu>
|
||||
</Modal>
|
||||
</div>
|
||||
</Table.Row>
|
||||
);
|
||||
};
|
||||
|
||||
export default RoomRow;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
// Components
|
||||
import RoomTable from './Table';
|
||||
import RoomTable from './RomTable';
|
||||
|
||||
// Styled
|
||||
import { StyledRoom, Title } from './styled';
|
||||
@@ -10,7 +10,7 @@ import Button from '../../commons/styles/Button';
|
||||
|
||||
// Types
|
||||
import Modal from '../../components/Modal';
|
||||
import RoomForm from './Form';
|
||||
import RoomForm from './RoomForm';
|
||||
|
||||
const Room = () => {
|
||||
const [reload, setReload] = useState(true);
|
||||
@@ -22,10 +22,10 @@ const Room = () => {
|
||||
<Title>List Room</Title>
|
||||
|
||||
<Modal>
|
||||
<Modal.Open modalName="cabin-form">
|
||||
<Modal.Open modalName="room-form">
|
||||
<Button>Add room</Button>
|
||||
</Modal.Open>
|
||||
<Modal.Window name="cabin-form" title="Add form">
|
||||
<Modal.Window name="room-form" title="Add form">
|
||||
<RoomForm setReload={setReload} reload={reload} />
|
||||
</Modal.Window>
|
||||
</Modal>
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import {
|
||||
Dispatch,
|
||||
MutableRefObject,
|
||||
SetStateAction,
|
||||
forwardRef,
|
||||
useEffect,
|
||||
} from 'react';
|
||||
|
||||
// Components
|
||||
import Dialog from '../../components/Dialog';
|
||||
import UserForm from './Form';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { IUser } from '../../types/users';
|
||||
|
||||
// Hooks
|
||||
import { useForwardRef } from '../../hooks/useForwardRef';
|
||||
|
||||
interface IUserDialog {
|
||||
onClose: () => void;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
ref: MutableRefObject<Nullable<HTMLDialogElement>>;
|
||||
user: Nullable<IUser>;
|
||||
isAdd: boolean;
|
||||
}
|
||||
|
||||
const UserDialog = forwardRef<HTMLDialogElement, IUserDialog>((props, ref) => {
|
||||
const dialogRef = useForwardRef(ref);
|
||||
|
||||
const {
|
||||
onClose,
|
||||
setReload,
|
||||
reload,
|
||||
user,
|
||||
isAdd,
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
if (dialogRef.current) {
|
||||
dialogRef.current.addEventListener('click', (e: MouseEvent) => {
|
||||
const dialogDimensions = dialogRef.current!.getBoundingClientRect();
|
||||
if (
|
||||
e.clientX < dialogDimensions.left ||
|
||||
e.clientX > dialogDimensions.right ||
|
||||
e.clientY < dialogDimensions.top ||
|
||||
e.clientY > dialogDimensions.bottom
|
||||
) {
|
||||
dialogRef.current!.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [dialogRef]);
|
||||
|
||||
return (
|
||||
<Dialog title={'Add user'} onClose={onClose} ref={dialogRef}>
|
||||
<UserForm
|
||||
onClose={onClose!}
|
||||
reload={reload!}
|
||||
setReload={setReload!}
|
||||
user={user}
|
||||
isAdd={isAdd!}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
});
|
||||
|
||||
export default UserDialog;
|
||||
+16
-23
@@ -11,12 +11,12 @@ import toast from 'react-hot-toast';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
|
||||
// Styled
|
||||
import Input from '../../commons/styles/Input';
|
||||
import Input from '../../commons/styles/Input.ts';
|
||||
|
||||
// Components
|
||||
import Form from '../../components/Form';
|
||||
import Form from '../../components/Form/index.tsx';
|
||||
import FormRow from '../../components/LabelControl/index.tsx';
|
||||
import Select, { ISelectOptions } from '../../components/Select';
|
||||
import Select, { ISelectOptions } from '../../components/Select/index.tsx';
|
||||
|
||||
// Helpers
|
||||
import {
|
||||
@@ -48,26 +48,19 @@ import { IRoom } from '../../types/rooms.ts';
|
||||
import { createUser, updateUser } from '../../services/userServices.ts';
|
||||
|
||||
interface IUserFormProp {
|
||||
onClose: () => void;
|
||||
onCloseModal?: () => void;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
user: Nullable<IUser>;
|
||||
isAdd: boolean;
|
||||
user?: Nullable<IUser>;
|
||||
}
|
||||
|
||||
const UserForm = ({
|
||||
onClose,
|
||||
reload,
|
||||
setReload,
|
||||
user,
|
||||
isAdd,
|
||||
}: IUserFormProp) => {
|
||||
const UserForm = ({ onCloseModal, reload, setReload, user }: IUserFormProp) => {
|
||||
const formMethods = useForm<IUser>();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { errors, isDirty, isValid },
|
||||
formState: { errors, isDirty, isValid, isSubmitting },
|
||||
trigger,
|
||||
} = formMethods;
|
||||
const [rooms, setRooms] = useState<IRoom[]>([]);
|
||||
@@ -77,8 +70,8 @@ const UserForm = ({
|
||||
useEffect(() => {
|
||||
const load = async () => {
|
||||
const options: ISelectOptions[] = [];
|
||||
const tempUser = isAdd
|
||||
? {}
|
||||
const tempUser = !user
|
||||
? { roomId: 0 }
|
||||
: { ...user };
|
||||
|
||||
// Load and set default options room
|
||||
@@ -111,13 +104,13 @@ const UserForm = ({
|
||||
};
|
||||
|
||||
load();
|
||||
}, [reset, user, isAdd, rooms]);
|
||||
}, [reset, user, rooms]);
|
||||
|
||||
// Submit form
|
||||
const onSubmit = useCallback(
|
||||
async (newUser: IUser) => {
|
||||
try {
|
||||
if (isAdd) {
|
||||
if (!user) {
|
||||
// Add request
|
||||
const response = await createUser(newUser);
|
||||
|
||||
@@ -147,9 +140,9 @@ const UserForm = ({
|
||||
}
|
||||
|
||||
reset();
|
||||
onClose();
|
||||
onCloseModal!();
|
||||
},
|
||||
[isAdd, onClose, reload, reset, setReload, user]
|
||||
[onCloseModal, reload, reset, setReload, user]
|
||||
);
|
||||
|
||||
// Load all rooms
|
||||
@@ -233,14 +226,14 @@ const UserForm = ({
|
||||
</FormRow>
|
||||
|
||||
<Form.Action>
|
||||
<FormBtn type="submit" name="submit" disabled={!isDirty || !isValid}>
|
||||
<FormBtn type="submit" name="submit" disabled={!isDirty || !isValid || isSubmitting}>
|
||||
{
|
||||
isAdd
|
||||
!user
|
||||
? 'Add'
|
||||
: 'Save'
|
||||
}
|
||||
</FormBtn>
|
||||
<FormBtn type="button" styled="secondary" onClick={onClose}>
|
||||
<FormBtn type="button" styled="secondary" onClick={onCloseModal}>
|
||||
Close
|
||||
</FormBtn>
|
||||
</Form.Action>
|
||||
+2
-91
@@ -1,10 +1,7 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
// Components
|
||||
import { RiEditBoxFill } from 'react-icons/ri';
|
||||
import { IoExit } from 'react-icons/io5';
|
||||
import Menus from '../../components/Menus';
|
||||
import Table from '../../components/Table';
|
||||
import Direction from '../../commons/styles/Direction';
|
||||
@@ -14,113 +11,29 @@ import SortBy from '../../components/SortBy';
|
||||
import OrderBy from '../../components/OrderBy';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { IUser } from '../../types/users';
|
||||
|
||||
// Hooks
|
||||
import { useFetch } from '../../hooks/useFetch';
|
||||
|
||||
// Constants
|
||||
import { STATUS_CODE } from '../../constants/responseStatus';
|
||||
import { ORDERBY_OPTIONS, USER_PAGE } from '../../constants/variables';
|
||||
import { CONFIRM_MESSAGE, DENIED_ACTION } from '../../constants/messages';
|
||||
|
||||
// Styled
|
||||
import { StyledOperationTable } from './styled';
|
||||
import Spinner from '../../commons/styles/Spinner';
|
||||
import UserRow from './UserRow';
|
||||
|
||||
// Services
|
||||
import { updateRoomStatus } from '../../services/roomServices';
|
||||
import { checkOutUser } from '../../services/userServices';
|
||||
|
||||
interface IUserRow {
|
||||
user: IUser;
|
||||
openFormDialog: () => void;
|
||||
setUser: Dispatch<SetStateAction<Nullable<IUser>>>;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const UserRow = ({
|
||||
user,
|
||||
openFormDialog,
|
||||
setUser,
|
||||
reload,
|
||||
setReload,
|
||||
}: IUserRow) => {
|
||||
const handleEdit = (user: IUser) => {
|
||||
setUser(user);
|
||||
openFormDialog();
|
||||
};
|
||||
|
||||
const handleCheckOut = async (user: IUser) => {
|
||||
if(user.roomId !== 0) {
|
||||
if (confirm(CONFIRM_MESSAGE)) {
|
||||
const resUpdateStatus = await updateRoomStatus(user.roomId, false);
|
||||
const resCheckoutUser = await checkOutUser(user);
|
||||
|
||||
if (
|
||||
resCheckoutUser?.statusCode === STATUS_CODE.OK &&
|
||||
resUpdateStatus?.statusCode === STATUS_CODE.OK
|
||||
) {
|
||||
toast.success('Check out complete!');
|
||||
|
||||
// Reload table
|
||||
setReload(!reload);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toast.error(DENIED_ACTION);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const { id, name, identifiedCode, phone, roomId } = user;
|
||||
|
||||
return (
|
||||
<Table.Row>
|
||||
<div>{id}</div>
|
||||
<div>{name}</div>
|
||||
<div>{identifiedCode}</div>
|
||||
<div>{phone}</div>
|
||||
<div>{
|
||||
roomId
|
||||
? roomId
|
||||
: 'None'
|
||||
}</div>
|
||||
|
||||
<Menus.Menu>
|
||||
<Menus.Toggle id={id.toString()} />
|
||||
|
||||
<Menus.List id={id.toString()}>
|
||||
<Menus.Button
|
||||
icon={<RiEditBoxFill />}
|
||||
onClick={() => handleEdit(user)}
|
||||
>
|
||||
Edit
|
||||
</Menus.Button>
|
||||
<Menus.Button icon={<IoExit />} onClick={() => handleCheckOut(user)}>
|
||||
Check out
|
||||
</Menus.Button>
|
||||
</Menus.List>
|
||||
</Menus.Menu>
|
||||
</Table.Row>
|
||||
);
|
||||
};
|
||||
|
||||
interface IUserTable {
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
openFormDialog: () => void;
|
||||
setUser?: Dispatch<SetStateAction<Nullable<IUser>>>;
|
||||
}
|
||||
|
||||
const UserTable = ({
|
||||
reload,
|
||||
setReload,
|
||||
openFormDialog,
|
||||
setUser,
|
||||
}: IUserTable) => {
|
||||
const UserTable = ({ reload, setReload }: IUserTable) => {
|
||||
const [users, setUsers] = useState<IUser[]>([]);
|
||||
const [phoneSearch, setPhoneSearch] = useState('');
|
||||
const [searchParams] = useSearchParams();
|
||||
@@ -185,8 +98,6 @@ const UserTable = ({
|
||||
key={user.id}
|
||||
reload={reload}
|
||||
setReload={setReload}
|
||||
openFormDialog={openFormDialog}
|
||||
setUser={setUser!}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@@ -0,0 +1,88 @@
|
||||
import toast from 'react-hot-toast';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
|
||||
// Components
|
||||
import { RiEditBoxFill } from 'react-icons/ri';
|
||||
import { IoExit } from 'react-icons/io5';
|
||||
import Modal from '../../components/Modal';
|
||||
import UserForm from './FormUser';
|
||||
import Table from '../../components/Table';
|
||||
import Menus from '../../components/Menus';
|
||||
|
||||
// Constants
|
||||
import { STATUS_CODE } from '../../constants/responseStatus';
|
||||
import { CONFIRM_MESSAGE, DENIED_ACTION } from '../../constants/messages';
|
||||
|
||||
// Services
|
||||
import { updateRoomStatus } from '../../services/roomServices';
|
||||
import { checkOutUser } from '../../services/userServices';
|
||||
|
||||
// Types
|
||||
import { IUser } from '../../types/users';
|
||||
|
||||
interface IUserRow {
|
||||
user: IUser;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const UserRow = ({ user, reload, setReload }: IUserRow) => {
|
||||
const handleCheckOut = async (user: IUser) => {
|
||||
if (user.roomId !== 0) {
|
||||
if (confirm(CONFIRM_MESSAGE)) {
|
||||
const resUpdateStatus = await updateRoomStatus(user.roomId, false);
|
||||
const resCheckoutUser = await checkOutUser(user);
|
||||
|
||||
if (
|
||||
resCheckoutUser?.statusCode === STATUS_CODE.OK &&
|
||||
resUpdateStatus?.statusCode === STATUS_CODE.OK
|
||||
) {
|
||||
toast.success('Check out complete!');
|
||||
|
||||
// Reload table
|
||||
setReload(!reload);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toast.error(DENIED_ACTION);
|
||||
}
|
||||
};
|
||||
|
||||
const { id, name, identifiedCode, phone, roomId } = user;
|
||||
|
||||
return (
|
||||
<Table.Row>
|
||||
<div>{id}</div>
|
||||
<div>{name}</div>
|
||||
<div>{identifiedCode}</div>
|
||||
<div>{phone}</div>
|
||||
<div>{roomId ? roomId : 'None'}</div>
|
||||
|
||||
<div>
|
||||
<Modal>
|
||||
<Menus.Menu>
|
||||
<Menus.Toggle id={id.toString()} />
|
||||
|
||||
<Menus.List id={id.toString()}>
|
||||
<Modal.Open modalName="edit">
|
||||
<Menus.Button icon={<RiEditBoxFill />}>Edit</Menus.Button>
|
||||
</Modal.Open>
|
||||
<Menus.Button
|
||||
icon={<IoExit />}
|
||||
onClick={() => handleCheckOut(user)}
|
||||
>
|
||||
Check out
|
||||
</Menus.Button>
|
||||
</Menus.List>
|
||||
|
||||
<Modal.Window name="edit" title="Edit user">
|
||||
<UserForm user={user} setReload={setReload} reload={reload} />
|
||||
</Modal.Window>
|
||||
</Menus.Menu>
|
||||
</Modal>
|
||||
</div>
|
||||
</Table.Row>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserRow;
|
||||
@@ -1,57 +1,38 @@
|
||||
import { useRef, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
// Components
|
||||
import UserTable from './Table';
|
||||
import UserTable from './TableUser';
|
||||
|
||||
// Styled
|
||||
import Button from '../../commons/styles/Button';
|
||||
import Direction from '../../commons/styles/Direction';
|
||||
import { StyledUser, Title } from './styled';
|
||||
import UserDialog from './Dialog';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { IUser } from '../../types/users';
|
||||
import Modal from '../../components/Modal';
|
||||
import UserForm from './FormUser';
|
||||
|
||||
const User = () => {
|
||||
const dialogRef = useRef<HTMLDialogElement>(null);
|
||||
const [reload, setReload] = useState(true);
|
||||
const [user, setUser] = useState<Nullable<IUser>>(null);
|
||||
const [isAdd, setIsAdd] = useState(false);
|
||||
|
||||
const openFormDialog = (isAddForm: boolean = false) => {
|
||||
setIsAdd(isAddForm);
|
||||
dialogRef.current?.showModal();
|
||||
};
|
||||
|
||||
const closeFormDialog = () => {
|
||||
dialogRef.current?.close();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledUser>
|
||||
<Direction type="horizontal">
|
||||
<Title>List User</Title>
|
||||
<Button onClick={() => openFormDialog(true)}>Add user</Button>
|
||||
|
||||
<Modal>
|
||||
<Modal.Open modalName="user-form">
|
||||
<Button>Add user</Button>
|
||||
</Modal.Open>
|
||||
<Modal.Window name="user-form" title="Add form">
|
||||
<UserForm setReload={setReload} reload={reload} />
|
||||
</Modal.Window>
|
||||
</Modal>
|
||||
</Direction>
|
||||
|
||||
<UserTable
|
||||
reload={reload}
|
||||
setReload={setReload}
|
||||
openFormDialog={() => openFormDialog()}
|
||||
setUser={setUser}
|
||||
/>
|
||||
<UserTable reload={reload} setReload={setReload} />
|
||||
</StyledUser>
|
||||
|
||||
<UserDialog
|
||||
onClose={closeFormDialog}
|
||||
ref={dialogRef}
|
||||
setReload={setReload}
|
||||
reload={reload}
|
||||
user={user}
|
||||
isAdd={isAdd}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user