mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-22 20:01:59 +00:00
Fix logic code relative user and room
This commit is contained in:
@@ -11,6 +11,7 @@ node_modules
|
|||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
|
.vscode
|
||||||
|
|
||||||
src/db.json
|
src/db.json
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ const StyledMenu = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledButton = styled.button`
|
const StyledButton = styled.button`
|
||||||
width: 100%;
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
font-size: var(--fs-sm-x);
|
font-size: var(--fs-sm-x);
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -60,6 +60,7 @@ const StyledList = styled.ul`
|
|||||||
|
|
||||||
right: -10px;
|
right: -10px;
|
||||||
top: 40px;
|
top: 40px;
|
||||||
|
width: max-content;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export { StyledMenu, StyledButton, StyledList, StyledToggle };
|
export { StyledMenu, StyledButton, StyledList, StyledToggle };
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ const RenderSelect = ({
|
|||||||
id={id}
|
id={id}
|
||||||
value={value}
|
value={value}
|
||||||
{...register(id!, optionsConfigForm)}
|
{...register(id!, optionsConfigForm)}
|
||||||
onChange={onChange}
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</StyledSelect>
|
</StyledSelect>
|
||||||
|
|||||||
@@ -4,13 +4,17 @@ const errorMsg = (errorCode: number, msg: string) => {
|
|||||||
|
|
||||||
const ADD_SUCCESS = 'Add success';
|
const ADD_SUCCESS = 'Add success';
|
||||||
const EDIT_SUCCESS = 'Edit success';
|
const EDIT_SUCCESS = 'Edit success';
|
||||||
const CONFIRM_DELETE = 'Are you sure to delete it?';
|
const CONFIRM_MESSAGE = 'Do you want to checkout this user?';
|
||||||
|
const CONFIRM_DELETE = 'Are you sure to delete it?'
|
||||||
const DELETE_SUCCESS = 'Delete success';
|
const DELETE_SUCCESS = 'Delete success';
|
||||||
|
const CHECKOUT_SUCCESS = 'Check out success';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
ADD_SUCCESS,
|
ADD_SUCCESS,
|
||||||
errorMsg,
|
errorMsg,
|
||||||
EDIT_SUCCESS,
|
EDIT_SUCCESS,
|
||||||
|
CONFIRM_MESSAGE,
|
||||||
CONFIRM_DELETE,
|
CONFIRM_DELETE,
|
||||||
DELETE_SUCCESS,
|
DELETE_SUCCESS,
|
||||||
|
CHECKOUT_SUCCESS,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ export const DASHBOARD = '/dashboard';
|
|||||||
export const USER = '/user';
|
export const USER = '/user';
|
||||||
export const ROOM = '/room';
|
export const ROOM = '/room';
|
||||||
export const OTHER_PATH = '*';
|
export const OTHER_PATH = '*';
|
||||||
export const BASE_URL = 'https://hotel-management-api.loiphan.com/';
|
export const BASE_URL = 'http://localhost:3000/';
|
||||||
export const USER_PATH = 'users';
|
export const USER_PATH = 'users';
|
||||||
export const ROOM_PATH = 'rooms';
|
export const ROOM_PATH = 'rooms';
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
const STATUS_CODE = {
|
||||||
|
OK: 200,
|
||||||
|
CREATE: 201,
|
||||||
|
NOT_FOUND: 404,
|
||||||
|
INTERNAL_SERVER_ERROR: 500,
|
||||||
|
};
|
||||||
|
|
||||||
|
const RESPONSE_MESSAGE = {
|
||||||
|
UPDATE_SUCCESS: 'Update success',
|
||||||
|
};
|
||||||
|
|
||||||
|
export { STATUS_CODE, RESPONSE_MESSAGE };
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
const STATUS_CODE = {
|
|
||||||
OK: 200,
|
|
||||||
CREATE: 201,
|
|
||||||
NOT_FOUND: 404,
|
|
||||||
};
|
|
||||||
|
|
||||||
export { STATUS_CODE };
|
|
||||||
@@ -34,18 +34,19 @@ const USER_PAGE = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ORDERBY_OPTIONS = [
|
||||||
|
{
|
||||||
|
value: 'asc',
|
||||||
|
label: 'Ascending',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'desc',
|
||||||
|
label: 'Descending',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const ROOM_PAGE = {
|
const ROOM_PAGE = {
|
||||||
ORDERBY_OPTIONS: [
|
|
||||||
{
|
|
||||||
value: 'asc',
|
|
||||||
label: 'Ascending',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'desc',
|
|
||||||
label: 'Descending',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
SORTBY_OPTIONS: [
|
SORTBY_OPTIONS: [
|
||||||
{
|
{
|
||||||
value: 'id',
|
value: 'id',
|
||||||
@@ -82,4 +83,20 @@ const INITIAL_STATE_SCHEMA = {
|
|||||||
const VALUE = 'value';
|
const VALUE = 'value';
|
||||||
const ERROR = 'error';
|
const ERROR = 'error';
|
||||||
|
|
||||||
export { USER_PAGE, ROOM_PAGE, VALUE, ERROR, INITIAL_STATE_SCHEMA };
|
const INIT_VALUE_USER_FORM = {
|
||||||
|
name: '',
|
||||||
|
id: 0,
|
||||||
|
identifiedCode: '',
|
||||||
|
address: '',
|
||||||
|
phone: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
USER_PAGE,
|
||||||
|
ROOM_PAGE,
|
||||||
|
VALUE,
|
||||||
|
ERROR,
|
||||||
|
INITIAL_STATE_SCHEMA,
|
||||||
|
ORDERBY_OPTIONS,
|
||||||
|
INIT_VALUE_USER_FORM
|
||||||
|
};
|
||||||
|
|||||||
@@ -42,9 +42,10 @@ type TValidator = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type TResponse = {
|
type TResponse<T> = {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
msg: string;
|
msg: string;
|
||||||
|
data?: T;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { BASE_URL } from '../constants/path';
|
|||||||
// Types
|
// Types
|
||||||
import { TResponse } from '../globals/types';
|
import { TResponse } from '../globals/types';
|
||||||
|
|
||||||
type TMethodRequest = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
type TMethodRequest = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The send request method to the server
|
* The send request method to the server
|
||||||
@@ -13,11 +13,11 @@ type TMethodRequest = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|||||||
* @param method HTTP method
|
* @param method HTTP method
|
||||||
* @returns The status code and message from server
|
* @returns The status code and message from server
|
||||||
*/
|
*/
|
||||||
export const sendRequest = async (
|
export const sendRequest = async <T,>(
|
||||||
path: string,
|
path: string,
|
||||||
body: BodyInit | null | undefined,
|
|
||||||
method: TMethodRequest = 'GET',
|
method: TMethodRequest = 'GET',
|
||||||
): Promise<TResponse> => {
|
body?: BodyInit,
|
||||||
|
): Promise<TResponse<T>> => {
|
||||||
const response = await fetch(BASE_URL + path, {
|
const response = await fetch(BASE_URL + path, {
|
||||||
method,
|
method,
|
||||||
body,
|
body,
|
||||||
@@ -28,8 +28,11 @@ export const sendRequest = async (
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const data = await response.json() as T;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
statusCode: response.status,
|
statusCode: response.status,
|
||||||
msg: response.statusText,
|
msg: response.statusText,
|
||||||
|
data
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -116,6 +116,8 @@ const searchQuery = (
|
|||||||
return query;
|
return query;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
isRequired,
|
isRequired,
|
||||||
getPropValues,
|
getPropValues,
|
||||||
|
|||||||
@@ -40,10 +40,15 @@ const isValidString = (value: string): boolean => {
|
|||||||
*/
|
*/
|
||||||
const skipCheck = () => true;
|
const skipCheck = () => true;
|
||||||
|
|
||||||
|
const isEmptyObj = (obj: object) => {
|
||||||
|
return Object.keys(obj).length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
isValidNumber,
|
isValidNumber,
|
||||||
isValidPhoneNumber,
|
isValidPhoneNumber,
|
||||||
isValidString,
|
isValidString,
|
||||||
skipCheck,
|
skipCheck,
|
||||||
isValidDiscount,
|
isValidDiscount,
|
||||||
|
isEmptyObj
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Button from '../../commons/styles/Button.ts';
|
|||||||
import { TRoom } from '../../globals/types.ts';
|
import { TRoom } from '../../globals/types.ts';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { ROOM_PATH } from '../../constants/path.ts';
|
import { ROOM_PATH } from '../../constants/path.ts';
|
||||||
import { STATUS_CODE } from '../../constants/statusCode.ts';
|
import { STATUS_CODE } from '../../constants/responseStatus.ts';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { ADD_SUCCESS, EDIT_SUCCESS, errorMsg } from '../../constants/messages.ts';
|
import { ADD_SUCCESS, EDIT_SUCCESS, errorMsg } from '../../constants/messages.ts';
|
||||||
import { sendRequest } from '../../helpers/sendRequest.ts';
|
import { sendRequest } from '../../helpers/sendRequest.ts';
|
||||||
@@ -63,8 +63,8 @@ const RoomForm = ({
|
|||||||
// Add request
|
// Add request
|
||||||
const response = await sendRequest(
|
const response = await sendRequest(
|
||||||
ROOM_PATH,
|
ROOM_PATH,
|
||||||
|
'POST',
|
||||||
JSON.stringify(room),
|
JSON.stringify(room),
|
||||||
'POST'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode === STATUS_CODE.CREATE) {
|
if (response.statusCode === STATUS_CODE.CREATE) {
|
||||||
@@ -76,8 +76,8 @@ const RoomForm = ({
|
|||||||
// Edit request
|
// Edit request
|
||||||
const response = await sendRequest(
|
const response = await sendRequest(
|
||||||
ROOM_PATH + `/${room!.id}`,
|
ROOM_PATH + `/${room!.id}`,
|
||||||
|
'PUT',
|
||||||
JSON.stringify(room),
|
JSON.stringify(room),
|
||||||
'PUT'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == STATUS_CODE.OK) {
|
if (response.statusCode == STATUS_CODE.OK) {
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import { TRoom } from '../../globals/types';
|
|||||||
// Constants
|
// Constants
|
||||||
import { useFetch } from '../../hooks/useFetch';
|
import { useFetch } from '../../hooks/useFetch';
|
||||||
import { ROOM_PATH } from '../../constants/path';
|
import { ROOM_PATH } from '../../constants/path';
|
||||||
import { STATUS_CODE } from '../../constants/statusCode';
|
import { STATUS_CODE } from '../../constants/responseStatus';
|
||||||
import { CONFIRM_DELETE, DELETE_SUCCESS } from '../../constants/messages';
|
import { CONFIRM_DELETE, DELETE_SUCCESS } from '../../constants/messages';
|
||||||
import { ROOM_PAGE } from '../../constants/variables';
|
import { ORDERBY_OPTIONS, ROOM_PAGE } from '../../constants/variables';
|
||||||
|
|
||||||
// Styled
|
// Styled
|
||||||
import Spinner from '../../commons/styles/Spinner';
|
import Spinner from '../../commons/styles/Spinner';
|
||||||
@@ -54,8 +54,7 @@ const RoomRow = ({
|
|||||||
if (confirm(CONFIRM_DELETE)) {
|
if (confirm(CONFIRM_DELETE)) {
|
||||||
const response = await sendRequest(
|
const response = await sendRequest(
|
||||||
ROOM_PATH + `/${room.id}`,
|
ROOM_PATH + `/${room.id}`,
|
||||||
null,
|
'DELETE'
|
||||||
'DELETE',
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode === STATUS_CODE.OK) {
|
if (response.statusCode === STATUS_CODE.OK) {
|
||||||
@@ -148,7 +147,7 @@ const RoomTable = ({
|
|||||||
<>
|
<>
|
||||||
<Direction>
|
<Direction>
|
||||||
<StyledOperationTable>
|
<StyledOperationTable>
|
||||||
<OrderBy options={ROOM_PAGE.ORDERBY_OPTIONS} />
|
<OrderBy options={ORDERBY_OPTIONS} />
|
||||||
|
|
||||||
<SortBy options={ROOM_PAGE.SORTBY_OPTIONS} />
|
<SortBy options={ROOM_PAGE.SORTBY_OPTIONS} />
|
||||||
<Search
|
<Search
|
||||||
|
|||||||
@@ -10,19 +10,17 @@ import TextArea from '../../commons/styles/TextArea';
|
|||||||
import Form from '../../components/Form';
|
import Form from '../../components/Form';
|
||||||
import FormRow from '../../components/LabelControl/index.tsx';
|
import FormRow from '../../components/LabelControl/index.tsx';
|
||||||
|
|
||||||
// Types
|
|
||||||
import { TKeyValue, TUser } from '../../globals/types';
|
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { sendRequest } from '../../helpers/sendRequest.ts';
|
import { sendRequest } from '../../helpers/sendRequest.ts';
|
||||||
import {
|
import {
|
||||||
|
isEmptyObj,
|
||||||
isValidNumber,
|
isValidNumber,
|
||||||
isValidPhoneNumber,
|
isValidPhoneNumber,
|
||||||
isValidString,
|
isValidString,
|
||||||
} from '../../helpers/validators.ts';
|
} from '../../helpers/validators.ts';
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import { STATUS_CODE } from '../../constants/statusCode.ts';
|
import { STATUS_CODE } from '../../constants/responseStatus.ts';
|
||||||
import {
|
import {
|
||||||
ADD_SUCCESS,
|
ADD_SUCCESS,
|
||||||
EDIT_SUCCESS,
|
EDIT_SUCCESS,
|
||||||
@@ -32,11 +30,17 @@ import { USER_PATH } from '../../constants/path.ts';
|
|||||||
import Select, { ISelectOptions } from '../../components/Select';
|
import Select, { ISelectOptions } from '../../components/Select';
|
||||||
|
|
||||||
// Hooks
|
// Hooks
|
||||||
import { useFetch } from '../../hooks/useFetch.ts';
|
|
||||||
|
|
||||||
// Styled
|
// Styled
|
||||||
import { FormBtn } from './styled.ts';
|
import { FormBtn } from './styled.ts';
|
||||||
import { INVALID_FIELD, INVALID_PHONE, REQUIRED_FIELD_ERROR } from '../../constants/formValidateMessage.ts';
|
import {
|
||||||
|
INVALID_FIELD,
|
||||||
|
INVALID_PHONE,
|
||||||
|
REQUIRED_FIELD_ERROR,
|
||||||
|
} from '../../constants/formValidateMessage.ts';
|
||||||
|
import { getAllRoom, updateRoomStatus } from '../../services/roomServices.ts';
|
||||||
|
import { TUser } from '../../globals/types.ts';
|
||||||
|
import { INIT_VALUE_USER_FORM } from '../../constants/variables.ts';
|
||||||
|
|
||||||
interface IUserFormProp {
|
interface IUserFormProp {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -53,11 +57,7 @@ const UserForm = ({
|
|||||||
user,
|
user,
|
||||||
isAdd,
|
isAdd,
|
||||||
}: IUserFormProp) => {
|
}: IUserFormProp) => {
|
||||||
const formMethods = useForm<TUser>({
|
const formMethods = useForm<TUser>();
|
||||||
defaultValues: {
|
|
||||||
roomId: 1,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@@ -66,42 +66,55 @@ const UserForm = ({
|
|||||||
trigger,
|
trigger,
|
||||||
} = formMethods;
|
} = formMethods;
|
||||||
const [options, setOptions] = useState<ISelectOptions[]>();
|
const [options, setOptions] = useState<ISelectOptions[]>();
|
||||||
const { data, errorFetchMsg } = useFetch('rooms');
|
|
||||||
|
|
||||||
|
// Init value when edit form and load options
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user) {
|
const load = async () => {
|
||||||
reset(user);
|
const rooms = await getAllRoom();
|
||||||
}
|
const options: ISelectOptions[] = [];
|
||||||
}, [reset, user]);
|
const tempUser = isAdd
|
||||||
|
? {}
|
||||||
|
: {...user};
|
||||||
|
|
||||||
useEffect(() => {
|
// Load and set default options room
|
||||||
if (data) {
|
if (rooms) {
|
||||||
const tempData = data as TKeyValue[];
|
rooms.forEach((item) => {
|
||||||
const tempOptions: ISelectOptions[] = [];
|
if (!item.status || tempUser?.roomId === item.id)
|
||||||
tempData.forEach((item) => {
|
options.push({
|
||||||
tempOptions.push({
|
label: item.name! as string,
|
||||||
label: item.name! as string,
|
value: item.id!.toString(),
|
||||||
value: item.id! as string,
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
setOptions(tempOptions);
|
setOptions(options);
|
||||||
}
|
reset({ roomId: +options[0].value });
|
||||||
|
}
|
||||||
|
|
||||||
if (errorFetchMsg) {
|
if (!isEmptyObj(tempUser)) {
|
||||||
toast.error(errorFetchMsg);
|
// Init value
|
||||||
}
|
// Set default value when user not have room yet.
|
||||||
}, [data, errorFetchMsg]);
|
if (!tempUser.roomId) {
|
||||||
|
tempUser.roomId = +options[0].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(tempUser);
|
||||||
|
} else {
|
||||||
|
reset(INIT_VALUE_USER_FORM);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
load();
|
||||||
|
}, [reset, user, isAdd]);
|
||||||
|
|
||||||
// Submit form
|
// Submit form
|
||||||
const onSubmit = async (user: TUser) => {
|
const onSubmit = async (newUser: TUser) => {
|
||||||
try {
|
try {
|
||||||
if (isAdd) {
|
if (isAdd) {
|
||||||
// Add request
|
// Add request
|
||||||
const response = await sendRequest(
|
const response = await sendRequest(
|
||||||
USER_PATH,
|
USER_PATH,
|
||||||
JSON.stringify(user),
|
'POST',
|
||||||
'POST'
|
JSON.stringify(newUser)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode === STATUS_CODE.CREATE) {
|
if (response.statusCode === STATUS_CODE.CREATE) {
|
||||||
@@ -110,14 +123,14 @@ const UserForm = ({
|
|||||||
throw new Error(errorMsg(response.statusCode, response.msg));
|
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Update status when user create
|
// Update room status
|
||||||
|
updateRoomStatus(newUser.roomId, true);
|
||||||
} else {
|
} else {
|
||||||
// Edit request
|
// Edit request
|
||||||
const response = await sendRequest(
|
const response = await sendRequest(
|
||||||
USER_PATH + `/${user!.id}`,
|
USER_PATH + `/${newUser.id}`,
|
||||||
JSON.stringify(user),
|
'PUT',
|
||||||
'PUT'
|
JSON.stringify(newUser)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == STATUS_CODE.OK) {
|
if (response.statusCode == STATUS_CODE.OK) {
|
||||||
@@ -125,6 +138,9 @@ const UserForm = ({
|
|||||||
} else {
|
} else {
|
||||||
throw new Error(errorMsg(response.statusCode, response.msg));
|
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update room status
|
||||||
|
updateRoomStatus(user!.roomId, true, newUser.roomId);
|
||||||
}
|
}
|
||||||
// Reload table data
|
// Reload table data
|
||||||
setReload(!reload);
|
setReload(!reload);
|
||||||
@@ -167,8 +183,7 @@ const UserForm = ({
|
|||||||
{...register('identifiedCode', {
|
{...register('identifiedCode', {
|
||||||
required: REQUIRED_FIELD_ERROR,
|
required: REQUIRED_FIELD_ERROR,
|
||||||
validate: {
|
validate: {
|
||||||
checkIdentifiedCode: (v) =>
|
checkIdentifiedCode: (v) => isValidNumber(v) || INVALID_FIELD,
|
||||||
isValidNumber(v) || INVALID_FIELD,
|
|
||||||
},
|
},
|
||||||
onChange: () => trigger('identifiedCode'),
|
onChange: () => trigger('identifiedCode'),
|
||||||
})}
|
})}
|
||||||
@@ -182,8 +197,7 @@ const UserForm = ({
|
|||||||
{...register('phone', {
|
{...register('phone', {
|
||||||
required: REQUIRED_FIELD_ERROR,
|
required: REQUIRED_FIELD_ERROR,
|
||||||
validate: {
|
validate: {
|
||||||
checkPhoneNum: (v) =>
|
checkPhoneNum: (v) => isValidPhoneNumber(v) || INVALID_PHONE,
|
||||||
isValidPhoneNumber(v) || INVALID_PHONE,
|
|
||||||
},
|
},
|
||||||
onChange: () => trigger('phone'),
|
onChange: () => trigger('phone'),
|
||||||
})}
|
})}
|
||||||
@@ -191,7 +205,15 @@ const UserForm = ({
|
|||||||
</FormRow>
|
</FormRow>
|
||||||
|
|
||||||
<FormRow label="Room">
|
<FormRow label="Room">
|
||||||
<Select id="roomId" options={options!} ariaLabel='RoomId'/>
|
<Select
|
||||||
|
id="roomId"
|
||||||
|
options={options!}
|
||||||
|
ariaLabel="RoomId"
|
||||||
|
optionsConfigForm={{
|
||||||
|
valueAsNumber: true,
|
||||||
|
onChange: () => trigger('roomId'),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
|
|
||||||
<FormRow label="Address" error={errors.address?.message}>
|
<FormRow label="Address" error={errors.address?.message}>
|
||||||
@@ -201,8 +223,7 @@ const UserForm = ({
|
|||||||
{...register('address', {
|
{...register('address', {
|
||||||
required: REQUIRED_FIELD_ERROR,
|
required: REQUIRED_FIELD_ERROR,
|
||||||
validate: {
|
validate: {
|
||||||
checkValidString: (v) =>
|
checkValidString: (v) => isValidString(v) || INVALID_FIELD,
|
||||||
isValidString(v) || INVALID_FIELD,
|
|
||||||
},
|
},
|
||||||
onChange: () => trigger('address'),
|
onChange: () => trigger('address'),
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { useEffect, useState } from 'react';
|
|||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { HiSquare2Stack } from 'react-icons/hi2';
|
import { RiEditBoxFill } from 'react-icons/ri';
|
||||||
import { HiTrash } from 'react-icons/hi';
|
import { IoExit } from 'react-icons/io5';
|
||||||
import { StyledOperationTable } from './styled';
|
import { StyledOperationTable } from './styled';
|
||||||
import Menus from '../../components/Menus';
|
import Menus from '../../components/Menus';
|
||||||
import Table from '../../components/Table';
|
import Table from '../../components/Table';
|
||||||
@@ -19,16 +19,16 @@ import { TUser } from '../../globals/types';
|
|||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import { useFetch } from '../../hooks/useFetch';
|
import { useFetch } from '../../hooks/useFetch';
|
||||||
import { USER_PATH } from '../../constants/path';
|
import { STATUS_CODE } from '../../constants/responseStatus';
|
||||||
import { STATUS_CODE } from '../../constants/statusCode';
|
import { ORDERBY_OPTIONS, USER_PAGE } from '../../constants/variables';
|
||||||
import { CONFIRM_DELETE, DELETE_SUCCESS } from '../../constants/messages';
|
|
||||||
import { USER_PAGE } from '../../constants/variables';
|
|
||||||
|
|
||||||
// Styled
|
// Styled
|
||||||
import Spinner from '../../commons/styles/Spinner';
|
import Spinner from '../../commons/styles/Spinner';
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { sendRequest } from '../../helpers/sendRequest';
|
import { updateRoomStatus } from '../../services/roomServices';
|
||||||
|
import { checkOutUser } from '../../services/userServices';
|
||||||
|
import { CONFIRM_MESSAGE } from '../../constants/messages';
|
||||||
|
|
||||||
interface IUserRow {
|
interface IUserRow {
|
||||||
user: TUser;
|
user: TUser;
|
||||||
@@ -50,16 +50,16 @@ const UserRow = ({
|
|||||||
openFormDialog();
|
openFormDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOnDelete = async (user: TUser) => {
|
const handleOnCheckOut = async (user: TUser) => {
|
||||||
if (confirm(CONFIRM_DELETE)) {
|
if (confirm(CONFIRM_MESSAGE)) {
|
||||||
const response = await sendRequest(
|
const resUpdateStatus = await updateRoomStatus(user.roomId, false);
|
||||||
USER_PATH + `/${user.id}`,
|
const resCheckoutUser = await checkOutUser(user);
|
||||||
null,
|
|
||||||
'DELETE',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.statusCode === STATUS_CODE.OK) {
|
if (
|
||||||
toast.success(DELETE_SUCCESS);
|
resCheckoutUser?.statusCode === STATUS_CODE.OK &&
|
||||||
|
resUpdateStatus?.statusCode === STATUS_CODE.OK
|
||||||
|
) {
|
||||||
|
toast.success('Check out complete!');
|
||||||
|
|
||||||
// Reload table
|
// Reload table
|
||||||
setReload(!reload);
|
setReload(!reload);
|
||||||
@@ -75,20 +75,27 @@ const UserRow = ({
|
|||||||
<div>{name}</div>
|
<div>{name}</div>
|
||||||
<div>{identifiedCode}</div>
|
<div>{identifiedCode}</div>
|
||||||
<div>{phone}</div>
|
<div>{phone}</div>
|
||||||
<div>{roomId}</div>
|
<div>{
|
||||||
|
roomId
|
||||||
|
? roomId
|
||||||
|
: 'None'
|
||||||
|
}</div>
|
||||||
|
|
||||||
<Menus.Menu>
|
<Menus.Menu>
|
||||||
<Menus.Toggle id={id.toString()} />
|
<Menus.Toggle id={id.toString()} />
|
||||||
|
|
||||||
<Menus.List id={id.toString()}>
|
<Menus.List id={id.toString()}>
|
||||||
<Menus.Button
|
<Menus.Button
|
||||||
icon={<HiSquare2Stack />}
|
icon={<RiEditBoxFill />}
|
||||||
onClick={() => handleOnEdit(user)}
|
onClick={() => handleOnEdit(user)}
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Menus.Button>
|
</Menus.Button>
|
||||||
<Menus.Button icon={<HiTrash />} onClick={() => handleOnDelete(user)}>
|
<Menus.Button
|
||||||
Delete
|
icon={<IoExit />}
|
||||||
|
onClick={() => handleOnCheckOut(user)}
|
||||||
|
>
|
||||||
|
Check out
|
||||||
</Menus.Button>
|
</Menus.Button>
|
||||||
</Menus.List>
|
</Menus.List>
|
||||||
</Menus.Menu>
|
</Menus.Menu>
|
||||||
@@ -125,7 +132,7 @@ const UserTable = ({
|
|||||||
phoneSearch,
|
phoneSearch,
|
||||||
sortByValue,
|
sortByValue,
|
||||||
orderByValue,
|
orderByValue,
|
||||||
reload,
|
reload
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -140,11 +147,12 @@ const UserTable = ({
|
|||||||
}
|
}
|
||||||
}, [data, errorFetchMsg]);
|
}, [data, errorFetchMsg]);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Direction>
|
<Direction>
|
||||||
<StyledOperationTable>
|
<StyledOperationTable>
|
||||||
<OrderBy options={USER_PAGE.ORDERBY_OPTIONS} />
|
<OrderBy options={ORDERBY_OPTIONS} />
|
||||||
|
|
||||||
<SortBy options={USER_PAGE.SORTBY_OPTIONS} />
|
<SortBy options={USER_PAGE.SORTBY_OPTIONS} />
|
||||||
<Search
|
<Search
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import { TResponse, TRoom } from '../globals/types';
|
||||||
|
import { sendRequest } from '../helpers/sendRequest';
|
||||||
|
import { STATUS_CODE, RESPONSE_MESSAGE } from '../constants/responseStatus';
|
||||||
|
import { errorMsg } from '../constants/messages';
|
||||||
|
import { ROOM_PATH } from '../constants/path';
|
||||||
|
|
||||||
|
const getAllRoom = async (): Promise<TRoom[] | null> => {
|
||||||
|
try {
|
||||||
|
const response = await sendRequest<TRoom[]>(ROOM_PATH);
|
||||||
|
|
||||||
|
if (response.statusCode === STATUS_CODE.OK) {
|
||||||
|
const rooms = response.data!;
|
||||||
|
|
||||||
|
return rooms;
|
||||||
|
} else {
|
||||||
|
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
toast.error(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRoom = async (roomId: number): Promise<TRoom | null> => {
|
||||||
|
try {
|
||||||
|
const response = await sendRequest<TRoom>(ROOM_PATH + '/' + roomId);
|
||||||
|
|
||||||
|
if (response.statusCode === STATUS_CODE.OK) {
|
||||||
|
const rooms = response.data!;
|
||||||
|
|
||||||
|
return rooms;
|
||||||
|
} else {
|
||||||
|
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
toast.error(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateRoom = async (room: TRoom): Promise<TResponse<TRoom> | null> => {
|
||||||
|
try {
|
||||||
|
const response = await sendRequest<TRoom>(
|
||||||
|
ROOM_PATH + '/' + room.id,
|
||||||
|
'PUT',
|
||||||
|
JSON.stringify(room)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode !== STATUS_CODE.OK) {
|
||||||
|
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
toast.error(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateRoomStatus = async (
|
||||||
|
roomId: number,
|
||||||
|
status: boolean,
|
||||||
|
roomIdNew?: number
|
||||||
|
): Promise<TResponse<TRoom> | null> => {
|
||||||
|
if (!roomIdNew) {
|
||||||
|
const response = await sendRequest<TRoom>(
|
||||||
|
ROOM_PATH + '/' + roomId,
|
||||||
|
'PATCH',
|
||||||
|
JSON.stringify({ status: status })
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
// Update new room status
|
||||||
|
const resNewRoom = await sendRequest<TRoom>(
|
||||||
|
ROOM_PATH + '/' + roomIdNew,
|
||||||
|
'PATCH',
|
||||||
|
JSON.stringify({ status: status })
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update old room status;
|
||||||
|
const resOldRoom = await sendRequest<TRoom>(
|
||||||
|
ROOM_PATH + '/' + roomId,
|
||||||
|
'PATCH',
|
||||||
|
JSON.stringify({ status: !status })
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
resNewRoom.statusCode === STATUS_CODE.OK &&
|
||||||
|
resOldRoom.statusCode === STATUS_CODE.OK
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
statusCode: STATUS_CODE.OK,
|
||||||
|
msg: RESPONSE_MESSAGE.UPDATE_SUCCESS,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusCode: STATUS_CODE.INTERNAL_SERVER_ERROR,
|
||||||
|
msg: 'Something went wrong!',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (rooms?.length) {
|
||||||
|
// const oldRoom = rooms.find((room) => room.id === roomId);
|
||||||
|
// const newRoom = rooms.find((room) => room.id === roomIdNew);
|
||||||
|
|
||||||
|
// if(newRoom) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
// oldRoom!.status = status;
|
||||||
|
// const response = await updateRoom(oldRoom!);
|
||||||
|
|
||||||
|
// return response;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getRoom, updateRoom, updateRoomStatus, getAllRoom };
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import { errorMsg } from '../constants/messages';
|
||||||
|
import { USER_PATH } from '../constants/path';
|
||||||
|
import { STATUS_CODE } from '../constants/responseStatus';
|
||||||
|
import { TResponse, TUser } from '../globals/types';
|
||||||
|
import { sendRequest } from '../helpers/sendRequest';
|
||||||
|
|
||||||
|
const updateUser = async (user: TUser): Promise<TResponse<TUser> | null> => {
|
||||||
|
try {
|
||||||
|
const response = await sendRequest<TUser>(
|
||||||
|
USER_PATH + '/' + user.id,
|
||||||
|
'PUT',
|
||||||
|
JSON.stringify(user)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response.statusCode !== STATUS_CODE.OK) {
|
||||||
|
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
toast.error(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkOutUser = async (user: TUser): Promise<TResponse<TUser> | null> => {
|
||||||
|
const tempUser = user;
|
||||||
|
|
||||||
|
if (tempUser) {
|
||||||
|
tempUser.roomId = 0;
|
||||||
|
const resUpdateUser = await updateUser(tempUser);
|
||||||
|
|
||||||
|
return resUpdateUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { updateUser, checkOutUser };
|
||||||
Reference in New Issue
Block a user