mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-22 20:01:59 +00:00
340 lines
7.1 KiB
TypeScript
340 lines
7.1 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import styled from 'styled-components';
|
|
import toast from 'react-hot-toast';
|
|
|
|
// Styled
|
|
import Input from '../../commons/styles/Input';
|
|
import TextArea from '../../commons/styles/TextArea';
|
|
|
|
// Components
|
|
import Form from '../../components/Form';
|
|
import FormRow from '../../components/FormRow';
|
|
import Button from '../../commons/styles/Button.ts';
|
|
|
|
// Types
|
|
import {
|
|
TKeyValue,
|
|
TStateSchema,
|
|
TUser,
|
|
TValidator,
|
|
} from '../../globals/types';
|
|
|
|
// Hooks
|
|
import useForm from '../../hooks/useForm';
|
|
|
|
// Utils
|
|
import {
|
|
isValidString,
|
|
isValidNumber,
|
|
isValidPhoneNumber,
|
|
} from '../../helpers/validators';
|
|
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 { USER_PATH } from '../../constants/path.ts';
|
|
|
|
const FormBtn = styled(Button)`
|
|
width: 100%;
|
|
|
|
&:disabled,
|
|
&[disabled] {
|
|
background-color: var(--disabled-btn-color);
|
|
}
|
|
`;
|
|
|
|
interface IUserFormProp {
|
|
onClose: () => void;
|
|
reload: boolean;
|
|
setReload: React.Dispatch<React.SetStateAction<boolean>>;
|
|
user?: TUser | null;
|
|
isAdd: boolean;
|
|
}
|
|
|
|
const UserForm = ({
|
|
onClose,
|
|
reload,
|
|
setReload,
|
|
user,
|
|
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.toLocaleString();
|
|
|
|
const {
|
|
idValue,
|
|
nameValue,
|
|
identifiedCodeValue,
|
|
phoneValue,
|
|
roomIdValue,
|
|
addressValue,
|
|
} = getValueFromObj<TUser>(user);
|
|
|
|
// Define your state schema
|
|
// prettier-ignore
|
|
const stateSchema: TStateSchema = {
|
|
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,
|
|
prop: 'full name'
|
|
}),
|
|
identifiedCode: addValidator({
|
|
validatorFunc: isValidNumber,
|
|
prop: 'identified code',
|
|
}),
|
|
phone: addValidator({
|
|
validatorFunc: isValidPhoneNumber,
|
|
prop: 'phone number',
|
|
}),
|
|
roomId: addValidator({
|
|
validatorFunc: isValidNumber,
|
|
prop: 'room number'
|
|
}),
|
|
address: addValidator({
|
|
validatorFunc: isValidString,
|
|
prop: 'address'
|
|
}),
|
|
};
|
|
|
|
// Submit form
|
|
const onSubmitForm = async (state: TKeyValue) => {
|
|
// Convert to user type
|
|
const data: TUser = {
|
|
id: +state.id!,
|
|
name: '' + state.name,
|
|
identifiedCode: '' + state.identifiedCode,
|
|
phone: '' + state.phone,
|
|
roomId: +state.roomId!,
|
|
address: '' + state.address,
|
|
};
|
|
|
|
try {
|
|
if (isAdd) {
|
|
// Add request
|
|
const response = await sendRequest(
|
|
USER_PATH,
|
|
JSON.stringify(data),
|
|
'POST',
|
|
);
|
|
|
|
if (response.statusCode === STATUS_CODE.CREATE) {
|
|
toast.success(ADD_SUCCESS);
|
|
} else {
|
|
throw new Error(errorMsg(response.statusCode, response.msg));
|
|
}
|
|
|
|
onResetForm();
|
|
} else {
|
|
// Edit request
|
|
const response = await sendRequest(
|
|
USER_PATH + `/${user!.id}`,
|
|
JSON.stringify(data),
|
|
'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();
|
|
};
|
|
|
|
// prettier-ignore
|
|
const {
|
|
values,
|
|
errors,
|
|
dirty,
|
|
handleOnChange,
|
|
handleOnSubmit,
|
|
disable } =
|
|
useForm(
|
|
stateSchema,
|
|
stateValidatorSchema,
|
|
onSubmitForm,
|
|
initialValue
|
|
);
|
|
|
|
// prettier-ignore
|
|
const {
|
|
id,
|
|
name,
|
|
identifiedCode,
|
|
phone,
|
|
roomId,
|
|
address
|
|
} = values;
|
|
|
|
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="Full 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="Identified Code"
|
|
error={
|
|
errors.identifiedCode && dirty.identifiedCode
|
|
? (errors.identifiedCode as string)
|
|
: ''
|
|
}
|
|
>
|
|
<Input
|
|
type="text"
|
|
name="identifiedCode"
|
|
value={identifiedCode as string}
|
|
onChange={handleOnChange}
|
|
/>
|
|
</FormRow>
|
|
|
|
<FormRow
|
|
label="Phone"
|
|
error={
|
|
// prettier-ignore
|
|
errors.phone && dirty.phone
|
|
? (errors.phone as string)
|
|
: ''
|
|
}
|
|
>
|
|
<Input
|
|
type="text"
|
|
name="phone"
|
|
value={phone as string}
|
|
onChange={handleOnChange}
|
|
/>
|
|
</FormRow>
|
|
|
|
<FormRow
|
|
label="Room"
|
|
error={
|
|
// prettier-ignore
|
|
errors.roomId && dirty.roomId
|
|
? (errors.roomId as string)
|
|
: ''
|
|
}
|
|
>
|
|
<Input
|
|
type="text"
|
|
name="roomId"
|
|
value={roomId as string}
|
|
onChange={handleOnChange}
|
|
/>
|
|
</FormRow>
|
|
|
|
<FormRow
|
|
label="Address"
|
|
error={
|
|
// prettier-ignore
|
|
errors.address && dirty.address
|
|
? (errors.address as string)
|
|
: ''
|
|
}
|
|
>
|
|
<TextArea
|
|
name="address"
|
|
rows={3}
|
|
value={address 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 UserForm;
|