mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-22 20:01:59 +00:00
Fix bug and optimzed code
This commit is contained in:
@@ -12,7 +12,7 @@ import RoomForm from './Form';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { TRoom } from '../../types/rooms';
|
||||
import { IRoom } from '../../types/rooms';
|
||||
|
||||
// Hooks
|
||||
import { useForwardRef } from '../../hooks/useForwardRef';
|
||||
@@ -22,7 +22,7 @@ interface IRoomDialog {
|
||||
reload?: boolean;
|
||||
setReload?: Dispatch<SetStateAction<boolean>>;
|
||||
ref?: MutableRefObject<Nullable<HTMLDialogElement>>;
|
||||
room?: Nullable<TRoom>;
|
||||
room?: Nullable<IRoom>;
|
||||
isAdd?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,15 +11,12 @@ import Input from '../../commons/styles/Input.ts';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { TRoom } from '../../types/rooms.ts';
|
||||
import { IRoom } from '../../types/rooms';
|
||||
|
||||
// Constants
|
||||
import { ROOM_PATH } from '../../constants/path.ts';
|
||||
import { STATUS_CODE } from '../../constants/responseStatus.ts';
|
||||
import {
|
||||
ADD_SUCCESS,
|
||||
EDIT_SUCCESS,
|
||||
errorMsg,
|
||||
} from '../../constants/messages.ts';
|
||||
import {
|
||||
INVALID_DISCOUNT,
|
||||
@@ -28,7 +25,6 @@ import {
|
||||
} from '../../constants/formValidateMessage.ts';
|
||||
|
||||
// Helpers
|
||||
import { sendRequest } from '../../helpers/sendRequest.ts';
|
||||
import {
|
||||
isValidDiscount,
|
||||
isValidNumber,
|
||||
@@ -38,6 +34,8 @@ import {
|
||||
// Components
|
||||
import FormRow from '../../components/LabelControl/index.tsx';
|
||||
import Form from '../../components/Form/index.tsx';
|
||||
import { addRoom, updateRoom } from '../../services/roomServices.ts';
|
||||
import { INIT_VALUE_ROOM_FORM } from '../../constants/variables.ts';
|
||||
|
||||
const FormBtn = styled(Button)`
|
||||
width: 100%;
|
||||
@@ -53,7 +51,7 @@ interface IRoomFormProp {
|
||||
onClose: () => void;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
room?: Nullable<TRoom>;
|
||||
room?: Nullable<IRoom>;
|
||||
isAdd: boolean;
|
||||
}
|
||||
|
||||
@@ -64,7 +62,7 @@ const RoomForm = ({
|
||||
room,
|
||||
isAdd,
|
||||
}: IRoomFormProp) => {
|
||||
const formMethods = useForm<TRoom>();
|
||||
const formMethods = useForm<IRoom>();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
@@ -74,43 +72,32 @@ const RoomForm = ({
|
||||
} = formMethods;
|
||||
|
||||
useEffect(() => {
|
||||
if (room) {
|
||||
if (room && !isAdd) {
|
||||
reset(room);
|
||||
} else {
|
||||
reset(INIT_VALUE_ROOM_FORM);
|
||||
}
|
||||
}, [room, reset]);
|
||||
}, [room, reset, isAdd]);
|
||||
|
||||
// Submit form
|
||||
const onSubmit = async (room: TRoom) => {
|
||||
const onSubmit = async (room: IRoom) => {
|
||||
// Calculate final price
|
||||
room.finalPrice = room.price - (room.price * room.discount) / 100;
|
||||
|
||||
try {
|
||||
if (isAdd) {
|
||||
// Add request
|
||||
|
||||
const response = await sendRequest(
|
||||
ROOM_PATH,
|
||||
'POST',
|
||||
JSON.stringify(room)
|
||||
);
|
||||
|
||||
if (response.statusCode === STATUS_CODE.CREATE) {
|
||||
const response = await addRoom(room);
|
||||
|
||||
if(response) {
|
||||
toast.success(ADD_SUCCESS);
|
||||
} else {
|
||||
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||
}
|
||||
} else {
|
||||
// Edit request
|
||||
const response = await sendRequest(
|
||||
ROOM_PATH + `/${room!.id}`,
|
||||
'PUT',
|
||||
JSON.stringify(room)
|
||||
);
|
||||
const response = await updateRoom(room);
|
||||
|
||||
if (response.statusCode == STATUS_CODE.OK) {
|
||||
if (response) {
|
||||
toast.success(EDIT_SUCCESS);
|
||||
} else {
|
||||
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||
}
|
||||
}
|
||||
// Reload table data
|
||||
|
||||
@@ -16,7 +16,7 @@ import OrderBy from '../../components/OrderBy';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { TRoom } from '../../types/rooms';
|
||||
import { IRoom } from '../../types/rooms';
|
||||
|
||||
// Constants
|
||||
import { useFetch } from '../../hooks/useFetch';
|
||||
@@ -30,12 +30,12 @@ import Spinner from '../../commons/styles/Spinner';
|
||||
|
||||
// Helpers
|
||||
import { sendRequest } from '../../helpers/sendRequest';
|
||||
import { formatCurrency } from '../../helpers/utils';
|
||||
import { formatCurrency } from '../../helpers/helper';
|
||||
|
||||
interface IRoomRow {
|
||||
room: TRoom;
|
||||
room: IRoom;
|
||||
openFormDialog: () => void;
|
||||
setRoom: Dispatch<SetStateAction<Nullable<TRoom>>>;
|
||||
setRoom: Dispatch<SetStateAction<Nullable<IRoom>>>;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
@@ -47,12 +47,12 @@ const RoomRow = ({
|
||||
reload,
|
||||
setReload,
|
||||
}: IRoomRow) => {
|
||||
const handleEdit = (room: TRoom) => {
|
||||
const handleEdit = (room: IRoom) => {
|
||||
setRoom(room);
|
||||
openFormDialog();
|
||||
};
|
||||
|
||||
const handleDelete = async (room: TRoom) => {
|
||||
const handleDelete = async (room: IRoom) => {
|
||||
if (confirm(CONFIRM_DELETE)) {
|
||||
const response = await sendRequest(ROOM_PATH + `/${room.id}`, 'DELETE');
|
||||
|
||||
@@ -101,7 +101,7 @@ interface IRoomTable {
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
openFormDialog: () => void;
|
||||
setRoom?: Dispatch<SetStateAction<Nullable<TRoom>>>;
|
||||
setRoom?: Dispatch<SetStateAction<Nullable<IRoom>>>;
|
||||
}
|
||||
|
||||
const RoomTable = ({
|
||||
@@ -112,7 +112,7 @@ const RoomTable = ({
|
||||
}: IRoomTable) => {
|
||||
const [nameSearch, setNameSearch] = useState('');
|
||||
const [searchParams] = useSearchParams();
|
||||
const [rooms, setRooms] = useState<TRoom[]>([]);
|
||||
const [rooms, setRooms] = useState<IRoom[]>([]);
|
||||
const sortByValue = searchParams.get('sortBy')
|
||||
? searchParams.get('sortBy')!
|
||||
: '';
|
||||
@@ -165,9 +165,9 @@ const RoomTable = ({
|
||||
<div>Price</div>
|
||||
<div>Status</div>
|
||||
</Table.Header>
|
||||
<Table.Body<TRoom>
|
||||
<Table.Body<IRoom>
|
||||
data={rooms}
|
||||
render={(room: TRoom) => (
|
||||
render={(room: IRoom) => (
|
||||
<RoomRow
|
||||
room={room}
|
||||
key={room.id}
|
||||
|
||||
@@ -11,12 +11,12 @@ import RoomDialog from './Dialog';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { TRoom } from '../../types/rooms';
|
||||
import { IRoom } from '../../types/rooms';
|
||||
|
||||
const Room = () => {
|
||||
const dialogRef = useRef<HTMLDialogElement>(null);
|
||||
const [reload, setReload] = useState(true);
|
||||
const [room, setRoom] = useState<Nullable<TRoom>>(null);
|
||||
const [room, setRoom] = useState<Nullable<IRoom>>(null);
|
||||
const [isAdd, setIsAdd] = useState(false);
|
||||
|
||||
const openFormDialog = (isAddForm: boolean = false) => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import UserForm from './Form';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { TUser } from '../../types/user';
|
||||
import { IUser } from '../../types/users';
|
||||
|
||||
// Hooks
|
||||
import { useForwardRef } from '../../hooks/useForwardRef';
|
||||
@@ -22,7 +22,7 @@ interface IUserDialog {
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
ref: MutableRefObject<Nullable<HTMLDialogElement>>;
|
||||
user: Nullable<TUser>;
|
||||
user: Nullable<IUser>;
|
||||
isAdd: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import FormRow from '../../components/LabelControl/index.tsx';
|
||||
import Select, { ISelectOptions } from '../../components/Select';
|
||||
|
||||
// Helpers
|
||||
import { sendRequest } from '../../helpers/sendRequest.ts';
|
||||
import {
|
||||
isEmptyObj,
|
||||
isValidName,
|
||||
@@ -28,13 +27,7 @@ import {
|
||||
} from '../../helpers/validators.ts';
|
||||
|
||||
// Constants
|
||||
import { STATUS_CODE } from '../../constants/responseStatus.ts';
|
||||
import {
|
||||
ADD_SUCCESS,
|
||||
EDIT_SUCCESS,
|
||||
errorMsg,
|
||||
} from '../../constants/messages.ts';
|
||||
import { USER_PATH } from '../../constants/path.ts';
|
||||
import { ADD_SUCCESS, EDIT_SUCCESS } from '../../constants/messages.ts';
|
||||
import {
|
||||
INVALID_FIELD,
|
||||
INVALID_PHONE,
|
||||
@@ -49,15 +42,16 @@ import { FormBtn } from './styled.ts';
|
||||
import { getAllRoom, updateRoomStatus } from '../../services/roomServices.ts';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { TUser } from '../../types/user.ts';
|
||||
import { TRoom } from '../../types/rooms.ts';
|
||||
import { Nullable } from '../../types/common.ts';
|
||||
import { IUser } from '../../types/users.ts';
|
||||
import { IRoom } from '../../types/rooms.ts';
|
||||
import { createUser, updateUser } from '../../services/userServices.ts';
|
||||
|
||||
interface IUserFormProp {
|
||||
onClose: () => void;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
user: Nullable<TUser>;
|
||||
user: Nullable<IUser>;
|
||||
isAdd: boolean;
|
||||
}
|
||||
|
||||
@@ -68,7 +62,7 @@ const UserForm = ({
|
||||
user,
|
||||
isAdd,
|
||||
}: IUserFormProp) => {
|
||||
const formMethods = useForm<TUser>();
|
||||
const formMethods = useForm<IUser>();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
@@ -76,17 +70,25 @@ const UserForm = ({
|
||||
formState: { errors, isDirty, isValid },
|
||||
trigger,
|
||||
} = formMethods;
|
||||
const [rooms, setRooms] = useState<TRoom[]>([]);
|
||||
const [rooms, setRooms] = useState<IRoom[]>([]);
|
||||
const [options, setOptions] = useState<ISelectOptions[]>();
|
||||
|
||||
// Init value when edit form and load options
|
||||
useEffect(() => {
|
||||
const load = async () => {
|
||||
const options: ISelectOptions[] = [];
|
||||
const tempUser = isAdd ? {} : { ...user };
|
||||
const tempUser = isAdd
|
||||
? {}
|
||||
: { ...user };
|
||||
|
||||
// Load and set default options room
|
||||
if (rooms.length > 0) {
|
||||
// Init first options
|
||||
options.push({
|
||||
label: '---Select---',
|
||||
value: '0',
|
||||
});
|
||||
|
||||
rooms.forEach((item) => {
|
||||
if (!item.status || tempUser?.roomId === item.id)
|
||||
options.push({
|
||||
@@ -98,16 +100,10 @@ const UserForm = ({
|
||||
|
||||
if (options.length > 0) {
|
||||
setOptions(options);
|
||||
reset({ roomId: +options[0].value });
|
||||
}
|
||||
|
||||
if (!isEmptyObj(tempUser)) {
|
||||
// Init value
|
||||
// Set default value when user not have room yet.
|
||||
if (!tempUser.roomId) {
|
||||
tempUser.roomId = +options[0].value;
|
||||
}
|
||||
|
||||
reset(tempUser);
|
||||
} else {
|
||||
reset(INIT_VALUE_USER_FORM);
|
||||
@@ -119,36 +115,24 @@ const UserForm = ({
|
||||
|
||||
// Submit form
|
||||
const onSubmit = useCallback(
|
||||
async (newUser: TUser) => {
|
||||
async (newUser: IUser) => {
|
||||
try {
|
||||
if (isAdd) {
|
||||
// Add request
|
||||
const response = await sendRequest(
|
||||
USER_PATH,
|
||||
'POST',
|
||||
JSON.stringify(newUser)
|
||||
);
|
||||
const response = await createUser(newUser);
|
||||
|
||||
if (response.statusCode === STATUS_CODE.CREATE) {
|
||||
if (response) {
|
||||
toast.success(ADD_SUCCESS);
|
||||
} else {
|
||||
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||
}
|
||||
|
||||
// Update room status
|
||||
updateRoomStatus(newUser.roomId, true);
|
||||
} else {
|
||||
// Edit request
|
||||
const response = await sendRequest(
|
||||
USER_PATH + `/${newUser.id}`,
|
||||
'PUT',
|
||||
JSON.stringify(newUser)
|
||||
);
|
||||
const response = await updateUser(newUser);
|
||||
|
||||
if (response.statusCode == STATUS_CODE.OK) {
|
||||
if (response) {
|
||||
toast.success(EDIT_SUCCESS);
|
||||
} else {
|
||||
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||
}
|
||||
|
||||
// Update room status
|
||||
@@ -232,7 +216,7 @@ const UserForm = ({
|
||||
</FormRow>
|
||||
|
||||
<FormRow label="Room">
|
||||
{options && options.length > 0 ? (
|
||||
{options && options.length > 1 ? (
|
||||
<Select
|
||||
id="roomId"
|
||||
options={options!}
|
||||
@@ -240,6 +224,7 @@ const UserForm = ({
|
||||
optionsConfigForm={{
|
||||
valueAsNumber: true,
|
||||
onChange: () => trigger('roomId'),
|
||||
validate: (v) => v !== 0,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
@@ -249,7 +234,11 @@ const UserForm = ({
|
||||
|
||||
<Form.Action>
|
||||
<FormBtn type="submit" name="submit" disabled={!isDirty || !isValid}>
|
||||
{isAdd ? 'Add' : 'Save'}
|
||||
{
|
||||
isAdd
|
||||
? 'Add'
|
||||
: 'Save'
|
||||
}
|
||||
</FormBtn>
|
||||
<FormBtn type="button" styled="secondary" onClick={onClose}>
|
||||
Close
|
||||
|
||||
@@ -15,7 +15,7 @@ import OrderBy from '../../components/OrderBy';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { TUser } from '../../types/user';
|
||||
import { IUser } from '../../types/users';
|
||||
|
||||
// Hooks
|
||||
import { useFetch } from '../../hooks/useFetch';
|
||||
@@ -23,7 +23,7 @@ import { useFetch } from '../../hooks/useFetch';
|
||||
// Constants
|
||||
import { STATUS_CODE } from '../../constants/responseStatus';
|
||||
import { ORDERBY_OPTIONS, USER_PAGE } from '../../constants/variables';
|
||||
import { CONFIRM_MESSAGE } from '../../constants/messages';
|
||||
import { CONFIRM_MESSAGE, DENIED_ACTION } from '../../constants/messages';
|
||||
|
||||
// Styled
|
||||
import { StyledOperationTable } from './styled';
|
||||
@@ -34,9 +34,9 @@ import { updateRoomStatus } from '../../services/roomServices';
|
||||
import { checkOutUser } from '../../services/userServices';
|
||||
|
||||
interface IUserRow {
|
||||
user: TUser;
|
||||
user: IUser;
|
||||
openFormDialog: () => void;
|
||||
setUser: Dispatch<SetStateAction<Nullable<TUser>>>;
|
||||
setUser: Dispatch<SetStateAction<Nullable<IUser>>>;
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
@@ -48,26 +48,31 @@ const UserRow = ({
|
||||
reload,
|
||||
setReload,
|
||||
}: IUserRow) => {
|
||||
const handleEdit = (user: TUser) => {
|
||||
const handleEdit = (user: IUser) => {
|
||||
setUser(user);
|
||||
openFormDialog();
|
||||
};
|
||||
|
||||
const handleCheckOut = async (user: TUser) => {
|
||||
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);
|
||||
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;
|
||||
@@ -107,7 +112,7 @@ interface IUserTable {
|
||||
reload: boolean;
|
||||
setReload: Dispatch<SetStateAction<boolean>>;
|
||||
openFormDialog: () => void;
|
||||
setUser?: Dispatch<SetStateAction<Nullable<TUser>>>;
|
||||
setUser?: Dispatch<SetStateAction<Nullable<IUser>>>;
|
||||
}
|
||||
|
||||
const UserTable = ({
|
||||
@@ -116,7 +121,7 @@ const UserTable = ({
|
||||
openFormDialog,
|
||||
setUser,
|
||||
}: IUserTable) => {
|
||||
const [users, setUsers] = useState<TUser[]>([]);
|
||||
const [users, setUsers] = useState<IUser[]>([]);
|
||||
const [phoneSearch, setPhoneSearch] = useState('');
|
||||
const [searchParams] = useSearchParams();
|
||||
const sortByValue = searchParams.get('sortBy')
|
||||
@@ -172,9 +177,9 @@ const UserTable = ({
|
||||
<div>Phone</div>
|
||||
<div>Room Id</div>
|
||||
</Table.Header>
|
||||
<Table.Body<TUser>
|
||||
<Table.Body<IUser>
|
||||
data={users}
|
||||
render={(user: TUser) => (
|
||||
render={(user: IUser) => (
|
||||
<UserRow
|
||||
user={user}
|
||||
key={user.id}
|
||||
|
||||
@@ -11,12 +11,12 @@ import UserDialog from './Dialog';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { TUser } from '../../types/user';
|
||||
import { IUser } from '../../types/users';
|
||||
|
||||
const User = () => {
|
||||
const dialogRef = useRef<HTMLDialogElement>(null);
|
||||
const [reload, setReload] = useState(true);
|
||||
const [user, setUser] = useState<Nullable<TUser>>(null);
|
||||
const [user, setUser] = useState<Nullable<IUser>>(null);
|
||||
const [isAdd, setIsAdd] = useState(false);
|
||||
|
||||
const openFormDialog = (isAddForm: boolean = false) => {
|
||||
|
||||
Reference in New Issue
Block a user