Fix comments

This commit is contained in:
2023-11-30 22:28:13 +07:00
parent 3f2747379c
commit 60b4723ddf
21 changed files with 274 additions and 140 deletions
@@ -23,6 +23,7 @@ interface IButton {
children?: string; children?: string;
icon?: ReactNode; icon?: ReactNode;
onClick?: () => void; onClick?: () => void;
disabled?: boolean;
} }
const Menus = ({ children }: { children: ReactNode }) => { const Menus = ({ children }: { children: ReactNode }) => {
@@ -69,7 +70,7 @@ const List = ({
return <StyledList ref={ref}>{children}</StyledList>; return <StyledList ref={ref}>{children}</StyledList>;
}; };
const Button = ({ children, icon, onClick }: IButton): ReactNode => { const Button = ({ children, icon, onClick, disabled }: IButton): ReactNode => {
const { close } = useContext(MenusContext); const { close } = useContext(MenusContext);
const handleClick = () => { const handleClick = () => {
onClick?.(); onClick?.();
@@ -83,6 +84,7 @@ const Button = ({ children, icon, onClick }: IButton): ReactNode => {
onClick={handleClick} onClick={handleClick}
iconStyle={{ color: COLOR.PRIMARY, size: '19px' }} iconStyle={{ color: COLOR.PRIMARY, size: '19px' }}
style={{ fontSize: '16px' }} style={{ fontSize: '16px' }}
disabled={disabled}
> >
{children} {children}
</ButtonIcon> </ButtonIcon>
@@ -4,7 +4,7 @@ import renderer from 'react-test-renderer';
import Table from '.'; import Table from '.';
// Types // Types
import { IUser } from '@type/users'; import { IUser } from '@type/user';
interface ITableRow { interface ITableRow {
user: IUser; user: IUser;
@@ -16,7 +16,9 @@ type TAction =
| 'addUser' | 'addUser'
| 'updateStatusUser' | 'updateStatusUser'
| 'updateUserName' | 'updateUserName'
| 'updateRoomName'; | 'updateRoomName'
| 'removeUser'
| 'removeRoom';
interface IAction { interface IAction {
type: TAction; type: TAction;
@@ -96,6 +98,12 @@ const reducer = (state: IUserRoomState, action: IAction) => {
}; };
} }
case 'removeUser':
return {
...state,
usersAvailable: state.usersAvailable.filter((user) => user.id !== action.payload[0].id)
}
case 'addRoom': { case 'addRoom': {
const tempArr = state.roomsAvailable; const tempArr = state.roomsAvailable;
const itemExist = state.roomsAvailable.find( const itemExist = state.roomsAvailable.find(
@@ -142,6 +150,12 @@ const reducer = (state: IUserRoomState, action: IAction) => {
}; };
} }
case 'removeRoom':
return {
...state,
roomsAvailable: state.roomsAvailable.filter((room) => room.id !== action.payload[0].id)
}
default: default:
throw new Error('Action unknown'); throw new Error('Action unknown');
} }
+5 -1
View File
@@ -26,4 +26,8 @@ const isValidString = (value: string): boolean => {
return value.trim().length >= 5; return value.trim().length >= 5;
}; };
export { isValidRegex, isValidString, isValidDiscount }; const compareTwoDates = (startDate: Date, endDate: Date): boolean => {
return startDate > endDate;
};
export { isValidRegex, isValidString, isValidDiscount, compareTwoDates };
@@ -2,34 +2,38 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
// Services // Services
import { deleteRoom as deleteRoomFn } from '@service/roomServices'; import { setIsDeleteRoom as setIsDeleteRoomFn } from '@service/roomServices';
// Constants // Constants
import * as messages from '@constant/messages'; import * as messages from '@constant/messages';
import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
/** /**
* Delete the room from database * Delete the room from database
* @returns The boolean of status deleting and deleteRoom function * @returns The boolean of status deleting and deleteRoom function
*/ */
const useDeleteRoom = () => { const useSetIsDeleteRoom = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { dispatch } = useUserRoomAvailable();
const { const {
isPending: isDeleting, isPending: isDeleting,
mutate: deleteRoom, mutate: setIsDeleteRoom,
isSuccess isSuccess,
} = useMutation({ } = useMutation({
mutationFn: deleteRoomFn, mutationFn: setIsDeleteRoomFn,
onSuccess: () => { onSuccess: (room) => {
toast.success(messages.DELETE_SUCCESS); toast.success(messages.DELETE_SUCCESS);
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ['rooms'], queryKey: ['rooms'],
}); });
dispatch?.({ type: 'removeRoom', payload: [{ id: room.id }] });
}, },
onError: (err) => toast.error(err.message), onError: (err) => toast.error(err.message),
}); });
return { isDeleting, deleteRoom, isSuccess }; return { isDeleting, setIsDeleteRoom, isSuccess };
}; };
export { useDeleteRoom }; export { useSetIsDeleteRoom };
@@ -2,34 +2,39 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
// Services // Services
import { deleteUser as deleteUserFn } from '@service/userServices'; import { setIsDeleteUser as setIsDeleteUserFn } from '@service/userServices';
// Constants // Constants
import * as messages from '@constant/messages'; import * as messages from '@constant/messages';
import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
/** /**
* Delete the user from database * Delete the user from database
* @returns The boolean of status deleting and deleteUser function * @returns The boolean of status deleting and deleteUser function
*/ */
const useDeleteUser = () => { const useIsDeleteUser = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { dispatch } = useUserRoomAvailable();
const { const {
isPending: isDeleting, isPending: isDeleting,
mutate: deleteUser, mutate: setIsDeleteUser,
isSuccess, isSuccess,
} = useMutation({ } = useMutation({
mutationFn: deleteUserFn, mutationFn: setIsDeleteUserFn,
onSuccess: () => { onSuccess: (user) => {
toast.success(messages.DELETE_SUCCESS); toast.success(messages.DELETE_SUCCESS);
queryClient.invalidateQueries({ queryClient.invalidateQueries({
queryKey: ['users'], queryKey: ['users'],
}); });
// Remove user from global state
dispatch?.({ type: 'removeUser', payload: [{ id: user.id }] });
}, },
onError: (err) => toast.error(err.message), onError: (err) => toast.error(err.message),
}); });
return { isDeleting, deleteUser, isSuccess }; return { isDeleting, setIsDeleteUser, isSuccess };
}; };
export { useDeleteUser }; export { useIsDeleteUser };
@@ -1,4 +1,4 @@
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form';
// Styled // Styled
@@ -17,11 +17,7 @@ import { useUpdateBooking } from '@hook/bookings/useUpdateBooking.ts';
import { useUserRoomAvailable } from '@hook/useUserRoomAvailable.ts'; import { useUserRoomAvailable } from '@hook/useUserRoomAvailable.ts';
// Helpers // Helpers
import { import { formatCurrency, getDayDiff } from '@helper/helper.ts';
convertCurrencyToNumber,
formatCurrency,
getDayDiff,
} from '@helper/helper.ts';
// Services // Services
import { getRoomById, updateRoomStatus } from '@service/roomServices.ts'; import { getRoomById, updateRoomStatus } from '@service/roomServices.ts';
@@ -35,24 +31,25 @@ interface IBookingFormProp {
booking?: TBookingResponse; booking?: TBookingResponse;
} }
interface IBookingForm extends Omit<IBooking, 'amount'> {
amount: string;
}
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 formMethods = useForm<IBookingForm>({ const [ amountValue, setAmountValue ] = useState(
editValues.amount
? formatCurrency(editValues.amount)
: '$0.00'
);
const formMethods = useForm<IBooking>({
defaultValues: editId defaultValues: editId
? { ? {
startDate: editValues.startDate, startDate: editValues.startDate,
endDate: editValues.endDate, endDate: editValues.endDate,
roomId: editValues.rooms?.id, roomId: editValues.rooms?.id,
userId: editValues.users?.id, userId: editValues.users?.id,
amount: formatCurrency(editValues.amount!), amount: editValues.amount!,
} }
: {}, : {},
}); });
@@ -67,12 +64,10 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
} = formMethods; } = formMethods;
// Submit form // Submit form
const onSubmit = async (newBooking: IBookingForm) => { const onSubmit = async (newBooking: IBooking) => {
if (!editId) { if (!editId) {
// Add request // Add request
createBooking( createBooking(newBooking, {
{ ...newBooking, amount: convertCurrencyToNumber(newBooking.amount) },
{
onSuccess: async () => { onSuccess: async () => {
reset(); reset();
onCloseModal?.(); onCloseModal?.();
@@ -91,14 +86,11 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
await updateRoomStatus(newBooking.roomId, true); await updateRoomStatus(newBooking.roomId, true);
await updateUserBookedStatus(newBooking.userId, true); await updateUserBookedStatus(newBooking.userId, true);
}, },
} });
);
} else { } else {
// Edit request // Edit request
newBooking.id = editId!; newBooking.id = editId!;
updateBooking( updateBooking(newBooking, {
{ ...newBooking, amount: convertCurrencyToNumber(newBooking.amount) },
{
onSuccess: async () => { onSuccess: async () => {
reset(); reset();
onCloseModal?.(); onCloseModal?.();
@@ -123,8 +115,7 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
// Change status new room // Change status new room
await updateRoomStatus(newBooking.roomId, true); await updateRoomStatus(newBooking.roomId, true);
}, },
} });
);
} }
}; };
@@ -161,12 +152,13 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
// Calculate the final price // Calculate the final price
const computePrice = useCallback(async () => { const computePrice = useCallback(async () => {
setValue('amount', 'Loading...');
const startDateValue = getValues('startDate'); const startDateValue = getValues('startDate');
const endDateValue = getValues('endDate'); const endDateValue = getValues('endDate');
const roomValue = getValues('roomId'); const roomValue = getValues('roomId');
if (startDateValue && endDateValue && roomValue) { if (startDateValue && endDateValue && roomValue) {
setAmountValue('Loading...');
const daysDiff = getDayDiff( const daysDiff = getDayDiff(
new Date(startDateValue), new Date(startDateValue),
new Date(endDateValue) new Date(endDateValue)
@@ -176,10 +168,20 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
const room = await getRoomById(roomValue.toString()); const room = await getRoomById(roomValue.toString());
const amount = daysDiff * room.price; const amount = daysDiff * room.price;
setValue('amount', formatCurrency(amount), { shouldValidate: true }); setValue('amount', amount, { shouldValidate: true });
setAmountValue(formatCurrency(amount));
} }
}, [getValues, setValue]); }, [getValues, setValue]);
const checkValidTwoDates = useCallback(() => {
const startDate = new Date(getValues().startDate);
const endDate = new Date(getValues().endDate);
if(startDate >= endDate) {
setValue('endDate', '');
}
}, [setValue, getValues]);
const startDateValidate = useMemo( const startDateValidate = useMemo(
() => new Date().toISOString().split('T')[0], () => new Date().toISOString().split('T')[0],
[] []
@@ -241,13 +243,15 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
required: REQUIRED_FIELD_ERROR, required: REQUIRED_FIELD_ERROR,
onChange: () => { onChange: () => {
trigger('startDate'); trigger('startDate');
checkValidTwoDates();
computePrice(); computePrice();
}, },
})} })}
/> />
</Form.Row> </Form.Row>
<Form.Row label="End Date" error={errors?.startDate?.message}> <Form.Row label="End Date" error={errors?.endDate?.message}>
<Input <Input
type="date" type="date"
id="endDate" id="endDate"
@@ -259,13 +263,15 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
trigger('endDate'); trigger('endDate');
computePrice(); computePrice();
}, },
validate: (endDateValue) =>
endDateValue > getValues().startDate || 'Invalid date',
})} })}
/> />
</Form.Row> </Form.Row>
<Form.Row label="Amount"> <Form.Row label="Amount">
<Input <Input
type="text" type="hidden"
id="amount" id="amount"
{...register('amount', { {...register('amount', {
required: REQUIRED_FIELD_ERROR, required: REQUIRED_FIELD_ERROR,
@@ -273,6 +279,8 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
})} })}
readOnly readOnly
/> />
<span>{amountValue}</span>
</Form.Row> </Form.Row>
<Form.Action> <Form.Action>
@@ -281,13 +289,13 @@ 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 type="button" variations="secondary" onClick={onCloseModal}> <Form.Button
type="button"
variations="secondary"
onClick={onCloseModal}
>
Close Close
</Form.Button> </Form.Button>
</Form.Action> </Form.Action>
@@ -29,35 +29,33 @@ interface IBookingRow {
const BookingRow = ({ booking }: IBookingRow) => { const BookingRow = ({ booking }: IBookingRow) => {
const { checkOutBooking } = useCheckOut(); const { checkOutBooking } = useCheckOut();
const { const { id, users, startDate, endDate, rooms, amount, status } = booking;
id, const statusText = status ? 'Check in' : 'Check out';
users,
startDate,
endDate,
rooms,
amount,
status
} = booking;
const statusText = status
? 'Check in'
: 'Check out';
const formattedPrice = useMemo(() => formatCurrency(amount), [amount]); const formattedPrice = useMemo(() => formatCurrency(amount), [amount]);
const renderEditBtn = useCallback( const renderEditBtn = useCallback(
(onCloseModal: () => void) => ( (onCloseModal: () => void) => (
<Menus.Button onClick={onCloseModal} icon={<RiEditBoxFill />}> <Menus.Button
onClick={onCloseModal}
icon={<RiEditBoxFill />}
disabled={!status}
>
Edit Edit
</Menus.Button> </Menus.Button>
), ),
[] [status]
); );
const renderCheckOutBtn = useCallback( const renderCheckOutBtn = useCallback(
(onCloseModal: () => void) => ( (onCloseModal: () => void) => (
<Menus.Button onClick={onCloseModal} icon={<ImExit />}> <Menus.Button
onClick={onCloseModal}
icon={<ImExit />}
disabled={!status}
>
Checkout Checkout
</Menus.Button> </Menus.Button>
), ),
[] [status]
); );
const handleClickCheckOutBtn = useCallback(() => { const handleClickCheckOutBtn = useCallback(() => {
+1 -1
View File
@@ -2,7 +2,7 @@
import Input from '@commonStyle/Input.ts'; import Input from '@commonStyle/Input.ts';
// Types // Types
import { IRoom } from '@type/rooms.ts'; import { IRoom } from '@type/room.ts';
// Constants // Constants
import { import {
+4 -4
View File
@@ -4,7 +4,7 @@ import { useCallback, useMemo } from 'react';
import { formatCurrency } from '@helper/helper'; import { formatCurrency } from '@helper/helper';
// Types // Types
import { IRoom } from '@type/rooms'; import { IRoom } from '@type/room';
// Components // Components
import RoomForm from './RoomForm'; import RoomForm from './RoomForm';
@@ -16,7 +16,7 @@ import { HiTrash } from 'react-icons/hi';
import ConfirmMessage from '@component/ConfirmMessage'; import ConfirmMessage from '@component/ConfirmMessage';
// Hooks // Hooks
import { useDeleteRoom } from '@hook/rooms/useDeleteRoom'; import { useSetIsDeleteRoom } from '@hook/rooms/useSetIsDeleteRoom';
// Constants // Constants
import { FORM } from '@constant/commons'; import { FORM } from '@constant/commons';
@@ -27,7 +27,7 @@ interface IRoomRow {
const RoomRow = ({ room }: IRoomRow) => { const RoomRow = ({ room }: IRoomRow) => {
const { id, name, price, status } = room; const { id, name, price, status } = room;
const { deleteRoom } = useDeleteRoom(); const { setIsDeleteRoom } = useSetIsDeleteRoom();
const statusText = status const statusText = status
? 'Unavailable' ? 'Unavailable'
: 'Available'; : 'Available';
@@ -79,7 +79,7 @@ const RoomRow = ({ room }: IRoomRow) => {
<Modal.Window name={FORM.DELETE} title="Delete Room"> <Modal.Window name={FORM.DELETE} title="Delete Room">
<ConfirmMessage <ConfirmMessage
message={`Are you sure to delete ${name}?`} message={`Are you sure to delete ${name}?`}
onConfirm={() => deleteRoom(id)} onConfirm={() => setIsDeleteRoom(id)}
/> />
</Modal.Window> </Modal.Window>
</Menus.Menu> </Menus.Menu>
@@ -10,7 +10,7 @@ import OrderBy from '@component/OrderBy';
import RoomRow from './RoomRow'; import RoomRow from './RoomRow';
// Types // Types
import { IRoom } from '@type/rooms'; import { IRoom } from '@type/room';
// Constants // Constants
import { ORDERBY_OPTIONS, ROOM_PAGE } from '@constant/commons'; import { ORDERBY_OPTIONS, ROOM_PAGE } from '@constant/commons';
@@ -2,7 +2,7 @@ import renderer from 'react-test-renderer';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
// Types // Types
import { IRoom } from '@type/rooms'; import { IRoom } from '@type/room';
// Components // Components
import RoomRow from '../RoomRow'; import RoomRow from '../RoomRow';
+1 -1
View File
@@ -20,7 +20,7 @@ import {
import { REGEX } from '@constant/commons.ts'; import { REGEX } from '@constant/commons.ts';
// Types // Types
import { IUser } from '@type/users.ts'; import { IUser } from '@type/user';
interface IUserFormProp { interface IUserFormProp {
onCloseModal?: () => void; onCloseModal?: () => void;
+4 -4
View File
@@ -6,12 +6,12 @@ import Menus from '@component/Menus';
import UserForm from './UserForm'; import UserForm from './UserForm';
// Types // Types
import { IUser } from '@type/users'; import { IUser } from '@type/user';
import { FORM } from '@constant/commons'; import { FORM } from '@constant/commons';
import { HiTrash } from 'react-icons/hi'; import { HiTrash } from 'react-icons/hi';
import { useCallback } from 'react'; import { useCallback } from 'react';
import ConfirmMessage from '@component/ConfirmMessage'; import ConfirmMessage from '@component/ConfirmMessage';
import { useDeleteUser } from '@hook/users/useDeleteUser'; import { useIsDeleteUser } from '@hook/users/useSetIsDeleteUser';
interface IUserRow { interface IUserRow {
user: IUser; user: IUser;
@@ -19,7 +19,7 @@ interface IUserRow {
const UserRow = ({ user }: IUserRow) => { const UserRow = ({ user }: IUserRow) => {
const { id, name, phone, isBooked } = user; const { id, name, phone, isBooked } = user;
const { deleteUser } = useDeleteUser(); const { setIsDeleteUser } = useIsDeleteUser();
const renderEditBtn = useCallback( const renderEditBtn = useCallback(
(onCloseModal: () => void) => ( (onCloseModal: () => void) => (
@@ -72,7 +72,7 @@ const UserRow = ({ user }: IUserRow) => {
<Modal.Window name={FORM.DELETE} title="Delete User"> <Modal.Window name={FORM.DELETE} title="Delete User">
<ConfirmMessage <ConfirmMessage
message={`Are you sure to delete ${name}?`} message={`Are you sure to delete ${name}?`}
onConfirm={() => deleteUser(id)} onConfirm={() => setIsDeleteUser(id)}
/> />
</Modal.Window> </Modal.Window>
</Menus.Menu> </Menus.Menu>
@@ -10,7 +10,7 @@ import OrderBy from '@component/OrderBy';
import UserRow from './UserRow'; import UserRow from './UserRow';
// Types // Types
import { IUser } from '@type/users'; import { IUser } from '@type/user';
// Constants // Constants
import { ORDERBY_OPTIONS, USER_PAGE } from '@constant/commons'; import { ORDERBY_OPTIONS, USER_PAGE } from '@constant/commons';
@@ -2,7 +2,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import renderer from 'react-test-renderer'; import renderer from 'react-test-renderer';
// Types // Types
import { IUser } from '@type/users'; import { IUser } from '@type/user';
// Components // Components
import UserRow from '../UserRow'; import UserRow from '../UserRow';
+16 -13
View File
@@ -1,5 +1,5 @@
// Types // Types
import { IRoom } from '@type/rooms'; import { IRoom } from '@type/room';
// Services // Services
import supabase from './supabaseService'; import supabase from './supabaseService';
@@ -38,7 +38,8 @@ const getAllRooms = async ({
.from(ROOMS_TABLE) .from(ROOMS_TABLE)
.select('*', { count: 'exact' }) .select('*', { count: 'exact' })
.order(sortBy, { ascending: orderBy === 'asc' }) .order(sortBy, { ascending: orderBy === 'asc' })
.like('name', `%${roomSearch}%`); .like('name', `%${roomSearch}%`)
.eq('isDelete', false);
if (page) { if (page) {
query = query.range(from, to); query = query.range(from, to);
@@ -94,16 +95,23 @@ const createRoom = async (room: IRoom): Promise<IRoom> => {
}; };
/** /**
* Delete room in database * Set room is delete status
* @param idRoom The id of room need to delete * @param idRoom The id of room need to set
*/ */
const deleteRoom = async (idRoom: number) => { const setIsDeleteRoom = async (idRoom: number) => {
const { error } = await supabase.from(ROOMS_TABLE).delete().eq('id', idRoom); const { data, error } = await supabase
.from(ROOMS_TABLE)
.update({ isDelete: true })
.eq('id', idRoom)
.select()
.single();
if (error) { if (error) {
console.error(error.message); console.error(error.message);
throw new Error(ERROR_DELETE_ROOM); throw new Error(ERROR_DELETE_ROOM);
} }
return data;
}; };
/** /**
@@ -126,16 +134,12 @@ const getRoomById = async (idRoom: string): Promise<IRoom> => {
return data; return data;
}; };
/** /**
* Update status of room * Update status of room
* @param id The id of room need to be change status * @param id The id of room need to be change status
* @param status The status of room * @param status The status of room
*/ */
const updateRoomStatus = async ( const updateRoomStatus = async (id: number, status: boolean): Promise<void> => {
id: number,
status: boolean
): Promise<void> => {
const { error } = await supabase const { error } = await supabase
.from(ROOMS_TABLE) .from(ROOMS_TABLE)
.update({ status }) .update({ status })
@@ -145,14 +149,13 @@ const updateRoomStatus = async (
console.error(error.message); console.error(error.message);
throw new Error(ERROR_UPDATE_ROOM); throw new Error(ERROR_UPDATE_ROOM);
} }
}; };
export { export {
getAllRooms, getAllRooms,
updateRoom, updateRoom,
createRoom, createRoom,
deleteRoom, setIsDeleteRoom,
getRoomById, getRoomById,
updateRoomStatus, updateRoomStatus,
}; };
+14 -6
View File
@@ -1,5 +1,5 @@
// Types // Types
import { IUser } from '@type/users'; import { IUser } from '@type/user';
// Services // Services
import supabase from './supabaseService'; import supabase from './supabaseService';
@@ -55,16 +55,23 @@ const updateUser = async (user: IUser): Promise<IUser> => {
}; };
/** /**
* Delete user in database * Set user in delete status
* @param idUser The id of user need to delete * @param idUser The id of user need to delete
*/ */
const deleteUser = async (idUser: number) => { const setIsDeleteUser = async (idUser: number) => {
const { error } = await supabase.from('users').delete().eq('id', idUser); const { data, error } = await supabase
.from(USERS_TABLE)
.update({isDelete: true})
.eq('id', idUser)
.select()
.single();
if (error) { if (error) {
console.error(error.message); console.error(error.message);
throw new Error(ERROR_DELETE_USER); throw new Error(ERROR_DELETE_USER);
} }
return data;
}; };
interface IGetAllUsers { interface IGetAllUsers {
@@ -94,7 +101,8 @@ const getAllUsers = async ({
.from(USERS_TABLE) .from(USERS_TABLE)
.select('*', { count: 'exact' }) .select('*', { count: 'exact' })
.order(sortBy, { ascending: orderBy === 'asc' }) .order(sortBy, { ascending: orderBy === 'asc' })
.like('phone', `%${phoneSearch}%`); .like('phone', `%${phoneSearch}%`)
.eq('isDelete', false);
if (page) { if (page) {
query = query.range(from, to); query = query.range(from, to);
@@ -144,7 +152,7 @@ export {
updateUser, updateUser,
createUser, createUser,
getAllUsers, getAllUsers,
deleteUser, setIsDeleteUser,
getUserNotBooked, getUserNotBooked,
updateUserBookedStatus, updateUserBookedStatus,
}; };
@@ -3,6 +3,7 @@ interface IRoom {
name: string; name: string;
price: number; price: number;
status: boolean; status: boolean;
isDelete: boolean;
} }
export type { IRoom }; export type { IRoom };
+87 -1
View File
@@ -25,7 +25,7 @@ export interface Database {
id?: number id?: number
roomId: number roomId: number
startDate: string startDate: string
status: boolean status?: boolean
userId: number userId: number
} }
Update: { Update: {
@@ -57,18 +57,21 @@ export interface Database {
rooms: { rooms: {
Row: { Row: {
id: number id: number
isDelete: boolean
name: string name: string
price: number price: number
status: boolean status: boolean
} }
Insert: { Insert: {
id?: number id?: number
isDelete?: boolean
name: string name: string
price: number price: number
status?: boolean status?: boolean
} }
Update: { Update: {
id?: number id?: number
isDelete?: boolean
name?: string name?: string
price?: number price?: number
status?: boolean status?: boolean
@@ -79,18 +82,21 @@ export interface Database {
Row: { Row: {
id: number id: number
isBooked: boolean isBooked: boolean
isDelete: boolean
name: string name: string
phone: string phone: string
} }
Insert: { Insert: {
id?: number id?: number
isBooked?: boolean isBooked?: boolean
isDelete?: boolean
name: string name: string
phone: string phone: string
} }
Update: { Update: {
id?: number id?: number
isBooked?: boolean isBooked?: boolean
isDelete?: boolean
name?: string name?: string
phone?: string phone?: string
} }
@@ -111,3 +117,83 @@ export interface Database {
} }
} }
} }
export type Tables<
PublicTableNameOrOptions extends
| keyof (Database["public"]["Tables"] & Database["public"]["Views"])
| { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof (Database[PublicTableNameOrOptions["schema"]]["Tables"] &
Database[PublicTableNameOrOptions["schema"]]["Views"])
: never = never
> = PublicTableNameOrOptions extends { schema: keyof Database }
? (Database[PublicTableNameOrOptions["schema"]]["Tables"] &
Database[PublicTableNameOrOptions["schema"]]["Views"])[TableName] extends {
Row: infer R
}
? R
: never
: PublicTableNameOrOptions extends keyof (Database["public"]["Tables"] &
Database["public"]["Views"])
? (Database["public"]["Tables"] &
Database["public"]["Views"])[PublicTableNameOrOptions] extends {
Row: infer R
}
? R
: never
: never
export type TablesInsert<
PublicTableNameOrOptions extends
| keyof Database["public"]["Tables"]
| { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"]
: never = never
> = PublicTableNameOrOptions extends { schema: keyof Database }
? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends {
Insert: infer I
}
? I
: never
: PublicTableNameOrOptions extends keyof Database["public"]["Tables"]
? Database["public"]["Tables"][PublicTableNameOrOptions] extends {
Insert: infer I
}
? I
: never
: never
export type TablesUpdate<
PublicTableNameOrOptions extends
| keyof Database["public"]["Tables"]
| { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"]
: never = never
> = PublicTableNameOrOptions extends { schema: keyof Database }
? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends {
Update: infer U
}
? U
: never
: PublicTableNameOrOptions extends keyof Database["public"]["Tables"]
? Database["public"]["Tables"][PublicTableNameOrOptions] extends {
Update: infer U
}
? U
: never
: never
export type Enums<
PublicEnumNameOrOptions extends
| keyof Database["public"]["Enums"]
| { schema: keyof Database },
EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database }
? keyof Database[PublicEnumNameOrOptions["schema"]]["Enums"]
: never = never
> = PublicEnumNameOrOptions extends { schema: keyof Database }
? Database[PublicEnumNameOrOptions["schema"]]["Enums"][EnumName]
: PublicEnumNameOrOptions extends keyof Database["public"]["Enums"]
? Database["public"]["Enums"][PublicEnumNameOrOptions]
: never
@@ -3,6 +3,7 @@ interface IUser {
name: string; name: string;
phone: string; phone: string;
isBooked: boolean; isBooked: boolean;
isDelete: boolean;
} }
export type { IUser }; export type { IUser };