diff --git a/src/app/[lang]/(blank-layout-pages)/(guest-only)/login/page.tsx b/src/app/[lang]/(blank-layout-pages)/(guest-only)/login/page.tsx index 68331f0..e566a84 100644 --- a/src/app/[lang]/(blank-layout-pages)/(guest-only)/login/page.tsx +++ b/src/app/[lang]/(blank-layout-pages)/(guest-only)/login/page.tsx @@ -13,10 +13,11 @@ export const metadata: Metadata = { } const LoginPage = async () => { - // Vars - const mode = await getServerMode() - - return + return ( +
+ +
+ ) } export default LoginPage diff --git a/src/views/AuthIllustrationWrapper.tsx b/src/views/AuthIllustrationWrapper.tsx new file mode 100644 index 0000000..d61cad0 --- /dev/null +++ b/src/views/AuthIllustrationWrapper.tsx @@ -0,0 +1,43 @@ +'use client' + +// MUI Imports +import { styled } from '@mui/material/styles' + +// Styled Component +const AuthIllustrationWrapper = styled('div')(({ theme }) => ({ + width: '100%', + maxWidth: 450, + position: 'relative', + [theme.breakpoints.up('md')]: { + '&:before': { + zIndex: -1, + position: 'absolute', + height: '234px', + width: '238px', + content: '""', + top: '-80px', + left: '-45px', + backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='238' height='234' viewBox='0 0 238 234' fill='none'%3E%3Crect x='87.9395' y='0.5' width='149' height='149' rx='19.5' stroke='%23${theme.palette.primary.main.slice( + 1 + )}' stroke-opacity='0.16'/%3E%3Crect y='33.5608' width='200' height='200' rx='10' fill='%23${theme.palette.primary.main.slice( + 1 + )}' fill-opacity='0.08'/%3E%3C/svg%3E")` + }, + '&:after': { + zIndex: -1, + position: 'absolute', + height: '180px', + width: '180px', + content: '""', + right: '-57px', + bottom: '-64px', + backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180' viewBox='0 0 180 180' fill='none'%3E%3Crect x='1' y='1' width='178' height='178' rx='19' stroke='%23${theme.palette.primary.main.slice( + 1 + )}' stroke-opacity='0.16' stroke-width='2' stroke-dasharray='8 8'/%3E%3Crect x='22.5' y='22.5' width='135' height='135' rx='10' fill='%23${theme.palette.primary.main.slice( + 1 + )}' fill-opacity='0.08'/%3E%3C/svg%3E")` + } + } +})) + +export default AuthIllustrationWrapper diff --git a/src/views/Login.tsx b/src/views/Login.tsx index ae7d45c..d478164 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -8,8 +8,8 @@ import Link from 'next/link' import { useParams, useRouter, useSearchParams } from 'next/navigation' // MUI Imports -import useMediaQuery from '@mui/material/useMediaQuery' -import { styled, useTheme } from '@mui/material/styles' +import Card from '@mui/material/Card' +import CardContent from '@mui/material/CardContent' import Typography from '@mui/material/Typography' import IconButton from '@mui/material/IconButton' import InputAdornment from '@mui/material/InputAdornment' @@ -17,7 +17,7 @@ import Checkbox from '@mui/material/Checkbox' import Button from '@mui/material/Button' import FormControlLabel from '@mui/material/FormControlLabel' import Divider from '@mui/material/Divider' -import Alert from '@mui/material/Alert' +import { CircularProgress } from '@mui/material' // Third-party Imports import { Controller, useForm } from 'react-hook-form' @@ -25,11 +25,10 @@ import { valibotResolver } from '@hookform/resolvers/valibot' import { email, object, minLength, string, pipe, nonEmpty } from 'valibot' import type { SubmitHandler } from 'react-hook-form' import type { InferInput } from 'valibot' -import classnames from 'classnames' +import { toast } from 'react-toastify' // Type Imports -import type { SystemMode } from '@core/types' -import type { Locale } from '@/configs/i18n' +import type { Locale } from '@configs/i18n' // Component Imports import Logo from '@components/layout/shared/Logo' @@ -38,39 +37,12 @@ import CustomTextField from '@core/components/mui/TextField' // Config Imports import themeConfig from '@configs/themeConfig' -// Hook Imports -import { useImageVariant } from '@core/hooks/useImageVariant' -import { useSettings } from '@core/hooks/useSettings' - // Util Imports import { getLocalizedUrl } from '@/utils/i18n' import { useAuthMutation } from '../services/mutations/auth' -import { CircularProgress } from '@mui/material' -import { toast } from 'react-toastify' -// Styled Custom Components -const LoginIllustration = styled('img')(({ theme }) => ({ - zIndex: 2, - blockSize: 'auto', - maxBlockSize: 680, - maxInlineSize: '100%', - margin: theme.spacing(12), - [theme.breakpoints.down(1536)]: { - maxBlockSize: 550 - }, - [theme.breakpoints.down('lg')]: { - maxBlockSize: 450 - } -})) - -const MaskImg = styled('img')({ - blockSize: 'auto', - maxBlockSize: 355, - inlineSize: '100%', - position: 'absolute', - insetBlockEnd: 0, - zIndex: -1 -}) +// Styled Component Imports +import AuthIllustrationWrapper from './AuthIllustrationWrapper' type ErrorType = { message: string[] @@ -87,29 +59,17 @@ const schema = object({ ) }) -const Login = ({ mode }: { mode: SystemMode }) => { +const Login = () => { // States const [isPasswordShown, setIsPasswordShown] = useState(false) const [errorState, setErrorState] = useState(null) const { login } = useAuthMutation() - // Vars - const darkImg = '/images/pages/auth-mask-dark.png' - const lightImg = '/images/pages/auth-mask-light.png' - const darkIllustration = '/images/illustrations/auth/v2-login-dark.png' - const lightIllustration = '/images/illustrations/auth/v2-login-light.png' - const borderedDarkIllustration = '/images/illustrations/auth/v2-login-dark-border.png' - const borderedLightIllustration = '/images/illustrations/auth/v2-login-light-border.png' - // Hooks const router = useRouter() const searchParams = useSearchParams() const { lang: locale } = useParams() - const { settings } = useSettings() - const theme = useTheme() - const hidden = useMediaQuery(theme.breakpoints.down('md')) - const authBackground = useImageVariant(mode, lightImg, darkImg) const { control, @@ -123,14 +83,6 @@ const Login = ({ mode }: { mode: SystemMode }) => { } }) - const characterIllustration = useImageVariant( - mode, - lightIllustration, - darkIllustration, - borderedLightIllustration, - borderedDarkIllustration - ) - const handleClickShowPassword = () => setIsPasswordShown(show => !show) const onSubmit: SubmitHandler = async (data: FormData) => { @@ -138,11 +90,9 @@ const Login = ({ mode }: { mode: SystemMode }) => { onSuccess: (data: any) => { if (data?.user?.role === 'admin') { const redirectURL = searchParams.get('redirectTo') ?? '/dashboards/overview' - router.replace(getLocalizedUrl(redirectURL, locale as Locale)) } else { const redirectURL = searchParams.get('redirectTo') ?? '/sa/organizations/list' - router.replace(getLocalizedUrl(redirectURL, locale as Locale)) } }, @@ -153,34 +103,17 @@ const Login = ({ mode }: { mode: SystemMode }) => { } return ( -
-
- - {!hidden && } -
-
-
- -
-
-
+ + + + + + +
{`Welcome to ${themeConfig.templateName}! 馃憢馃徎`} Please sign-in to your account and start the adventure
-
{}} - onSubmit={handleSubmit(onSubmit)} - className='flex flex-col gap-6' - > + { fullWidth label='Password' placeholder='路路路路路路路路路路路路' - id='login-password' + id='outlined-adornment-password' type={isPasswordShown ? 'text' : 'password'} onChange={e => { field.onChange(e.target.value) @@ -263,10 +196,25 @@ const Login = ({ mode }: { mode: SystemMode }) => { Create an account
+ or +
+ + + + + + + + + + + + +
-
-
-
+ + + ) }