diff --git a/hotel-management/src/assets/images/logo.png b/hotel-management/src/assets/images/logo.png new file mode 100644 index 0000000..198ab2b Binary files /dev/null and b/hotel-management/src/assets/images/logo.png differ diff --git a/hotel-management/src/commons/styles/Button.ts b/hotel-management/src/commons/styles/Button.ts index ad82be0..f0c6360 100644 --- a/hotel-management/src/commons/styles/Button.ts +++ b/hotel-management/src/commons/styles/Button.ts @@ -37,6 +37,7 @@ const Button = styled.button` &:disabled, &[disabled] { cursor: not-allowed; + background-color: var(--disabled-btn-color); } `; diff --git a/hotel-management/src/commons/styles/Direction.ts b/hotel-management/src/commons/styles/Direction.ts index 6fe5a18..c1a0661 100644 --- a/hotel-management/src/commons/styles/Direction.ts +++ b/hotel-management/src/commons/styles/Direction.ts @@ -1,7 +1,6 @@ +import { TDirection } from '@type/common'; import styled, { css } from 'styled-components'; -type TDirection = 'vertical' | 'horizontal'; - interface IDirection { type?: TDirection; } diff --git a/hotel-management/src/components/ButtonIcon/index.tsx b/hotel-management/src/components/ButtonIcon/index.tsx index dff27b0..6671291 100644 --- a/hotel-management/src/components/ButtonIcon/index.tsx +++ b/hotel-management/src/components/ButtonIcon/index.tsx @@ -1,4 +1,6 @@ import { ReactNode } from 'react'; + +// Styled import { StyledButtonIcon } from './styled'; interface IButtonIcon { @@ -14,6 +16,7 @@ interface IButtonIcon { size?: string; }; onClick?: () => void; + disabled?: boolean; } const ButtonIcon = ({ @@ -22,6 +25,7 @@ const ButtonIcon = ({ style, iconStyle, onClick, + disabled, }: IButtonIcon) => { const isHaveChildren = Boolean(children); @@ -35,6 +39,7 @@ const ButtonIcon = ({ }} iconStyle={iconStyle} onClick={onClick} + disabled={disabled} > {icon} {children} diff --git a/hotel-management/src/components/Form/index.tsx b/hotel-management/src/components/Form/index.tsx index 6dd2cc3..891934b 100644 --- a/hotel-management/src/components/Form/index.tsx +++ b/hotel-management/src/components/Form/index.tsx @@ -10,6 +10,9 @@ import { FormBtn, } from './styled'; +// Types +import { TDirection } from '@type/common'; + interface IFormProps { children: ReactNode; onSubmit: (event: FormEvent) => void; @@ -20,6 +23,7 @@ interface IFormRow { label: string; error?: string; children: ReactNode; + direction?: TDirection; } const Form = ({ children, onSubmit, id }: IFormProps) => { @@ -30,9 +34,9 @@ const Form = ({ children, onSubmit, id }: IFormProps) => { ); }; -const FormRow = ({ label, error, children }: IFormRow) => { +const FormRow = ({ label, error, children, direction }: IFormRow) => { return ( - +
{children} diff --git a/hotel-management/src/components/Form/styled.ts b/hotel-management/src/components/Form/styled.ts index 01ed87f..f9a2192 100644 --- a/hotel-management/src/components/Form/styled.ts +++ b/hotel-management/src/components/Form/styled.ts @@ -1,4 +1,11 @@ -import styled from 'styled-components'; +import styled, { css } from 'styled-components'; + +// Types +import { TDirection } from '@type/common'; + +interface IStyledFormRow { + direction?: TDirection; +} // Styled import Button from '@commonStyle/Button'; @@ -16,11 +23,20 @@ const StyledActionBtn = styled.div` gap: 100px; `; -const StyledFormRow = styled.div` +const StyledFormRow = styled.div` display: flex; justify-content: space-between; - align-items: center; - gap: 100px; + + ${(props) => + props.direction === 'horizontal' + ? css` + align-items: center; + gap: 100px; + ` + : css` + flex-direction: column; + gap: 15px; + `} `; const Label = styled.label` @@ -45,4 +61,8 @@ const FormBtn = styled(Button)` } `; +StyledFormRow.defaultProps = { + direction: 'horizontal', +}; + export { StyledForm, StyledActionBtn, StyledFormRow, Label, Error, FormBtn }; diff --git a/hotel-management/src/components/HeaderMenu/index.tsx b/hotel-management/src/components/HeaderMenu/index.tsx index 9a5cd93..adfd681 100644 --- a/hotel-management/src/components/HeaderMenu/index.tsx +++ b/hotel-management/src/components/HeaderMenu/index.tsx @@ -6,7 +6,12 @@ import ButtonIcon from '@component/ButtonIcon'; // Styled import { StyledHeaderMenu } from './styled'; +// Hooks +import { useLogout } from '@hook/authentication/useLogout'; + const HeaderMenu = () => { + const { logout, isPending } = useLogout(); + return (
  • @@ -18,9 +23,11 @@ const HeaderMenu = () => {
  • } - iconStyle={{size: '23px' }} + iconStyle={{ size: '23px' }} />
  • diff --git a/hotel-management/src/components/RootLayout/index.tsx b/hotel-management/src/components/RootLayout/index.tsx new file mode 100644 index 0000000..8ca6e58 --- /dev/null +++ b/hotel-management/src/components/RootLayout/index.tsx @@ -0,0 +1,24 @@ +import { Outlet } from 'react-router-dom'; + +// Styled +import Spinner from '@commonStyle/Spinner'; +import { FullPageLayout } from './styled'; + +// Hooks +import { useAccount } from '@hook/authentication/useAccount'; + +const RootLayout = () => { + const { isPending } = useAccount(); + + return isPending ? ( + + + + ) : ( + <> + + + ); +}; + +export default RootLayout; diff --git a/hotel-management/src/components/RootLayout/styled.ts b/hotel-management/src/components/RootLayout/styled.ts new file mode 100644 index 0000000..159ab1c --- /dev/null +++ b/hotel-management/src/components/RootLayout/styled.ts @@ -0,0 +1,11 @@ +import styled from 'styled-components'; + +const FullPageLayout = styled.div` + height: 100vh; + background-color: var(--color-grey-50); + display: flex; + align-items: center; + justify-content: center; +`; + +export { FullPageLayout }; diff --git a/hotel-management/src/components/RouteProtected/index.tsx b/hotel-management/src/components/RouteProtected/index.tsx new file mode 100644 index 0000000..9f970f2 --- /dev/null +++ b/hotel-management/src/components/RouteProtected/index.tsx @@ -0,0 +1,15 @@ +import { useAccount } from '@hook/authentication/useAccount'; +import { ReactNode } from 'react'; +import { Navigate } from 'react-router-dom'; + +interface IRouteProtected { + children: ReactNode; +} +const RouteProtected = ({ children }: IRouteProtected) => { + // Load user login + const { account } = useAccount(); + + return !account ? : children; +}; + +export default RouteProtected; diff --git a/hotel-management/src/constants/path.ts b/hotel-management/src/constants/path.ts index a83803e..89dc268 100644 --- a/hotel-management/src/constants/path.ts +++ b/hotel-management/src/constants/path.ts @@ -4,3 +4,4 @@ export const ROOM = '/room'; export const OTHER_PATH = '*'; export const USER_PATH = 'users'; export const ROOM_PATH = 'rooms'; +export const LOGIN = 'login'; diff --git a/hotel-management/src/styles/abstracts/variables.css b/hotel-management/src/styles/abstracts/variables.css index d9ae533..8ced783 100644 --- a/hotel-management/src/styles/abstracts/variables.css +++ b/hotel-management/src/styles/abstracts/variables.css @@ -23,6 +23,8 @@ --form-color: #fff; + --background-login: #f8f8f8; + --shadow-sm: 0px 10px 20px rgba(0, 0, 0, 0.2); --fs-md: 30px; diff --git a/hotel-management/src/types/common.ts b/hotel-management/src/types/common.ts index 7445679..08e954e 100644 --- a/hotel-management/src/types/common.ts +++ b/hotel-management/src/types/common.ts @@ -7,4 +7,11 @@ interface IDataState { isBooked?: boolean; } -export type { Nullable, IDataState }; +interface ILogin { + email: string; + password: string; +} + +type TDirection = 'vertical' | 'horizontal'; + +export type { Nullable, IDataState, TDirection, ILogin };