Remove unnecessary code, refactor, fix bug and add section comment

This commit is contained in:
2023-12-01 11:24:31 +07:00
parent 7c6c33d455
commit 5b0d5671b3
44 changed files with 261 additions and 193 deletions

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+1 -1
View File
@@ -14,7 +14,7 @@ import RootLayout from '@component/RootLayout';
import User from './pages/User'; import User from './pages/User';
import Booking from './pages/Booking'; import Booking from './pages/Booking';
import Room from './pages/Room'; import Room from './pages/Room';
import NotFound from './pages/NotFound'; import NotFound from './pages/NotFound/NotFound';
import Login from '@page/Login'; import Login from '@page/Login';
import Account from '@page/Account'; import Account from '@page/Account';
@@ -1,5 +1,4 @@
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
import { COLOR, SIZE } from '@constant/styles';
interface IStyledButtonIcon { interface IStyledButtonIcon {
isHaveChildren: boolean; isHaveChildren: boolean;
@@ -77,13 +76,13 @@ const StyledButtonIcon = styled.button<IStyledButtonIcon>`
StyledButtonIcon.defaultProps = { StyledButtonIcon.defaultProps = {
style: { style: {
fontSize: SIZE.DEFAULT, fontSize: '14px',
backgroundColor: COLOR.DEFAULT, backgroundColor: 'var(--primary-color)',
color: COLOR.BLACK, color: '#000',
}, },
iconStyle: { iconStyle: {
color: COLOR.BLACK, color: '#000',
size: SIZE.DEFAULT, size: '14px',
}, },
}; };
@@ -13,7 +13,11 @@ interface IConfirmMessage {
} }
const ConfirmMessage = memo( const ConfirmMessage = memo(
({ message, onConfirm, onCloseModal }: IConfirmMessage) => { ({
message,
onConfirm,
onCloseModal
}: IConfirmMessage) => {
const handleConfirmBtn = useCallback(() => { const handleConfirmBtn = useCallback(() => {
onConfirm(); onConfirm();
onCloseModal!(); onCloseModal!();
@@ -34,7 +34,12 @@ const Form = ({ children, onSubmit, id }: IFormProps) => {
); );
}; };
const FormRow = ({ label, error, children, direction }: IFormRow) => { const FormRow = ({
label,
error,
children,
direction
}: IFormRow) => {
return ( return (
<StyledFormRow direction={direction}> <StyledFormRow direction={direction}>
<Label>{label}</Label> <Label>{label}</Label>
@@ -65,4 +65,11 @@ StyledFormRow.defaultProps = {
direction: 'horizontal', direction: 'horizontal',
}; };
export { StyledForm, StyledActionBtn, StyledFormRow, Label, Error, FormBtn }; export {
StyledForm,
StyledActionBtn,
StyledFormRow,
Label,
Error,
FormBtn
};
@@ -16,9 +16,6 @@ import MenusContext from '@context/MenuContext';
// Types // Types
import { Nullable } from '@type/common'; import { Nullable } from '@type/common';
// Constants
import { COLOR } from '@constant/styles';
interface IButton { interface IButton {
children?: string; children?: string;
icon?: ReactNode; icon?: ReactNode;
@@ -32,18 +29,28 @@ const Menus = ({ children }: { children: ReactNode }) => {
const open = setOpenId; const open = setOpenId;
return ( return (
<MenusContext.Provider value={{ openId, close, open }}> <MenusContext.Provider
value={{
openId,
close,
open,
}}
>
{children} {children}
</MenusContext.Provider> </MenusContext.Provider>
); );
}; };
const Toggle = ({ id }: { id: string }): ReactNode => { const Toggle = ({ id }: { id: string }): ReactNode => {
const { openId, close, open } = useContext(MenusContext); const {
openId,
close,
open
} = useContext(MenusContext);
const handleClick = (e: MouseEvent<HTMLButtonElement>) => { const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation(); e.stopPropagation();
openId === '' || openId !== id openId !== id
? open!(id) ? open!(id)
: close!(); : close!();
}; };
@@ -82,7 +89,7 @@ const Button = ({ children, icon, onClick, disabled }: IButton): ReactNode => {
<ButtonIcon <ButtonIcon
icon={icon} icon={icon}
onClick={handleClick} onClick={handleClick}
iconStyle={{ color: COLOR.PRIMARY, size: '19px' }} iconStyle={{ color: 'var(--primary-color)', size: '19px' }}
style={{ fontSize: '16px' }} style={{ fontSize: '16px' }}
disabled={disabled} disabled={disabled}
> >
@@ -63,4 +63,9 @@ const StyledList = styled.ul`
width: max-content; width: max-content;
`; `;
export { StyledMenu, StyledButton, StyledList, StyledToggle }; export {
StyledMenu,
StyledButton,
StyledList,
StyledToggle
};
@@ -39,4 +39,9 @@ const TitleModal = styled.p`
margin-bottom: 30px; margin-bottom: 30px;
` `
export { StyledModal, Overlay, StyledModalContent, TitleModal }; export {
StyledModal,
Overlay,
StyledModalContent,
TitleModal
};
@@ -1,4 +1,3 @@
import { useCallback, useMemo } from 'react';
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
// Constants // Constants
@@ -22,35 +21,24 @@ const Pagination = ({ count }: IPagination) => {
const totalPage = Math.ceil(count / DEFAULT_PAGE_SIZE); const totalPage = Math.ceil(count / DEFAULT_PAGE_SIZE);
const nextPage = useCallback(() => { const nextPage = () => {
const next = currentPage === totalPage const next = currentPage === totalPage ? currentPage : currentPage + 1;
? currentPage
: currentPage + 1;
searchParams.set('page', next.toString()); searchParams.set('page', next.toString());
setSearchParams(searchParams); setSearchParams(searchParams);
}, [currentPage, searchParams, totalPage, setSearchParams]); };
const previousPage = useCallback(() => { const previousPage = () => {
const previous = currentPage === 1 const previous = currentPage === 1 ? currentPage : currentPage - 1;
? currentPage
: currentPage - 1;
searchParams.set('page', previous.toString()); searchParams.set('page', previous.toString());
setSearchParams(searchParams); setSearchParams(searchParams);
}, [currentPage, searchParams, setSearchParams]); };
const fromIndex = useMemo( const fromIndex = (currentPage - 1) * DEFAULT_PAGE_SIZE + 1;
() => (currentPage - 1) * DEFAULT_PAGE_SIZE + 1,
[currentPage]
);
const toIndex = useMemo( const toIndex =
() => (currentPage === totalPage currentPage === totalPage ? count : currentPage * DEFAULT_PAGE_SIZE;
? count
: currentPage * DEFAULT_PAGE_SIZE),
[currentPage, count, totalPage]
);
return ( return (
totalPage > 1 && ( totalPage > 1 && (
@@ -47,4 +47,8 @@ const PaginationBtn = styled.button<IPaginationBtn>`
} }
`; `;
export { StyledPagination, PaginationBtn, Buttons }; export {
StyledPagination,
PaginationBtn,
Buttons
};
@@ -1,5 +1,5 @@
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
import { ChangeEvent } from 'react'; import { ChangeEvent, memo } from 'react';
// Components // Components
import Select from '@component/Select'; import Select from '@component/Select';
@@ -11,7 +11,7 @@ interface ISortByProps {
}[]; }[];
} }
const SortBy = ({ options }: ISortByProps) => { const SortBy = memo(({ options }: ISortByProps) => {
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const sortBy = searchParams.get('sortBy') || ''; const sortBy = searchParams.get('sortBy') || '';
const handleChange = (event: ChangeEvent<HTMLSelectElement>) => { const handleChange = (event: ChangeEvent<HTMLSelectElement>) => {
@@ -27,6 +27,6 @@ const SortBy = ({ options }: ISortByProps) => {
ariaLabel="Sort" ariaLabel="Sort"
/> />
); );
}; });
export default SortBy; export default SortBy;
@@ -9,7 +9,6 @@ const BOOKINGS_TABLE = 'bookings';
const ERROR_FETCHING_BOOKING = "Can't fetch booking data!"; const ERROR_FETCHING_BOOKING = "Can't fetch booking data!";
const ERROR_UPDATE_BOOKING = "Can't update booking!"; const ERROR_UPDATE_BOOKING = "Can't update booking!";
const ERROR_CREATE_BOOKING = "Can't create booking!"; const ERROR_CREATE_BOOKING = "Can't create booking!";
const ERROR_DELETE_BOOKING = "Can't delete booking!";
const CHECKOUT_SUCCESS = 'Check out success!'; const CHECKOUT_SUCCESS = 'Check out success!';
const ERROR_CHECKOUT = "Can't checkout!"; const ERROR_CHECKOUT = "Can't checkout!";
@@ -41,7 +40,6 @@ export {
ERROR_FETCHING_BOOKING, ERROR_FETCHING_BOOKING,
ERROR_UPDATE_BOOKING, ERROR_UPDATE_BOOKING,
ERROR_CREATE_BOOKING, ERROR_CREATE_BOOKING,
ERROR_DELETE_BOOKING,
ROOMS_TABLE, ROOMS_TABLE,
ERROR_FETCHING_ROOM, ERROR_FETCHING_ROOM,
ERROR_UPDATE_ROOM, ERROR_UPDATE_ROOM,
-11
View File
@@ -1,11 +0,0 @@
const COLOR = {
PRIMARY: '#0010ba',
BLACK: '#000',
DEFAULT: 'transparent',
};
const SIZE = {
DEFAULT: '14px',
};
export { COLOR, SIZE };
+5 -1
View File
@@ -34,4 +34,8 @@ const convertCurrencyToNumber = (currency: string) => {
return Number(currency.replace(/[^0-9.-]+/g,"")) return Number(currency.replace(/[^0-9.-]+/g,""))
} }
export { formatCurrency, getDayDiff, convertCurrencyToNumber }; export {
formatCurrency,
getDayDiff,
convertCurrencyToNumber
};
+12 -1
View File
@@ -26,8 +26,19 @@ const isValidString = (value: string): boolean => {
return value.trim().length >= 5; return value.trim().length >= 5;
}; };
/**
* Compare two days
* @param startDate The start date
* @param endDate The end date
* @returns Return true if start date greater than end date
*/
const compareTwoDates = (startDate: Date, endDate: Date): boolean => { const compareTwoDates = (startDate: Date, endDate: Date): boolean => {
return startDate > endDate; return startDate > endDate;
}; };
export { isValidRegex, isValidString, isValidDiscount, compareTwoDates }; export {
isValidRegex,
isValidString,
isValidDiscount,
compareTwoDates
};
@@ -3,6 +3,10 @@ import { useQuery } from '@tanstack/react-query';
// Services // Services
import { getCurrentAccount } from '@service/authenticationService'; import { getCurrentAccount } from '@service/authenticationService';
/**
* Get data of account currently login
* @returns The data of account currently login
*/
const useAccount = () => { const useAccount = () => {
let isAuthenticated: boolean = false; let isAuthenticated: boolean = false;
const { data: account, isPending } = useQuery({ const { data: account, isPending } = useQuery({
@@ -8,6 +8,10 @@ import { login as loginFn } from '@service/authenticationService';
// Types // Types
import { ILogin } from '@type/common'; import { ILogin } from '@type/common';
/**
* Login web
* @returns The login function and isPending boolean
*/
const useLogin = () => { const useLogin = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const navigate = useNavigate(); const navigate = useNavigate();
@@ -4,6 +4,10 @@ import { useNavigate } from 'react-router-dom';
// Services // Services
import { logout as logoutFn } from '@service/authenticationService'; import { logout as logoutFn } from '@service/authenticationService';
/**
* Logout web
* @returns The logout function and isPending boolean
*/
const useLogout = () => { const useLogout = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
@@ -7,6 +7,10 @@ import { updateAccount as updateAccountFn } from '@service/authenticationService
// Constants // Constants
import { UPDATE_ACCOUNT_SUCCESSFUL } from '@constant/messages'; import { UPDATE_ACCOUNT_SUCCESSFUL } from '@constant/messages';
/**
* Update account currently login.
* @returns Return updateAccount function and isUpdating boolean
*/
const useUpdateAccount = () => { const useUpdateAccount = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
@@ -1,35 +0,0 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
// Services
import { deleteBooking as deleteBookingFn } from '@service/bookingServices';
// Constants
import { DELETE_SUCCESS } from '@constant/messages';
/**
* Delete the booking from database
* @returns The boolean of status deleting and deleteBooking function
*/
const useDeleteBooking = () => {
const queryClient = useQueryClient();
const {
isPending: isDeleting,
mutate: deleteBooking,
isSuccess,
} = useMutation({
mutationFn: deleteBookingFn,
onSuccess: () => {
toast.success(DELETE_SUCCESS);
queryClient.invalidateQueries({
queryKey: ['bookings'],
});
},
onError: (err) => toast.error(err.message),
});
return { isDeleting, deleteBooking, isSuccess };
};
export { useDeleteBooking };
@@ -1,5 +1,11 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
/**
* The debounce hooks use to execute the callback function every x delay time
* @param value The value need to be pass
* @param delay The number of time want to delay
* @returns Return the value after delay number
*/
const useDebounce = <T>(value: T, delay: number): T => { const useDebounce = <T>(value: T, delay: number): T => {
const [debouncedValue, setDebouncedValue] = useState<T>(value); const [debouncedValue, setDebouncedValue] = useState<T>(value);
@@ -3,6 +3,10 @@ import { useContext } from 'react';
// Contexts // Contexts
import { UserRoomAvailableContext } from '@context/UserRoomAvailableContext'; import { UserRoomAvailableContext } from '@context/UserRoomAvailableContext';
/**
* The hooks check the place call is in UserRoomAvailableProvider or not
* @returns The context of UserRoomAvailableContext
*/
const useUserRoomAvailable = () => { const useUserRoomAvailable = () => {
const context = useContext(UserRoomAvailableContext); const context = useContext(UserRoomAvailableContext);
+6 -1
View File
@@ -33,4 +33,9 @@ const FormArea = styled.div`
margin-top: 50px; margin-top: 50px;
` `
export { Title, StyledAccount, FormArea, SubTitle }; export {
Title,
StyledAccount,
FormArea,
SubTitle
};
@@ -32,16 +32,18 @@ interface IBookingFormProp {
} }
const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => { const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
const { roomsAvailable, usersAvailable, dispatch } = useUserRoomAvailable(); const {
roomsAvailable,
usersAvailable,
dispatch
} = useUserRoomAvailable();
const { isCreating, createBooking } = useCreateBooking(); const { isCreating, createBooking } = useCreateBooking();
const { isUpdating, updateBooking } = useUpdateBooking(); const { isUpdating, updateBooking } = useUpdateBooking();
const isLoading = isCreating || isUpdating; const isLoading = isCreating || isUpdating;
const { id: editId, ...editValues } = { ...booking }; const { id: editId, ...editValues } = { ...booking };
const [ amountValue, setAmountValue ] = useState( const [amountValue, setAmountValue] = useState(
editValues.amount editValues.amount ? formatCurrency(editValues.amount) : '$0.00'
? formatCurrency(editValues.amount) );
: '$0.00'
);
const formMethods = useForm<IBooking>({ const formMethods = useForm<IBooking>({
defaultValues: editId defaultValues: editId
? { ? {
@@ -177,15 +179,12 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
const startDate = new Date(getValues().startDate); const startDate = new Date(getValues().startDate);
const endDate = new Date(getValues().endDate); const endDate = new Date(getValues().endDate);
if(startDate >= endDate) { if (startDate >= endDate) {
setValue('endDate', ''); setValue('endDate', '');
} }
}, [setValue, getValues]); }, [setValue, getValues]);
const startDateValidate = useMemo( const startDateValidate = new Date().toISOString().split('T')[0];
() => new Date().toISOString().split('T')[0],
[]
);
const endDateValidate = () => { const endDateValidate = () => {
if (getValues('startDate')) { if (getValues('startDate')) {
@@ -201,7 +200,7 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
return ( return (
<FormProvider {...formMethods}> <FormProvider {...formMethods}>
<Form onSubmit={handleSubmit(onSubmit)}> <Form onSubmit={handleSubmit(onSubmit)}>
<Form.Row label="User" error={errors?.userId?.message}> <Form.Row label="User:" error={errors?.userId?.message}>
{userOptions.length ? ( {userOptions.length ? (
<Select <Select
ariaLabel="user-select" ariaLabel="user-select"
@@ -218,7 +217,7 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
)} )}
</Form.Row> </Form.Row>
<Form.Row label="Room" error={errors?.roomId?.message}> <Form.Row label="Room:" error={errors?.roomId?.message}>
{roomOptions.length ? ( {roomOptions.length ? (
<Select <Select
ariaLabel="user-select" ariaLabel="user-select"
@@ -234,7 +233,7 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
)} )}
</Form.Row> </Form.Row>
<Form.Row label="Start Date" error={errors?.startDate?.message}> <Form.Row label="Start Date:" error={errors?.startDate?.message}>
<Input <Input
type="date" type="date"
id="startDate" id="startDate"
@@ -251,7 +250,7 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
/> />
</Form.Row> </Form.Row>
<Form.Row label="End Date" error={errors?.endDate?.message}> <Form.Row label="End Date:" error={errors?.endDate?.message}>
<Input <Input
type="date" type="date"
id="endDate" id="endDate"
@@ -269,7 +268,7 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
/> />
</Form.Row> </Form.Row>
<Form.Row label="Amount"> <Form.Row label="Amount:">
<Input <Input
type="hidden" type="hidden"
id="amount" id="amount"
@@ -289,7 +288,11 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
name="submit" name="submit"
disabled={!isDirty || !isValid || isLoading} disabled={!isDirty || !isValid || isLoading}
> >
{!editId ? 'Add' : 'Save'} {
!editId
? 'Add'
: 'Save'
}
</Form.Button> </Form.Button>
<Form.Button <Form.Button
type="button" type="button"
@@ -29,8 +29,15 @@ interface IBookingRow {
const BookingRow = ({ booking }: IBookingRow) => { const BookingRow = ({ booking }: IBookingRow) => {
const { checkOutBooking } = useCheckOut(); const { checkOutBooking } = useCheckOut();
const { id, users, startDate, endDate, rooms, amount, status } = booking; const {
const statusText = status ? 'Check in' : 'Check out'; id,
users,
startDate,
endDate,
rooms,
amount,
status
} = booking;
const formattedPrice = useMemo(() => formatCurrency(amount), [amount]); const formattedPrice = useMemo(() => formatCurrency(amount), [amount]);
const renderEditBtn = useCallback( const renderEditBtn = useCallback(
(onCloseModal: () => void) => ( (onCloseModal: () => void) => (
@@ -79,7 +86,11 @@ const BookingRow = ({ booking }: IBookingRow) => {
</div> </div>
<div>{rooms?.name}</div> <div>{rooms?.name}</div>
<div>{formattedPrice}</div> <div>{formattedPrice}</div>
<div>{statusText}</div> <div>{
status
? 'Check in'
: 'Check out'
}</div>
<div> <div>
<Modal> <Modal>
+5 -1
View File
@@ -21,4 +21,8 @@ const StyledOperationTable = styled.div`
justify-content: flex-end; justify-content: flex-end;
`; `;
export { StyledBooking, Title, StyledOperationTable }; export {
StyledBooking,
Title,
StyledOperationTable
};
+1 -4
View File
@@ -3,9 +3,6 @@ import { Navigate } from 'react-router-dom';
// Styled // Styled
import { LoginLayout, StyledLogo, TitleStyled } from './styled'; import { LoginLayout, StyledLogo, TitleStyled } from './styled';
// Assets
import logo from '@assets/images/logo.png';
// Components // Components
import LoginForm from './LoginForm'; import LoginForm from './LoginForm';
@@ -21,7 +18,7 @@ const Login = () => {
return ( return (
<LoginLayout> <LoginLayout>
<StyledLogo src={logo} /> <StyledLogo src={'./assets/images/logo.png'} />
<TitleStyled>Log In</TitleStyled> <TitleStyled>Log In</TitleStyled>
<LoginForm /> <LoginForm />
+7 -1
View File
@@ -40,4 +40,10 @@ const FieldInput = styled.input`
width: 300px; width: 300px;
` `
export { LoginLayout, StyledLogo, TitleStyled, StyledLoginForm, FieldInput }; export {
LoginLayout,
StyledLogo,
TitleStyled,
StyledLoginForm,
FieldInput
};
@@ -0,0 +1,21 @@
import { useNavigate } from 'react-router-dom';
// Styled
import { Button, Heading, StyledNotFound } from '.';
const NotFound = () => {
const useMoveBack = () => {
const navigate = useNavigate();
return () => navigate(-1);
};
return (
<StyledNotFound>
<Heading>The page not found!</Heading>
<Button onClick={useMoveBack}>Go back!</Button>
</StyledNotFound>
);
};
export default NotFound;
@@ -1,5 +1,4 @@
import { useNavigate } from 'react-router-dom'; import styled from "styled-components";
import styled from 'styled-components';
const StyledNotFound = styled.div` const StyledNotFound = styled.div`
height: 100vh; height: 100vh;
@@ -27,20 +26,8 @@ const Button = styled.button`
border-radius: var(--radius-sm); border-radius: var(--radius-sm);
`; `;
const useMoveBack = () => { export {
const navigate = useNavigate(); StyledNotFound,
return () => navigate(-1); Heading,
}; Button,
}
const NotFound = () => {
const onBack = useMoveBack();
return (
<StyledNotFound>
<Heading>The page not found!</Heading>
<Button onClick={onBack}>Go back!</Button>
</StyledNotFound>
);
};
export default NotFound;
+13 -7
View File
@@ -26,11 +26,13 @@ interface IRoomRow {
} }
const RoomRow = ({ room }: IRoomRow) => { const RoomRow = ({ room }: IRoomRow) => {
const { id, name, price, status } = room; const {
id,
name,
price,
status
} = room;
const { setIsDeleteRoom } = useSetIsDeleteRoom(); const { setIsDeleteRoom } = useSetIsDeleteRoom();
const statusText = status
? 'Unavailable'
: 'Available';
const formattedPrice = useMemo(() => formatCurrency(price), [price]); const formattedPrice = useMemo(() => formatCurrency(price), [price]);
const renderEditBtn = useCallback( const renderEditBtn = useCallback(
(onCloseModal: () => void) => ( (onCloseModal: () => void) => (
@@ -42,11 +44,11 @@ const RoomRow = ({ room }: IRoomRow) => {
); );
const renderDeleteBtn = useCallback( const renderDeleteBtn = useCallback(
(onCloseModal: () => void) => ( (onCloseModal: () => void) => (
<Menus.Button icon={<HiTrash />} onClick={onCloseModal}> <Menus.Button icon={<HiTrash />} onClick={onCloseModal} disabled={status}>
Delete Delete
</Menus.Button> </Menus.Button>
), ),
[] [status]
); );
return ( return (
@@ -54,7 +56,11 @@ const RoomRow = ({ room }: IRoomRow) => {
<div>{id}</div> <div>{id}</div>
<div>{name}</div> <div>{name}</div>
<div>{formattedPrice}</div> <div>{formattedPrice}</div>
<div>{statusText}</div> <div>{
status
? 'Unavailable'
: 'Available'
}</div>
<div> <div>
<Modal> <Modal>
@@ -26,7 +26,11 @@ import Pagination from '@component/Pagination';
const RoomTable = () => { const RoomTable = () => {
const columnName = ['Id', 'Name', 'Price', 'Status']; const columnName = ['Id', 'Name', 'Price', 'Status'];
const { isLoading, rooms, count } = useRooms(); const {
isLoading,
rooms,
count
} = useRooms();
const renderRoomRow = useCallback( const renderRoomRow = useCallback(
(room: IRoom) => <RoomRow room={room} key={room.id} />, (room: IRoom) => <RoomRow room={room} key={room.id} />,
+5 -1
View File
@@ -21,4 +21,8 @@ const StyledOperationTable = styled.div`
justify-content: flex-end; justify-content: flex-end;
`; `;
export { StyledRoom, Title, StyledOperationTable }; export {
StyledRoom,
Title,
StyledOperationTable
};
+8 -3
View File
@@ -18,7 +18,12 @@ interface IUserRow {
} }
const UserRow = ({ user }: IUserRow) => { const UserRow = ({ user }: IUserRow) => {
const { id, name, phone, isBooked } = user; const {
id,
name,
phone,
isBooked
} = user;
const { setIsDeleteUser } = useIsDeleteUser(); const { setIsDeleteUser } = useIsDeleteUser();
const renderEditBtn = useCallback( const renderEditBtn = useCallback(
@@ -32,11 +37,11 @@ const UserRow = ({ user }: IUserRow) => {
const renderDeleteBtn = useCallback( const renderDeleteBtn = useCallback(
(onCloseModal: () => void) => ( (onCloseModal: () => void) => (
<Menus.Button icon={<HiTrash />} onClick={onCloseModal}> <Menus.Button icon={<HiTrash />} onClick={onCloseModal} disabled={isBooked}>
Delete Delete
</Menus.Button> </Menus.Button>
), ),
[] [isBooked]
); );
return ( return (
<Table.Row> <Table.Row>
+12 -3
View File
@@ -25,8 +25,17 @@ import { useUsers } from '@hook/users/useUsers';
import Pagination from '@component/Pagination'; import Pagination from '@component/Pagination';
const UserTable = () => { const UserTable = () => {
const columnName = ['Id', 'Name', 'Phone', 'Is Booked']; const columnName = [
const { isLoading, users, count } = useUsers(); 'Id',
'Name',
'Phone',
'Is Booked'
];
const {
isLoading,
users,
count
} = useUsers();
const renderUserRow = useCallback( const renderUserRow = useCallback(
(user: IUser) => ( (user: IUser) => (
@@ -52,7 +61,7 @@ const UserTable = () => {
{users && users.length ? ( {users && users.length ? (
<Menus> <Menus>
<Table columns="10% 35% 30% 15% 10%"> <Table columns="10% 35% 30% 15% 5%">
<Table.Header headerColumn={columnName} /> <Table.Header headerColumn={columnName} />
<Table.Body<IUser> data={users} render={renderUserRow} /> <Table.Body<IUser> data={users} render={renderUserRow} />
<Table.Footer> <Table.Footer>
+5 -1
View File
@@ -21,4 +21,8 @@ const StyledOperationTable = styled.div`
justify-content: flex-end; justify-content: flex-end;
`; `;
export { StyledUser, Title, StyledOperationTable }; export {
StyledUser,
Title,
StyledOperationTable
};
@@ -7,6 +7,11 @@ import supabase from './supabaseService';
// Types // Types
import { IAccount } from '@type/account'; import { IAccount } from '@type/account';
/**
* Login services
* @param param0 The object contains email and password to login
* @returns The data of account login if success
*/
const login = async ({ email, password }: ILogin) => { const login = async ({ email, password }: ILogin) => {
const { data, error } = await supabase.auth.signInWithPassword({ const { data, error } = await supabase.auth.signInWithPassword({
email, email,
@@ -20,6 +25,10 @@ const login = async ({ email, password }: ILogin) => {
return data; return data;
}; };
/**
* Get data of account current login
* @returns The data of account currently login
*/
const getCurrentAccount = async () => { const getCurrentAccount = async () => {
const { data } = await supabase.auth.getSession(); const { data } = await supabase.auth.getSession();
@@ -36,6 +45,9 @@ const getCurrentAccount = async () => {
return accountData.user; return accountData.user;
}; };
/**
* Logout services
*/
const logout = async () => { const logout = async () => {
const { error } = await supabase.auth.signOut(); const { error } = await supabase.auth.signOut();
@@ -44,6 +56,11 @@ const logout = async () => {
} }
}; };
/**
* Update account currently login
* @param param0 The object contain fullName, password to be updated
* @returns The data of account after updated
*/
const updateAccount = async ({ fullName, password }: IAccount) => { const updateAccount = async ({ fullName, password }: IAccount) => {
let accountUpdate: UserAttributes | null = null; let accountUpdate: UserAttributes | null = null;
@@ -10,7 +10,6 @@ import {
BOOKINGS_TABLE, BOOKINGS_TABLE,
ERROR_CHECKOUT, ERROR_CHECKOUT,
ERROR_CREATE_BOOKING, ERROR_CREATE_BOOKING,
ERROR_DELETE_BOOKING,
ERROR_FETCHING_BOOKING, ERROR_FETCHING_BOOKING,
ERROR_UPDATE_BOOKING, ERROR_UPDATE_BOOKING,
} from '@constant/messages'; } from '@constant/messages';
@@ -100,22 +99,6 @@ const createBooking = async (booking: IBooking): Promise<IBooking> => {
return data; return data;
}; };
/**
* Delete booking in database
* @param idRoom The id of booking need to delete
*/
const deleteBooking = async (idBooking: number) => {
const { error } = await supabase
.from(BOOKINGS_TABLE)
.delete()
.eq('id', idBooking);
if (error) {
console.error(error.message);
throw new Error(ERROR_DELETE_BOOKING);
}
};
/** /**
* Check out booking services * Check out booking services
* @param param0 The ICheckOutBooking object * @param param0 The ICheckOutBooking object
@@ -150,6 +133,5 @@ export {
createBooking, createBooking,
getAllBookings, getAllBookings,
updateBooking, updateBooking,
deleteBooking,
checkOutBooking, checkOutBooking,
}; };
+2 -15
View File
@@ -3,7 +3,8 @@ import { IUser } from '@type/user';
// Services // Services
import supabase from './supabaseService'; import supabase from './supabaseService';
import { IDataState } from '@type/common';
// Constants
import { DEFAULT_PAGE_SIZE } from '@constant/config'; import { DEFAULT_PAGE_SIZE } from '@constant/config';
import { import {
ERROR_CREATE_USER, ERROR_CREATE_USER,
@@ -118,19 +119,6 @@ const getAllUsers = async ({
return { data, count }; return { data, count };
}; };
const getUserNotBooked = async (): Promise<IDataState[]> => {
const { data, error } = await supabase
.from(USERS_TABLE)
.select('id, name, isBooked');
if (error) {
console.error(error.message);
throw new Error(ERROR_FETCHING_USER);
}
return data;
};
const updateUserBookedStatus = async ( const updateUserBookedStatus = async (
id: number, id: number,
isBooked: boolean isBooked: boolean
@@ -153,6 +141,5 @@ export {
createUser, createUser,
getAllUsers, getAllUsers,
setIsDeleteUser, setIsDeleteUser,
getUserNotBooked,
updateUserBookedStatus, updateUserBookedStatus,
}; };
@@ -1,7 +1,7 @@
@font-face { @font-face {
font-family: 'Cabin'; font-family: 'Cabin';
src: url('../../assets/fonts/Cabin.woff2') format('woff2'), src: url('./assets/fonts/Cabin.woff2') format('woff2'),
url('../../assets/fonts/Cabin.ttf') format('truetype'); url('./assets/fonts/Cabin.ttf') format('truetype');
font-display: swap; font-display: swap;
} }
-1
View File
@@ -33,7 +33,6 @@
"@commonStyle/*": ["./src/commons/styles/*"], "@commonStyle/*": ["./src/commons/styles/*"],
"@type/*": ["./src/types/*"], "@type/*": ["./src/types/*"],
"@page/*": ["./src/pages/*"], "@page/*": ["./src/pages/*"],
"@assets/*": ["./src/assets/*"],
} }
}, },
"include": ["src", "test"], "include": ["src", "test"],