diff --git a/hotel-management/jest-setup.ts b/hotel-management/jest-setup.ts
new file mode 100644
index 0000000..c44951a
--- /dev/null
+++ b/hotel-management/jest-setup.ts
@@ -0,0 +1 @@
+import '@testing-library/jest-dom'
diff --git a/hotel-management/jest.config.ts b/hotel-management/jest.config.ts
index 24064df..c621d0e 100644
--- a/hotel-management/jest.config.ts
+++ b/hotel-management/jest.config.ts
@@ -1,25 +1,18 @@
import type { Config } from 'jest';
const config: Config = {
+ preset: 'ts-jest',
verbose: true,
testEnvironment: 'jsdom',
transform: {
'^.+\\.tsx?$': 'ts-jest',
+ '.+\\.(svg|css|styl|less|sass|scss|png|jpg|ttf|woff|gif)$':
+ 'jest-transform-stub',
},
moduleNameMapper: {
- '\\.(gif|ttf|eot|svg|png)$': '/test/__mocks__/fileMock.ts',
- '\\.(css|less|sass|scss)$': 'identity-obj-proxy',
- '@service/(.*)': ['/src/services/$1'],
- '@constant/(.*)': ['/src/constants/$1'],
- '@hook/(.*)': ['/src/hooks/$1'],
- '@helper/(.*)': ['/src/helpers/$1'],
- '@context/(.*)': ['/src/contexts/$1'],
- '@component/(.*)': ['/src/components/$1'],
- '@commonStyle/(.*)': ['/src/commons/styles/$1'],
- '@type/(.*)': ['/src/types/$1'],
- '@page/(.*)': ['/src/pages/$1'],
+ '@src/(.*)': ['/src/$1'],
},
- setupFilesAfterEnv: ['/jest.setup.ts'],
+ setupFilesAfterEnv: ['/jest-setup.ts'],
setupFiles: ['/.jest/setEnvVar.ts'],
testEnvironmentOptions: {
customExportConditions: [''],
diff --git a/hotel-management/jest.setup.ts b/hotel-management/jest.setup.ts
deleted file mode 100644
index d0de870..0000000
--- a/hotel-management/jest.setup.ts
+++ /dev/null
@@ -1 +0,0 @@
-import "@testing-library/jest-dom";
diff --git a/hotel-management/package.json b/hotel-management/package.json
index 9c8d398..a8092fb 100644
--- a/hotel-management/package.json
+++ b/hotel-management/package.json
@@ -28,6 +28,7 @@
"styled-components": "^6.1.0"
},
"devDependencies": {
+ "@babel/preset-typescript": "^7.23.3",
"@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^14.1.0",
"@testing-library/user-event": "^14.5.1",
@@ -45,6 +46,7 @@
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
+ "jest-transform-stub": "^2.0.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"typescript": "^5.0.2",
diff --git a/hotel-management/pnpm-lock.yaml b/hotel-management/pnpm-lock.yaml
index 72ff2fd..742fe4c 100644
--- a/hotel-management/pnpm-lock.yaml
+++ b/hotel-management/pnpm-lock.yaml
@@ -40,6 +40,9 @@ dependencies:
version: 6.1.0(react-dom@18.2.0)(react@18.2.0)
devDependencies:
+ '@babel/preset-typescript':
+ specifier: ^7.23.3
+ version: 7.23.3(@babel/core@7.23.2)
'@testing-library/jest-dom':
specifier: ^6.1.4
version: 6.1.4(@types/jest@29.5.8)(jest@29.7.0)
@@ -91,6 +94,9 @@ devDependencies:
jest-environment-jsdom:
specifier: ^29.7.0
version: 29.7.0
+ jest-transform-stub:
+ specifier: ^2.0.0
+ version: 2.0.0
ts-jest:
specifier: ^29.1.1
version: 29.1.1(@babel/core@7.23.2)(jest@29.7.0)(typescript@5.2.2)
@@ -175,6 +181,13 @@ packages:
jsesc: 2.5.2
dev: true
+ /@babel/helper-annotate-as-pure@7.22.5:
+ resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.0
+ dev: true
+
/@babel/helper-compilation-targets@7.22.15:
resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==}
engines: {node: '>=6.9.0'}
@@ -186,6 +199,24 @@ packages:
semver: 6.3.1
dev: true
+ /@babel/helper-create-class-features-plugin@7.23.5(@babel/core@7.23.2):
+ resolution: {integrity: sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.2
+ '@babel/helper-annotate-as-pure': 7.22.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-function-name': 7.23.0
+ '@babel/helper-member-expression-to-functions': 7.23.0
+ '@babel/helper-optimise-call-expression': 7.22.5
+ '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.2)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ semver: 6.3.1
+ dev: true
+
/@babel/helper-environment-visitor@7.22.20:
resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
engines: {node: '>=6.9.0'}
@@ -206,6 +237,13 @@ packages:
'@babel/types': 7.23.0
dev: true
+ /@babel/helper-member-expression-to-functions@7.23.0:
+ resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.0
+ dev: true
+
/@babel/helper-module-imports@7.22.15:
resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
engines: {node: '>=6.9.0'}
@@ -227,11 +265,44 @@ packages:
'@babel/helper-validator-identifier': 7.22.20
dev: true
+ /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.2):
+ resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.2
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-module-imports': 7.22.15
+ '@babel/helper-simple-access': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/helper-validator-identifier': 7.22.20
+ dev: true
+
+ /@babel/helper-optimise-call-expression@7.22.5:
+ resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.0
+ dev: true
+
/@babel/helper-plugin-utils@7.22.5:
resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
engines: {node: '>=6.9.0'}
dev: true
+ /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.2):
+ resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.2
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-member-expression-to-functions': 7.23.0
+ '@babel/helper-optimise-call-expression': 7.22.5
+ dev: true
+
/@babel/helper-simple-access@7.22.5:
resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
engines: {node: '>=6.9.0'}
@@ -239,6 +310,13 @@ packages:
'@babel/types': 7.23.0
dev: true
+ /@babel/helper-skip-transparent-expression-wrappers@7.22.5:
+ resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.0
+ dev: true
+
/@babel/helper-split-export-declaration@7.22.6:
resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
engines: {node: '>=6.9.0'}
@@ -418,6 +496,18 @@ packages:
'@babel/helper-plugin-utils': 7.22.5
dev: true
+ /@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.23.2):
+ resolution: {integrity: sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.2
+ '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.2)
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-simple-access': 7.22.5
+ dev: true
+
/@babel/plugin-transform-react-jsx-self@7.22.5(@babel/core@7.23.2):
resolution: {integrity: sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==}
engines: {node: '>=6.9.0'}
@@ -438,6 +528,33 @@ packages:
'@babel/helper-plugin-utils': 7.22.5
dev: true
+ /@babel/plugin-transform-typescript@7.23.5(@babel/core@7.23.2):
+ resolution: {integrity: sha512-2fMkXEJkrmwgu2Bsv1Saxgj30IXZdJ+84lQcKKI7sm719oXs0BBw2ZENKdJdR1PjWndgLCEBNXJOri0fk7RYQA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.2
+ '@babel/helper-annotate-as-pure': 7.22.5
+ '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.2)
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.2)
+ dev: true
+
+ /@babel/preset-typescript@7.23.3(@babel/core@7.23.2):
+ resolution: {integrity: sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.2
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/helper-validator-option': 7.22.15
+ '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.2)
+ '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.2)
+ '@babel/plugin-transform-typescript': 7.23.5(@babel/core@7.23.2)
+ dev: true
+
/@babel/runtime@7.23.2:
resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==}
engines: {node: '>=6.9.0'}
@@ -3383,6 +3500,10 @@ packages:
- supports-color
dev: true
+ /jest-transform-stub@2.0.0:
+ resolution: {integrity: sha512-lspHaCRx/mBbnm3h4uMMS3R5aZzMwyNpNIJLXj4cEsV0mIUtS4IjYJLSoyjRCtnxb6RIGJ4NL2quZzfIeNhbkg==}
+ dev: true
+
/jest-util@29.7.0:
resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
diff --git a/hotel-management/src/App.test.tsx b/hotel-management/src/App.test.tsx
index 761b4f7..3879495 100644
--- a/hotel-management/src/App.test.tsx
+++ b/hotel-management/src/App.test.tsx
@@ -1,14 +1,14 @@
import { render, act, RenderResult } from '@testing-library/react';
// Services
-import * as userServices from '@service/userServices';
-import * as roomServices from '@service/roomServices';
+import * as userServices from '@src/services/userServices';
+import * as roomServices from '@src/services/roomServices';
// Components
import App from './App';
-jest.mock('@service/userServices');
-jest.mock('@service/roomServices');
+jest.mock('@src/services/userServices');
+jest.mock('@src/services/roomServices');
describe('App', () => {
let wrapper: RenderResult | null = null;
diff --git a/hotel-management/src/App.tsx b/hotel-management/src/App.tsx
index 534dbb3..b837bdc 100644
--- a/hotel-management/src/App.tsx
+++ b/hotel-management/src/App.tsx
@@ -2,106 +2,51 @@ 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';
-import { useEffect, useMemo, useReducer } from 'react';
// Components
import AppLayout from './components/AppLayout';
import Toast from './components/Toast';
-import RouteProtected from '@component/RouteProtected';
-import RootLayout from '@component/RootLayout';
+import RouteProtected from '@src/components/RouteProtected';
+import RootLayout from '@src/components/RootLayout';
// Pages
import User from './pages/User';
import Booking from './pages/Booking';
import Room from './pages/Room';
import NotFound from './pages/NotFound';
-import Login from '@page/Login';
-import Account from '@page/Account';
+import Login from '@src/pages/Login';
+import Account from '@src/pages/Account';
// Constants
import * as PATH from './constants/path';
-// Hooks
-import {
- UserRoomAvailableContext,
- initialState,
- reducer,
-} from '@context/UserRoomAvailableContext';
-
-// Services
-import { getAllUsers } from '@service/userServices';
-import { getAllRooms } from '@service/roomServices';
-
const queryClient = new QueryClient();
function App() {
- const [{ usersAvailable, roomsAvailable }, dispatch] = useReducer(
- reducer,
- initialState
- );
-
- // Init list user and room available
- useEffect(() => {
- const load = async () => {
- const tempUser = await getAllUsers({
- sortBy: 'id',
- orderBy: 'asc',
- phoneSearch: '',
- page: 0,
- });
-
- if (tempUser) {
- dispatch({ type: 'initUser', payload: tempUser.data });
- }
-
- const tempRoom = await getAllRooms({
- sortBy: 'id',
- orderBy: 'asc',
- roomSearch: '',
- page: 0,
- });
-
- if (tempRoom) {
- dispatch({ type: 'initRoom', payload: tempRoom.data });
- }
- };
-
- load();
- }, []);
-
- const store = useMemo(() => {
- return { roomsAvailable, usersAvailable, dispatch };
- }, [roomsAvailable, usersAvailable]);
-
return (
-
-
-
- }>
-
-
-
- }
- >
- }
- />
- } />
- } />
- } />
- } />
-
- } />
- } />
+
+
+ }>
+
+
+
+ }
+ >
+ } />
+ } />
+ } />
+ } />
+ } />
-
-
-
+ } />
+ } />
+
+
+
diff --git a/hotel-management/src/commons/styles/Direction.ts b/hotel-management/src/commons/styles/Direction.ts
index 60a3944..d671927 100644
--- a/hotel-management/src/commons/styles/Direction.ts
+++ b/hotel-management/src/commons/styles/Direction.ts
@@ -1,7 +1,7 @@
import styled, { css } from 'styled-components';
// Types
-import { TDirection } from '@type/common';
+import { TDirection } from '@src/types/common';
interface IDirection {
type?: TDirection;
diff --git a/hotel-management/src/commons/styles/Spinner.ts b/hotel-management/src/commons/styles/Spinner.ts
index 38f3f49..ebe349b 100644
--- a/hotel-management/src/commons/styles/Spinner.ts
+++ b/hotel-management/src/commons/styles/Spinner.ts
@@ -16,7 +16,6 @@ const Spinner = styled.div`
top/10px 10px no-repeat,
conic-gradient(#0000 30%, var(--primary-color));
-webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - 10px), #000 0);
- mask: none;
animation: ${rotate} 1.5s infinite linear;
`;
diff --git a/hotel-management/src/components/AppLayout/__snapshots__/AppLayout.test.tsx.snap b/hotel-management/src/components/AppLayout/__snapshots__/AppLayout.test.tsx.snap
index 45eb3ab..06f0d09 100644
--- a/hotel-management/src/components/AppLayout/__snapshots__/AppLayout.test.tsx.snap
+++ b/hotel-management/src/components/AppLayout/__snapshots__/AppLayout.test.tsx.snap
@@ -21,8 +21,9 @@ exports[`AppLayout Should render correctly 1`] = `
@@ -172,8 +172,9 @@ exports[`AppLayout Should render correctly 1`] = `
diff --git a/hotel-management/src/components/AppLayout/index.tsx b/hotel-management/src/components/AppLayout/index.tsx
index e4070a6..74bb6f7 100644
--- a/hotel-management/src/components/AppLayout/index.tsx
+++ b/hotel-management/src/components/AppLayout/index.tsx
@@ -1,26 +1,71 @@
import { Outlet } from 'react-router-dom';
// Components
-import Header from '@component/Header';
-import Sidebar from '@component/Sidebar';
+import Header from '../Header';
+import Sidebar from '../Sidebar';
// Styled
import { Main, StyledAppLayout } from './styled';
// Hooks
-import { useAccount } from '@hook/authentication/useAccount';
+import { useAccount } from '@src/hooks/authentication/useAccount';
+
+// Contexts
+import { initialState, reducer, UserRoomAvailableContext } from '@src/contexts/UserRoomAvailableContext.ts';
+import { useEffect, useReducer } from 'react';
+
+// Services
+import { getAllUsers } from '@src/services/userServices.ts';
+import { getAllRooms } from '@src/services/roomServices.ts';
const AppLayout = () => {
const { account } = useAccount();
+ const [{ usersAvailable, roomsAvailable }, dispatch] = useReducer(
+ reducer,
+ initialState
+ );
+
+ // Init list user and room available
+ // Init list user and room available
+ useEffect(() => {
+ const load = async () => {
+ const tempUser = await getAllUsers({
+ sortBy: 'id',
+ orderBy: 'asc',
+ phoneSearch: '',
+ page: 0,
+ });
+
+ if (tempUser) {
+ dispatch({ type: 'initUser', payload: tempUser.data });
+ }
+
+ const tempRoom = await getAllRooms({
+ sortBy: 'id',
+ orderBy: 'asc',
+ roomSearch: '',
+ page: 0,
+ });
+
+ if (tempRoom) {
+ dispatch({ type: 'initRoom', payload: tempRoom.data });
+ }
+ };
+
+ load();
+ }, []);
+
return (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
);
};
diff --git a/hotel-management/src/components/ButtonIcon/ButtonIcon.test.tsx b/hotel-management/src/components/ButtonIcon/ButtonIcon.test.tsx
index 2ba19a9..b4ca1cf 100644
--- a/hotel-management/src/components/ButtonIcon/ButtonIcon.test.tsx
+++ b/hotel-management/src/components/ButtonIcon/ButtonIcon.test.tsx
@@ -9,7 +9,6 @@ describe('ButtonIcon', () => {
}
- iconStyle={{ size: '23px' }}
/>
);
diff --git a/hotel-management/src/components/ButtonIcon/__snapshots__/ButtonIcon.test.tsx.snap b/hotel-management/src/components/ButtonIcon/__snapshots__/ButtonIcon.test.tsx.snap
index 12e3a40..d7202f3 100644
--- a/hotel-management/src/components/ButtonIcon/__snapshots__/ButtonIcon.test.tsx.snap
+++ b/hotel-management/src/components/ButtonIcon/__snapshots__/ButtonIcon.test.tsx.snap
@@ -6,8 +6,10 @@ exports[`ButtonIcon Should render correctly 1`] = `
"baseElement":
,
"container":
,
"debug": [Function],
diff --git a/hotel-management/src/components/ButtonIcon/index.tsx b/hotel-management/src/components/ButtonIcon/index.tsx
index 44e47c0..0249f6f 100644
--- a/hotel-management/src/components/ButtonIcon/index.tsx
+++ b/hotel-management/src/components/ButtonIcon/index.tsx
@@ -1,50 +1,35 @@
-import { ReactNode } from 'react';
+import { ButtonHTMLAttributes, ReactNode } from 'react';
// Styled
import { StyledButtonIcon } from './styled';
-interface IButtonIcon {
+interface IButtonIcon extends ButtonHTMLAttributes {
icon: ReactNode;
- children?: ReactNode;
- style?: {
- fontSize?: string;
- backgroundColor?: string;
- color?: string;
- };
- iconStyle?: {
- color?: string;
- size?: string;
- };
- onClick?: () => void;
- disabled?: boolean;
- label?: string;
+ iconSize?: string;
+ iconColor?: string;
+ fontSize?: string;
+ text?: string;
+ variations?: string;
}
const ButtonIcon = ({
icon,
- children,
- style,
- iconStyle,
- onClick,
- disabled,
- label,
+ iconSize,
+ iconColor,
+ text,
+ fontSize,
+ variations,
+ ...props
}: IButtonIcon) => {
- const isHaveChildren = Boolean(children);
-
return (
- {icon} {children}
+ {icon} {text && {text}}
);
};
diff --git a/hotel-management/src/components/ButtonIcon/styled.ts b/hotel-management/src/components/ButtonIcon/styled.ts
index d0cd174..f308b2b 100644
--- a/hotel-management/src/components/ButtonIcon/styled.ts
+++ b/hotel-management/src/components/ButtonIcon/styled.ts
@@ -1,89 +1,104 @@
-import styled, { css } from 'styled-components';
+import styled, { css, RuleSet } from 'styled-components';
interface IStyledButtonIcon {
- isHaveChildren: boolean;
- style?: {
- fontSize?: string;
- backgroundColor?: string;
- color?: string;
- };
- iconStyle?: {
- color?: string;
- size?: string;
- };
+ iconSize?: string;
+ iconColor?: string;
+ fontSize?: string;
+ variations?: string;
}
+export interface IVariations {
+ [key: string]: RuleSet
@@ -84,10 +84,10 @@ exports[`Pagination Should render correctly 1`] = `
Showing
1
to
- 5
+ 10
of
- 10
+ 20
results
diff --git a/hotel-management/src/components/Pagination/index.test.tsx b/hotel-management/src/components/Pagination/index.test.tsx
index aa428cb..d3fe58f 100644
--- a/hotel-management/src/components/Pagination/index.test.tsx
+++ b/hotel-management/src/components/Pagination/index.test.tsx
@@ -5,7 +5,7 @@ import { BrowserRouter } from 'react-router-dom';
import Pagination from '.';
describe('Pagination', () => {
- const count = 10;
+ const count = 20;
let wrapper: RenderResult | null = null;
beforeEach(() => {
diff --git a/hotel-management/src/components/Pagination/index.tsx b/hotel-management/src/components/Pagination/index.tsx
index 2ed3d40..0eaec52 100644
--- a/hotel-management/src/components/Pagination/index.tsx
+++ b/hotel-management/src/components/Pagination/index.tsx
@@ -1,7 +1,7 @@
import { useSearchParams } from 'react-router-dom';
// Constants
-import { DEFAULT_PAGE_SIZE } from '@constant/config';
+import { DEFAULT_PAGE_SIZE } from '@src/constants/config';
// Styled
import { Buttons, PaginationBtn, StyledPagination } from './styled';
diff --git a/hotel-management/src/components/RootLayout/index.tsx b/hotel-management/src/components/RootLayout/index.tsx
index 8ca6e58..7bfe8a3 100644
--- a/hotel-management/src/components/RootLayout/index.tsx
+++ b/hotel-management/src/components/RootLayout/index.tsx
@@ -1,11 +1,11 @@
import { Outlet } from 'react-router-dom';
// Styled
-import Spinner from '@commonStyle/Spinner';
+import Spinner from '@src/commons/styles/Spinner';
import { FullPageLayout } from './styled';
// Hooks
-import { useAccount } from '@hook/authentication/useAccount';
+import { useAccount } from '@src/hooks/authentication/useAccount';
const RootLayout = () => {
const { isPending } = useAccount();
diff --git a/hotel-management/src/components/RouteProtected/index.test.tsx b/hotel-management/src/components/RouteProtected/index.test.tsx
index 69da977..cab085e 100644
--- a/hotel-management/src/components/RouteProtected/index.test.tsx
+++ b/hotel-management/src/components/RouteProtected/index.test.tsx
@@ -1,6 +1,6 @@
import { render } from '@testing-library/react';
import RouteProtected from '.';
-import AppLayout from '@component/AppLayout';
+import AppLayout from '../AppLayout';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { BrowserRouter } from 'react-router-dom';
diff --git a/hotel-management/src/components/RouteProtected/index.tsx b/hotel-management/src/components/RouteProtected/index.tsx
index 1726ef0..1b18703 100644
--- a/hotel-management/src/components/RouteProtected/index.tsx
+++ b/hotel-management/src/components/RouteProtected/index.tsx
@@ -1,4 +1,4 @@
-import { useAccount } from '@hook/authentication/useAccount';
+import { useAccount } from '@src/hooks/authentication/useAccount';
import { ReactNode } from 'react';
import { Navigate } from 'react-router-dom';
diff --git a/hotel-management/src/components/Search/Search.test.tsx b/hotel-management/src/components/Search/Search.test.tsx
index 5e6ff00..3949f6b 100644
--- a/hotel-management/src/components/Search/Search.test.tsx
+++ b/hotel-management/src/components/Search/Search.test.tsx
@@ -9,7 +9,7 @@ jest.mock('react-router-dom', () => ({
useSearchParams: jest.fn(),
}));
-jest.mock('@hook/useDebounce', () => ({
+jest.mock('@src/hooks/useDebounce', () => ({
useDebounce: jest.fn((value) => value),
}));
diff --git a/hotel-management/src/components/Search/index.tsx b/hotel-management/src/components/Search/index.tsx
index fcd8bb6..da50c11 100644
--- a/hotel-management/src/components/Search/index.tsx
+++ b/hotel-management/src/components/Search/index.tsx
@@ -5,10 +5,10 @@ import { useSearchParams } from 'react-router-dom';
import { StyledSearch } from './styled';
// Hooks
-import { useDebounce } from '@hook/useDebounce';
+import { useDebounce } from '@src/hooks/useDebounce';
// Types
-import { Nullable } from '@type/common';
+import { Nullable } from '@src/types/common';
interface ISearch {
setPlaceHolder: string;
@@ -17,7 +17,12 @@ interface ISearch {
const Search = ({ setPlaceHolder }: ISearch) => {
const field = 'search';
const [searchParams, setSearchParams] = useSearchParams();
- const [query, setQuery] = useState>(null);
+ const [query, setQuery] = useState>(
+ searchParams.get(field)
+ ? searchParams.get(field)
+ : '',
+ );
+
const debounceValue = useDebounce>(query, 700);
useEffect(() => {
@@ -32,6 +37,7 @@ const Search = ({ setPlaceHolder }: ISearch) => {
setQuery(e.target.value)}
placeholder={setPlaceHolder}
+ value={query!}
/>
);
};
diff --git a/hotel-management/src/components/Sidebar/index.tsx b/hotel-management/src/components/Sidebar/index.tsx
index 7d97768..89a8159 100644
--- a/hotel-management/src/components/Sidebar/index.tsx
+++ b/hotel-management/src/components/Sidebar/index.tsx
@@ -1,5 +1,5 @@
// Components
-import Nav from '@component/Nav';
+import Nav from '../Nav';
// Styled
import { Heading, StyledSidebar } from './styled';
diff --git a/hotel-management/src/components/SortBy/index.tsx b/hotel-management/src/components/SortBy/index.tsx
index 546e5ed..ca85296 100644
--- a/hotel-management/src/components/SortBy/index.tsx
+++ b/hotel-management/src/components/SortBy/index.tsx
@@ -2,7 +2,7 @@ import { useSearchParams } from 'react-router-dom';
import { ChangeEvent, memo } from 'react';
// Components
-import Select from '@component/Select';
+import Select from '../Select';
interface ISortByProps {
options: {
diff --git a/hotel-management/src/components/Table/Table.test.tsx b/hotel-management/src/components/Table/Table.test.tsx
deleted file mode 100644
index 9f6100f..0000000
--- a/hotel-management/src/components/Table/Table.test.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import { render } from '@testing-library/react';
-
-// Components
-import Table from '.';
-
-// Types
-import { IUser } from '@type/user';
-
-interface ITableRow {
- user: IUser;
-}
-
-describe('Table', () => {
- const columnName = ['Column 1', 'Column 2'];
- const tempUser: IUser[] = [
- {
- id: 1,
- name: 'Nezumi',
- phone: '123',
- isBooked: true,
- isDelete: true,
- },
- {
- id: 2,
- name: 'Loi Phan',
- phone: '453',
- isBooked: false,
- isDelete: true,
- },
- ];
- const TableRow = ({ user }: ITableRow) => {
- const {
- id,
- name,
- phone,
- isBooked
- } = user;
-
- return (
-
- {id}
- {name}
- {phone}
- {isBooked}
-
- );
- };
- const renderRow = (user: IUser) => ;
-
- const wrapper = render(
-
-
- data={tempUser} render={renderRow} />
-
- );
-
- test('Should render correctly', () => {
- expect(wrapper).toMatchSnapshot();
- });
-});
diff --git a/hotel-management/src/components/Table/index.tsx b/hotel-management/src/components/Table/index.tsx
index 76024e3..9de0afa 100644
--- a/hotel-management/src/components/Table/index.tsx
+++ b/hotel-management/src/components/Table/index.tsx
@@ -1,70 +1,151 @@
-import { ReactNode, useContext } from 'react';
+// Types
+import {ColumnProps} from '@src/types/common';
// Styled
import {
StyledBody,
+ StyledFooter,
StyledHeader,
StyledRow,
StyledTable,
- StyledFooter,
} from './styled';
-// Contexts
-import TableContext from '@context/TableContext';
+// Components
+import Pagination from '../Pagination';
+import {TbArrowNarrowRight} from 'react-icons/tb';
+import {StyledTableOption} from '@src/pages/Room/styled.ts';
+import OrderBy from '@src/components/OrderBy';
+import {ORDERBY_OPTIONS} from '@src/constants/commons.ts';
+import SortBy from '@src/components/SortBy';
+import Search from '@src/components/Search';
+import Direction from '@src/commons/styles/Direction.ts';
+import {Dispatch, SetStateAction} from 'react';
-export interface ITable {
- columns?: string;
- children: ReactNode;
-}
+const parseWidthString = (columnsWidth: number[]): string => {
+ let result: string = '';
-export interface IHeader {
- headerColumn: string[];
-}
+ const totalWidth = columnsWidth.reduce((
+ partialSum,
+ a
+ ) => partialSum + a, 0);
+ columnsWidth.forEach((width) => {
+ result += Math.round((
+ width / totalWidth
+ ) * 100)
+ .toString() + '% ';
+ });
-interface ITableBody {
- data?: T[];
- render?: CallbackMapFunc;
-}
-
-type CallbackMapFunc = (value: T, index: number, array: T[]) => ReactNode;
-
-const Table = ({ columns, children }: ITable) => {
- return (
-
- {children}
-
- );
+ return result;
};
-const Header = ({ headerColumn }: IHeader) => {
- const { columns } = useContext(TableContext);
+type Props = {
+ columns: ColumnProps[];
+ rows: T[];
+ stateSelected: {
+ itemSelected: T | undefined;
+ setItemSelected: Dispatch>;
+ };
+ count?: number | null;
+ onRowClick?: (rowData: T) => void;
+ enabledOrder?: boolean;
+ sortBy?: {
+ value: string;
+ label: string;
+ }[];
+ searchPlaceHolder?: string;
+};
+
+const Table = ({
+ rows,
+ columns,
+ count,
+ onRowClick,
+ stateSelected,
+ sortBy,
+ searchPlaceHolder,
+ enabledOrder = false,
+}: Props) => {
+ const width = parseWidthString(columns.map((item) => item.width));
+ const {itemSelected, setItemSelected} = stateSelected;
+
+ const headers = columns.map((
+ column,
+ index
+ ) => {
+ return {column.title}
;
+ });
+
+ const renderRows = rows.map((
+ row,
+ rowIndex
+ ) => {
+ const handleRowClick = () => {
+ if (onRowClick) {
+ onRowClick(row);
+ setItemSelected(row);
+ }
+ };
+
+ return (
+
+ {columns.map((
+ column,
+ columnIndex
+ ) => {
+ const value = row[column.key as keyof typeof row] as string;
+
+ if (column.isDateValue) {
+ return (
+
+ {value[0]}
+ {value[1]}
+
+ );
+ }
+
+ return {value}
;
+ })}
+
+ );
+ });
return (
-
- {headerColumn.map((item) => (
- {item}
- ))}
-
+
+
+ {enabledOrder && }
+ {Boolean(sortBy?.length) && }
+ {Boolean(searchPlaceHolder) && }
+
+
+ {rows && rows.length &&
+ (
+
+ {headers}
+
+ {renderRows}
+
+ {Boolean(count) && (
+
+
+
+ )}
+
+ )
+ }
+
);
-};
-
-const Body = ({ data, render }: ITableBody) => {
- return (
- data!.length && (
- {data?.map(render as CallbackMapFunc)}
- )
- );
-};
-
-const Row = ({ children }: ITable) => {
- const { columns } = useContext(TableContext);
-
- return {children};
-};
-
-Table.Header = Header;
-Table.Body = Body;
-Table.Row = Row;
-Table.Footer = StyledFooter;
+}
export default Table;
diff --git a/hotel-management/src/components/Table/styled.ts b/hotel-management/src/components/Table/styled.ts
index 7c10749..57d76bd 100644
--- a/hotel-management/src/components/Table/styled.ts
+++ b/hotel-management/src/components/Table/styled.ts
@@ -1,7 +1,8 @@
import styled from 'styled-components';
-// Interfaces
-import { ITable } from '.';
+interface ICommonRow {
+ width: string;
+}
const StyledTable = styled.div`
border: 1px solid var(--border-color);
@@ -10,9 +11,9 @@ const StyledTable = styled.div`
font-size: 20px;
`;
-const CommonRow = styled.div`
+const CommonRow = styled.div`
display: grid;
- grid-template-columns: ${(props) => props.columns};
+ grid-template-columns: ${(props) => props.width};
column-gap: 10px;
align-items: center;
justify-items: center;
@@ -24,6 +25,16 @@ const StyledBody = styled.div`
const StyledRow = styled(CommonRow)`
padding: 20px;
+
+ cursor: pointer;
+
+ &:hover {
+ background-color: var(--item-hover);
+ }
+
+ &.selected {
+ background-color: var(--item-selected);
+ }
&:not(:last-child) {
border-bottom: 1px solid var(--border-color);
diff --git a/hotel-management/src/contexts/ItemSelected.ts b/hotel-management/src/contexts/ItemSelected.ts
new file mode 100644
index 0000000..0832895
--- /dev/null
+++ b/hotel-management/src/contexts/ItemSelected.ts
@@ -0,0 +1,35 @@
+import { Dispatch, createContext } from 'react';
+
+export type TItemSelectAction = 'setData' | 'removeData';
+
+interface IAction {
+ type: TItemSelectAction;
+ payload: T;
+}
+
+interface IItemSelect {
+ data?: any;
+ dispatch?: Dispatch>;
+}
+
+const ItemSelectContext = createContext({});
+
+const itemSelectReducer =
+ () =>
+ (state: T, action: IAction) => {
+ switch (action.type) {
+ // Init data for the first load
+ case 'setData': {
+ const tempData = { ...state };
+
+ return {
+ data: tempData,
+ };
+ }
+
+ default:
+ throw new Error('Action unknown');
+ }
+ };
+
+export { itemSelectReducer, ItemSelectContext };
diff --git a/hotel-management/src/contexts/UserRoomAvailableContext.ts b/hotel-management/src/contexts/UserRoomAvailableContext.ts
index 66d03f4..9cf76db 100644
--- a/hotel-management/src/contexts/UserRoomAvailableContext.ts
+++ b/hotel-management/src/contexts/UserRoomAvailableContext.ts
@@ -1,7 +1,7 @@
import { Dispatch, createContext } from 'react';
// Types
-import { IDataState } from '@type/common';
+import { IDataState } from '@src/types/common';
interface IUserRoomState {
usersAvailable: IDataState[];
diff --git a/hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx b/hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx
index 90b2d00..93764f3 100644
--- a/hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx
+++ b/hotel-management/src/contexts/__tests__/userRoomAvailableContext.test.tsx
@@ -1,8 +1,8 @@
// Contexts
-import { reducer } from '@context/UserRoomAvailableContext';
+import { reducer } from '../UserRoomAvailableContext';
// Types
-import { IDataState } from '@type/common';
+import { IDataState } from '@src/types/common';
describe('userRoomAvailableContext', () => {
let initialState: {
diff --git a/hotel-management/src/helpers/__tests__/helpers.test.ts b/hotel-management/src/helpers/__tests__/helpers.test.ts
index 4e24245..b112d48 100644
--- a/hotel-management/src/helpers/__tests__/helpers.test.ts
+++ b/hotel-management/src/helpers/__tests__/helpers.test.ts
@@ -1,5 +1,5 @@
// Helpers
-import { formatCurrency, getDayDiff } from '@helper/helper';
+import { formatCurrency, getDayDiff } from '../helper';
describe('formatCurrency', () => {
test('Should format correctly', () => {
diff --git a/hotel-management/src/helpers/__tests__/validators.test.ts b/hotel-management/src/helpers/__tests__/validators.test.ts
index 2d6be25..1abd19f 100644
--- a/hotel-management/src/helpers/__tests__/validators.test.ts
+++ b/hotel-management/src/helpers/__tests__/validators.test.ts
@@ -1,5 +1,5 @@
// Constants
-import { REGEX } from '@constant/commons';
+import { REGEX } from '@src/constants/commons';
// Helpers
import {
@@ -7,7 +7,7 @@ import {
isValidDiscount,
isValidRegex,
isValidString,
-} from '@helper/validators';
+} from '../validators';
describe('isValidPhone', () => {
const isValidPhone = (phone: string) =>
diff --git a/hotel-management/src/helpers/helper.ts b/hotel-management/src/helpers/helper.ts
index 7b0c324..56f7f58 100644
--- a/hotel-management/src/helpers/helper.ts
+++ b/hotel-management/src/helpers/helper.ts
@@ -29,7 +29,12 @@ const getDayDiff = (startDate: Date, endDate: Date): number => {
return 0;
}
+const findItemInListById = (id: number, listItem: T[]): T | undefined => {
+ return listItem.find((item) => item["id" as keyof typeof item] === id);
+}
+
export {
formatCurrency,
getDayDiff,
+ findItemInListById,
};
diff --git a/hotel-management/src/hooks/__tests__/useDebounce.test.tsx b/hotel-management/src/hooks/__tests__/useDebounce.test.tsx
index 5db8fce..9e917d0 100644
--- a/hotel-management/src/hooks/__tests__/useDebounce.test.tsx
+++ b/hotel-management/src/hooks/__tests__/useDebounce.test.tsx
@@ -2,7 +2,7 @@ import { act, fireEvent, render } from '@testing-library/react';
import { useState } from 'react';
// Hooks
-import { useDebounce } from '@hook/useDebounce';
+import { useDebounce } from '../useDebounce';
jest.useFakeTimers();
diff --git a/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx b/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx
index 0873162..4331d26 100644
--- a/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx
+++ b/hotel-management/src/hooks/__tests__/useOutsideClick.test.tsx
@@ -1,7 +1,7 @@
import { fireEvent, render, renderHook, screen } from '@testing-library/react';
// Hooks
-import { useOutsideClick } from '@hook/useOutsideClick';
+import { useOutsideClick } from '../useOutsideClick';
describe('useOutsideClick', () => {
test('Call handler when click outside element', () => {
diff --git a/hotel-management/src/hooks/authentication/__tests__/useAccount.test.ts b/hotel-management/src/hooks/authentication/__tests__/useAccount.test.ts
index 2fe036a..c7d098f 100644
--- a/hotel-management/src/hooks/authentication/__tests__/useAccount.test.ts
+++ b/hotel-management/src/hooks/authentication/__tests__/useAccount.test.ts
@@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react';
import { User } from '@supabase/supabase-js';
// Services
-import * as authenticationService from '@service/authenticationService';
+import * as authenticationService from '@src/services/authenticationService';
// Hooks
import { useAccount } from '../useAccount';
diff --git a/hotel-management/src/hooks/authentication/useAccount.ts b/hotel-management/src/hooks/authentication/useAccount.ts
index 869f278..6a60876 100644
--- a/hotel-management/src/hooks/authentication/useAccount.ts
+++ b/hotel-management/src/hooks/authentication/useAccount.ts
@@ -1,7 +1,7 @@
import { useQuery } from '@tanstack/react-query';
// Services
-import { getCurrentAccount } from '@service/authenticationService';
+import { getCurrentAccount } from '@src/services/authenticationService';
/**
* Get data of account currently login
diff --git a/hotel-management/src/hooks/authentication/useLogin.ts b/hotel-management/src/hooks/authentication/useLogin.ts
index 6cf34fe..3cc6be9 100644
--- a/hotel-management/src/hooks/authentication/useLogin.ts
+++ b/hotel-management/src/hooks/authentication/useLogin.ts
@@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom';
import toast from 'react-hot-toast';
// Services
-import { login as loginFn } from '@service/authenticationService';
+import { login as loginFn } from '@src/services/authenticationService';
/**
* Login web
diff --git a/hotel-management/src/hooks/authentication/useLogout.ts b/hotel-management/src/hooks/authentication/useLogout.ts
index fd6cb28..10ec984 100644
--- a/hotel-management/src/hooks/authentication/useLogout.ts
+++ b/hotel-management/src/hooks/authentication/useLogout.ts
@@ -2,7 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
// Services
-import { logout as logoutFn } from '@service/authenticationService';
+import { logout as logoutFn } from '@src/services/authenticationService';
/**
* Logout web
diff --git a/hotel-management/src/hooks/authentication/useUpdateAccount.ts b/hotel-management/src/hooks/authentication/useUpdateAccount.ts
index ebe4d9d..f451a61 100644
--- a/hotel-management/src/hooks/authentication/useUpdateAccount.ts
+++ b/hotel-management/src/hooks/authentication/useUpdateAccount.ts
@@ -2,10 +2,10 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import { toast } from 'react-hot-toast';
// Services
-import { updateAccount as updateAccountFn } from '@service/authenticationService';
+import { updateAccount as updateAccountFn } from '@src/services/authenticationService';
// Constants
-import { UPDATE_ACCOUNT_SUCCESSFUL } from '@constant/messages';
+import { UPDATE_ACCOUNT_SUCCESSFUL } from '@src/constants/messages';
/**
* Update account currently login.
diff --git a/hotel-management/src/hooks/bookings/__tests__/useBookings.test.tsx b/hotel-management/src/hooks/bookings/__tests__/useBookings.test.tsx
index 4f58c8b..134124f 100644
--- a/hotel-management/src/hooks/bookings/__tests__/useBookings.test.tsx
+++ b/hotel-management/src/hooks/bookings/__tests__/useBookings.test.tsx
@@ -11,7 +11,7 @@ import { URLSearchParams } from 'url';
import { useBookings } from '../useBookings';
// Services
-import { getAllBookings } from '@service/bookingServices';
+import { getAllBookings } from '@src/services/bookingServices';
jest.mock('react-router-dom', () => ({
useSearchParams: jest.fn(),
@@ -22,7 +22,7 @@ jest.mock('@tanstack/react-query', () => ({
useQuery: jest.fn(),
}));
-jest.mock('@service/bookingServices', () => ({
+jest.mock('@src/services/bookingServices', () => ({
getAllBookings: jest.fn(),
}));
@@ -67,7 +67,7 @@ describe('useBookings hook', () => {
});
test('Should prefetch the second page when in the first page', async () => {
- const sampleDate = { data: [{ id: 1, name: 'Booking 1' }], count: 7 };
+ const sampleDate = { data: [{ id: 1, name: 'Booking 1' }], count: 11 };
(queryClient.prefetchQuery as jest.Mock) = jest.fn();
(useSearchParams as jest.Mock).mockReturnValue([
@@ -105,7 +105,7 @@ describe('useBookings hook', () => {
});
test('Should prefetch the previous page and next page when in the second page', async () => {
- const sampleDate = { data: [{ id: 1, name: 'Booking 1' }], count: 12 };
+ const sampleDate = { data: [{ id: 1, name: 'Booking 1' }], count: 22 };
(useSearchParams as jest.Mock).mockReturnValue([
new URLSearchParams('page=2'),
diff --git a/hotel-management/src/hooks/bookings/__tests__/useCheckout.test.tsx b/hotel-management/src/hooks/bookings/__tests__/useCheckout.test.tsx
index a8b4772..32b0ce5 100644
--- a/hotel-management/src/hooks/bookings/__tests__/useCheckout.test.tsx
+++ b/hotel-management/src/hooks/bookings/__tests__/useCheckout.test.tsx
@@ -8,13 +8,13 @@ import useCheckOut from '../useCheckout';
import { act, renderHook } from '@testing-library/react';
// Services
-import { checkOutBooking } from '@service/bookingServices';
+import { checkOutBooking } from '@src/services/bookingServices';
// Hooks
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
+import { useUserRoomAvailable } from '@src/hooks/useUserRoomAvailable';
// Constants
-import { CHECKOUT_SUCCESS } from '@constant/messages';
+import { CHECKOUT_SUCCESS } from '@src/constants/messages';
// Mock services and constants
jest.mock('react-hot-toast');
@@ -22,10 +22,10 @@ jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useQueryClient: jest.fn(),
}));
-jest.mock('@service/bookingServices', () => ({
+jest.mock('@src/services/bookingServices', () => ({
checkOutBooking: jest.fn(),
}));
-jest.mock('@hook/useUserRoomAvailable', () => ({
+jest.mock('@src/hooks/useUserRoomAvailable', () => ({
useUserRoomAvailable: jest.fn(),
}));
diff --git a/hotel-management/src/hooks/bookings/__tests__/useCreateBooking.test.tsx b/hotel-management/src/hooks/bookings/__tests__/useCreateBooking.test.tsx
index 4bbda0d..bde07f2 100644
--- a/hotel-management/src/hooks/bookings/__tests__/useCreateBooking.test.tsx
+++ b/hotel-management/src/hooks/bookings/__tests__/useCreateBooking.test.tsx
@@ -11,20 +11,20 @@ import toast from 'react-hot-toast';
import { useCreateBooking } from '../useCreateBooking';
// Types
-import { IBooking } from '@type/booking';
+import { IBooking } from '@src/types/booking';
// Constants
-import { ADD_SUCCESS } from '@constant/messages';
+import { ADD_SUCCESS } from '@src/constants/messages';
// Services
-import { createBooking } from '@service/bookingServices';
+import { createBooking } from '@src/services/bookingServices';
// Mock the necessary dependencies
jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useQueryClient: jest.fn(),
}));
-jest.mock('@service/bookingServices', () => ({
+jest.mock('@src/services/bookingServices', () => ({
createBooking: jest.fn(),
}));
jest.mock('react-hot-toast');
diff --git a/hotel-management/src/hooks/bookings/__tests__/useUpdateBooking.test.tsx b/hotel-management/src/hooks/bookings/__tests__/useUpdateBooking.test.tsx
index 1e064fa..9468dc3 100644
--- a/hotel-management/src/hooks/bookings/__tests__/useUpdateBooking.test.tsx
+++ b/hotel-management/src/hooks/bookings/__tests__/useUpdateBooking.test.tsx
@@ -8,13 +8,13 @@ import {
import { ReactNode } from 'react';
// Types
-import { IBooking } from '@type/booking';
+import { IBooking } from '@src/types/booking';
// Constants
-import { UPDATE_SUCCESS } from '@constant/messages';
+import { UPDATE_SUCCESS } from '@src/constants/messages';
// Services
-import { updateBooking } from '@service/bookingServices';
+import { updateBooking } from '@src/services/bookingServices';
// Hooks
import { useUpdateBooking } from '../useUpdateBooking';
@@ -24,7 +24,7 @@ jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useQueryClient: jest.fn(),
}));
-jest.mock('@service/bookingServices', () => ({
+jest.mock('@src/services/bookingServices', () => ({
updateBooking: jest.fn(),
}));
jest.mock('react-hot-toast');
diff --git a/hotel-management/src/hooks/bookings/useBookings.ts b/hotel-management/src/hooks/bookings/useBookings.ts
index 7b37689..3cbd2d8 100644
--- a/hotel-management/src/hooks/bookings/useBookings.ts
+++ b/hotel-management/src/hooks/bookings/useBookings.ts
@@ -3,10 +3,10 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useSearchParams } from 'react-router-dom';
// Services
-import { getAllBookings } from '@service/bookingServices';
+import { getAllBookings } from '@src/services/bookingServices';
// Constants
-import { DEFAULT_PAGE_SIZE } from '@constant/config';
+import { DEFAULT_PAGE_SIZE } from '@src/constants/config';
/**
* Fetch booking from database
diff --git a/hotel-management/src/hooks/bookings/useCheckout.ts b/hotel-management/src/hooks/bookings/useCheckout.ts
index 8ee438b..97b9d16 100644
--- a/hotel-management/src/hooks/bookings/useCheckout.ts
+++ b/hotel-management/src/hooks/bookings/useCheckout.ts
@@ -2,13 +2,13 @@ import toast from 'react-hot-toast';
import { useMutation, useQueryClient } from '@tanstack/react-query';
// Constants
-import { CHECKOUT_SUCCESS } from '@constant/messages';
+import { CHECKOUT_SUCCESS } from '@src/constants/messages';
// Hooks
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
+import { useUserRoomAvailable } from '../useUserRoomAvailable';
// Services
-import { checkOutBooking as checkOutBookingFn } from '@service/bookingServices';
+import { checkOutBooking as checkOutBookingFn } from '@src/services/bookingServices';
const useCheckOut = () => {
const queryClient = useQueryClient();
diff --git a/hotel-management/src/hooks/bookings/useCreateBooking.ts b/hotel-management/src/hooks/bookings/useCreateBooking.ts
index 4b9dc27..a402b47 100644
--- a/hotel-management/src/hooks/bookings/useCreateBooking.ts
+++ b/hotel-management/src/hooks/bookings/useCreateBooking.ts
@@ -2,10 +2,10 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
// Services
-import { createBooking as createBookingFn } from '@service/bookingServices';
+import { createBooking as createBookingFn} from '@src/services/bookingServices';
// Constants
-import { ADD_SUCCESS } from '@constant/messages';
+import { ADD_SUCCESS } from '@src/constants/messages';
/**
* Create booking on database
diff --git a/hotel-management/src/hooks/bookings/useUpdateBooking.ts b/hotel-management/src/hooks/bookings/useUpdateBooking.ts
index 1c04d30..0d6624f 100644
--- a/hotel-management/src/hooks/bookings/useUpdateBooking.ts
+++ b/hotel-management/src/hooks/bookings/useUpdateBooking.ts
@@ -2,10 +2,10 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
// Services
-import { updateBooking as updateBookingFn } from '@service/bookingServices';
+import { updateBooking as updateBookingFn } from '@src/services/bookingServices';
// Constants
-import { UPDATE_SUCCESS } from '@constant/messages';
+import { UPDATE_SUCCESS } from '@src/constants/messages';
/**
* Update booking from database
diff --git a/hotel-management/src/hooks/rooms/__tests__/useCreateRoom.test.tsx b/hotel-management/src/hooks/rooms/__tests__/useCreateRoom.test.tsx
index 41c21ec..d9ae52e 100644
--- a/hotel-management/src/hooks/rooms/__tests__/useCreateRoom.test.tsx
+++ b/hotel-management/src/hooks/rooms/__tests__/useCreateRoom.test.tsx
@@ -8,22 +8,22 @@ import {
import { ReactNode } from 'react';
// Types
-import { IRoom } from '@type/room';
+import { IRoom } from '@src/types/room';
// Hooks
import { useCreateRoom } from '../useCreateRoom';
// Constants
-import { ADD_SUCCESS } from '@constant/messages';
+import { ADD_SUCCESS } from '@src/constants/messages';
// Services
-import { createRoom } from '@service/roomServices';
+import { createRoom } from '@src/services/roomServices';
jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useQueryClient: jest.fn(),
}));
-jest.mock('@service/roomServices', () => ({
+jest.mock('@src/services/roomServices', () => ({
createRoom: jest.fn(),
}));
jest.mock('react-hot-toast');
diff --git a/hotel-management/src/hooks/rooms/__tests__/useRooms.test.tsx b/hotel-management/src/hooks/rooms/__tests__/useRooms.test.tsx
index 7f2687c..d186617 100644
--- a/hotel-management/src/hooks/rooms/__tests__/useRooms.test.tsx
+++ b/hotel-management/src/hooks/rooms/__tests__/useRooms.test.tsx
@@ -8,7 +8,7 @@ import { renderHook } from '@testing-library/react';
import { URLSearchParams } from 'url';
// Services
-import { getAllRooms } from '@service/roomServices';
+import { getAllRooms } from '@src/services/roomServices';
// Hooks
import { useRooms } from '../useRooms';
@@ -22,7 +22,7 @@ jest.mock('@tanstack/react-query', () => ({
useQuery: jest.fn(),
}));
-jest.mock('@service/roomServices', () => ({
+jest.mock('@src/services/roomServices', () => ({
getAllRooms: jest.fn(),
}));
@@ -69,7 +69,7 @@ describe('useRooms hook', () => {
});
test('Should prefetch the second page when in the first page', async () => {
- const sampleDate = { data: [{ id: 1, name: 'Room 1' }], count: 7 };
+ const sampleDate = { data: [{ id: 1, name: 'Room 1' }], count: 11 };
(useSearchParams as jest.Mock).mockReturnValue([
new URLSearchParams('page=1'),
@@ -106,7 +106,7 @@ describe('useRooms hook', () => {
});
test('Should prefetch the previous page and next page when in the second page', async () => {
- const sampleDate = { data: [{ id: 1, name: 'Room 1' }], count: 12 };
+ const sampleDate = { data: [{ id: 1, name: 'Room 1' }], count: 22 };
(useSearchParams as jest.Mock).mockReturnValue([
new URLSearchParams('page=2'),
diff --git a/hotel-management/src/hooks/rooms/__tests__/useSetIsDeleteRoom.test.tsx b/hotel-management/src/hooks/rooms/__tests__/useSetIsDeleteRoom.test.tsx
index 8c38731..3dae2e7 100644
--- a/hotel-management/src/hooks/rooms/__tests__/useSetIsDeleteRoom.test.tsx
+++ b/hotel-management/src/hooks/rooms/__tests__/useSetIsDeleteRoom.test.tsx
@@ -8,13 +8,13 @@ import {
import { ReactNode } from 'react';
// Types
-import { IRoom } from '@type/room';
+import { IRoom } from '@src/types/room';
// Constants
-import { DELETE_SUCCESS } from '@constant/messages';
+import { DELETE_SUCCESS } from '@src/constants/messages';
// Services
-import { setIsDeleteRoom } from '@service/roomServices';
+import { setIsDeleteRoom } from '@src/services/roomServices';
// Hooks
import { useSetIsDeleteRoom } from '../useSetIsDeleteRoom';
@@ -24,7 +24,7 @@ jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useQueryClient: jest.fn(),
}));
-jest.mock('@service/roomServices', () => ({
+jest.mock('@src/services/roomServices', () => ({
setIsDeleteRoom: jest.fn(),
}));
jest.mock('react-hot-toast');
diff --git a/hotel-management/src/hooks/rooms/__tests__/useUpdateRoom.test.tsx b/hotel-management/src/hooks/rooms/__tests__/useUpdateRoom.test.tsx
index 064c1d8..03d12e4 100644
--- a/hotel-management/src/hooks/rooms/__tests__/useUpdateRoom.test.tsx
+++ b/hotel-management/src/hooks/rooms/__tests__/useUpdateRoom.test.tsx
@@ -8,13 +8,13 @@ import {
import { ReactNode } from 'react';
// Types
-import { IRoom } from '@type/room';
+import { IRoom } from '@src/types/room';
// Constants
-import { UPDATE_SUCCESS } from '@constant/messages';
+import { UPDATE_SUCCESS } from '@src/constants/messages';
// Services
-import { updateRoom } from '@service/roomServices';
+import { updateRoom } from '@src/services/roomServices';
// Hooks
import { useUpdateRoom } from '../useUpdateRoom';
@@ -24,7 +24,7 @@ jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useQueryClient: jest.fn(),
}));
-jest.mock('@service/roomServices', () => ({
+jest.mock('@src/services/roomServices', () => ({
updateRoom: jest.fn(),
}));
jest.mock('react-hot-toast');
diff --git a/hotel-management/src/hooks/rooms/useCreateRoom.ts b/hotel-management/src/hooks/rooms/useCreateRoom.ts
index ba3f767..fb56ee4 100644
--- a/hotel-management/src/hooks/rooms/useCreateRoom.ts
+++ b/hotel-management/src/hooks/rooms/useCreateRoom.ts
@@ -2,13 +2,13 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
// Services
-import { createRoom as createRoomFn } from '@service/roomServices';
+import { createRoom as createRoomFn} from '@src/services/roomServices';
// Constants
-import { ADD_SUCCESS } from '@constant/messages';
+import { ADD_SUCCESS } from '@src/constants/messages';
// Hooks
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
+import { useUserRoomAvailable } from '../useUserRoomAvailable';
/**
* Create room on database
diff --git a/hotel-management/src/hooks/rooms/useRooms.ts b/hotel-management/src/hooks/rooms/useRooms.ts
index 1a1ad03..a6d6601 100644
--- a/hotel-management/src/hooks/rooms/useRooms.ts
+++ b/hotel-management/src/hooks/rooms/useRooms.ts
@@ -3,10 +3,10 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useSearchParams } from 'react-router-dom';
// Services
-import { getAllRooms } from '@service/roomServices';
+import { getAllRooms } from '@src/services/roomServices';
// Constants
-import { DEFAULT_PAGE_SIZE } from '@constant/config';
+import { DEFAULT_PAGE_SIZE } from '@src/constants/config';
/**
* Fetch room from database
diff --git a/hotel-management/src/hooks/rooms/useSetIsDeleteRoom.ts b/hotel-management/src/hooks/rooms/useSetIsDeleteRoom.ts
index b68b766..5eda176 100644
--- a/hotel-management/src/hooks/rooms/useSetIsDeleteRoom.ts
+++ b/hotel-management/src/hooks/rooms/useSetIsDeleteRoom.ts
@@ -2,13 +2,13 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
// Services
-import { setIsDeleteRoom as setIsDeleteRoomFn } from '@service/roomServices';
+import { setIsDeleteRoom as setIsDeleteRoomFn } from '@src/services/roomServices';
// Constants
-import * as messages from '@constant/messages';
+import { DELETE_SUCCESS } from '@src/constants/messages';
// Hooks
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
+import { useUserRoomAvailable } from '../useUserRoomAvailable';
/**
* Delete the room from database
@@ -25,7 +25,7 @@ const useSetIsDeleteRoom = () => {
} = useMutation({
mutationFn: setIsDeleteRoomFn,
onSuccess: (room) => {
- toast.success(messages.DELETE_SUCCESS);
+ toast.success(DELETE_SUCCESS);
queryClient.invalidateQueries({
queryKey: ['rooms'],
});
diff --git a/hotel-management/src/hooks/rooms/useUpdateRoom.ts b/hotel-management/src/hooks/rooms/useUpdateRoom.ts
index 7560074..3ac8b0e 100644
--- a/hotel-management/src/hooks/rooms/useUpdateRoom.ts
+++ b/hotel-management/src/hooks/rooms/useUpdateRoom.ts
@@ -2,13 +2,13 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
// Services
-import { updateRoom as updateRoomFn } from '@service/roomServices';
+import { updateRoom as updateRoomFn } from '@src/services/roomServices';
// Constants
-import { UPDATE_SUCCESS } from '@constant/messages';
+import { UPDATE_SUCCESS } from '@src/constants/messages';
// Hooks
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
+import { useUserRoomAvailable } from '../useUserRoomAvailable';
/**
* Update room from database
diff --git a/hotel-management/src/hooks/useItemSelected.ts b/hotel-management/src/hooks/useItemSelected.ts
new file mode 100644
index 0000000..a2fe3e5
--- /dev/null
+++ b/hotel-management/src/hooks/useItemSelected.ts
@@ -0,0 +1,22 @@
+import { useContext } from 'react';
+
+// Contexts
+import { ItemSelectContext } from '@src/contexts/ItemSelected';
+
+/**
+ * The hooks check the place call is in UserRoomAvailableProvider or not
+ * @returns The context of UserRoomAvailableContext
+ */
+const useItemSelect = () => {
+ const context = useContext(ItemSelectContext);
+
+ if (context === undefined) {
+ throw new Error(
+ 'ItemSelectContext was used outside of ItemSelectContextProvider'
+ );
+ }
+
+ return context;
+};
+
+export { useItemSelect };
diff --git a/hotel-management/src/hooks/useOutsideClick.ts b/hotel-management/src/hooks/useOutsideClick.ts
index 84a2248..24182a0 100644
--- a/hotel-management/src/hooks/useOutsideClick.ts
+++ b/hotel-management/src/hooks/useOutsideClick.ts
@@ -1,7 +1,7 @@
import { MutableRefObject, useEffect, useRef } from 'react';
// Types
-import { Nullable } from '@type/common';
+import { Nullable } from '@src/types/common';
/**
* Custom hook to call handler when click outside element
diff --git a/hotel-management/src/hooks/useUserRoomAvailable.ts b/hotel-management/src/hooks/useUserRoomAvailable.ts
index ffc1fbd..e34043a 100644
--- a/hotel-management/src/hooks/useUserRoomAvailable.ts
+++ b/hotel-management/src/hooks/useUserRoomAvailable.ts
@@ -1,7 +1,7 @@
import { useContext } from 'react';
// Contexts
-import { UserRoomAvailableContext } from '@context/UserRoomAvailableContext';
+import { UserRoomAvailableContext } from '@src/contexts/UserRoomAvailableContext';
/**
* The hooks check the place call is in UserRoomAvailableProvider or not
diff --git a/hotel-management/src/hooks/users/__tests__/useCreateUser.test.tsx b/hotel-management/src/hooks/users/__tests__/useCreateUser.test.tsx
index 3b8aee8..d7fba49 100644
--- a/hotel-management/src/hooks/users/__tests__/useCreateUser.test.tsx
+++ b/hotel-management/src/hooks/users/__tests__/useCreateUser.test.tsx
@@ -11,20 +11,20 @@ import { ReactNode } from 'react';
import { useCreateUser } from '../useCreateUser';
// Types
-import { IUser } from '@type/user';
+import { IUser } from '@src/types/user';
// Constants
-import { ADD_SUCCESS } from '@constant/messages';
+import { ADD_SUCCESS } from '@src/constants/messages';
// Services
-import { createUser } from '@service/userServices';
+import { createUser } from '@src/services/userServices';
// Mock the necessary dependencies
jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useQueryClient: jest.fn(),
}));
-jest.mock('@service/userServices', () => ({
+jest.mock('@src/services/userServices', () => ({
createUser: jest.fn(),
}));
jest.mock('react-hot-toast');
diff --git a/hotel-management/src/hooks/users/__tests__/useSetIsDeleteUser.test.tsx b/hotel-management/src/hooks/users/__tests__/useSetIsDeleteUser.test.tsx
index 544abea..78b2729 100644
--- a/hotel-management/src/hooks/users/__tests__/useSetIsDeleteUser.test.tsx
+++ b/hotel-management/src/hooks/users/__tests__/useSetIsDeleteUser.test.tsx
@@ -8,13 +8,13 @@ import {
import { ReactNode } from 'react';
// Types
-import { IUser } from '@type/user';
+import { IUser } from '@src/types/user';
// Constants
-import { DELETE_SUCCESS } from '@constant/messages';
+import { DELETE_SUCCESS } from '@src/constants/messages';
// Services
-import { setIsDeleteUser } from '@service/userServices';
+import { setIsDeleteUser } from '@src/services/userServices';
// Hooks
import { useIsDeleteUser } from '../useSetIsDeleteUser';
@@ -24,7 +24,7 @@ jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useQueryClient: jest.fn(),
}));
-jest.mock('@service/userServices', () => ({
+jest.mock('@src/services/userServices', () => ({
setIsDeleteUser: jest.fn(),
}));
jest.mock('react-hot-toast');
diff --git a/hotel-management/src/hooks/users/__tests__/useUpdateUser.test.tsx b/hotel-management/src/hooks/users/__tests__/useUpdateUser.test.tsx
index c2bd258..bd507a1 100644
--- a/hotel-management/src/hooks/users/__tests__/useUpdateUser.test.tsx
+++ b/hotel-management/src/hooks/users/__tests__/useUpdateUser.test.tsx
@@ -8,13 +8,13 @@ import {
import { ReactNode } from 'react';
// Types
-import { IUser } from '@type/user';
+import { IUser } from '@src/types/user';
// Constants
-import { UPDATE_SUCCESS } from '@constant/messages';
+import { UPDATE_SUCCESS } from '@src/constants/messages';
// Services
-import { updateUser } from '@service/userServices';
+import { updateUser } from '@src/services/userServices';
// Hooks
import { useUpdateUser } from '../useUpdateUser';
@@ -24,7 +24,7 @@ jest.mock('@tanstack/react-query', () => ({
...jest.requireActual('@tanstack/react-query'),
useQueryClient: jest.fn(),
}));
-jest.mock('@service/userServices', () => ({
+jest.mock('@src/services/userServices', () => ({
updateUser: jest.fn(),
}));
jest.mock('react-hot-toast');
diff --git a/hotel-management/src/hooks/users/__tests__/useUsers.test.tsx b/hotel-management/src/hooks/users/__tests__/useUsers.test.tsx
index 8c2dcbf..46b319a 100644
--- a/hotel-management/src/hooks/users/__tests__/useUsers.test.tsx
+++ b/hotel-management/src/hooks/users/__tests__/useUsers.test.tsx
@@ -8,7 +8,7 @@ import { renderHook } from '@testing-library/react';
import { URLSearchParams } from 'url';
// Services
-import { getAllUsers } from '@service/userServices';
+import { getAllUsers } from '@src/services/userServices';
// Hooks
import { useUsers } from '../useUsers';
@@ -22,7 +22,7 @@ jest.mock('@tanstack/react-query', () => ({
useQuery: jest.fn(),
}));
-jest.mock('@service/userServices', () => ({
+jest.mock('@src/services/userServices', () => ({
getAllUsers: jest.fn(),
}));
@@ -69,7 +69,7 @@ describe('useUsers hook', () => {
});
test('Should prefetch the second page when in the first page', async () => {
- const sampleDate = { data: [{ id: 1, name: 'User 1' }], count: 7 };
+ const sampleDate = { data: [{ id: 1, name: 'User 1' }], count: 11 };
(useSearchParams as jest.Mock).mockReturnValue([
new URLSearchParams('page=1'),
@@ -106,7 +106,7 @@ describe('useUsers hook', () => {
});
test('Should prefetch the previous page and next page when in the second page', async () => {
- const sampleDate = { data: [{ id: 1, name: 'User 1' }], count: 12 };
+ const sampleDate = { data: [{ id: 1, name: 'User 1' }], count: 22 };
(useSearchParams as jest.Mock).mockReturnValue([
new URLSearchParams('page=2'),
diff --git a/hotel-management/src/hooks/users/useCreateUser.ts b/hotel-management/src/hooks/users/useCreateUser.ts
index dcd7830..15146c3 100644
--- a/hotel-management/src/hooks/users/useCreateUser.ts
+++ b/hotel-management/src/hooks/users/useCreateUser.ts
@@ -2,13 +2,13 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
// Services
-import { createUser as createUserFn } from '@service/userServices';
+import { createUser as createUserFn } from '@src/services/userServices';
// Constants
-import { ADD_SUCCESS } from '@constant/messages';
+import { ADD_SUCCESS } from '@src/constants/messages';
// Hooks
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
+import { useUserRoomAvailable } from '../useUserRoomAvailable';
/**
* Create user in database
diff --git a/hotel-management/src/hooks/users/useSetIsDeleteUser.ts b/hotel-management/src/hooks/users/useSetIsDeleteUser.ts
index 4a2cad6..7b97cca 100644
--- a/hotel-management/src/hooks/users/useSetIsDeleteUser.ts
+++ b/hotel-management/src/hooks/users/useSetIsDeleteUser.ts
@@ -2,11 +2,13 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
// Services
-import { setIsDeleteUser as setIsDeleteUserFn } from '@service/userServices';
+import { setIsDeleteUser as setIsDeleteUserFn } from '@src/services/userServices';
// Constants
-import * as messages from '@constant/messages';
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
+import { DELETE_SUCCESS } from '@src/constants/messages';
+
+// Hooks
+import { useUserRoomAvailable } from '../useUserRoomAvailable';
/**
* Delete the user from database
@@ -23,7 +25,7 @@ const useIsDeleteUser = () => {
} = useMutation({
mutationFn: setIsDeleteUserFn,
onSuccess: (user) => {
- toast.success(messages.DELETE_SUCCESS);
+ toast.success(DELETE_SUCCESS);
queryClient.invalidateQueries({
queryKey: ['users'],
});
diff --git a/hotel-management/src/hooks/users/useUpdateUser.ts b/hotel-management/src/hooks/users/useUpdateUser.ts
index db023b2..7773ac6 100644
--- a/hotel-management/src/hooks/users/useUpdateUser.ts
+++ b/hotel-management/src/hooks/users/useUpdateUser.ts
@@ -2,13 +2,13 @@ import toast from 'react-hot-toast';
import { useMutation, useQueryClient } from '@tanstack/react-query';
// Services
-import { updateUser as updateUserFn } from '@service/userServices';
+import { updateUser as updateUserFn } from '@src/services/userServices';
// Constants
-import { UPDATE_SUCCESS } from '@constant/messages';
+import { UPDATE_SUCCESS } from '@src/constants/messages';
// Hooks
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
+import { useUserRoomAvailable } from '../useUserRoomAvailable';
/**
* Update user from database
diff --git a/hotel-management/src/hooks/users/useUsers.ts b/hotel-management/src/hooks/users/useUsers.ts
index fd0582f..4da439d 100644
--- a/hotel-management/src/hooks/users/useUsers.ts
+++ b/hotel-management/src/hooks/users/useUsers.ts
@@ -3,10 +3,10 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useSearchParams } from 'react-router-dom';
// Services
-import { getAllUsers } from '@service/userServices';
+import { getAllUsers } from '@src/services/userServices';
// Constants
-import { DEFAULT_PAGE_SIZE } from '@constant/config';
+import { DEFAULT_PAGE_SIZE } from '@src/constants/config';
/**
* Fetch data of users from database
diff --git a/hotel-management/src/pages/Account/AccountInforForm.tsx b/hotel-management/src/pages/Account/AccountInforForm.tsx
index 1494b7f..28d0fe7 100644
--- a/hotel-management/src/pages/Account/AccountInforForm.tsx
+++ b/hotel-management/src/pages/Account/AccountInforForm.tsx
@@ -1,17 +1,17 @@
import { useForm } from 'react-hook-form';
// Styled
-import Input from '@commonStyle/Input';
+import Input from '@src/commons/styles/Input';
// Components
-import Form from '@component/Form';
+import Form from '@src/components/Form';
// Constants
-import { REQUIRED_FIELD_ERROR } from '@constant/formValidateMessage';
+import { REQUIRED_FIELD_ERROR } from '@src/constants/formValidateMessage';
// Hooks
-import { useUpdateAccount } from '@hook/authentication/useUpdateAccount';
-import { useAccount } from '@hook/authentication/useAccount';
+import { useUpdateAccount } from '@src/hooks/authentication/useUpdateAccount';
+import { useAccount } from '@src/hooks/authentication/useAccount';
interface IAccountForm {
fullName: string;
diff --git a/hotel-management/src/pages/Account/AccountPasswordForm.tsx b/hotel-management/src/pages/Account/AccountPasswordForm.tsx
index 8f97e99..5b8f7c4 100644
--- a/hotel-management/src/pages/Account/AccountPasswordForm.tsx
+++ b/hotel-management/src/pages/Account/AccountPasswordForm.tsx
@@ -3,24 +3,24 @@ import { useForm } from 'react-hook-form';
import toast from 'react-hot-toast';
// Styled
-import Input from '@commonStyle/Input';
+import Input from '@src/commons/styles/Input';
// Components
-import Form from '@component/Form';
+import Form from '@src/components/Form';
// Constants
-import { REGEX } from '@constant/commons';
+import { REGEX } from '@src/constants/commons';
import {
PASSWORD_CONDITION,
PASSWORD_NOT_MATCH,
PASSWORD_NOT_MATCH_REQUIREMENT,
-} from '@constant/formValidateMessage';
+} from '@src/constants/formValidateMessage';
// Helpers
-import { isValidRegex } from '@helper/validators';
+import { isValidRegex } from '@src/helpers/validators';
// Hooks
-import { useUpdateAccount } from '@hook/authentication/useUpdateAccount';
+import { useUpdateAccount } from '@src/hooks/authentication/useUpdateAccount';
interface IAccountPasswordForm {
password: string;
diff --git a/hotel-management/src/pages/Account/__tests__/AccountInforForm.test.tsx b/hotel-management/src/pages/Account/__tests__/AccountInforForm.test.tsx
index 28fa3e2..b720cef 100644
--- a/hotel-management/src/pages/Account/__tests__/AccountInforForm.test.tsx
+++ b/hotel-management/src/pages/Account/__tests__/AccountInforForm.test.tsx
@@ -2,14 +2,14 @@ import { act, fireEvent, render, RenderResult, waitFor } from '@testing-library/
import '@testing-library/jest-dom';
// Components
-import AccountInforForm from '@page/Account/AccountInforForm';
+import AccountInforForm from '@src/pages/Account/AccountInforForm';
// Hooks
-import { useAccount } from '@hook/authentication/useAccount';
-import { useUpdateAccount } from '@hook/authentication/useUpdateAccount';
+import { useAccount } from '@src/hooks/authentication/useAccount';
+import { useUpdateAccount } from '@src/hooks/authentication/useUpdateAccount';
-jest.mock('@hook/authentication/useUpdateAccount');
-jest.mock('@hook/authentication/useAccount');
+jest.mock('@src/hooks/authentication/useUpdateAccount');
+jest.mock('@src/hooks/authentication/useAccount');
const mockAccount = {
email: 'admin@nezumi.site',
diff --git a/hotel-management/src/pages/Account/__tests__/AccountPasswordForm.test.tsx b/hotel-management/src/pages/Account/__tests__/AccountPasswordForm.test.tsx
index 46dd14b..aacf471 100644
--- a/hotel-management/src/pages/Account/__tests__/AccountPasswordForm.test.tsx
+++ b/hotel-management/src/pages/Account/__tests__/AccountPasswordForm.test.tsx
@@ -10,9 +10,9 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import AccountPasswordForm from '../AccountPasswordForm';
// Hooks
-import { useUpdateAccount } from '@hook/authentication/useUpdateAccount';
+import { useUpdateAccount } from '@src/hooks/authentication/useUpdateAccount';
-jest.mock('@hook/authentication/useUpdateAccount');
+jest.mock('@src/hooks/authentication/useUpdateAccount');
describe('AccountPasswordForm', () => {
let wrapper: RenderResult | null = null;
diff --git a/hotel-management/src/pages/Booking/BookingForm.tsx b/hotel-management/src/pages/Booking/BookingForm.tsx
index 8b27fad..fe948d0 100644
--- a/hotel-management/src/pages/Booking/BookingForm.tsx
+++ b/hotel-management/src/pages/Booking/BookingForm.tsx
@@ -2,29 +2,29 @@ import { useCallback, useMemo, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
// Styled
-import Input from '@commonStyle/Input.ts';
+import Input from '@src/commons/styles/Input';
// Constants
-import { REQUIRED_FIELD_ERROR } from '@constant/formValidateMessage.ts';
+import { REQUIRED_FIELD_ERROR } from '@src/constants/formValidateMessage';
// Components
-import Form from '@component/Form/index.tsx';
-import Select, { ISelectOptions } from '@component/Select/index.tsx';
+import Form from '@src/components/Form';
+import Select, { ISelectOptions } from '@src/components/Select/index.tsx';
// Hooks
-import { useCreateBooking } from '@hook/bookings/useCreateBooking.ts';
-import { useUpdateBooking } from '@hook/bookings/useUpdateBooking.ts';
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable.ts';
+import { useCreateBooking } from '@src/hooks/bookings/useCreateBooking';
+import { useUpdateBooking } from '@src/hooks/bookings/useUpdateBooking';
+import { useUserRoomAvailable } from '@src/hooks/useUserRoomAvailable';
// Helpers
-import { formatCurrency, getDayDiff } from '@helper/helper.ts';
+import { formatCurrency, getDayDiff } from '@src/helpers/helper';
// Services
-import { getRoomById, updateRoomStatus } from '@service/roomServices.ts';
-import { updateUserBookedStatus } from '@service/userServices.ts';
+import { getRoomById, updateRoomStatus } from '@src/services/roomServices';
+import { updateUserBookedStatus } from '@src/services/userServices';
// Types
-import { IBooking, TBookingResponse } from '@type/booking.ts';
+import { IBooking, TBookingResponse } from '@src/types/booking';
interface IBookingFormProp {
onCloseModal?: () => void;
@@ -37,6 +37,7 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
usersAvailable,
dispatch
} = useUserRoomAvailable();
+
const { isCreating, createBooking } = useCreateBooking();
const { isUpdating, updateBooking } = useUpdateBooking();
const isLoading = isCreating || isUpdating;
@@ -83,7 +84,7 @@ const BookingForm = ({ onCloseModal, booking }: IBookingFormProp) => {
type: 'updateStatusRoom',
payload: [{ id: newBooking.roomId, status: true }],
});
-
+
// Update room, user available in server
await updateRoomStatus(newBooking.roomId, true);
await updateUserBookedStatus(newBooking.userId, true);
diff --git a/hotel-management/src/pages/Booking/BookingRow.tsx b/hotel-management/src/pages/Booking/BookingRow.tsx
deleted file mode 100644
index ab7f9bd..0000000
--- a/hotel-management/src/pages/Booking/BookingRow.tsx
+++ /dev/null
@@ -1,129 +0,0 @@
-import toast from 'react-hot-toast';
-import { useCallback, useMemo } from 'react';
-
-// Helpers
-import { formatCurrency } from '@helper/helper';
-
-// Types
-import { TBookingResponse } from '@type/booking';
-
-// Components
-import Modal from '@component/Modal';
-import Table from '@component/Table';
-import Menus from '@component/Menus';
-import { RiEditBoxFill } from 'react-icons/ri';
-import { TbArrowNarrowRight } from 'react-icons/tb';
-import { ImExit } from 'react-icons/im';
-import BookingForm from './BookingForm';
-import ConfirmMessage from '@component/ConfirmMessage';
-
-// Hooks
-import useCheckOut from '@hook/bookings/useCheckout';
-
-// Constants
-import { FORM } from '@constant/commons';
-
-interface IBookingRow {
- booking: TBookingResponse;
-}
-
-const BookingRow = ({ booking }: IBookingRow) => {
- const { checkOutBooking } = useCheckOut();
- const {
- id,
- users,
- startDate,
- endDate,
- rooms,
- amount,
- status
- } = booking;
- const formattedPrice = useMemo(() => formatCurrency(amount), [amount]);
- const renderEditBtn = useCallback(
- (onCloseModal: () => void) => (
- }
- disabled={!status}
- >
- Edit
-
- ),
- [status]
- );
-
- const renderCheckOutBtn = useCallback(
- (onCloseModal: () => void) => (
- }
- disabled={!status}
- >
- Checkout
-
- ),
- [status]
- );
-
- const handleClickCheckOutBtn = useCallback(() => {
- if (booking.status) {
- checkOutBooking({
- idBooking: booking.id,
- roomId: booking!.rooms!.id,
- userId: booking!.users!.id,
- });
- } else {
- toast.error('User already checkout!');
- }
- }, [booking, checkOutBooking]);
-
- return (
-
- {users?.name}
-
- {startDate}
- {endDate}
-
- {rooms?.name}
- {formattedPrice}
- {
- status
- ? 'Check in'
- : 'Check out'
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default BookingRow;
diff --git a/hotel-management/src/pages/Booking/BookingTable.tsx b/hotel-management/src/pages/Booking/BookingTable.tsx
deleted file mode 100644
index dd5faea..0000000
--- a/hotel-management/src/pages/Booking/BookingTable.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { useCallback } from 'react';
-
-// Components
-import Menus from '@component/Menus';
-import Table from '@component/Table';
-import Message from '@component/Message';
-import Search from '@component/Search';
-import Pagination from '@component/Pagination';
-import BookingRow from './BookingRow';
-
-// Styled
-import { StyledOperationTable } from './styled';
-import Direction from '@commonStyle/Direction';
-import Spinner from '@commonStyle/Spinner';
-
-// Hooks
-import { useBookings } from '@hook/bookings/useBookings';
-
-// Types
-import { TBookingResponse } from '@type/booking';
-
-const BookingTable = () => {
- const columnName = [
- 'User',
- 'Date',
- 'Room',
- 'Amount',
- 'Status'
- ];
- const {
- isLoading,
- bookings,
- count
- } = useBookings();
-
- const renderBookingRow = useCallback(
- (booking: TBookingResponse) => (
-
- ),
- []
- );
-
- return (
- <>
-
-
-
-
-
- {isLoading && }
-
- {bookings && bookings.length ? (
-
-
-
-
- data={bookings}
- render={renderBookingRow}
- />
-
-
-
-
-
- ) : (
- !isLoading && No data to show here!
- )}
-
- >
- );
-};
-
-export default BookingTable;
diff --git a/hotel-management/src/pages/Booking/__tests__/BookingForm.test.tsx b/hotel-management/src/pages/Booking/__tests__/BookingForm.test.tsx
index 61ff7f5..f29bfa8 100644
--- a/hotel-management/src/pages/Booking/__tests__/BookingForm.test.tsx
+++ b/hotel-management/src/pages/Booking/__tests__/BookingForm.test.tsx
@@ -8,25 +8,25 @@ import {
} from '@testing-library/react';
// Types
-import { TBookingResponse } from '@type/booking';
+import { TBookingResponse } from '@src/types/booking';
// Components
import BookingForm from '../BookingForm';
// Hooks
-import { useUserRoomAvailable } from '@hook/useUserRoomAvailable';
+import { useUserRoomAvailable } from '@src/hooks/useUserRoomAvailable';
const mockUpdateBooking = jest.fn();
-jest.mock('@hook/bookings/useUpdateBooking', () => ({
- ...jest.requireActual('@hook/bookings/useUpdateBooking'),
+jest.mock('@src/hooks/bookings/useUpdateBooking', () => ({
+ ...jest.requireActual('@src/hooks/bookings/useUpdateBooking'),
useUpdateBooking: jest.fn(() => ({
isUpdating: false,
updateBooking: mockUpdateBooking,
})),
}));
-jest.mock('@hook/useUserRoomAvailable.ts');
+jest.mock('@src/hooks/useUserRoomAvailable.ts');
const mockUseUserRoomAvailable = useUserRoomAvailable as jest.MockedFunction<
typeof useUserRoomAvailable
diff --git a/hotel-management/src/pages/Booking/__tests__/BookingRow.test.tsx b/hotel-management/src/pages/Booking/__tests__/BookingRow.test.tsx
deleted file mode 100644
index 570ab85..0000000
--- a/hotel-management/src/pages/Booking/__tests__/BookingRow.test.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { render } from '@testing-library/react';
-
-// Types
-import { TBookingResponse } from '@type/booking';
-
-// Components
-import BookingRow from '../BookingRow';
-
-describe('BookingRow', () => {
- const tempBooking: TBookingResponse = {
- id: 1,
- startDate: '2024-11-21',
- endDate: '2024-11-22',
- amount: 1200,
- status: true,
- rooms: {
- id: 1,
- name: 'Room 1',
- },
- users: {
- id: 2,
- name: 'Room 2',
- },
- };
-
- const queryClient = new QueryClient();
- const wrapper = render(
-
-
-
- );
-
- test('Should render correctly', () => {
- expect(wrapper).toMatchSnapshot();
- });
-});
diff --git a/hotel-management/src/pages/Booking/__tests__/BookingTable.test.tsx b/hotel-management/src/pages/Booking/__tests__/BookingTable.test.tsx
deleted file mode 100644
index 15470f4..0000000
--- a/hotel-management/src/pages/Booking/__tests__/BookingTable.test.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { BrowserRouter } from 'react-router-dom';
-import { render } from '@testing-library/react';
-
-// Components
-import BookingTable from '@page/Booking/BookingTable';
-
-describe('UserTable', () => {
- const queryClient = new QueryClient();
-
- const wrapper = render(
-
-
-
-
-
- );
-
- test('Should render correctly', () => {
- expect(wrapper).toMatchSnapshot();
- });
-});
diff --git a/hotel-management/src/pages/Booking/__tests__/__snapshots__/BookingForm.test.tsx.snap b/hotel-management/src/pages/Booking/__tests__/__snapshots__/BookingForm.test.tsx.snap
index 54009f0..0683a96 100644
--- a/hotel-management/src/pages/Booking/__tests__/__snapshots__/BookingForm.test.tsx.snap
+++ b/hotel-management/src/pages/Booking/__tests__/__snapshots__/BookingForm.test.tsx.snap
@@ -79,7 +79,7 @@ exports[`BookingForm Should render correctly 1`] = `
@@ -223,7 +223,7 @@ exports[`BookingForm Should render correctly 1`] = `
diff --git a/hotel-management/src/pages/Booking/index.tsx b/hotel-management/src/pages/Booking/index.tsx
index 0edb7b4..6a9a122 100644
--- a/hotel-management/src/pages/Booking/index.tsx
+++ b/hotel-management/src/pages/Booking/index.tsx
@@ -1,36 +1,209 @@
-// Styled
-import Direction from '@commonStyle/Direction';
-import { StyledBooking, Title } from './styled';
-import Button from '@commonStyle/Button';
-
// Components
-import Modal from '@component/Modal';
-import BookingTable from './BookingTable';
import BookingForm from './BookingForm';
+import Modal from '@src/components/Modal';
+import ButtonIcon from '@src/components/ButtonIcon';
+import Direction from '@src/commons/styles/Direction';
+import {FiEdit} from 'react-icons/fi';
+import {MdOutlineAddCircleOutline} from 'react-icons/md';
+import Table from '@src/components/Table';
-// Constants
-import { FORM } from '@constant/commons';
+// Styled
+import {ActionTable, StyledBooking, Title} from './styled';
+import Spinner from '@src/commons/styles/Spinner.ts';
+
+// Types
+import {ColumnProps} from '@src/types/common.ts';
+import {TBookingResponse} from '@src/types/booking.ts';
+
+// Hooks
+import {useBookings} from '@src/hooks/bookings/useBookings.ts';
+import {useEffect, useState} from 'react';
+import {FORM} from '@src/constants/commons.ts';
+import {findItemInListById, formatCurrency} from '@src/helpers/helper.ts';
+import ConfirmMessage from '@src/components/ConfirmMessage';
+import useCheckOut from '@src/hooks/bookings/useCheckout.ts';
+import toast from 'react-hot-toast';
+import {ImExit} from "react-icons/im";
+import Message from "@src/components/Message";
+
+interface IBookingTable extends Omit {
+ amount: string;
+ status: string;
+}
const Booking = () => {
+ const {checkOutBooking} = useCheckOut();
+ const [itemSelected, setItemSelected] = useState();
+ let bookingSelected: TBookingResponse | undefined;
+
+ const columns: ColumnProps[] = [
+ {
+ key: 'user',
+ title: 'User',
+ width: 10
+ },
+ {
+ key: 'date',
+ title: 'Date',
+ width: 25,
+ isDateValue: true
+ },
+ {
+ key: 'room',
+ title: 'Room',
+ width: 20
+ },
+ {
+ key: 'amount',
+ title: 'Amount',
+ width: 15
+ },
+ {
+ key: 'status',
+ title: 'Status',
+ width: 20
+ }
+ ];
+ const {isLoading, bookings, count} = useBookings();
+
+ // Reset value when bookings changed.
+ useEffect(() => {
+ setItemSelected(undefined);
+ }, [bookings]);
+
+ const tempBookings = bookings?.map((booking) => (
+ {
+ ...booking,
+ date: [booking.startDate, booking.endDate],
+ amount: formatCurrency(booking.amount),
+ room: booking.rooms!.name,
+ user: booking.users!.name,
+ status: booking.status
+ ? 'Check in'
+ : 'Check out',
+ }
+ ));
+
+ if (itemSelected && bookings) {
+ bookingSelected = findItemInListById(itemSelected.id, bookings);
+ }
+
+ const handleClickCheckOutBtn = () => {
+ if (itemSelected && itemSelected.status) {
+ checkOutBooking({
+ idBooking: itemSelected.id,
+ roomId: itemSelected!.rooms!.id,
+ userId: itemSelected!.users!.id
+ });
+ } else {
+ toast.error('User already checkout!');
+ }
+ };
+
return (
List Booking
- (
-
- )}
- />
-
-
-
+
+ (
+ }
+ text={'Add Booking'}
+ iconSize={'18px'}
+ fontSize={'var(--fs-sm)'}
+ variations={'primary'}
+ iconColor={'white'}
+ onClick={onCloseModal}
+ />
+ )}
+ />
+
+ (
+ }
+ text={'Edit'}
+ iconSize={'18px'}
+ fontSize={'var(--fs-sm)'}
+ variations={'success'}
+ iconColor={'white'}
+ disabled={!itemSelected || itemSelected?.status === 'Check out'}
+ onClick={onCloseModal}
+ />
+ )}
+ />
+
+ (
+ }
+ text={'Check out'}
+ iconSize={'18px'}
+ fontSize={'var(--fs-sm)'}
+ variations={'danger'}
+ iconColor={'white'}
+ disabled={!itemSelected || itemSelected?.status === 'Check out'}
+ onClick={onCloseModal}
+ />
+ )}
+ />
+
+ (
+
+ )}
+ />
+
+
+
+ }/>
+
+
+
+ }/>
+
+
-
+ {isLoading && }
+
+ {
+ tempBookings &&
+ Boolean(tempBookings.length) &&
+
+ columns={columns}
+ rows={tempBookings}
+ count={count}
+ searchPlaceHolder={'Search by name...'}
+ stateSelected={{
+ itemSelected,
+ setItemSelected
+ }}
+ onRowClick={(data) => {
+ setItemSelected(data);
+ }}/>
+ }
+
+ {tempBookings && Boolean(!tempBookings.length) && No data to show here!}
);
};
diff --git a/hotel-management/src/pages/Booking/styled.ts b/hotel-management/src/pages/Booking/styled.ts
index 7ea7730..7595e3a 100644
--- a/hotel-management/src/pages/Booking/styled.ts
+++ b/hotel-management/src/pages/Booking/styled.ts
@@ -14,14 +14,20 @@ const Title = styled.h2`
text-transform: capitalize;
`;
-const StyledOperationTable = styled.div`
+const StyledTableOption = styled.div`
display: flex;
gap: 30px;
justify-content: flex-end;
`;
+const ActionTable = styled.div`
+ display: flex;
+ gap: 30px;
+`
+
export {
StyledBooking,
Title,
- StyledOperationTable
+ StyledTableOption,
+ ActionTable
};
diff --git a/hotel-management/src/pages/Login/LoginForm.tsx b/hotel-management/src/pages/Login/LoginForm.tsx
index af7d617..cca73dd 100644
--- a/hotel-management/src/pages/Login/LoginForm.tsx
+++ b/hotel-management/src/pages/Login/LoginForm.tsx
@@ -1,29 +1,29 @@
import { useForm } from 'react-hook-form';
// Components
-import Form from '@component/Form';
+import Form from '@src/components/Form';
// Styled
import { FieldInput, StyledLoginForm } from './styled';
-import Button from '@commonStyle/Button';
+import Button from '@src/commons/styles/Button';
// Constants
import {
INVALID_EMAIL,
REQUIRED_FIELD_ERROR,
-} from '@constant/formValidateMessage';
+} from '@src/constants/formValidateMessage';
// Types
-import { ILogin } from '@type/common';
+import { ILogin } from '@src/types/common';
// Hooks
-import { useLogin } from '@hook/authentication/useLogin';
+import { useLogin } from '@src/hooks/authentication/useLogin';
// Helpers
-import { isValidRegex } from '@helper/validators';
+import { isValidRegex } from '@src/helpers/validators';
// Constants
-import { REGEX } from '@constant/commons';
+import { REGEX } from '@src/constants/commons';
const LoginForm = () => {
const {
diff --git a/hotel-management/src/pages/Login/__tests__/LoginForm.test.tsx b/hotel-management/src/pages/Login/__tests__/LoginForm.test.tsx
index 46e477a..05cbcc4 100644
--- a/hotel-management/src/pages/Login/__tests__/LoginForm.test.tsx
+++ b/hotel-management/src/pages/Login/__tests__/LoginForm.test.tsx
@@ -1,10 +1,10 @@
-import { useLogin } from "@hook/authentication/useLogin";
-import LoginForm from "@page/Login/LoginForm";
+import { useLogin } from "@src/hooks/authentication/useLogin";
+import LoginForm from "@src/pages/Login/LoginForm";
import { fireEvent, render, waitFor } from "@testing-library/react";
// Mock the useLogin hook
-jest.mock('@hook/authentication/useLogin', () => ({
+jest.mock('@src/hooks/authentication/useLogin', () => ({
useLogin: jest.fn(),
}));
diff --git a/hotel-management/src/pages/Login/index.tsx b/hotel-management/src/pages/Login/index.tsx
index e809c1c..84edaae 100644
--- a/hotel-management/src/pages/Login/index.tsx
+++ b/hotel-management/src/pages/Login/index.tsx
@@ -7,7 +7,7 @@ import { LoginLayout, StyledLogo, TitleStyled } from './styled';
import LoginForm from './LoginForm';
// Hooks
-import { useAccount } from '@hook/authentication/useAccount';
+import { useAccount } from '@src/hooks/authentication/useAccount';
const Login = () => {
const { account } = useAccount();
diff --git a/hotel-management/src/pages/Login/styled.ts b/hotel-management/src/pages/Login/styled.ts
index 0dbc971..a5bfa43 100644
--- a/hotel-management/src/pages/Login/styled.ts
+++ b/hotel-management/src/pages/Login/styled.ts
@@ -1,7 +1,7 @@
import styled from 'styled-components';
// Styled
-import CommonInput from '@commonStyle/CommonInput';
+import CommonInput from '@src/commons/styles/CommonInput';
const LoginLayout = styled.main`
height: 100vh;
diff --git a/hotel-management/src/pages/NotFound/__tests__/index.test.tsx b/hotel-management/src/pages/NotFound/__tests__/index.test.tsx
index c09765d..1fadf02 100644
--- a/hotel-management/src/pages/NotFound/__tests__/index.test.tsx
+++ b/hotel-management/src/pages/NotFound/__tests__/index.test.tsx
@@ -1,4 +1,4 @@
-import { fireEvent, render, screen } from "@testing-library/react";
+import { fireEvent, render } from "@testing-library/react";
import NotFound from "..";
import { useNavigate } from "react-router-dom";
@@ -9,18 +9,18 @@ jest.mock('react-router-dom', () => ({
describe('NotFound', () => {
test('Should render correctly', () => {
- render();
+ const wrapper = render();
- expect(screen.getByText('The page not found!')).toBeInTheDocument();
- expect(screen.getByText('Go back!')).toBeInTheDocument();
+ expect(wrapper.getByText('The page not found!')).toBeInTheDocument();
+ expect(wrapper.getByText('Go back!')).toBeInTheDocument();
});
test('Should call navigate correctly when click button', () => {
const mockNavigate = jest.fn();
(useNavigate as jest.Mock).mockReturnValue(mockNavigate);
- render();
+ const wrapper = render();
- fireEvent.click(screen.getByText('Go back!'));
+ fireEvent.click(wrapper.getByText('Go back!'));
expect(mockNavigate).toHaveBeenCalledTimes(1);
expect(mockNavigate).toHaveBeenCalledWith(-1);
diff --git a/hotel-management/src/pages/Room/RoomForm.tsx b/hotel-management/src/pages/Room/RoomForm.tsx
index 2b1fdde..078e6cb 100644
--- a/hotel-management/src/pages/Room/RoomForm.tsx
+++ b/hotel-management/src/pages/Room/RoomForm.tsx
@@ -1,27 +1,27 @@
import { useForm } from 'react-hook-form';
// Styled
-import Input from '@commonStyle/Input.ts';
+import Input from '@src/commons/styles/Input.ts';
// Types
-import { IRoom } from '@type/room.ts';
+import { IRoom } from '@src/types/room.ts';
// Constants
import {
INVALID_FIELD,
REQUIRED_FIELD_ERROR,
-} from '@constant/formValidateMessage.ts';
+} from '@src/constants/formValidateMessage.ts';
import { REGEX } from '../../constants/commons.ts';
// Helpers
-import { isValidRegex, isValidString } from '@helper/validators.ts';
+import { isValidRegex, isValidString } from '@src/helpers/validators.ts';
// Components
-import Form from '@component/Form/index.tsx';
+import Form from '@src/components/Form/index.tsx';
// Hooks
-import { useCreateRoom } from '@hook/rooms/useCreateRoom.ts';
-import { useUpdateRoom } from '@hook/rooms/useUpdateRoom.ts';
+import { useCreateRoom } from '@src/hooks/rooms/useCreateRoom.ts';
+import { useUpdateRoom } from '@src/hooks/rooms/useUpdateRoom.ts';
interface IRoomFormProp {
onCloseModal?: () => void;
diff --git a/hotel-management/src/pages/Room/RoomRow.tsx b/hotel-management/src/pages/Room/RoomRow.tsx
deleted file mode 100644
index df5d73e..0000000
--- a/hotel-management/src/pages/Room/RoomRow.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import { useCallback, useMemo } from 'react';
-
-// Helpers
-import { formatCurrency } from '@helper/helper';
-
-// Types
-import { IRoom } from '@type/room';
-
-// Components
-import RoomForm from './RoomForm';
-import Modal from '@component/Modal';
-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 { useSetIsDeleteRoom } from '@hook/rooms/useSetIsDeleteRoom';
-
-// Constants
-import { FORM } from '@constant/commons';
-
-interface IRoomRow {
- room: IRoom;
-}
-
-const RoomRow = ({ room }: IRoomRow) => {
- const {
- id,
- name,
- price,
- status
- } = room;
- const { setIsDeleteRoom } = useSetIsDeleteRoom();
- const formattedPrice = useMemo(() => formatCurrency(price), [price]);
- const renderEditBtn = useCallback(
- (onCloseModal: () => void) => (
- }>
- Edit
-
- ),
- []
- );
- const renderDeleteBtn = useCallback(
- (onCloseModal: () => void) => (
- } onClick={onCloseModal} disabled={status}>
- Delete
-
- ),
- [status]
- );
-
- return (
-
- {id}
- {name}
- {formattedPrice}
- {
- status
- ? 'Unavailable'
- : 'Available'
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setIsDeleteRoom(id)}
- />
-
-
-
-
-
- );
-};
-
-export default RoomRow;
diff --git a/hotel-management/src/pages/Room/RoomTable.tsx b/hotel-management/src/pages/Room/RoomTable.tsx
deleted file mode 100644
index e0d8ce6..0000000
--- a/hotel-management/src/pages/Room/RoomTable.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import { useCallback } from 'react';
-
-// Components
-import Menus from '@component/Menus';
-import Table from '@component/Table';
-import Message from '@component/Message';
-import Search from '@component/Search';
-import SortBy from '@component/SortBy';
-import OrderBy from '@component/OrderBy';
-import RoomRow from './RoomRow';
-
-// Types
-import { IRoom } from '@type/room';
-
-// Constants
-import { ORDERBY_OPTIONS, ROOM_PAGE } from '@constant/commons';
-
-// Styled
-import { StyledOperationTable } from './styled';
-import Direction from '@commonStyle/Direction';
-import Spinner from '@commonStyle/Spinner';
-
-// Hooks
-import { useRooms } from '@hook/rooms/useRooms';
-import Pagination from '@component/Pagination';
-
-const RoomTable = () => {
- const columnName = ['Id', 'Name', 'Price', 'Status'];
- const {
- isLoading,
- rooms,
- count
- } = useRooms();
-
- const renderRoomRow = useCallback(
- (room: IRoom) => ,
- []
- );
-
- return (
- <>
-
-
-
-
-
-
-
-
- {isLoading && }
-
- {rooms && rooms.length ? (
-
-
-
- data={rooms} render={renderRoomRow} />
-
-
-
-
-
- ) : (
- !isLoading && No data to show here!
- )}
-
- >
- );
-};
-
-export default RoomTable;
diff --git a/hotel-management/src/pages/Room/__tests__/RoomForm.test.tsx b/hotel-management/src/pages/Room/__tests__/RoomForm.test.tsx
index 535f39b..6d06e9f 100644
--- a/hotel-management/src/pages/Room/__tests__/RoomForm.test.tsx
+++ b/hotel-management/src/pages/Room/__tests__/RoomForm.test.tsx
@@ -8,7 +8,7 @@ import {
} from '@testing-library/react';
// Types
-import { IRoom } from '@type/room';
+import { IRoom } from '@src/types/room';
// Components
import RoomForm from '../RoomForm';
@@ -16,16 +16,16 @@ import RoomForm from '../RoomForm';
const mockCreateRoom = jest.fn();
const mockUpdateRoom = jest.fn();
-jest.mock('@hook/rooms/useCreateRoom.ts', () => ({
- ...jest.requireActual('@hook/rooms/useCreateRoom.ts'),
+jest.mock('@src/hooks/rooms/useCreateRoom.ts', () => ({
+ ...jest.requireActual('@src/hooks/rooms/useCreateRoom.ts'),
useCreateRoom: jest.fn(() => ({
isCreating: false,
createRoom: mockCreateRoom,
})),
}));
-jest.mock('@hook/rooms/useUpdateRoom', () => ({
- ...jest.requireActual('@hook/rooms/useUpdateRoom'),
+jest.mock('@src/hooks/rooms/useUpdateRoom', () => ({
+ ...jest.requireActual('@src/hooks/rooms/useUpdateRoom'),
useUpdateRoom: jest.fn(() => ({
isUpdating: false,
updateRoom: mockUpdateRoom,
diff --git a/hotel-management/src/pages/Room/__tests__/RoomRow.test.tsx b/hotel-management/src/pages/Room/__tests__/RoomRow.test.tsx
deleted file mode 100644
index 838f984..0000000
--- a/hotel-management/src/pages/Room/__tests__/RoomRow.test.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { render } from '@testing-library/react';
-
-// Types
-import { IRoom } from '@type/room';
-
-// Components
-import RoomRow from '../RoomRow';
-
-describe('RoomRow', () => {
- const tempRoom: IRoom = {
- id: 1,
- name: 'Temp Room',
- price: 2399,
- status: false,
- isDelete: true,
- };
-
- const queryClient = new QueryClient();
- const wrapper = render(
-
-
-
- );
-
- test('Should render correctly', () => {
- expect(wrapper).toMatchSnapshot();
- });
-});
diff --git a/hotel-management/src/pages/Room/__tests__/RoomTable.test.tsx b/hotel-management/src/pages/Room/__tests__/RoomTable.test.tsx
deleted file mode 100644
index d069141..0000000
--- a/hotel-management/src/pages/Room/__tests__/RoomTable.test.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { BrowserRouter } from 'react-router-dom';
-import { render } from '@testing-library/react';
-
-// Components
-import RoomTable from '@page/Room/RoomTable';
-
-describe('UserTable', () => {
- const queryClient = new QueryClient();
-
- const wrapper = render(
-
-
-
-
-
- );
-
- test('Should render correctly', () => {
- expect(wrapper).toMatchSnapshot();
- });
-});
diff --git a/hotel-management/src/pages/Room/index.tsx b/hotel-management/src/pages/Room/index.tsx
index ddde771..a97a32c 100644
--- a/hotel-management/src/pages/Room/index.tsx
+++ b/hotel-management/src/pages/Room/index.tsx
@@ -1,33 +1,185 @@
// Components
-import RoomTable from './RoomTable';
import RoomForm from './RoomForm';
-import Modal from '@component/Modal';
+import Modal from '@src/components/Modal';
+import ButtonIcon from '@src/components/ButtonIcon';
+import Direction from '@src/commons/styles/Direction';
+import { FiEdit } from 'react-icons/fi';
+import { FaRegTrashAlt } from 'react-icons/fa';
+import { MdOutlineAddCircleOutline } from 'react-icons/md';
+import Table from '@src/components/Table';
// Styled
-import { StyledRoom, Title } from './styled';
-import Direction from '@commonStyle/Direction.ts';
-import Button from '@commonStyle/Button';
+import { ActionTable, StyledRoom, Title } from './styled';
+import Spinner from '@src/commons/styles/Spinner.ts';
+
+// Types
+import { ColumnProps } from '@src/types/common.ts';
+import { IRoom } from '@src/types/room.ts';
+
+// Hooks
+import { useRooms } from '@src/hooks/rooms/useRooms.ts';
+import { useEffect, useState } from 'react';
+import {FORM, ROOM_PAGE} from '@src/constants/commons.ts';
+import { findItemInListById } from '@src/helpers/helper.ts';
+import ConfirmMessage from '@src/components/ConfirmMessage';
+import { useSetIsDeleteRoom } from '@src/hooks/rooms/useSetIsDeleteRoom.ts';
+import Message from "@src/components/Message";
+
+interface IRoomTable extends Omit {
+ status: string;
+}
const Room = () => {
+ const { setIsDeleteRoom } = useSetIsDeleteRoom();
+ const [itemSelected, setItemSelected] = useState();
+ let roomSelected: IRoom | undefined;
+
+ const columns: ColumnProps[] = [
+ {
+ key: 'id',
+ title: 'Id',
+ width: 10
+ },
+ {
+ key: 'name',
+ title: 'Name',
+ width: 40
+ },
+ {
+ key: 'price',
+ title: 'Price',
+ width: 20
+ },
+ {
+ key: 'status',
+ title: 'Status',
+ width: 20
+ }
+ ];
+ const { isLoading, rooms, count } = useRooms();
+
+ // Reset value when rooms changed.
+ useEffect(() => {
+ setItemSelected(undefined);
+ }, [rooms]);
+
+ const tempRooms = rooms?.map((room) => ({
+ ...room,
+ status: room.status
+ ? 'Unavailable'
+ : 'Available'
+ }));
+
+ if (itemSelected && rooms) {
+ roomSelected = findItemInListById(itemSelected.id, rooms);
+ }
+
return (
List Room
- (
-
- )}
- />
-
-
-
+
+ (
+ }
+ text={'Add Room'}
+ iconSize={'18px'}
+ fontSize={'var(--fs-sm)'}
+ variations={'primary'}
+ iconColor={'white'}
+ onClick={onCloseModal}
+ />
+ )}
+ />
+
+ (
+ }
+ text={'Edit'}
+ iconSize={'18px'}
+ fontSize={'var(--fs-sm)'}
+ variations={'success'}
+ iconColor={'white'}
+ disabled={!itemSelected}
+ onClick={onCloseModal}
+ />
+ )}
+ />
+
+ (
+ }
+ text={'Delete'}
+ iconSize={'18px'}
+ fontSize={'var(--fs-sm)'}
+ variations={'danger'}
+ iconColor={'white'}
+ disabled={!itemSelected || itemSelected?.status === 'Available'}
+ onClick={onCloseModal}
+ />
+ )}
+ />
+
+ (
+
+ )}
+ />
+
+
+
+ } />
+
+
+ setIsDeleteRoom(roomSelected!.id)}
+ onCloseModal={onCloseModal}
+ />
+ } />
+
+
-
+ {isLoading && }
+
+ {
+ tempRooms &&
+ Boolean(tempRooms.length) &&
+
+ columns={columns}
+ rows={tempRooms}
+ count={count}
+ sortBy={ROOM_PAGE.SORTBY_OPTIONS}
+ enabledOrder={true}
+ searchPlaceHolder={'Search by name...'}
+ stateSelected={{
+ itemSelected,
+ setItemSelected
+ }}
+ onRowClick={(data) => {
+ setItemSelected(data);
+ }} />
+ }
+
+ {tempRooms && Boolean(!tempRooms.length) && No data to show here!}
);
};
diff --git a/hotel-management/src/pages/Room/styled.ts b/hotel-management/src/pages/Room/styled.ts
index d6ded8e..239f9e9 100644
--- a/hotel-management/src/pages/Room/styled.ts
+++ b/hotel-management/src/pages/Room/styled.ts
@@ -14,14 +14,20 @@ const Title = styled.h2`
text-transform: capitalize;
`;
-const StyledOperationTable = styled.div`
+const StyledTableOption = styled.div`
display: flex;
gap: 30px;
justify-content: flex-end;
`;
+const ActionTable = styled.div`
+ display: flex;
+ gap: 30px;
+`
+
export {
StyledRoom,
Title,
- StyledOperationTable
+ StyledTableOption,
+ ActionTable
};
diff --git a/hotel-management/src/pages/User/UserForm.tsx b/hotel-management/src/pages/User/UserForm.tsx
index ed9457f..d4fe3c1 100644
--- a/hotel-management/src/pages/User/UserForm.tsx
+++ b/hotel-management/src/pages/User/UserForm.tsx
@@ -1,28 +1,28 @@
import { FormProvider, useForm } from 'react-hook-form';
// Hooks
-import { useCreateUser } from '@hook/users/useCreateUser.ts';
-import { useUpdateUser } from '@hook/users/useUpdateUser.ts';
+import { useCreateUser } from '@src/hooks/users/useCreateUser';
+import { useUpdateUser } from '@src/hooks/users/useUpdateUser';
// Styled
-import Input from '@commonStyle/Input.ts';
+import Input from '@src/commons/styles/Input';
// Components
-import Form from '@component/Form/index.tsx';
+import Form from '@src/components/Form';
// Helpers
-import { isValidRegex } from '@helper/validators.ts';
+import { isValidRegex } from '@src/helpers/validators';
// Constants
import {
INVALID_FIELD,
INVALID_PHONE,
REQUIRED_FIELD_ERROR,
-} from '@constant/formValidateMessage.ts';
-import { REGEX } from '@constant/commons.ts';
+} from '@src/constants/formValidateMessage';
+import { REGEX } from '@src/constants/commons';
// Types
-import { IUser } from '@type/user';
+import { IUser } from '@src/types/user';
interface IUserFormProp {
onCloseModal?: () => void;
diff --git a/hotel-management/src/pages/User/UserRow.tsx b/hotel-management/src/pages/User/UserRow.tsx
deleted file mode 100644
index 027449a..0000000
--- a/hotel-management/src/pages/User/UserRow.tsx
+++ /dev/null
@@ -1,95 +0,0 @@
-import { useCallback } from 'react';
-
-// Components
-import { RiEditBoxFill } from 'react-icons/ri';
-import Modal from '@component/Modal';
-import Table from '@component/Table';
-import Menus from '@component/Menus';
-import UserForm from './UserForm';
-import ConfirmMessage from '@component/ConfirmMessage';
-import { HiTrash } from 'react-icons/hi';
-
-// Types
-import { IUser } from '@type/user';
-
-// Constants
-import { FORM } from '@constant/commons';
-
-// Hooks
-import { useIsDeleteUser } from '@hook/users/useSetIsDeleteUser';
-
-interface IUserRow {
- user: IUser;
-}
-
-const UserRow = ({ user }: IUserRow) => {
- const {
- id,
- name,
- phone,
- isBooked
- } = user;
- const { setIsDeleteUser } = useIsDeleteUser();
-
- const renderEditBtn = useCallback(
- (onCloseModal: () => void) => (
- }>
- Edit
-
- ),
- []
- );
-
- const renderDeleteBtn = useCallback(
- (onCloseModal: () => void) => (
- } onClick={onCloseModal} disabled={isBooked}>
- Delete
-
- ),
- [isBooked]
- );
- return (
-
- {id}
- {name}
- {phone}
- {
- isBooked
- ? 'Yes'
- : 'No'
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setIsDeleteUser(id)}
- />
-
-
-
-
-
- );
-};
-
-export default UserRow;
diff --git a/hotel-management/src/pages/User/UserTable.tsx b/hotel-management/src/pages/User/UserTable.tsx
deleted file mode 100644
index 2e453ef..0000000
--- a/hotel-management/src/pages/User/UserTable.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-import { useCallback } from 'react';
-
-// Components
-import Menus from '@component/Menus';
-import Table from '@component/Table';
-import Message from '@component/Message';
-import Search from '@component/Search';
-import SortBy from '@component/SortBy';
-import OrderBy from '@component/OrderBy';
-import UserRow from './UserRow';
-import Pagination from '@component/Pagination';
-
-// Types
-import { IUser } from '@type/user';
-
-// Constants
-import { ORDERBY_OPTIONS, USER_PAGE } from '@constant/commons';
-
-// Styled
-import Direction from '@commonStyle/Direction';
-import { StyledOperationTable } from './styled';
-import Spinner from '@commonStyle/Spinner';
-
-// Hooks
-import { useUsers } from '@hook/users/useUsers';
-
-const UserTable = () => {
- const columnName = [
- 'Id',
- 'Name',
- 'Phone',
- 'Is Booked'
- ];
- const {
- isLoading,
- users,
- count
- } = useUsers();
-
- const renderUserRow = useCallback(
- (user: IUser) => (
-
- ),
- []
- );
-
- return (
- <>
-
-
-
-
-
-
-
-
- {isLoading && }
-
- {users && users.length ? (
-
-
-
- data={users} render={renderUserRow} />
-
-
-
-
-
- ) : (
- !isLoading && No data to show here!
- )}
-
- >
- );
-};
-
-export default UserTable;
diff --git a/hotel-management/src/pages/User/__tests__/UserForm.test.tsx b/hotel-management/src/pages/User/__tests__/UserForm.test.tsx
index 4df7455..bb387a1 100644
--- a/hotel-management/src/pages/User/__tests__/UserForm.test.tsx
+++ b/hotel-management/src/pages/User/__tests__/UserForm.test.tsx
@@ -11,21 +11,21 @@ import {
import UserForm from '../UserForm';
// Types
-import { IUser } from '@type/user';
+import { IUser } from '@src/types/user';
const mockCreateUser = jest.fn();
const mockUpdateUser = jest.fn();
-jest.mock('@hook/users/useCreateUser.ts', () => ({
- ...jest.requireActual('@hook/users/useCreateUser.ts'),
+jest.mock('@src/hooks/users/useCreateUser.ts', () => ({
+ ...jest.requireActual('@src/hooks/users/useCreateUser.ts'),
useCreateUser: jest.fn(() => ({
isCreating: false,
createUser: mockCreateUser,
})),
}));
-jest.mock('@hook/users/useUpdateUser', () => ({
- ...jest.requireActual('@hook/users/useUpdateUser'),
+jest.mock('@src/hooks/users/useUpdateUser', () => ({
+ ...jest.requireActual('@src/hooks/users/useUpdateUser'),
useUpdateUser: jest.fn(() => ({
isUpdating: false,
updateUser: mockUpdateUser,
diff --git a/hotel-management/src/pages/User/__tests__/UserRow.test.tsx b/hotel-management/src/pages/User/__tests__/UserRow.test.tsx
deleted file mode 100644
index bc484a5..0000000
--- a/hotel-management/src/pages/User/__tests__/UserRow.test.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { render } from '@testing-library/react';
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-
-// Types
-import { IUser } from '@type/user';
-
-// Components
-import UserRow from '../UserRow';
-
-describe('UserRow', () => {
- const tempUser: IUser = {
- id: 1,
- name: 'Temp Room',
- phone: '0324421232',
- isBooked: false,
- isDelete: true,
- };
- const queryClient = new QueryClient();
- const wrapper = render(
-
-
-
- );
-
- test('Should render correctly', () => {
- expect(wrapper).toMatchSnapshot();
- });
-});
diff --git a/hotel-management/src/pages/User/__tests__/UserTable.test.tsx b/hotel-management/src/pages/User/__tests__/UserTable.test.tsx
deleted file mode 100644
index 9f69a75..0000000
--- a/hotel-management/src/pages/User/__tests__/UserTable.test.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { render } from '@testing-library/react';
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
-import { BrowserRouter } from 'react-router-dom';
-
-// Components
-import RoomTable from '@page/Room/RoomTable';
-
-describe('UserTable', () => {
- const queryClient = new QueryClient();
-
- const wrapper = render(
-
-
-
-
-
- );
-
- test('Should render correctly', () => {
- expect(wrapper).toMatchSnapshot();
- });
-});
diff --git a/hotel-management/src/pages/User/index.tsx b/hotel-management/src/pages/User/index.tsx
index 3a29e9f..d52fe54 100644
--- a/hotel-management/src/pages/User/index.tsx
+++ b/hotel-management/src/pages/User/index.tsx
@@ -1,41 +1,188 @@
// Components
-import UserTable from './UserTable';
-import Modal from '@component/Modal';
import UserForm from './UserForm';
+import Modal from '@src/components/Modal';
+import ButtonIcon from '@src/components/ButtonIcon';
+import Direction from '@src/commons/styles/Direction';
+import {FiEdit} from 'react-icons/fi';
+import {FaRegTrashAlt} from 'react-icons/fa';
+import {MdOutlineAddCircleOutline} from 'react-icons/md';
+import Table from '@src/components/Table';
// Styled
-import Button from '@commonStyle/Button';
-import Direction from '@commonStyle/Direction.ts';
-import { StyledUser, Title } from './styled';
+import {ActionTable, StyledUser, Title} from './styled';
+import Spinner from '@src/commons/styles/Spinner.ts';
-// Constants
-import { FORM } from '@constant/commons';
+// Types
+import {ColumnProps} from '@src/types/common.ts';
+import {IUser} from '@src/types/user.ts';
+
+// Hooks
+import {useUsers} from '@src/hooks/users/useUsers.ts';
+import {useEffect, useState} from 'react';
+import {FORM, USER_PAGE} from '@src/constants/commons.ts';
+import {findItemInListById} from '@src/helpers/helper.ts';
+import ConfirmMessage from '@src/components/ConfirmMessage';
+import {useIsDeleteUser} from '@src/hooks/users/useSetIsDeleteUser.ts';
+import Message from "@src/components/Message";
+
+interface IUserTable extends Omit {
+ isBooked: string;
+}
const User = () => {
- const TITLE = 'Add user';
+ const {setIsDeleteUser} = useIsDeleteUser();
+ const [itemSelected, setItemSelected] = useState();
+ let userSelected: IUser | undefined;
+
+ const columns: ColumnProps[] = [
+ {
+ key: 'id',
+ title: 'Id',
+ width: 10
+ },
+ {
+ key: 'name',
+ title: 'Name',
+ width: 40
+ },
+ {
+ key: 'phone',
+ title: 'Phone',
+ width: 20
+ },
+ {
+ key: 'isBooked',
+ title: 'Is Booked',
+ width: 20
+ }
+ ];
+ const {isLoading, users, count} = useUsers();
+
+ // Reset value when users changed.
+ useEffect(() => {
+ setItemSelected(undefined);
+ }, [users]);
+
+ const tempUsers = users?.map((user) => (
+ {
+ ...user,
+ isBooked: user.isBooked
+ ? 'Yes'
+ : 'No'
+ }
+ ));
+
+ if (itemSelected && users) {
+ userSelected = findItemInListById(itemSelected.id, users);
+ }
return (
- <>
-
-
- List User
+
+
+ List User
-
+
+
(
-
+ }
+ text={'Add User'}
+ iconSize={'18px'}
+ fontSize={'var(--fs-sm)'}
+ variations={'primary'}
+ iconColor={'white'}
+ onClick={onCloseModal}
+ />
)}
/>
-
-
-
-
-
-
-
- >
+ (
+ }
+ text={'Edit'}
+ iconSize={'18px'}
+ fontSize={'var(--fs-sm)'}
+ variations={'success'}
+ iconColor={'white'}
+ disabled={!itemSelected}
+ onClick={onCloseModal}
+ />
+ )}
+ />
+
+ (
+ }
+ text={'Delete'}
+ iconSize={'18px'}
+ fontSize={'var(--fs-sm)'}
+ variations={'danger'}
+ iconColor={'white'}
+ disabled={!itemSelected || itemSelected?.isBooked === 'Yes'}
+ onClick={onCloseModal}
+ />
+ )}
+ />
+
+ (
+
+ )}
+ />
+
+
+
+ }/>
+
+
+ setIsDeleteUser(userSelected!.id)}
+ onCloseModal={onCloseModal}
+ />
+ }/>
+
+
+
+
+
+ {isLoading && }
+
+ {
+ tempUsers &&
+ Boolean(tempUsers.length) &&
+
+ columns={columns}
+ rows={tempUsers}
+ count={count}
+ sortBy={USER_PAGE.SORTBY_OPTIONS}
+ enabledOrder={true}
+ searchPlaceHolder={'Search by phone...'}
+ stateSelected={{
+ itemSelected,
+ setItemSelected
+ }}
+ onRowClick={(data) => {
+ setItemSelected(data);
+ }}/>
+ }
+
+ {tempUsers && Boolean(!tempUsers.length) && No data to show here!}
+
);
};
diff --git a/hotel-management/src/pages/User/styled.ts b/hotel-management/src/pages/User/styled.ts
index 3b1775b..f163b2e 100644
--- a/hotel-management/src/pages/User/styled.ts
+++ b/hotel-management/src/pages/User/styled.ts
@@ -14,14 +14,20 @@ const Title = styled.h2`
text-transform: capitalize;
`;
-const StyledOperationTable = styled.div`
+const StyledTableOption = styled.div`
display: flex;
gap: 30px;
justify-content: flex-end;
`;
+const ActionTable = styled.div`
+ display: flex;
+ gap: 30px;
+`
+
export {
StyledUser,
Title,
- StyledOperationTable
+ StyledTableOption,
+ ActionTable
};
diff --git a/hotel-management/src/services/__tests__/authenticationService.test.ts b/hotel-management/src/services/__tests__/authenticationService.test.ts
index d9bddcf..a1cfc7c 100644
--- a/hotel-management/src/services/__tests__/authenticationService.test.ts
+++ b/hotel-management/src/services/__tests__/authenticationService.test.ts
@@ -3,12 +3,12 @@ import {
login,
logout,
updateAccount,
-} from '@service/authenticationService';
-import supabase from '@service/supabaseService';
+} from '@src/services/authenticationService';
+import supabase from '@src/services/supabaseService';
import { Session, UserAttributes } from '@supabase/supabase-js';
// Mock Supabase module
-jest.mock('@service/supabaseService', () => ({
+jest.mock('@src/services/supabaseService', () => ({
auth: {
signInWithPassword: jest.fn(),
getSession: jest.fn(),
diff --git a/hotel-management/src/services/__tests__/bookingService.test.ts b/hotel-management/src/services/__tests__/bookingService.test.ts
index 3b726c0..ebf25e5 100644
--- a/hotel-management/src/services/__tests__/bookingService.test.ts
+++ b/hotel-management/src/services/__tests__/bookingService.test.ts
@@ -3,17 +3,17 @@ import {
ERROR_CREATE_BOOKING,
ERROR_FETCHING_BOOKING,
ERROR_UPDATE_BOOKING,
-} from '@constant/messages';
+} from '@src/constants/messages';
import {
checkOutBooking,
createBooking,
getAllBookings,
updateBooking,
-} from '@service/bookingServices';
-import supabase from '@service/supabaseService';
-import { IBooking } from '@type/booking';
+} from '@src/services/bookingServices';
+import supabase from '@src/services/supabaseService';
+import { IBooking } from '@src/types/booking';
-jest.mock('@service/supabaseService', () => ({
+jest.mock('@src/services/supabaseService', () => ({
__esModule: true,
default: {
from: jest.fn(() => ({
diff --git a/hotel-management/src/services/__tests__/roomService.test.ts b/hotel-management/src/services/__tests__/roomService.test.ts
index 12b8b95..abfe624 100644
--- a/hotel-management/src/services/__tests__/roomService.test.ts
+++ b/hotel-management/src/services/__tests__/roomService.test.ts
@@ -1,8 +1,8 @@
-import { ERROR_CREATE_ROOM, ERROR_DELETE_ROOM, ERROR_FETCHING_ROOM, ERROR_UPDATE_ROOM } from '@constant/messages';
-import { createRoom, getAllRooms, getRoomById, setIsDeleteRoom, updateRoom, updateRoomStatus } from '@service/roomServices';
-import supabase from '@service/supabaseService';
+import { ERROR_CREATE_ROOM, ERROR_DELETE_ROOM, ERROR_FETCHING_ROOM, ERROR_UPDATE_ROOM } from '@src/constants/messages';
+import { createRoom, getAllRooms, getRoomById, setIsDeleteRoom, updateRoom, updateRoomStatus } from '@src/services/roomServices';
+import supabase from '@src/services/supabaseService';
-jest.mock('@service/supabaseService', () => ({
+jest.mock('@src/services/supabaseService', () => ({
__esModule: true,
default: {
from: jest.fn(() => ({
diff --git a/hotel-management/src/services/__tests__/userService.test.ts b/hotel-management/src/services/__tests__/userService.test.ts
index fc17dcd..a9f4e2f 100644
--- a/hotel-management/src/services/__tests__/userService.test.ts
+++ b/hotel-management/src/services/__tests__/userService.test.ts
@@ -1,12 +1,12 @@
// Services
-import { createUser, getAllUsers, setIsDeleteUser, updateUser, updateUserBookedStatus } from '@service/userServices';
+import { createUser, getAllUsers, setIsDeleteUser, updateUser, updateUserBookedStatus } from '@src/services/userServices';
// Types
-import { IUser } from '@type/user';
-import supabase from '@service/supabaseService';
-import { ERROR_CREATE_USER, ERROR_DELETE_USER, ERROR_FETCHING_USER, ERROR_UPDATE_USER } from '@constant/messages';
+import { IUser } from '@src/types/user';
+import supabase from '@src/services/supabaseService';
+import { ERROR_CREATE_USER, ERROR_DELETE_USER, ERROR_FETCHING_USER, ERROR_UPDATE_USER } from '@src/constants/messages';
-jest.mock('@service/supabaseService', () => ({
+jest.mock('@src/services/supabaseService', () => ({
__esModule: true,
default: {
from: jest.fn(() => ({
diff --git a/hotel-management/src/services/authenticationService.ts b/hotel-management/src/services/authenticationService.ts
index a064ce3..ef43fd0 100644
--- a/hotel-management/src/services/authenticationService.ts
+++ b/hotel-management/src/services/authenticationService.ts
@@ -1,11 +1,11 @@
-import { ILogin } from '@type/common';
+import { ILogin } from '@src/types/common';
import { UserAttributes } from '@supabase/supabase-js';
// Services
import supabase from './supabaseService';
// Types
-import { IAccount } from '@type/account';
+import { IAccount } from '@src/types/account';
/**
* Login services
diff --git a/hotel-management/src/services/bookingServices.ts b/hotel-management/src/services/bookingServices.ts
index bd24708..aef0b11 100644
--- a/hotel-management/src/services/bookingServices.ts
+++ b/hotel-management/src/services/bookingServices.ts
@@ -1,18 +1,18 @@
// Types
-import { IBooking, TBookingResponse } from '@type/booking';
+import { IBooking, TBookingResponse } from '@src/types/booking';
// Services
import supabase from './supabaseService';
// Constants
-import { DEFAULT_PAGE_SIZE } from '@constant/config';
+import { DEFAULT_PAGE_SIZE } from '@src/constants/config';
import {
BOOKINGS_TABLE,
ERROR_CHECKOUT,
ERROR_CREATE_BOOKING,
ERROR_FETCHING_BOOKING,
ERROR_UPDATE_BOOKING,
-} from '@constant/messages';
+} from '@src/constants/messages';
import { updateRoomStatus } from './roomServices';
import { updateUserBookedStatus } from './userServices';
diff --git a/hotel-management/src/services/roomServices.ts b/hotel-management/src/services/roomServices.ts
index ed78b85..f59d4a1 100644
--- a/hotel-management/src/services/roomServices.ts
+++ b/hotel-management/src/services/roomServices.ts
@@ -1,18 +1,18 @@
// Types
-import { IRoom } from '@type/room';
+import { IRoom } from '@src/types/room';
// Services
import supabase from './supabaseService';
// Constants
-import { DEFAULT_PAGE_SIZE } from '@constant/config';
+import { DEFAULT_PAGE_SIZE } from '@src/constants/config';
import {
ERROR_CREATE_ROOM,
ERROR_DELETE_ROOM,
ERROR_FETCHING_ROOM,
ERROR_UPDATE_ROOM,
- ROOMS_TABLE,
-} from '@constant/messages';
+ ROOMS_TABLE
+} from '@src/constants/messages';
interface IGetAllRooms {
sortBy: string;
@@ -26,11 +26,11 @@ interface IGetAllRooms {
* @returns Return all rooms in database
*/
const getAllRooms = async ({
- sortBy,
- orderBy,
- roomSearch,
- page,
-}: IGetAllRooms): Promise<{ data: IRoom[]; count: number | null }> => {
+ sortBy,
+ orderBy,
+ roomSearch,
+ page
+ }: IGetAllRooms): Promise<{ data: IRoom[]; count: number | null }> => {
const from = (page - 1) * DEFAULT_PAGE_SIZE;
const to = from + DEFAULT_PAGE_SIZE - 1;
@@ -157,5 +157,5 @@ export {
createRoom,
setIsDeleteRoom,
getRoomById,
- updateRoomStatus,
+ updateRoomStatus
};
diff --git a/hotel-management/src/services/supabaseService.ts b/hotel-management/src/services/supabaseService.ts
index 27b485a..bd17283 100644
--- a/hotel-management/src/services/supabaseService.ts
+++ b/hotel-management/src/services/supabaseService.ts
@@ -1,10 +1,10 @@
import { createClient } from '@supabase/supabase-js';
// Types
-import { Database } from '@type/supabase';
+import { Database } from '@src/types/supabase';
// Constants
-import { supabaseKey, supabaseUrl } from '@constant/config';
+import { supabaseKey, supabaseUrl } from '@src/constants/config';
const supabase = createClient(supabaseUrl, supabaseKey!);
diff --git a/hotel-management/src/services/userServices.ts b/hotel-management/src/services/userServices.ts
index 2652372..cf2dc7b 100644
--- a/hotel-management/src/services/userServices.ts
+++ b/hotel-management/src/services/userServices.ts
@@ -1,18 +1,18 @@
// Types
-import { IUser } from '@type/user';
+import { IUser } from '@src/types/user';
// Services
import supabase from './supabaseService';
// Constants
-import { DEFAULT_PAGE_SIZE } from '@constant/config';
+import { DEFAULT_PAGE_SIZE } from '@src/constants/config';
import {
ERROR_CREATE_USER,
ERROR_DELETE_USER,
ERROR_FETCHING_USER,
ERROR_UPDATE_USER,
USERS_TABLE,
-} from '@constant/messages';
+} from '@src/constants/messages';
/**
* Create user to the database
diff --git a/hotel-management/src/styles/abstracts/variables.css b/hotel-management/src/styles/abstracts/variables.css
index 8ced783..2777805 100644
--- a/hotel-management/src/styles/abstracts/variables.css
+++ b/hotel-management/src/styles/abstracts/variables.css
@@ -1,13 +1,21 @@
:root {
--primary-color: #0010ba;
+ --primary-hover-color: #0010ba8c;
--header-table-color: #ebebeb;
+ --item-hover: #f1f1f1;
+ --item-selected: #ececec;
--border-color: #8c8c8c;
--footer-table-color: #ebebeb;
--secondary-btn-color: #d1d1d1;
--disabled-btn-color: #7f82a6;
+
--danger-btn-color: #ff4f4f;
+ --danger-btn-hover-color: #ff4f4f8c;
+
+ --success-btn-color: #228b22;
+ --success-btn-hover-color: #228b2299;
--hover-background-color: #f3f4f6;
--hover-dark-background-color: #d0d0d0;
diff --git a/hotel-management/src/types/common.ts b/hotel-management/src/types/common.ts
index 08e954e..440884b 100644
--- a/hotel-management/src/types/common.ts
+++ b/hotel-management/src/types/common.ts
@@ -12,6 +12,19 @@ interface ILogin {
password: string;
}
+interface ColumnProps {
+ key: string;
+ title: string;
+ width: number;
+ isDateValue?: boolean;
+}
+
type TDirection = 'vertical' | 'horizontal';
-export type { Nullable, IDataState, TDirection, ILogin };
+export type {
+ Nullable,
+ IDataState,
+ TDirection,
+ ILogin,
+ ColumnProps
+};
diff --git a/hotel-management/test/__mocks__/fileMock.ts b/hotel-management/test/__mocks__/fileMock.ts
deleted file mode 100644
index 86059f3..0000000
--- a/hotel-management/test/__mocks__/fileMock.ts
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = 'test-file-stub';
diff --git a/hotel-management/tsconfig.json b/hotel-management/tsconfig.json
index 75af449..fd9b15a 100644
--- a/hotel-management/tsconfig.json
+++ b/hotel-management/tsconfig.json
@@ -24,15 +24,7 @@
/* Alias */
"paths": {
- "@service/*": ["./src/services/*"],
- "@constant/*": ["./src/constants/*"],
- "@hook/*": ["./src/hooks/*"],
- "@helper/*": ["./src/helpers/*"],
- "@context/*": ["./src/contexts/*"],
- "@component/*": ["./src/components/*"],
- "@commonStyle/*": ["./src/commons/styles/*"],
- "@type/*": ["./src/types/*"],
- "@page/*": ["./src/pages/*"],
+ "@src/*": ["./src/*"],
}
},
"include": ["src", "test"],