From 5be84ac4c4c8fe71dae9dedbdc5d8fa2f78c8225 Mon Sep 17 00:00:00 2001 From: Ihor Date: Wed, 14 Aug 2024 20:08:29 +0300 Subject: [PATCH] feature: made responsive for login page --- public/svgs/auth-top.svg | 8 ++ src/app/(auth)/layout.tsx | 1 - src/app/test/arrow-link/page.tsx | 4 +- src/components/common/icons/Logo.tsx | 2 +- .../common/ui/arrow-link/ArrowLink.styles.ts | 6 + .../common/ui/arrow-link/ArrowLink.tsx | 20 ++-- .../common/ui/arrow-link/types/index.ts | 6 +- .../auth-pages/login-page/LoginPage.styles.ts | 48 ++++++-- .../pages/auth-pages/login-page/LoginPage.tsx | 108 ++++++------------ .../login-page/components/login-form.tsx | 91 +++++++++++++++ 10 files changed, 192 insertions(+), 102 deletions(-) create mode 100644 public/svgs/auth-top.svg create mode 100644 src/components/pages/auth-pages/login-page/components/login-form.tsx diff --git a/public/svgs/auth-top.svg b/public/svgs/auth-top.svg new file mode 100644 index 0000000..16ff561 --- /dev/null +++ b/public/svgs/auth-top.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/app/(auth)/layout.tsx b/src/app/(auth)/layout.tsx index d31c778..7398b05 100644 --- a/src/app/(auth)/layout.tsx +++ b/src/app/(auth)/layout.tsx @@ -14,7 +14,6 @@ const AuthLayout: FC = ({ children }) => { height: '100vh', display: 'grid', placeItems: 'center', - overflow: 'hidden', }} > {children} diff --git a/src/app/test/arrow-link/page.tsx b/src/app/test/arrow-link/page.tsx index e19f688..6eb657c 100644 --- a/src/app/test/arrow-link/page.tsx +++ b/src/app/test/arrow-link/page.tsx @@ -1,7 +1,7 @@ import { Box } from '@mui/material'; import ArrowLink from '@/components/common/ui/arrow-link'; -import { ArrowVariant } from '@/components/common/ui/arrow-link/types'; +import { IconPlace } from '@/components/common/ui/arrow-link/types'; const Page = () => { return ( @@ -9,7 +9,7 @@ const Page = () => { ); diff --git a/src/components/common/icons/Logo.tsx b/src/components/common/icons/Logo.tsx index be7c61c..5b9c730 100644 --- a/src/components/common/icons/Logo.tsx +++ b/src/components/common/icons/Logo.tsx @@ -15,7 +15,7 @@ const Logo: FC = ({ color = 'orange', }) => { const fill = - color !== 'black' ? theme.palette.orange[300] : theme.palette.dark[400]; + color === 'black' ? theme.palette.dark[400] : theme.palette.orange[300]; if (size === LogoVariant.MEDIUM) { return ( diff --git a/src/components/common/ui/arrow-link/ArrowLink.styles.ts b/src/components/common/ui/arrow-link/ArrowLink.styles.ts index b98c394..b748a48 100644 --- a/src/components/common/ui/arrow-link/ArrowLink.styles.ts +++ b/src/components/common/ui/arrow-link/ArrowLink.styles.ts @@ -2,6 +2,7 @@ import { SxProps, Theme } from '@mui/material/styles'; export const wrapper: SxProps = { a: { + margin: 0, display: 'flex', alignItems: 'center', color: 'white.main', @@ -13,5 +14,10 @@ export const wrapper: SxProps = { '&:active': { color: 'gray.400', }, + + svg: { + width: '24px', + height: '24px', + }, }, }; diff --git a/src/components/common/ui/arrow-link/ArrowLink.tsx b/src/components/common/ui/arrow-link/ArrowLink.tsx index e1b90c6..bcb6591 100644 --- a/src/components/common/ui/arrow-link/ArrowLink.tsx +++ b/src/components/common/ui/arrow-link/ArrowLink.tsx @@ -1,10 +1,10 @@ import { FC } from 'react'; -import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline'; +import { ChevronLeftIcon } from '@heroicons/react/24/outline'; import { Box, Typography } from '@mui/material'; import { SxProps, Theme } from '@mui/material/styles'; import Link from 'next/link'; -import { ArrowVariant } from '@/components/common/ui/arrow-link/types'; +import { IconPlace } from '@/components/common/ui/arrow-link/types'; import mergeSx from '@/lib/utils/mergeSx'; import * as styles from './ArrowLink.styles'; @@ -12,7 +12,8 @@ import * as styles from './ArrowLink.styles'; interface ArrowLinkProps { text: string; href: string; - arrow?: ArrowVariant; + iconPlace?: IconPlace; + icon?: React.ReactNode; target?: string; sx?: SxProps; } @@ -20,20 +21,17 @@ interface ArrowLinkProps { const ArrowLink: FC = ({ text, href, - arrow = ArrowVariant.LEFT, + iconPlace = 'left', + icon = , target, sx = {}, }) => { return ( - {arrow === ArrowVariant.LEFT && ( - - )} - {text} - {arrow === ArrowVariant.RIGHT && ( - - )} + {iconPlace === 'left' && icon} + {text} + {iconPlace === 'right' && icon} ); diff --git a/src/components/common/ui/arrow-link/types/index.ts b/src/components/common/ui/arrow-link/types/index.ts index ca2b9bd..5218129 100644 --- a/src/components/common/ui/arrow-link/types/index.ts +++ b/src/components/common/ui/arrow-link/types/index.ts @@ -1,5 +1 @@ -export enum ArrowVariant { - RIGHT = 'right', - LEFT = 'left', - NONE = 'none', -} +export type IconPlace = 'right' | 'left' | 'none'; diff --git a/src/components/pages/auth-pages/login-page/LoginPage.styles.ts b/src/components/pages/auth-pages/login-page/LoginPage.styles.ts index 585baa5..8648c1e 100644 --- a/src/components/pages/auth-pages/login-page/LoginPage.styles.ts +++ b/src/components/pages/auth-pages/login-page/LoginPage.styles.ts @@ -1,20 +1,40 @@ import { SxProps, Theme } from '@mui/material/styles'; export const wrapper: SxProps = { - width: '1064px', - height: '648px', + width: { + desktop: '1064px', + mobile: '100%', + }, + height: { + desktop: '648px', + mobile: '100%', + }, backgroundColor: 'dark.400', display: 'flex', - flexDirection: 'row', + flexDirection: { + desktop: 'row', + mobile: 'column', + }, justifyContent: 'space-between', + alignItems: 'center', overflow: 'hidden', + form: { - paddingLeft: '74px', + maxWidth: '520px', + width: { + desktop: '70%', + mobile: '100%', + }, + ml: { + desktop: '74px', + mobile: 0, + }, display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center', }, + section: { display: 'flex', flexDirection: 'column', @@ -27,6 +47,7 @@ export const wrapper: SxProps = { width: '100%', pr: '80px', }, + a: { alignSelf: 'flex-start', color: 'orange.500', @@ -36,17 +57,26 @@ export const wrapper: SxProps = { textDecoration: 'underline', }, }, -}; -export const textField: SxProps = { - width: '420px', - height: '44px', + img: { + width: '100%', + height: 'auto', + }, }; export const input: SxProps = {}; +export const image = { + width: '100%', + height: 'auto', + marginBottom: '20px', +}; + export const signInText: SxProps = { - typography: 'h4Bold', + typography: { + desktop: 'h4Bold', + mobile: 'h5Bold', + }, color: 'white.main', mb: '24px', }; diff --git a/src/components/pages/auth-pages/login-page/LoginPage.tsx b/src/components/pages/auth-pages/login-page/LoginPage.tsx index 3d847bc..7736862 100644 --- a/src/components/pages/auth-pages/login-page/LoginPage.tsx +++ b/src/components/pages/auth-pages/login-page/LoginPage.tsx @@ -1,91 +1,53 @@ 'use client'; import { FC } from 'react'; -import { Box, Stack, Typography } from '@mui/material'; -import axios from 'axios'; -import { useFormik } from 'formik'; +import { Box, Stack, Typography, useMediaQuery } from '@mui/material'; +import Image from 'next/image'; import Link from 'next/link'; -import { useRouter } from 'next/navigation'; -import ArrowLink from '@/components/common/ui/arrow-link'; import Button from '@/components/common/ui/button'; -import Input from '@/components/common/ui/input/Input'; import SideSection from '@/components/pages/auth-pages/components/side-section'; -import useToast from '@/hooks/use-toast'; -import AuthAPI from '@/lib/api/auth/AuthAPI'; -import { exceptionMapper } from '@/lib/utils/exception-mapper'; -import storageUtil from '@/lib/utils/storageUtil'; +import LoginForm from '@/components/pages/auth-pages/login-page/components/login-form'; +import theme from '@/styles/theme'; -import { initialValues } from './constants/initialValues'; import * as styles from './LoginPage.styles'; const LoginPage: FC = () => { - const router = useRouter(); - const toast = useToast(); - const formik = useFormik({ - initialValues, - onSubmit: async (values) => { - try { - const { accessToken } = await AuthAPI.login(values); - storageUtil.setToken(accessToken); - router.replace('/profile?tab=organisations'); - return; - } catch (e) { - if (axios.isAxiosError(e)) { - const { error } = e.response?.data; - const mapper = exceptionMapper[error]; - toast.error(mapper.title, mapper.description, 3000, 'filled'); - } - } - }, - }); + const isMobile = useMediaQuery(theme.breakpoints.down('desktop')); return ( -
- Вхід - - - - - Забув пароль? - - - - - - + )} + + {!isMobile ? ( + + + + ) : ( + + + Не маєте акаунту? + + + + + + )}
); }; diff --git a/src/components/pages/auth-pages/login-page/components/login-form.tsx b/src/components/pages/auth-pages/login-page/components/login-form.tsx new file mode 100644 index 0000000..649de08 --- /dev/null +++ b/src/components/pages/auth-pages/login-page/components/login-form.tsx @@ -0,0 +1,91 @@ +import { HomeIcon } from '@heroicons/react/24/outline'; +import { Stack, Typography, useMediaQuery } from '@mui/material'; +import axios from 'axios'; +import { useFormik } from 'formik'; +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; + +import ArrowLink from '@/components/common/ui/arrow-link'; +import Button from '@/components/common/ui/button'; +import { ButtonSize } from '@/components/common/ui/button/types'; +import Input from '@/components/common/ui/input/Input'; +import { initialValues } from '@/components/pages/auth-pages/login-page/constants/initialValues'; +import * as styles from '@/components/pages/auth-pages/login-page/LoginPage.styles'; +import useToast from '@/hooks/use-toast'; +import AuthAPI from '@/lib/api/auth/AuthAPI'; +import { exceptionMapper } from '@/lib/utils/exception-mapper'; +import storageUtil from '@/lib/utils/storageUtil'; +import theme from '@/styles/theme'; + +const LoginForm = () => { + const router = useRouter(); + const toast = useToast(); + const formik = useFormik({ + initialValues, + onSubmit: async (values) => { + try { + const { accessToken } = await AuthAPI.login(values); + storageUtil.setToken(accessToken); + router.replace('/profile?tab=organisations'); + return; + } catch (e) { + if (axios.isAxiosError(e)) { + const { error } = e.response?.data; + const mapper = exceptionMapper[error]; + toast.error(mapper.title, mapper.description, 3000, 'filled'); + } + } + }, + }); + + const isMobile = useMediaQuery(theme.breakpoints.down('desktop')); + + const buttonSize: ButtonSize = isMobile ? 'small' : 'medium'; + + return ( +
+ Вхід + + + + + Забув пароль? + + } + /> + + ); +}; + +export default LoginForm;