mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-22 20:01:59 +00:00
Implement add user function
This commit is contained in:
@@ -11,7 +11,7 @@ const UserDialog = forwardRef((props, ref) => {
|
||||
const dialogRef = ref as React.MutableRefObject<
|
||||
HTMLDialogElement | undefined
|
||||
>;
|
||||
const { onClose } = props;
|
||||
const { onClose, setReload, reload } = props;
|
||||
|
||||
useEffect(() => {
|
||||
if (dialogRef.current) {
|
||||
@@ -31,7 +31,7 @@ const UserDialog = forwardRef((props, ref) => {
|
||||
|
||||
return (
|
||||
<Dialog title={'Add user'} onClose={onClose} ref={dialogRef}>
|
||||
<UserForm onClose={onClose!} />
|
||||
<UserForm onClose={onClose!} reload={reload!} onReload={setReload!} />
|
||||
</Dialog>
|
||||
);
|
||||
}) as React.FC<IDialogProps>;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
// Styled
|
||||
import Input from '../../commons/styles/Input';
|
||||
import { useState } from 'react';
|
||||
import TextArea from '../../commons/styles/TextArea';
|
||||
|
||||
// Components
|
||||
@@ -11,7 +12,12 @@ import FormRow from '../../components/FormRow';
|
||||
import Button from '../../commons/styles/Button.ts';
|
||||
|
||||
// Types
|
||||
import { TKeyValue, TStateSchema, TValidator } from '../../globals/types';
|
||||
import {
|
||||
TKeyValue,
|
||||
TResponse,
|
||||
TStateSchema,
|
||||
TValidator,
|
||||
} from '../../globals/types';
|
||||
|
||||
// Hooks
|
||||
import useForm from '../../hooks/useForm';
|
||||
@@ -24,6 +30,11 @@ import {
|
||||
isValidString,
|
||||
} from '../../helpers/validators';
|
||||
import { addValidator } from '../../helpers/utils.ts';
|
||||
import { sendRequest } from '../../helpers/sendRequest.ts';
|
||||
|
||||
// Constants
|
||||
import { STATUS_CODE } from '../../constants/statusCode.ts';
|
||||
import { ADD_SUCCESS, ERROR_MSG } from '../../constants/messages.ts';
|
||||
|
||||
const FormBtn = styled(Button)`
|
||||
width: 100%;
|
||||
@@ -36,23 +47,25 @@ const FormBtn = styled(Button)`
|
||||
|
||||
interface IUserFormProp {
|
||||
onClose: () => void;
|
||||
reload: boolean;
|
||||
onReload: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const UserForm = ({ onClose }: IUserFormProp) => {
|
||||
const UserForm = ({ onClose, reload, onReload }: IUserFormProp) => {
|
||||
const [reset, setReset] = useState(true);
|
||||
|
||||
// Define your state schema
|
||||
const stateSchema: TStateSchema = {
|
||||
fullName: { value: '', error: '' },
|
||||
name: { value: '', error: '' },
|
||||
identifiedCode: { value: '', error: '' },
|
||||
phone: { value: '', error: '' },
|
||||
room: { value: '', error: '' },
|
||||
roomId: { value: '', error: '' },
|
||||
address: { value: '', error: '' },
|
||||
};
|
||||
|
||||
// prettier-ignore
|
||||
const stateValidatorSchema: TValidator = {
|
||||
fullName: addValidator({
|
||||
name: addValidator({
|
||||
validatorFunc: isValidString,
|
||||
prop: 'full name'
|
||||
}),
|
||||
@@ -64,7 +77,7 @@ const UserForm = ({ onClose }: IUserFormProp) => {
|
||||
validatorFunc: isValidPhoneNumber,
|
||||
prop: 'phone number',
|
||||
}),
|
||||
room: addValidator({
|
||||
roomId: addValidator({
|
||||
validatorFunc: isValidNumber,
|
||||
prop: 'room number'
|
||||
}),
|
||||
@@ -75,19 +88,38 @@ const UserForm = ({ onClose }: IUserFormProp) => {
|
||||
};
|
||||
|
||||
// Submit form
|
||||
const onSubmitForm = (state: TKeyValue) => {
|
||||
alert(JSON.stringify(state, null, 2));
|
||||
const onSubmitForm = async (state: TKeyValue) => {
|
||||
try {
|
||||
const response = await sendRequest(
|
||||
'users',
|
||||
JSON.stringify(state),
|
||||
'POST',
|
||||
);
|
||||
|
||||
if (response.statusCode === STATUS_CODE.CREATE) {
|
||||
toast.success(ADD_SUCCESS);
|
||||
onReload(!reload);
|
||||
} else {
|
||||
toast.error(ERROR_MSG(response.statusCode, response.msg));
|
||||
}
|
||||
|
||||
onResetForm();
|
||||
} catch (error) {
|
||||
toast.error(
|
||||
ERROR_MSG((error as TResponse).statusCode, (error as TResponse).msg),
|
||||
);
|
||||
}
|
||||
|
||||
onClose();
|
||||
onResetForm();
|
||||
};
|
||||
|
||||
// prettier-ignore
|
||||
const {
|
||||
values,
|
||||
errors,
|
||||
dirty,
|
||||
handleOnChange,
|
||||
handleOnSubmit,
|
||||
values,
|
||||
errors,
|
||||
dirty,
|
||||
handleOnChange,
|
||||
handleOnSubmit,
|
||||
disable } =
|
||||
useForm(
|
||||
stateSchema,
|
||||
@@ -97,10 +129,10 @@ const UserForm = ({ onClose }: IUserFormProp) => {
|
||||
|
||||
// prettier-ignore
|
||||
const {
|
||||
fullName,
|
||||
name,
|
||||
identifiedCode,
|
||||
phone,
|
||||
room,
|
||||
roomId,
|
||||
address
|
||||
} = values;
|
||||
|
||||
@@ -117,15 +149,15 @@ const UserForm = ({ onClose }: IUserFormProp) => {
|
||||
label="Full Name"
|
||||
error={
|
||||
// prettier-ignore
|
||||
errors.fullName && dirty.fullName ?
|
||||
(errors.fullName as string)
|
||||
errors.name && dirty.name ?
|
||||
(errors.name as string)
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
name="fullName"
|
||||
value={fullName as string}
|
||||
name="name"
|
||||
value={name as string}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</FormRow>
|
||||
@@ -167,15 +199,15 @@ const UserForm = ({ onClose }: IUserFormProp) => {
|
||||
label="Room"
|
||||
error={
|
||||
// prettier-ignore
|
||||
errors.room && dirty.room ?
|
||||
(errors.room as string)
|
||||
errors.roomId && dirty.roomId ?
|
||||
(errors.roomId as string)
|
||||
: ''
|
||||
}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
name="room"
|
||||
value={room as string}
|
||||
name="roomId"
|
||||
value={roomId as string}
|
||||
onChange={handleOnChange}
|
||||
/>
|
||||
</FormRow>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
// Components
|
||||
import { HiSquare2Stack } from 'react-icons/hi2';
|
||||
import { HiTrash } from 'react-icons/hi';
|
||||
@@ -15,7 +17,6 @@ import { useFetch } from '../../hooks/useFetch';
|
||||
|
||||
// Styled
|
||||
import Spinner from '../../commons/styles/Spinner';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
type TUserModal = { user: TUser };
|
||||
|
||||
@@ -53,13 +54,19 @@ const UserRow = ({ user }: TUserModal) => {
|
||||
);
|
||||
};
|
||||
|
||||
const UserTable = () => {
|
||||
const { data, isPending, errorMsg } = useFetch('users');
|
||||
interface IUserTable {
|
||||
reload: boolean;
|
||||
}
|
||||
|
||||
const UserTable = ({ reload }: IUserTable) => {
|
||||
const { data, isPending, errorMsg } = useFetch('users', reload);
|
||||
const [users, setUsers] = useState<TUser[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
setUsers(data);
|
||||
} else {
|
||||
setUsers([]);
|
||||
}
|
||||
|
||||
if (errorMsg) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react';
|
||||
import { useRef, useState } from 'react';
|
||||
|
||||
// Components
|
||||
import Direction from '../../commons/styles/Direction';
|
||||
@@ -11,6 +11,7 @@ import UserDialog from './Dialog';
|
||||
|
||||
const User = () => {
|
||||
const dialogRef = useRef<HTMLDialogElement>();
|
||||
const [reload, setReload] = useState(true);
|
||||
|
||||
const openDialog = () => {
|
||||
dialogRef.current?.showModal();
|
||||
@@ -28,10 +29,15 @@ const User = () => {
|
||||
<Button onClick={openDialog}>Add user</Button>
|
||||
</Direction>
|
||||
|
||||
<UserTable />
|
||||
<UserTable reload={reload} />
|
||||
</StyledUser>
|
||||
|
||||
<UserDialog onClose={closeDialog} ref={dialogRef} />
|
||||
<UserDialog
|
||||
onClose={closeDialog}
|
||||
ref={dialogRef}
|
||||
setReload={setReload}
|
||||
reload={reload}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user