Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

Commit

Permalink
feat: updated auth based on new design
Browse files Browse the repository at this point in the history
  • Loading branch information
nmashchenko committed Oct 18, 2023
1 parent 4ef91bf commit 15578e2
Show file tree
Hide file tree
Showing 18 changed files with 342 additions and 403 deletions.
69 changes: 45 additions & 24 deletions client/src/app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,67 @@
'use client';

import { GoogleOAuthProvider } from '@react-oauth/google';
import { useRouter } from 'next/navigation';
import { usePathname, useRouter } from 'next/navigation';
import { ReactNode, useState } from 'react';
import { ArrowLeft, LogoBig } from '@/shared/assets';
import { Button, Tabs } from '@/shared/ui';
import { LogoBig } from '@/shared/assets';
import { Flex, Tabs } from '@/shared/ui';
import styles from './styles.module.scss';

export default function AuthLayout({ children }: { children: ReactNode }) {
const router = useRouter();
const pathname = usePathname();
const options = ['Login', 'Sign Up'];
const [tab, setTab] = useState(options[0]);

const handleBack = () => {
router.push('/');
};
const handleChange = (option: string) => {
setTab(option);
router.push(`/${option.toLowerCase().replace(/\s/g, '')}`);
};

const handleBack = () => {
router.push('/');
};
const header = (
<header className={styles.header}>
<div className={styles.logo} onClick={handleBack}>
<LogoBig />
</div>
<div className={styles.headerNormalizer}>
<Tabs options={options} currentTab={tab} onTabChange={handleChange} />
</div>
</header>
);

return (
<GoogleOAuthProvider clientId={`${process.env.NEXT_PUBLIC_GOOGLE_API_OAUTH_TOKEN}`}>
<div className={styles.container}>
<header className={styles.header}>
<div className={styles.headerNormalizer}>
<Button onClick={handleBack} typeBtn='tertiary' content='text_button'>
<ArrowLeft />
<span>Back</span>
</Button>
</div>
<div className={styles.logo}>
<LogoBig />
</div>
<div className={styles.headerNormalizer}>
<Tabs options={options} currentTab={tab} onTabChange={handleChange} />
</div>
</header>
const basic = (
<div className={styles.container}>
{header}
<Flex
className={styles.children}
direction='column'
justify='center'
align='center'
width='100%'
>
{children}
</Flex>
</div>
);

<div className={styles.children}>{children}</div>
const alternative = (
<Flex className={styles.alternative}>
<div className={styles.left}>
{header}
<Flex className={styles.children} direction='column' justify='center' align='center'>
{children}
</Flex>
</div>
<img className={styles.right} src='https://dummyimage.com/4000x4000' alt='Main image' />

Check warning on line 58 in client/src/app/(auth)/layout.tsx

View workflow job for this annotation

GitHub Actions / pipeline (18.x)

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
</Flex>
);

return (
<GoogleOAuthProvider clientId={`${process.env.NEXT_PUBLIC_GOOGLE_API_OAUTH_TOKEN}`}>
{pathname === '/login' || pathname === '/signup' ? alternative : basic}
</GoogleOAuthProvider>
);
}
7 changes: 0 additions & 7 deletions client/src/app/(auth)/login/confirmation/page.tsx

This file was deleted.

114 changes: 56 additions & 58 deletions client/src/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { useGoogleLogin } from '@react-oauth/google';
import { useRouter } from 'next/navigation';
import { SubmitHandler, useForm } from 'react-hook-form';

import { Button, Input, InputPassword, Typography } from '@/shared/ui';
import { Button, Flex, Input, InputPassword, Typography } from '@/shared/ui';

import { useState } from 'react';
import styles from '../shared.module.scss';
import { Github, Google, Login } from '@/shared/assets';
import { Github, Google, LogoBig } from '@/shared/assets';

interface LoginProps {
email: string;
Expand All @@ -35,66 +35,64 @@ export default function LoginPage() {

return (
<form className={styles.container} onSubmit={handleSubmit(onSubmit)}>
<div className={styles.left}>
<div className={styles.interactive_container}>
<div className={styles.flex_wrapper}>
<Input
placeholder='Email'
{...register('email', { required: 'Email is required!' })}
type='email'
error={errors?.email ? errors.email.message : undefined}
value={email}
onChange={e => setEmail(e.target.value)}
<Flex gap={48} direction='column' maxWidth='370px' width='100%'>
<Flex className={styles.additional_logo} width='100%' justify='center' align='center'>
<LogoBig />
</Flex>
<Flex direction='column' gap={36}>
<Input
placeholder='Email'
{...register('email', { required: 'Email is required!' })}
type='email'
error={errors?.email ? errors.email.message : undefined}
value={email}
onChange={e => setEmail(e.target.value)}
/>

<div>
<InputPassword
placeholder='Password'
{...register('password', {
required: 'Password is required!',
minLength: { value: 8, message: 'Minimum length is 8!' },
})}
error={errors?.password ? errors.password.message : undefined}
value={password}
onChange={e => setPassword(e.target.value)}
/>
<div>
<InputPassword
placeholder='Password'
{...register('password', {
required: 'Password is required!',
minLength: { value: 8, message: 'Minimum length is 8!' },
})}
error={errors?.password ? errors.password.message : undefined}
value={password}
onChange={e => setPassword(e.target.value)}
/>
<div className={styles.forgot_link_wrapper}>
<div
className={styles.forgot_link}
onClick={() => router.push('/password/recover')}
>
<Typography size='body_s' color='greenBright'>
Forgot Password?
</Typography>
</div>
<Flex margin='8px 0 0 0' justify='flex-end'>
<div className={styles.forgot_link} onClick={() => router.push('/password/recover')}>
<Typography size='body_s' color='greenBright'>
Forgot Password?
</Typography>
</div>
</div>
</Flex>
</div>
<div className={styles.flex_wrapper__s}>
<Button type='submit'>Log in</Button>
<div className={styles.lines_container}>
<div className={styles.line} />
<Typography size='body_m' color='greyNormal'>
or log in with
</Typography>
<div className={styles.line} />
</div>
</Flex>

<div className={styles.buttons_container}>
<button className={styles.button} onClick={() => login()} type='button'>
<Google />
</button>
<button className={styles.button} type='button'>
<Github />
</button>
</div>
</div>
</div>
</div>
<div className={styles.right}>
<div className={styles.svg_container}>
<Login />
</div>
</div>
<Flex direction='column' gap={24}>
<Button type='submit'>Log in</Button>

<Flex justify='center' align='center' gap={13} className={styles.lines_container}>
<div className={styles.line} />
<Typography size='body_m' color='greyNormal'>
or log in with
</Typography>
<div className={styles.line} />
</Flex>

<Flex gap={8} justify='center' align='center'>
<Button typeBtn='secondary' size='l' width='100%' type='button' onClick={() => login()}>
<Google />
<Typography>Google</Typography>
</Button>
<Button typeBtn='secondary' size='l' width='100%' type='button'>
<Github />
<Typography>Github</Typography>
</Button>
</Flex>
</Flex>
</Flex>
</form>
);
}
8 changes: 8 additions & 0 deletions client/src/app/(auth)/password/confirmation/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
'use client';
import { IllustrationStatus } from '../../ui';
import { useRouter } from 'next/navigation';

export default function Confirmation() {
const router = useRouter();
const handleBack = () => {
router.push('/');
};
return (
<IllustrationStatus
mainText='Check your email'
subText='If your email is on file, we will send a reset link'
buttonText='Back to login'
buttonHandler={handleBack}
/>
);
}
8 changes: 8 additions & 0 deletions client/src/app/(auth)/password/expired/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
'use client';
import { IllustrationStatus } from '../../ui';
import { useRouter } from 'next/navigation';

export default function Expired() {
const router = useRouter();
const handleBack = () => {
router.push('/');
};
return (
<IllustrationStatus
mainText='Sorry, the link has expired'
subText='This link expires after 15 minutes and can be used once.'
buttonText='Back to login'
buttonHandler={handleBack}
/>
);
}
3 changes: 3 additions & 0 deletions client/src/app/(auth)/password/password.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.text_align {
text-align: center;
}
79 changes: 36 additions & 43 deletions client/src/app/(auth)/password/recover/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ import Link from 'next/link';
import { useState } from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';
import { ArrowLeft } from '@/shared/assets';
import { Button, Input, Typography } from '@/shared/ui';
import styles from '../shared.module.scss';
import { Button, Flex, Input, Typography } from '@/shared/ui';
import styles from '../password.module.scss';
import { useRouter } from 'next/navigation';
import clsx from 'clsx';

interface RecoverProps {
email: string;
Expand All @@ -28,46 +27,40 @@ export default function Recover() {
};

return (
<form
className={clsx(styles.info, {
[styles.width470px]: true,
})}
onSubmit={handleSubmit(onSubmit)}
>
<div
className={clsx(styles.gapContainer, {
[styles.gap8px]: true,
[styles.alignText]: true,
})}
>
<Typography color='greenBright' size='heading_m'>
Recover Password
</Typography>
<Typography size='body_m'>
Enter the email you used to register and we will send you link to reset your password
</Typography>
</div>
<Input
placeholder='Email'
{...register('email', { required: 'Email is required!' })}
type='email'
error={errors?.email ? errors.email.message : undefined}
value={email}
onChange={e => setEmail(e.target.value)}
/>
<div
className={clsx(styles.gapContainer, {
[styles.gap8px]: true,
})}
>
<Button width='100%' disabled={!email.length}>
Reset password
</Button>
<Button width='100%' typeBtn='secondary'>
<ArrowLeft />
<Link href='/login'>Back to Log in</Link>
</Button>
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<Flex direction='column' justify='center' align='center' gap={48} maxWidth='370px'>
<Flex
direction='column'
justify='center'
align='center'
gap={8}
className={styles.text_align}
>
<Typography color='greenBright' size='heading_m'>
Recover Password
</Typography>
<Typography size='body_m'>
Enter the email you used to register and we will send you link to reset your password
</Typography>
</Flex>
<Input
placeholder='Email'
{...register('email', { required: 'Email is required!' })}
type='email'
error={errors?.email ? errors.email.message : undefined}
value={email}
onChange={e => setEmail(e.target.value)}
/>
<Flex direction='column' justify='center' align='center' gap={8} width='100%'>
<Button width='100%' disabled={!email.length}>
Reset password
</Button>
<Button width='100%' typeBtn='secondary' type='button'>
<ArrowLeft />
<Link href='/login'>Back to Log in</Link>
</Button>
</Flex>
</Flex>
</form>
);
}
Loading

2 comments on commit 15578e2

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for teameights ready!

✅ Preview
https://teameights-d0csd564e-exortme1ster.vercel.app

Built with commit 15578e2.
This pull request is being automatically deployed with vercel-action

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for teameights-storybook ready!

✅ Preview
https://teameights-storybook-jx1a2b8ep-exortme1ster.vercel.app

Built with commit 15578e2.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.