Merge pull request #29 from Nez27/feat/update-room-and-user-page

Update room, user pages and service
This commit is contained in:
Loi Phan
2023-11-22 21:54:33 +07:00
committed by GitHub
11 changed files with 179 additions and 446 deletions
+11 -2
View File
@@ -1,6 +1,7 @@
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
import isPropValid from '@emotion/is-prop-valid';
import { StyleSheetManager } from 'styled-components';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
// Components
import AppLayout from './components/AppLayout';
@@ -13,9 +14,17 @@ import NotFound from './pages/NotFound';
import * as PATH from './constants/path';
import Toast from './components/Toast';
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000,
}
}
});
function App() {
return (
<>
<QueryClientProvider client={queryClient}>
<StyleSheetManager shouldForwardProp={shouldForwardProp}>
<BrowserRouter>
<Routes>
@@ -31,7 +40,7 @@ function App() {
</StyleSheetManager>
<Toast />
</>
</QueryClientProvider>
);
}
+14 -56
View File
@@ -1,5 +1,4 @@
import { useSearchParams } from 'react-router-dom';
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
import { useCallback } from 'react';
// Components
import Menus from '@component/Menus';
@@ -14,7 +13,6 @@ import RoomRow from './RoomRow';
import { IRoom } from '@type/rooms';
// Constants
import { useFetch } from '@hook/useFetch';
import { ORDERBY_OPTIONS, ROOM_PAGE } from '@constant/commons';
// Styled
@@ -22,45 +20,18 @@ import { StyledOperationTable } from './styled';
import Direction from '@commonStyle/Direction';
import Spinner from '@commonStyle/Spinner';
// Hooks
import { useRooms } from '@hook/rooms/useRooms';
interface IRoomTable {
reload: boolean;
setReload: Dispatch<SetStateAction<boolean>>;
}
const RoomTable = ({ reload, setReload }: IRoomTable) => {
const RoomTable = () => {
const columnName = ['Id', 'Name', 'Price', 'Status'];
const [nameSearch, setNameSearch] = useState('');
const [searchParams] = useSearchParams();
const [rooms, setRooms] = useState<IRoom[]>([]);
const sortByValue = searchParams.get('sortBy')
? searchParams.get('sortBy')!
: '';
const orderByValue = searchParams.get('orderBy')
? searchParams.get('orderBy')!
: '';
const { isLoading, rooms } = useRooms();
const { data, isPending, errorFetchMsg } = useFetch(
'rooms',
'name',
nameSearch,
sortByValue,
orderByValue,
reload
const renderRoomRow = useCallback(
(room: IRoom) => <RoomRow room={room} key={room.id} />,
[]
);
useEffect(() => {
if (data) {
setRooms(data);
} else {
setRooms([]);
}
if (errorFetchMsg) {
console.error(errorFetchMsg);
}
}, [data, errorFetchMsg]);
return (
<>
<Direction>
@@ -68,33 +39,20 @@ const RoomTable = ({ reload, setReload }: IRoomTable) => {
<OrderBy options={ORDERBY_OPTIONS} />
<SortBy options={ROOM_PAGE.SORTBY_OPTIONS} />
<Search
setValueSearch={setNameSearch}
setPlaceHolder="Search by name..."
/>
<Search setPlaceHolder="Search by name..." />
</StyledOperationTable>
{isPending && <Spinner />}
{isLoading && <Spinner />}
{rooms.length ? (
{rooms && rooms.length ? (
<Menus>
<Table columns="10% 40% 20% 20% 5%">
<Table.Header headerColumn={columnName}/>
<Table.Body<IRoom>
data={rooms}
render={(room: IRoom) => (
<RoomRow
room={room}
key={room.id}
reload={reload}
setReload={setReload}
/>
)}
/>
<Table.Header headerColumn={columnName} />
<Table.Body<IRoom> data={rooms} render={renderRoomRow} />
</Table>
</Menus>
) : (
!isPending && <Message>No data to show here!</Message>
!isLoading && <Message>No data to show here!</Message>
)}
</Direction>
</>
+40 -77
View File
@@ -1,40 +1,30 @@
import { Dispatch, SetStateAction, useEffect } from 'react';
import toast from 'react-hot-toast';
import styled from 'styled-components';
// Hooks
import { useForm } from 'react-hook-form';
// Styled
import Button from '@commonStyle/Button.ts';
import Input from '@commonStyle/Input.ts';
// Types
import { Nullable } from '@type/common.ts';
import { IRoom } from '@type/rooms.ts';
// Constants
import { ADD_SUCCESS, EDIT_SUCCESS } from '@constant/messages.ts';
import {
INVALID_DISCOUNT,
INVALID_FIELD,
REQUIRED_FIELD_ERROR,
} from '@constant/formValidateMessage.ts';
import { INIT_VALUE_ROOM_FORM, REGEX } from '../../constants/commons.ts';
import { REGEX } from '../../constants/commons.ts';
// Helpers
import {
isValidDiscount,
isValidRegex,
isValidString,
} from '@helper/validators.ts';
import { isValidRegex, isValidString } from '@helper/validators.ts';
// Components
import FormRow from '@component/LabelControl/index.tsx';
import Form from '@component/Form/index.tsx';
// Services
import { addRoom, updateRoom } from '@service/roomServices.ts';
// Hooks
import { useForm } from 'react-hook-form';
import { useCreateRoom } from '@hook/rooms/useCreateRoom.ts';
import { useUpdateRoom } from '@hook/rooms/useUpdateRoom.ts';
const FormBtn = styled(Button)`
width: 100%;
@@ -48,65 +38,51 @@ const FormBtn = styled(Button)`
interface IRoomFormProp {
onCloseModal?: () => void;
reload?: boolean;
setReload?: Dispatch<SetStateAction<boolean>>;
roomEdit?: Nullable<IRoom>;
room?: IRoom;
}
const RoomForm = ({
onCloseModal,
reload,
setReload,
roomEdit,
}: IRoomFormProp) => {
const formMethods = useForm<IRoom>();
const RoomForm = ({ onCloseModal, room }: IRoomFormProp) => {
const { isCreating, createRoom } = useCreateRoom();
const { isUpdating, updateRoom } = useUpdateRoom();
const isLoading = isCreating || isUpdating;
const { id: editId, ...editValues } = { ...room };
const formMethods = useForm<IRoom>({
defaultValues: editId
? editValues
: {},
});
const {
register,
handleSubmit,
reset,
formState: { errors, isDirty, isValid, isSubmitting },
formState: { errors, isDirty, isValid },
trigger,
} = formMethods;
useEffect(() => {
if (roomEdit) {
reset(roomEdit);
} else {
reset(INIT_VALUE_ROOM_FORM);
}
}, [roomEdit, reset]);
// Submit form
const onSubmit = async (room: IRoom) => {
// Calculate final price
room.finalPrice = room.price - (room.price * room.discount) / 100;
if (!roomEdit) {
const onSubmit = async (newRoom: IRoom) => {
if (!editId) {
// Add request
const response = await addRoom(room);
if (response) {
toast.success(ADD_SUCCESS);
}
createRoom(newRoom, {
onSuccess: () => {
reset();
onCloseModal?.();
},
});
} else {
// Edit request
const response = await updateRoom(room);
if (response) {
toast.success(EDIT_SUCCESS);
}
newRoom.id = editId!;
updateRoom(newRoom, {
onSuccess: () => {
reset();
onCloseModal?.();
},
});
}
// Reload table data
setReload!(!reload);
reset();
onCloseModal!();
};
return (
<Form onSubmit={handleSubmit(onSubmit)}>
<Input type="hidden" id="id" {...register('id')} />
<FormRow label="Name" error={errors?.name?.message}>
<Input
type="text"
@@ -114,7 +90,8 @@ const RoomForm = ({
{...register('name', {
required: REQUIRED_FIELD_ERROR,
validate: {
checkValidRoomName: (value) => isValidString(value) || INVALID_FIELD,
checkValidRoomName: (value) =>
isValidString(value) || INVALID_FIELD,
},
onChange: () => trigger('name'),
})}
@@ -130,41 +107,27 @@ const RoomForm = ({
required: REQUIRED_FIELD_ERROR,
validate: {
checkPrice: (v) =>
isValidRegex(new RegExp(REGEX.NUMBER), v.toString()) || INVALID_FIELD,
isValidRegex(new RegExp(REGEX.NUMBER), v.toString()) ||
INVALID_FIELD,
},
onChange: () => trigger('price'),
})}
/>
</FormRow>
<FormRow label="discount" error={errors?.discount?.message}>
<Input
type="text"
id="phone"
{...register('discount', {
valueAsNumber: true,
required: REQUIRED_FIELD_ERROR,
validate: {
checkDiscount: (v) => isValidDiscount(v) || INVALID_DISCOUNT,
},
onChange: () => trigger('discount'),
})}
/>
</FormRow>
<Form.Action>
<FormBtn
type="submit"
name="submit"
disabled={!isDirty || !isValid || isSubmitting}
disabled={!isDirty || !isValid || isLoading}
>
{
!roomEdit
!editId
? 'Add'
: 'Save'
}
</FormBtn>
<FormBtn type="button" styled="secondary" onClick={onCloseModal}>
<FormBtn type="button" variations="secondary" onClick={onCloseModal}>
Close
</FormBtn>
</Form.Action>
+45 -42
View File
@@ -1,13 +1,6 @@
import { Dispatch, SetStateAction } from 'react';
import toast from 'react-hot-toast';
// Constants
import { ROOM_PATH } from '@constant/path';
import { STATUS_CODE } from '@constant/responseStatus';
import { CONFIRM_DELETE, DELETE_SUCCESS } from '@constant/messages';
import { useCallback, useMemo } from 'react';
// Helpers
import { sendRequest } from '@helper/sendRequest';
import { formatCurrency } from '@helper/helper';
// Types
@@ -20,38 +13,47 @@ import Table from '@component/Table';
import Menus from '@component/Menus';
import { RiEditBoxFill } from 'react-icons/ri';
import { HiTrash } from 'react-icons/hi';
import ConfirmMessage from '@component/ConfirmMessage';
// Hooks
import { useDeleteRoom } from '@hook/rooms/useDeleteRoom';
// Constants
import { FORM } from '@constant/commons';
interface IRoomRow {
room: IRoom;
reload: boolean;
setReload: Dispatch<SetStateAction<boolean>>;
}
const RoomRow = ({ room, reload, setReload }: IRoomRow) => {
const handleDelete = async (room: IRoom) => {
if (confirm(CONFIRM_DELETE)) {
const response = await sendRequest(ROOM_PATH + `/${room.id}`, 'DELETE');
if (response.statusCode === STATUS_CODE.OK) {
toast.success(DELETE_SUCCESS);
// Reload table
setReload(!reload);
}
}
};
const { id, name, finalPrice, status } = room;
const RoomRow = ({ room }: IRoomRow) => {
const { id, name, price, status } = room;
const { isDeleting, deleteRoom } = useDeleteRoom();
const statusText = status
? 'Unavailable'
: 'Available';
const formattedPrice = useMemo(() => formatCurrency(price), [price]);
const renderEditBtn = useCallback(
(onCloseModal: () => void) => (
<Menus.Button onClick={onCloseModal} icon={<RiEditBoxFill />}>
Edit
</Menus.Button>
),
[]
);
const renderDeleteBtn = useCallback(
(onCloseModal: () => void) => (
<Menus.Button icon={<HiTrash />} onClick={onCloseModal}>
Delete
</Menus.Button>
),
[]
);
return (
<Table.Row>
<div>{id}</div>
<div>{name}</div>
<div>{formatCurrency(finalPrice)}</div>
<div>{formattedPrice}</div>
<div>{statusText}</div>
<div>
@@ -61,24 +63,25 @@ const RoomRow = ({ room, reload, setReload }: IRoomRow) => {
<Menus.List id={id.toString()}>
<Modal.Open
modalName="edit"
renderChildren={(onCloseModal) => (
<Menus.Button onClick={onCloseModal} icon={<RiEditBoxFill />}>
Edit
</Menus.Button>
)}
modalName={FORM.EDIT}
renderChildren={renderEditBtn}
/>
<Modal.Open
modalName={FORM.DELETE}
renderChildren={renderDeleteBtn}
/>
<Menus.Button
icon={<HiTrash />}
onClick={() => handleDelete(room)}
>
Delete
</Menus.Button>
</Menus.List>
<Modal.Window name="edit" title="Edit Room">
<RoomForm roomEdit={room} setReload={setReload} reload={reload} />
<Modal.Window name={FORM.EDIT} title="Edit Room">
<RoomForm room={room} />
</Modal.Window>
<Modal.Window name={FORM.DELETE} title="Delete Room">
<ConfirmMessage
disabled={isDeleting}
message={`Are you sure to delete ${name}?`}
onConfirm={() => deleteRoom(id)}
/>
</Modal.Window>
</Menus.Menu>
</Modal>
+3 -9
View File
@@ -1,20 +1,14 @@
import { useState } from 'react';
// Components
import RoomTable from './RomTable';
import RoomForm from './RoomForm';
import Modal from '@component/Modal';
// Styled
import { StyledRoom, Title } from './styled';
import Direction from '@commonStyle/Direction.ts';
import Button from '@commonStyle/Button';
// Types
import Modal from '@component/Modal';
const Room = () => {
const [reload, setReload] = useState(true);
return (
<>
<StyledRoom>
@@ -29,12 +23,12 @@ const Room = () => {
)}
/>
<Modal.Window name="room-form" title="Add form">
<RoomForm setReload={setReload} reload={reload} />
<RoomForm />
</Modal.Window>
</Modal>
</Direction>
<RoomTable reload={reload} setReload={setReload} />
<RoomTable />
</StyledRoom>
</>
);
+39 -144
View File
@@ -1,14 +1,7 @@
import {
Dispatch,
SetStateAction,
useCallback,
useEffect,
useState,
} from 'react';
import toast from 'react-hot-toast';
// Hooks
import { FormProvider, useForm } from 'react-hook-form';
import { useCreateUser } from '@hook/users/useCreateUser.ts';
import { useUpdateUser } from '@hook/users/useUpdateUser.ts';
// Styled
import Input from '@commonStyle/Input.ts';
@@ -16,139 +9,73 @@ import Input from '@commonStyle/Input.ts';
// Components
import Form from '@component/Form/index.tsx';
import FormRow from '@component/LabelControl/index.tsx';
import Select, { ISelectOptions } from '@component/Select/index.tsx';
// Helpers
import { isEmptyObj, isValidRegex } from '@helper/validators.ts';
import { isValidRegex } from '@helper/validators.ts';
// Constants
import { ADD_SUCCESS, EDIT_SUCCESS } from '@constant/messages.ts';
import {
INVALID_FIELD,
INVALID_PHONE,
REQUIRED_FIELD_ERROR,
} from '@constant/formValidateMessage.ts';
import { INIT_VALUE_USER_FORM, REGEX } from '@constant/commons.ts';
import { REGEX } from '@constant/commons.ts';
// Styled
import { FormBtn } from './styled.ts';
// Services
import { getAllRoom, updateRoomStatus } from '@service/roomServices.ts';
import { createUser, updateUser } from '@service/userServices.ts';
// Types
import { Nullable } from '@type/common.ts';
import { IUser } from '@type/users.ts';
import { IRoom } from '@type/rooms.ts';
interface IUserFormProp {
onCloseModal?: () => void;
reload: boolean;
setReload: Dispatch<SetStateAction<boolean>>;
user?: Nullable<IUser>;
user?: IUser;
}
const UserForm = ({ onCloseModal, reload, setReload, user }: IUserFormProp) => {
const formMethods = useForm<IUser>();
const UserForm = ({ onCloseModal, user }: IUserFormProp) => {
const { isCreating, createUser } = useCreateUser();
const { isUpdating, updateUser } = useUpdateUser();
const isLoading = isCreating || isUpdating;
const {id: editId, ...editValues} = {...user};
const formMethods = useForm<IUser>({
defaultValues: editId
? editValues
: {}
});
const {
register,
handleSubmit,
reset,
formState: { errors, isDirty, isValid, isSubmitting },
formState: { errors, isDirty, isValid },
trigger,
} = formMethods;
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 = !user ? { roomId: 0 } : { ...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({
label: item.name!,
value: item.id!.toString(),
});
});
}
if (options.length > 0) {
setOptions(options);
}
if (!isEmptyObj(tempUser)) {
// Init value
reset(tempUser);
} else {
reset(INIT_VALUE_USER_FORM);
}
};
load();
}, [reset, user, rooms]);
// Submit form
const onSubmit = useCallback(
async (newUser: IUser) => {
const onSubmit =
(newUser: IUser) => {
if (!user) {
// Add request
const response = await createUser(newUser);
if (response) {
toast.success(ADD_SUCCESS);
}
// Update room status
updateRoomStatus(newUser.roomId, true);
createUser(newUser, {
onSuccess: () => {
reset();
onCloseModal?.();
},
});
} else {
// Edit request
const response = await updateUser(newUser);
if (response) {
toast.success(EDIT_SUCCESS);
}
// Update room status
updateRoomStatus(user!.roomId, true, newUser.roomId);
}
// Reload table data
setReload(!reload);
reset();
onCloseModal!();
},
[onCloseModal, reload, reset, setReload, user]
);
// Load all rooms
useEffect(() => {
const loadRoom = async () => {
const rooms = await getAllRoom();
if (rooms) {
setRooms(rooms);
newUser.id = editId!;
updateUser(newUser, {
onSuccess: () => {
reset();
onCloseModal?.();
}
});
}
};
loadRoom();
}, [onSubmit]);
return (
<FormProvider {...formMethods}>
<Form onSubmit={handleSubmit(onSubmit)}>
<Input type="hidden" id="id" {...register('id')} />
<FormRow label="Full Name" error={errors?.name?.message}>
<Input
type="text"
@@ -164,25 +91,6 @@ const UserForm = ({ onCloseModal, reload, setReload, user }: IUserFormProp) => {
/>
</FormRow>
<FormRow
label="Identified Code"
error={errors?.identifiedCode?.message}
>
<Input
type="text"
id="identifiedCode"
{...register('identifiedCode', {
required: REQUIRED_FIELD_ERROR,
validate: {
checkIdentifiedCode: (v) =>
isValidRegex(new RegExp(REGEX.NUMBER), v.toString()) ||
INVALID_FIELD,
},
onChange: () => trigger('identifiedCode'),
})}
/>
</FormRow>
<FormRow label="Phone" error={errors?.phone?.message}>
<Input
type="text"
@@ -198,32 +106,19 @@ const UserForm = ({ onCloseModal, reload, setReload, user }: IUserFormProp) => {
/>
</FormRow>
<FormRow label="Room">
{options && options.length > 1 ? (
<Select
id="roomId"
options={options!}
ariaLabel="RoomId"
optionsConfigForm={{
valueAsNumber: true,
onChange: () => trigger('roomId'),
validate: (v) => v !== 0,
}}
/>
) : (
<p>No room available!</p>
)}
</FormRow>
<Form.Action>
<FormBtn
type="submit"
name="submit"
disabled={!isDirty || !isValid || isSubmitting}
disabled={!isDirty || !isValid || isLoading}
>
{!user ? 'Add' : 'Save'}
{
!user
? 'Add'
: 'Save'
}
</FormBtn>
<FormBtn type="button" styled="secondary" onClick={onCloseModal}>
<FormBtn type="button" variations="secondary" onClick={onCloseModal}>
Close
</FormBtn>
</Form.Action>
+3 -51
View File
@@ -1,68 +1,26 @@
import toast from 'react-hot-toast';
import { Dispatch, SetStateAction } from 'react';
// Components
import { RiEditBoxFill } from 'react-icons/ri';
import { IoExit } from 'react-icons/io5';
import Modal from '@component/Modal';
import Table from '@component/Table';
import Menus from '@component/Menus';
import UserForm from './UserForm';
// Constants
import { STATUS_CODE } from '@constant/responseStatus';
import { CONFIRM_MESSAGE, DENIED_ACTION } from '@constant/messages';
// Services
import { updateRoomStatus } from '@service/roomServices';
import { checkOutUser } from '@service/userServices';
// Types
import { IUser } from '@type/users';
interface IUserRow {
user: IUser;
reload: boolean;
setReload: Dispatch<SetStateAction<boolean>>;
}
const UserRow = ({ user, reload, setReload }: IUserRow) => {
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;
const UserRow = ({ user }: IUserRow) => {
const { id, name, phone } = user;
return (
<Table.Row>
<div>{id}</div>
<div>{name}</div>
<div>{identifiedCode}</div>
<div>{phone}</div>
<div>
{
roomId
? roomId
: 'None'
}
</div>
<div>
<Modal>
<Menus.Menu>
@@ -77,16 +35,10 @@ const UserRow = ({ user, reload, setReload }: IUserRow) => {
</Menus.Button>
)}
/>
<Menus.Button
icon={<IoExit />}
onClick={() => handleCheckOut(user)}
>
Check out
</Menus.Button>
</Menus.List>
<Modal.Window name="edit" title="Edit user">
<UserForm user={user} setReload={setReload} reload={reload} />
<UserForm user={user} />
</Modal.Window>
</Menus.Menu>
</Modal>
+20 -58
View File
@@ -1,5 +1,4 @@
import { useSearchParams } from 'react-router-dom';
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
import { useCallback } from 'react';
// Components
import Menus from '@component/Menus';
@@ -13,9 +12,6 @@ import UserRow from './UserRow';
// Types
import { IUser } from '@type/users';
// Hooks
import { useFetch } from '@hook/useFetch';
// Constants
import { ORDERBY_OPTIONS, USER_PAGE } from '@constant/commons';
@@ -24,44 +20,23 @@ import Direction from '@commonStyle/Direction';
import { StyledOperationTable } from './styled';
import Spinner from '@commonStyle/Spinner';
interface IUserTable {
reload: boolean;
setReload: Dispatch<SetStateAction<boolean>>;
}
// Hooks
import { useUsers } from '@hook/users/useUsers';
const UserTable = ({ reload, setReload }: IUserTable) => {
const columnName = ['Id', 'Name', 'Identified Code', 'Phone', 'Room Id'];
const [users, setUsers] = useState<IUser[]>([]);
const [phoneSearch, setPhoneSearch] = useState('');
const [searchParams] = useSearchParams();
const sortByValue = searchParams.get('sortBy')
? searchParams.get('sortBy')!
: '';
const orderByValue = searchParams.get('orderBy')
? searchParams.get('orderBy')!
: '';
const UserTable = () => {
const columnName = ['Id', 'Name', 'Phone'];
const { isLoading, users } = useUsers();
const { data, isPending, errorFetchMsg } = useFetch(
'users',
'phone',
phoneSearch,
sortByValue,
orderByValue,
reload
const renderUserRow = useCallback(
(user: IUser) => (
<UserRow
user={user}
key={user.id}
/>
),
[]
);
useEffect(() => {
if (data) {
setUsers(data);
} else {
setUsers([]);
}
if (errorFetchMsg) {
console.error(errorFetchMsg);
}
}, [data, errorFetchMsg, setUsers]);
return (
<>
<Direction>
@@ -69,33 +44,20 @@ const UserTable = ({ reload, setReload }: IUserTable) => {
<OrderBy options={ORDERBY_OPTIONS} />
<SortBy options={USER_PAGE.SORTBY_OPTIONS} />
<Search
setValueSearch={setPhoneSearch}
setPlaceHolder="Search by phone..."
/>
<Search setPlaceHolder="Search by phone..." />
</StyledOperationTable>
{isPending && <Spinner />}
{isLoading && <Spinner />}
{users.length ? (
{users && users.length ? (
<Menus>
<Table columns="10% 30% 20% 20% 10% 5%">
<Table columns="10% 40% 35% 15%">
<Table.Header headerColumn={columnName} />
<Table.Body<IUser>
data={users}
render={(user: IUser) => (
<UserRow
user={user}
key={user.id}
reload={reload}
setReload={setReload}
/>
)}
/>
<Table.Body<IUser> data={users} render={renderUserRow} />
</Table>
</Menus>
) : (
!isPending && <Message>No data to show here!</Message>
!isLoading && <Message>No data to show here!</Message>
)}
</Direction>
</>
+2 -5
View File
@@ -1,5 +1,3 @@
import { useState } from 'react';
// Components
import UserTable from './UserTable';
@@ -17,7 +15,6 @@ import { FORM } from '@constant/commons';
const User = () => {
const TITLE = 'Add user';
const [reload, setReload] = useState(true);
return (
<>
@@ -33,12 +30,12 @@ const User = () => {
)}
/>
<Modal.Window name={FORM.USER} title={TITLE}>
<UserForm setReload={setReload} reload={reload} />
<UserForm />
</Modal.Window>
</Modal>
</Direction>
<UserTable reload={reload} setReload={setReload} />
<UserTable />
</StyledUser>
</>
);
@@ -24,7 +24,7 @@ const getAllRooms = async (
.from(ROOMS_TABLE)
.select('*')
.order(sortBy, { ascending: orderBy === 'asc' })
.like('name', `%${roomName}%`);
.ilike('name', `%${roomName}%`);
if (error) {
console.error(error.message);
@@ -54,7 +54,7 @@ const getAllUsers = async (
.from(USERS_TABLE)
.select('*')
.order(sortBy, { ascending: orderBy === 'asc' })
.like('phone', `%${phoneSearch}%`);
.ilike('phone', `%${phoneSearch}%`);
if (error) {
console.error(error.message);