mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-22 20:01:59 +00:00
Update hooks and add content for room page
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledRoom = styled.main`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
const Room = () => {
|
||||
return (
|
||||
<StyledRoom>
|
||||
<p>Room page</p>
|
||||
</StyledRoom>
|
||||
);
|
||||
};
|
||||
|
||||
export default Room;
|
||||
@@ -0,0 +1,55 @@
|
||||
import { forwardRef, useEffect } from 'react';
|
||||
|
||||
// Components
|
||||
import Dialog from '../../components/Dialog';
|
||||
import RoomForm from './Form';
|
||||
|
||||
// Interfaces
|
||||
import { IDialogProps } from '../../globals/interfaces';
|
||||
|
||||
// Types
|
||||
import { TRoom } from '../../globals/types';
|
||||
|
||||
const RoomDialog = forwardRef((props, ref) => {
|
||||
const dialogRef = ref as React.MutableRefObject<
|
||||
HTMLDialogElement | undefined
|
||||
>;
|
||||
// prettier-ignore
|
||||
const {
|
||||
onClose,
|
||||
setReload,
|
||||
reload,
|
||||
data,
|
||||
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={data}
|
||||
isAdd={isAdd!}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
}) as React.FC<IDialogProps<TRoom>>;
|
||||
|
||||
export default RoomDialog;
|
||||
@@ -0,0 +1,334 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
// Styled
|
||||
import Input from '../../commons/styles/Input.ts';
|
||||
import TextArea from '../../commons/styles/TextArea.ts';
|
||||
|
||||
// Components
|
||||
import Form from '../../components/Form/index.tsx';
|
||||
import FormRow from '../../components/FormRow/index.tsx';
|
||||
import Button from '../../commons/styles/Button.ts';
|
||||
|
||||
// Types
|
||||
import {
|
||||
TKeyValue,
|
||||
TRoom,
|
||||
TStateSchema,
|
||||
TValidator,
|
||||
} from '../../globals/types.ts';
|
||||
|
||||
// Hooks
|
||||
import useForm from '../../hooks/useForm.ts';
|
||||
|
||||
// Utils
|
||||
import {
|
||||
isValidNumber,
|
||||
isValidString,
|
||||
skipCheck,
|
||||
} from '../../helpers/validators.ts';
|
||||
import { addValidator, getValueFromObj } from '../../helpers/utils.ts';
|
||||
import { sendRequest } from '../../helpers/sendRequest.ts';
|
||||
|
||||
// Constants
|
||||
import { STATUS_CODE } from '../../constants/statusCode.ts';
|
||||
import {
|
||||
ADD_SUCCESS,
|
||||
EDIT_SUCCESS,
|
||||
errorMsg,
|
||||
} from '../../constants/messages.ts';
|
||||
import { ROOM_PATH } from '../../constants/path.ts';
|
||||
|
||||
const FormBtn = styled(Button)`
|
||||
width: 100%;
|
||||
|
||||
&:disabled,
|
||||
&[disabled] {
|
||||
background-color: var(--disabled-btn-color);
|
||||
}
|
||||
`;
|
||||
|
||||
interface IRoomFormProp {
|
||||
onClose: () => void;
|
||||
reload: boolean;
|
||||
setReload: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
room?: TRoom | null;
|
||||
isAdd: boolean;
|
||||
}
|
||||
|
||||
const RoomForm = ({
|
||||
onClose,
|
||||
reload,
|
||||
setReload,
|
||||
room,
|
||||
isAdd,
|
||||
}: IRoomFormProp) => {
|
||||
const [reset, setReset] = useState(true);
|
||||
|
||||
if (isAdd) {
|
||||
// If this is add form, reset value
|
||||
room = null;
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
const initialValue: string = isAdd
|
||||
? ''
|
||||
: room!
|
||||
&& room.id;
|
||||
|
||||
const {
|
||||
idValue,
|
||||
nameValue,
|
||||
amountValue,
|
||||
priceValue,
|
||||
discountValue,
|
||||
statusValue,
|
||||
descriptionValue,
|
||||
} = getValueFromObj<TRoom>(room);
|
||||
|
||||
// Define your state schema
|
||||
const stateSchema: TStateSchema = {
|
||||
id: { value: idValue || '' },
|
||||
name: { value: nameValue || '', error: '' },
|
||||
amount: { value: amountValue || '', error: '' },
|
||||
price: { value: priceValue || '', error: '' },
|
||||
discount: { value: discountValue || '', error: '' },
|
||||
status: { value: statusValue || '', error: '' },
|
||||
description: { value: descriptionValue || '', error: '' },
|
||||
};
|
||||
|
||||
// prettier-ignore
|
||||
const stateValidatorSchema: TValidator = {
|
||||
name: addValidator({
|
||||
validatorFunc: isValidString,
|
||||
prop: 'name'
|
||||
}),
|
||||
amount: addValidator({
|
||||
validatorFunc: isValidNumber,
|
||||
prop: 'amount',
|
||||
}),
|
||||
price: addValidator({
|
||||
validatorFunc: isValidNumber,
|
||||
prop: 'price',
|
||||
}),
|
||||
discount: addValidator({
|
||||
validatorFunc: isValidNumber,
|
||||
prop: 'discount'
|
||||
}),
|
||||
status: addValidator({
|
||||
validatorFunc: skipCheck,
|
||||
prop: 'status',
|
||||
required: false,
|
||||
}),
|
||||
description: addValidator({
|
||||
validatorFunc: isValidString,
|
||||
prop: 'description'
|
||||
}),
|
||||
};
|
||||
|
||||
// Submit form
|
||||
const onSubmitForm = async (state: TKeyValue) => {
|
||||
try {
|
||||
if (isAdd) {
|
||||
// Add request
|
||||
const response = await sendRequest(
|
||||
ROOM_PATH,
|
||||
JSON.stringify(state),
|
||||
'POST',
|
||||
);
|
||||
|
||||
if (response.statusCode === STATUS_CODE.CREATE) {
|
||||
toast.success(ADD_SUCCESS);
|
||||
|
||||
onResetForm();
|
||||
} else {
|
||||
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||
}
|
||||
} else {
|
||||
// Edit request
|
||||
const response = await sendRequest(
|
||||
ROOM_PATH + `/${room!.id}`,
|
||||
JSON.stringify(state),
|
||||
'PUT',
|
||||
);
|
||||
|
||||
if (response.statusCode == STATUS_CODE.OK) {
|
||||
toast.success(EDIT_SUCCESS);
|
||||
} else {
|
||||
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||
}
|
||||
}
|
||||
// Reload table data
|
||||
setReload(!reload);
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
toast.error(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
onClose();
|
||||
};
|
||||
|
||||
// Close and reset form
|
||||
const closeAndReset = () => {
|
||||
onClose();
|
||||
onResetForm();
|
||||
};
|
||||
|
||||
console.log(initialValue);
|
||||
|
||||
// prettier-ignore
|
||||
const {
|
||||
values,
|
||||
errors,
|
||||
dirty,
|
||||
handleOnChange,
|
||||
handleOnSubmit,
|
||||
disable } =
|
||||
useForm(
|
||||
stateSchema,
|
||||
stateValidatorSchema,
|
||||
onSubmitForm,
|
||||
initialValue
|
||||
);
|
||||
|
||||
// prettier-ignore
|
||||
const {
|
||||
id,
|
||||
name,
|
||||
amount,
|
||||
price,
|
||||
discount,
|
||||
status,
|
||||
description
|
||||
} = values;
|
||||
|
||||
// Clear form value when this is a add form
|
||||
useEffect(() => {
|
||||
if (isAdd) {
|
||||
Object.keys(values).forEach((key) => (values[key] = ''));
|
||||
}
|
||||
}, [isAdd]); // eslint-disable-line
|
||||
|
||||
// Reset form
|
||||
const onResetForm = () => {
|
||||
setReset(!reset);
|
||||
Object.keys(values).forEach((key) => (values[key] = ''));
|
||||
};
|
||||
|
||||
return (
|
||||
<Form onSubmit={handleOnSubmit}>
|
||||
<Input type="hidden" name="id" value={id as string} />
|
||||
<FormRow
|
||||
label="Name"
|
||||
error={
|
||||
// prettier-ignore
|
||||
errors.name && dirty.name
|
||||
? (errors.name as string)
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
name="name"
|
||||
value={name as string}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</FormRow>
|
||||
|
||||
<FormRow
|
||||
label="Amount"
|
||||
// prettier-ignore
|
||||
error={
|
||||
errors.amount && dirty.amount
|
||||
? (errors.amount as string)
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
name="amount"
|
||||
value={amount as string}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</FormRow>
|
||||
|
||||
<FormRow
|
||||
label="Price"
|
||||
error={
|
||||
// prettier-ignore
|
||||
errors.price && dirty.price
|
||||
? (errors.price as string)
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
name="price"
|
||||
value={price as string}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</FormRow>
|
||||
|
||||
<FormRow
|
||||
label="Discount"
|
||||
error={
|
||||
// prettier-ignore
|
||||
errors.roomId && dirty.roomId
|
||||
? (errors.roomId as string)
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
name="discount"
|
||||
value={discount as string}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</FormRow>
|
||||
|
||||
<FormRow label="Status">
|
||||
<Input
|
||||
type="checkbox"
|
||||
name="status"
|
||||
checked={status as boolean}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</FormRow>
|
||||
|
||||
<FormRow
|
||||
label="Description"
|
||||
error={
|
||||
// prettier-ignore
|
||||
errors.description && dirty.description
|
||||
? (errors.description as string)
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<TextArea
|
||||
name="description"
|
||||
rows={3}
|
||||
value={description as string}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</FormRow>
|
||||
|
||||
<Form.Action>
|
||||
<FormBtn type="submit" name="submit" disabled={disable}>
|
||||
{
|
||||
// prettier-ignore
|
||||
isAdd
|
||||
? 'Add'
|
||||
: 'Edit'
|
||||
}
|
||||
</FormBtn>
|
||||
<FormBtn type="button" styled="secondary" onClick={closeAndReset}>
|
||||
Close
|
||||
</FormBtn>
|
||||
</Form.Action>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default RoomForm;
|
||||
@@ -0,0 +1,198 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useEffect, useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
// Components
|
||||
import { HiSquare2Stack } from 'react-icons/hi2';
|
||||
import { HiTrash } from 'react-icons/hi';
|
||||
import { StyledOperationTable } from './styled';
|
||||
import Menus from '../../components/Menus/Menus';
|
||||
import Table from '../../components/Table';
|
||||
import Direction from '../../commons/styles/Direction';
|
||||
import Message from '../../components/Message';
|
||||
import Search from '../../components/Search';
|
||||
import SortBy from '../../components/SortBy';
|
||||
import OrderBy from '../../components/OrderBy';
|
||||
|
||||
// Types
|
||||
import { TRoom } from '../../globals/types';
|
||||
|
||||
// Constants
|
||||
import { useFetch } from '../../hooks/useFetch';
|
||||
import { ROOM_PATH } from '../../constants/path';
|
||||
import { STATUS_CODE } from '../../constants/statusCode';
|
||||
import { CONFIRM_DELETE, DELETE_SUCCESS } from '../../constants/messages';
|
||||
import { ROOM_PAGE } from '../../constants/variables';
|
||||
|
||||
// Styled
|
||||
import Spinner from '../../commons/styles/Spinner';
|
||||
|
||||
// Utils
|
||||
import { sendRequest } from '../../helpers/sendRequest';
|
||||
|
||||
interface IRoomRow {
|
||||
room: TRoom;
|
||||
openFormDialog: () => void;
|
||||
setRoom: React.Dispatch<React.SetStateAction<TRoom | null>>;
|
||||
reload: boolean;
|
||||
setReload: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const RoomRow = ({
|
||||
room,
|
||||
openFormDialog,
|
||||
setRoom,
|
||||
reload,
|
||||
setReload,
|
||||
}: IRoomRow) => {
|
||||
const handleOnEdit = (room: TRoom) => {
|
||||
setRoom(room);
|
||||
openFormDialog();
|
||||
};
|
||||
|
||||
const handleOnDelete = async (room: TRoom) => {
|
||||
if (confirm(CONFIRM_DELETE)) {
|
||||
const response = await sendRequest(
|
||||
ROOM_PATH + `/${room.id}`,
|
||||
null,
|
||||
'DELETE',
|
||||
);
|
||||
|
||||
if (response.statusCode === STATUS_CODE.OK) {
|
||||
toast.success(DELETE_SUCCESS);
|
||||
|
||||
// Reload table
|
||||
setReload(!reload);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const { id, name, amount, price, discount, status } = room;
|
||||
|
||||
// prettier-ignore
|
||||
const statusText = status
|
||||
? 'Valid'
|
||||
: 'Invalid';
|
||||
|
||||
return (
|
||||
<Table.Row>
|
||||
<div>{id}</div>
|
||||
<div>{name}</div>
|
||||
<div>{amount}</div>
|
||||
<div>{price}</div>
|
||||
<div>{discount}</div>
|
||||
<div>{statusText}</div>
|
||||
|
||||
<Menus.Menu>
|
||||
<Menus.Toggle id={id} />
|
||||
|
||||
<Menus.List id={id}>
|
||||
<Menus.Button
|
||||
icon={<HiSquare2Stack />}
|
||||
onClick={() => handleOnEdit(room)}
|
||||
>
|
||||
Edit
|
||||
</Menus.Button>
|
||||
<Menus.Button icon={<HiTrash />} onClick={() => handleOnDelete(room)}>
|
||||
Delete
|
||||
</Menus.Button>
|
||||
</Menus.List>
|
||||
</Menus.Menu>
|
||||
</Table.Row>
|
||||
);
|
||||
};
|
||||
|
||||
interface IRoomTable {
|
||||
reload: boolean;
|
||||
setReload: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
openFormDialog: () => void;
|
||||
setRoom?: React.Dispatch<React.SetStateAction<TRoom | null>>;
|
||||
}
|
||||
|
||||
const RoomTable = ({
|
||||
reload,
|
||||
setReload,
|
||||
openFormDialog,
|
||||
setRoom,
|
||||
}: IRoomTable) => {
|
||||
const [nameSearch, setNameSearch] = useState('');
|
||||
const [searchParams] = useSearchParams();
|
||||
const [rooms, setRooms] = useState<TRoom[]>([]);
|
||||
const sortByValue = searchParams.get('sortBy')
|
||||
? searchParams.get('sortBy')!
|
||||
: '';
|
||||
const orderByValue = searchParams.get('orderBy')
|
||||
? searchParams.get('orderBy')!
|
||||
: '';
|
||||
|
||||
const { data, isPending, errorMsg } = useFetch(
|
||||
'rooms',
|
||||
'name',
|
||||
nameSearch,
|
||||
sortByValue,
|
||||
orderByValue,
|
||||
reload,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
setRooms(data);
|
||||
} else {
|
||||
setRooms([]);
|
||||
}
|
||||
|
||||
if (errorMsg) {
|
||||
console.error(errorMsg);
|
||||
}
|
||||
}, [data, errorMsg]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Direction>
|
||||
<StyledOperationTable>
|
||||
<OrderBy options={ROOM_PAGE.ORDERBY_OPTIONS} />
|
||||
|
||||
<SortBy options={ROOM_PAGE.SORTBY_OPTIONS} />
|
||||
<Search
|
||||
setValueSearch={setNameSearch}
|
||||
setPlaceHolder="Search by name..."
|
||||
/>
|
||||
</StyledOperationTable>
|
||||
|
||||
{isPending && <Spinner />}
|
||||
|
||||
{rooms.length ? (
|
||||
<Menus>
|
||||
<Table columns="10% 20% 20% 20% 10% 10% 5%">
|
||||
<Table.Header>
|
||||
<div>Id</div>
|
||||
<div>Name</div>
|
||||
<div>Amount</div>
|
||||
<div>Price</div>
|
||||
<div>Discount</div>
|
||||
<div>Status</div>
|
||||
</Table.Header>
|
||||
<Table.Body<TRoom>
|
||||
data={rooms}
|
||||
render={(room: TRoom) => (
|
||||
<RoomRow
|
||||
room={room}
|
||||
key={room.id}
|
||||
reload={reload}
|
||||
setReload={setReload}
|
||||
openFormDialog={openFormDialog}
|
||||
setRoom={setRoom!}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Table>
|
||||
</Menus>
|
||||
) : (
|
||||
!isPending && <Message>No data to show here!</Message>
|
||||
)}
|
||||
</Direction>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default RoomTable;
|
||||
@@ -0,0 +1,58 @@
|
||||
import { useRef, useState } from 'react';
|
||||
|
||||
// Components
|
||||
import Direction from '../../commons/styles/Direction';
|
||||
import Button from '../../commons/styles/Button';
|
||||
import RoomTable from './Table';
|
||||
|
||||
// Styled
|
||||
import { StyledRoom, Title } from './styled';
|
||||
import RoomDialog from './Dialog';
|
||||
|
||||
// Types
|
||||
import { TRoom } from '../../globals/types';
|
||||
|
||||
const Room = () => {
|
||||
const dialogRef = useRef<HTMLDialogElement>();
|
||||
const [reload, setReload] = useState(true);
|
||||
const [room, setRoom] = useState<TRoom | null>(null);
|
||||
const [isAdd, setIsAdd] = useState(false);
|
||||
|
||||
const openFormDialog = (isAddForm: boolean = false) => {
|
||||
setIsAdd(isAddForm);
|
||||
dialogRef.current?.showModal();
|
||||
};
|
||||
|
||||
const closeFormDialog = () => {
|
||||
dialogRef.current?.close();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledRoom>
|
||||
<Direction type="horizontal">
|
||||
<Title>List Room</Title>
|
||||
<Button onClick={() => openFormDialog(true)}>Add room</Button>
|
||||
</Direction>
|
||||
|
||||
<RoomTable
|
||||
reload={reload}
|
||||
setReload={setReload}
|
||||
openFormDialog={() => openFormDialog()}
|
||||
setRoom={setRoom}
|
||||
/>
|
||||
</StyledRoom>
|
||||
|
||||
<RoomDialog
|
||||
onClose={closeFormDialog}
|
||||
ref={dialogRef}
|
||||
setReload={setReload}
|
||||
reload={reload}
|
||||
data={room}
|
||||
isAdd={isAdd}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Room;
|
||||
@@ -0,0 +1,24 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledRoom = styled.main`
|
||||
padding: 20px;
|
||||
padding-bottom: 100px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 30px;
|
||||
`;
|
||||
|
||||
const Title = styled.h2`
|
||||
font-size: var(--fs-md);
|
||||
color: var(--dark-text);
|
||||
text-transform: capitalize;
|
||||
`;
|
||||
|
||||
const StyledOperationTable = styled.div`
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
justify-content: flex-end;
|
||||
`;
|
||||
|
||||
export { StyledRoom, Title, StyledOperationTable };
|
||||
@@ -6,17 +6,19 @@ import UserForm from './Form';
|
||||
|
||||
// Interfaces
|
||||
import { IDialogProps } from '../../globals/interfaces';
|
||||
import { TUser } from '../../globals/types';
|
||||
|
||||
const UserDialog = forwardRef((props, ref) => {
|
||||
const dialogRef = ref as React.MutableRefObject<
|
||||
HTMLDialogElement | undefined
|
||||
>;
|
||||
|
||||
// prettier-ignore
|
||||
const {
|
||||
onClose,
|
||||
setReload,
|
||||
reload,
|
||||
user,
|
||||
data,
|
||||
isAdd
|
||||
} = props;
|
||||
|
||||
@@ -42,11 +44,11 @@ const UserDialog = forwardRef((props, ref) => {
|
||||
onClose={onClose!}
|
||||
reload={reload!}
|
||||
setReload={setReload!}
|
||||
user={user}
|
||||
user={data}
|
||||
isAdd={isAdd!}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
}) as React.FC<IDialogProps>;
|
||||
}) as React.FC<IDialogProps<TUser>>;
|
||||
|
||||
export default UserDialog;
|
||||
|
||||
@@ -24,12 +24,12 @@ import useForm from '../../hooks/useForm';
|
||||
|
||||
// Utils
|
||||
import {
|
||||
isValidAddress,
|
||||
isValidString,
|
||||
isValidNumber,
|
||||
isValidPhoneNumber,
|
||||
isValidString,
|
||||
isValidName,
|
||||
} from '../../helpers/validators';
|
||||
import { addValidator, getValueUser } from '../../helpers/utils.ts';
|
||||
import { addValidator, getValueFromObj } from '../../helpers/utils.ts';
|
||||
import { sendRequest } from '../../helpers/sendRequest.ts';
|
||||
|
||||
// Constants
|
||||
@@ -66,26 +66,57 @@ const UserForm = ({
|
||||
isAdd,
|
||||
}: IUserFormProp) => {
|
||||
const [reset, setReset] = useState(true);
|
||||
|
||||
if (isAdd) {
|
||||
// If this is add form, reset value
|
||||
user = null;
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
const initialValue: string = isAdd
|
||||
? ''
|
||||
: user!
|
||||
&& user.id;
|
||||
|
||||
const {
|
||||
idValue,
|
||||
nameValue,
|
||||
identifiedCodeValue,
|
||||
phoneValue,
|
||||
roomIdValue,
|
||||
addressValue,
|
||||
} = getValueFromObj<TUser>(user);
|
||||
|
||||
// Define your state schema
|
||||
// prettier-ignore
|
||||
const stateSchema: TStateSchema = {
|
||||
id: { value: getValueUser(user, 'id') },
|
||||
name: { value: getValueUser(user, 'name'), error: '' },
|
||||
identifiedCode: { value: getValueUser(user, 'identifiedCode'), error: '' },
|
||||
phone: { value: getValueUser(user, 'phone'), error: '' },
|
||||
roomId: { value: getValueUser(user, 'roomId'), error: '' },
|
||||
address: { value: getValueUser(user, 'address'), error: '' },
|
||||
id: { value: idValue || '' },
|
||||
name: {
|
||||
value: nameValue || '',
|
||||
error: '' ,
|
||||
},
|
||||
identifiedCode: {
|
||||
value: identifiedCodeValue || '',
|
||||
error: '',
|
||||
},
|
||||
phone: {
|
||||
value: phoneValue || '',
|
||||
error: '',
|
||||
},
|
||||
roomId: {
|
||||
value: roomIdValue || '',
|
||||
error: '' ,
|
||||
},
|
||||
address: {
|
||||
value: addressValue || '',
|
||||
error: ''
|
||||
},
|
||||
};
|
||||
|
||||
// prettier-ignore
|
||||
const stateValidatorSchema: TValidator = {
|
||||
name: addValidator({
|
||||
validatorFunc: isValidString,
|
||||
validatorFunc: isValidName,
|
||||
prop: 'full name'
|
||||
}),
|
||||
identifiedCode: addValidator({
|
||||
@@ -101,7 +132,7 @@ const UserForm = ({
|
||||
prop: 'room number'
|
||||
}),
|
||||
address: addValidator({
|
||||
validatorFunc: isValidAddress,
|
||||
validatorFunc: isValidString,
|
||||
prop: 'address'
|
||||
}),
|
||||
};
|
||||
@@ -122,6 +153,8 @@ const UserForm = ({
|
||||
} else {
|
||||
throw new Error(errorMsg(response.statusCode, response.msg));
|
||||
}
|
||||
|
||||
onResetForm();
|
||||
} else {
|
||||
// Edit request
|
||||
const response = await sendRequest(
|
||||
@@ -138,7 +171,6 @@ const UserForm = ({
|
||||
}
|
||||
// Reload table data
|
||||
setReload(!reload);
|
||||
onResetForm();
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
toast.error(error.message);
|
||||
@@ -280,7 +312,12 @@ const UserForm = ({
|
||||
|
||||
<Form.Action>
|
||||
<FormBtn type="submit" name="submit" disabled={disable}>
|
||||
Add
|
||||
{
|
||||
// prettier-ignore
|
||||
isAdd
|
||||
? 'Add'
|
||||
: 'Edit'
|
||||
}
|
||||
</FormBtn>
|
||||
<FormBtn type="button" styled="secondary" onClick={closeAndReset}>
|
||||
Close
|
||||
|
||||
@@ -121,6 +121,7 @@ const UserTable = ({
|
||||
|
||||
const { data, isPending, errorMsg } = useFetch(
|
||||
'users',
|
||||
'phone',
|
||||
phoneSearch,
|
||||
sortByValue,
|
||||
orderByValue,
|
||||
@@ -146,7 +147,10 @@ const UserTable = ({
|
||||
<OrderBy options={USER_PAGE.ORDERBY_OPTIONS} />
|
||||
|
||||
<SortBy options={USER_PAGE.SORTBY_OPTIONS} />
|
||||
<Search setPhoneSearch={setPhoneSearch} />
|
||||
<Search
|
||||
setValueSearch={setPhoneSearch}
|
||||
setPlaceHolder="Search by phone..."
|
||||
/>
|
||||
</StyledOperationTable>
|
||||
|
||||
{isPending && <Spinner />}
|
||||
|
||||
@@ -48,7 +48,7 @@ const User = () => {
|
||||
ref={dialogRef}
|
||||
setReload={setReload}
|
||||
reload={reload}
|
||||
user={user}
|
||||
data={user}
|
||||
isAdd={isAdd}
|
||||
/>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user