mirror of
https://github.com/vercel/commerce.git
synced 2025-07-04 12:11:22 +00:00
Merge pull request #17 from KieIO/m3-lytran
M3: home page, modal login, register
This commit is contained in:
commit
ff30cb65f1
@ -1,14 +1,14 @@
|
|||||||
|
|
||||||
import { Layout } from 'src/components/common'
|
import { Layout } from 'src/components/common'
|
||||||
import { HomeBanner, HomeCollection, HomeCTA, HomeSubscribe, HomeVideo, HomeCategories } from 'src/components/modules/home';
|
import { HomeBanner, HomeCollection, HomeCTA, HomeSubscribe, HomeVideo, HomeCategories, HomeFeature, HomeRecipe } from 'src/components/modules/home';
|
||||||
import HomeRecipe from 'src/components/modules/home/HomeRecipe/HomeRecipe';
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<HomeBanner />
|
<HomeBanner />
|
||||||
<HomeCollection/>
|
<HomeFeature />
|
||||||
<HomeCategories/>
|
<HomeCategories />
|
||||||
|
<HomeCollection />
|
||||||
<HomeVideo />
|
<HomeVideo />
|
||||||
<HomeCTA />
|
<HomeCTA />
|
||||||
<HomeRecipe />
|
<HomeRecipe />
|
||||||
|
@ -5,7 +5,10 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
@screen md {
|
||||||
padding: 0.8rem 3.2rem;
|
padding: 0.8rem 3.2rem;
|
||||||
|
}
|
||||||
&:disabled {
|
&:disabled {
|
||||||
filter: brightness(0.9);
|
filter: brightness(0.9);
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
@ -76,10 +79,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.large {
|
&.large {
|
||||||
|
padding: 1rem 1.5rem;
|
||||||
|
&.onlyIcon {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
@screen md {
|
||||||
padding: 1.6rem 4.8rem;
|
padding: 1.6rem 4.8rem;
|
||||||
&.onlyIcon {
|
&.onlyIcon {
|
||||||
padding: 1.6rem;
|
padding: 1.6rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
&.loading {
|
&.loading {
|
||||||
&::before {
|
&::before {
|
||||||
width: 2.4rem;
|
width: 2.4rem;
|
||||||
@ -97,10 +106,6 @@
|
|||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
margin: 0 1.6rem 0 0;
|
margin: 0 1.6rem 0 0;
|
||||||
}
|
|
||||||
|
|
||||||
.label,
|
|
||||||
.icon {
|
|
||||||
svg path {
|
svg path {
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import React, { memo, useEffect, useState } from 'react'
|
import React, { memo, useEffect, useState } from 'react'
|
||||||
|
import { useModalCommon } from 'src/components/hooks/useModalCommon'
|
||||||
import { isMobile } from 'src/utils/funtion.utils'
|
import { isMobile } from 'src/utils/funtion.utils'
|
||||||
|
import ModalAuthenticate from '../ModalAuthenticate/ModalAuthenticate'
|
||||||
import HeaderHighLight from './components/HeaderHighLight/HeaderHighLight'
|
import HeaderHighLight from './components/HeaderHighLight/HeaderHighLight'
|
||||||
import HeaderMenu from './components/HeaderMenu/HeaderMenu'
|
import HeaderMenu from './components/HeaderMenu/HeaderMenu'
|
||||||
import HeaderSubMenu from './components/HeaderSubMenu/HeaderSubMenu'
|
import HeaderSubMenu from './components/HeaderSubMenu/HeaderSubMenu'
|
||||||
import HeaderSubMenuMobile from './components/HeaderSubMenuMobile/HeaderSubMenuMobile'
|
import HeaderSubMenuMobile from './components/HeaderSubMenuMobile/HeaderSubMenuMobile'
|
||||||
import s from './Header.module.scss'
|
import s from './Header.module.scss'
|
||||||
|
|
||||||
interface Props {
|
|
||||||
className?: string
|
|
||||||
children?: any
|
|
||||||
}
|
|
||||||
|
|
||||||
const Header = memo(({ }: Props) => {
|
const Header = memo(() => {
|
||||||
const [isFullHeader, setIsFullHeader] = useState<boolean>(true)
|
const [isFullHeader, setIsFullHeader] = useState<boolean>(true)
|
||||||
|
const { visible: visibleModalAuthen, closeModal: closeModalAuthen, openModal: openModalAuthen } = useModalCommon({ initialValue: true })
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('scroll', handleScroll)
|
window.addEventListener('scroll', handleScroll)
|
||||||
@ -36,11 +35,12 @@ const Header = memo(({ }: Props) => {
|
|||||||
<header className={classNames({ [s.header]: true, [s.full]: isFullHeader })}>
|
<header className={classNames({ [s.header]: true, [s.full]: isFullHeader })}>
|
||||||
<HeaderHighLight isShow={isFullHeader} />
|
<HeaderHighLight isShow={isFullHeader} />
|
||||||
<div className={s.menu}>
|
<div className={s.menu}>
|
||||||
<HeaderMenu isFull={isFullHeader} />
|
<HeaderMenu isFull={isFullHeader} openModalAuthen={openModalAuthen} />
|
||||||
<HeaderSubMenu isShow={isFullHeader} />
|
<HeaderSubMenu isShow={isFullHeader} />
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<HeaderSubMenuMobile />
|
<HeaderSubMenuMobile />
|
||||||
|
<ModalAuthenticate visible={visibleModalAuthen} closeModal={closeModalAuthen} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -1,13 +1,24 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { memo } from 'react'
|
import { memo, useMemo } from 'react'
|
||||||
import InputSearch from 'src/components/common/InputSearch/InputSearch'
|
import InputSearch from 'src/components/common/InputSearch/InputSearch'
|
||||||
import MenuDropdown from 'src/components/common/MenuDropdown/MenuDropdown'
|
import MenuDropdown from 'src/components/common/MenuDropdown/MenuDropdown'
|
||||||
import { IconBuy, IconHeart, IconHistory, IconUser } from 'src/components/icons'
|
import { IconBuy, IconHeart, IconHistory, IconUser } from 'src/components/icons'
|
||||||
import { ACCOUNT_TAB, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
|
import { ACCOUNT_TAB, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
|
||||||
import s from './HeaderMenu.module.scss'
|
import s from './HeaderMenu.module.scss'
|
||||||
|
|
||||||
const OPTION_MENU = [
|
interface Props {
|
||||||
|
children?: any,
|
||||||
|
isFull: boolean,
|
||||||
|
openModalAuthen: () => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
const HeaderMenu = memo(({ isFull, openModalAuthen }: Props) => {
|
||||||
|
const optionMenu = useMemo(() => [
|
||||||
|
{
|
||||||
|
onClick: openModalAuthen,
|
||||||
|
name: 'Login (Demo)',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
link: ROUTE.ACCOUNT,
|
link: ROUTE.ACCOUNT,
|
||||||
name: 'Account',
|
name: 'Account',
|
||||||
@ -17,14 +28,8 @@ const OPTION_MENU = [
|
|||||||
name: 'Logout',
|
name: 'Logout',
|
||||||
},
|
},
|
||||||
|
|
||||||
]
|
], [openModalAuthen])
|
||||||
|
|
||||||
interface Props {
|
|
||||||
children?: any,
|
|
||||||
isFull: boolean,
|
|
||||||
}
|
|
||||||
|
|
||||||
const HeaderMenu = memo(({ isFull }: Props) => {
|
|
||||||
return (
|
return (
|
||||||
<section className={classNames({ [s.headerMenu]: true, [s.full]: isFull })}>
|
<section className={classNames({ [s.headerMenu]: true, [s.full]: isFull })}>
|
||||||
<div className={s.left}>
|
<div className={s.left}>
|
||||||
@ -54,7 +59,7 @@ const HeaderMenu = memo(({ isFull }: Props) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<MenuDropdown options={OPTION_MENU} isHasArrow={false}><IconUser /></MenuDropdown>
|
<MenuDropdown options={optionMenu} isHasArrow={false}><IconUser /></MenuDropdown>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button>
|
<button>
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
padding: 2rem 1rem;
|
padding: 2rem 1rem;
|
||||||
border-top: 1px solid var(--border-line);
|
border-top: 1px solid var(--border-line);
|
||||||
box-shadow: -5px 6px 10px rgba(0, 0, 0, 0.2);
|
box-shadow: -5px 6px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
z-index: 9999;
|
||||||
.menu {
|
.menu {
|
||||||
@apply grid grid-cols-4;
|
@apply grid grid-cols-4;
|
||||||
li {
|
li {
|
||||||
|
@ -10,7 +10,7 @@ interface Props {
|
|||||||
children?: React.ReactNode,
|
children?: React.ReactNode,
|
||||||
value?: string | number,
|
value?: string | number,
|
||||||
placeholder?: string,
|
placeholder?: string,
|
||||||
type?: 'text' | 'number' | 'email',
|
type?: 'text' | 'number' | 'email' | 'password',
|
||||||
styleType?: 'default' | 'custom',
|
styleType?: 'default' | 'custom',
|
||||||
backgroundTransparent?: boolean,
|
backgroundTransparent?: boolean,
|
||||||
icon?: React.ReactNode,
|
icon?: React.ReactNode,
|
||||||
|
@ -62,17 +62,25 @@
|
|||||||
.menuIner {
|
.menuIner {
|
||||||
@apply rounded list-none bg-white;
|
@apply rounded list-none bg-white;
|
||||||
border: 1px solid var(--text-active);
|
border: 1px solid var(--text-active);
|
||||||
margin-top: .4rem;
|
margin-top: 0.4rem;
|
||||||
li {
|
li {
|
||||||
@apply block w-full transition-all duration-200 cursor-pointer text-active;
|
@apply block w-full transition-all duration-200 cursor-pointer text-active;
|
||||||
|
button {
|
||||||
|
all: unset;
|
||||||
|
color: currentColor;
|
||||||
|
@apply text-left w-full;
|
||||||
|
}
|
||||||
|
button,
|
||||||
|
a {
|
||||||
padding: 0.8rem 1.6rem;
|
padding: 0.8rem 1.6rem;
|
||||||
&:hover {
|
|
||||||
@apply bg-primary-lightest;
|
|
||||||
color: var(--primary);
|
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
@apply block;
|
@apply block;
|
||||||
}
|
}
|
||||||
|
&:hover {
|
||||||
|
@apply bg-primary-lightest;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import s from './MenuDropdown.module.scss';
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children?: React.ReactNode,
|
children?: React.ReactNode,
|
||||||
options: { link: string, name: string }[],
|
options: { link?: string, name: string, onClick?: () => void }[],
|
||||||
isHasArrow?: boolean,
|
isHasArrow?: boolean,
|
||||||
align?: 'left'
|
align?: 'left'
|
||||||
}
|
}
|
||||||
@ -26,11 +26,16 @@ const MenuDropdown = ({ options, children, isHasArrow = true, align }: Props) =>
|
|||||||
<ul className={s.menuIner}>
|
<ul className={s.menuIner}>
|
||||||
{
|
{
|
||||||
options.map(item => <li key={item.name}>
|
options.map(item => <li key={item.name}>
|
||||||
<Link href={item.link}>
|
{item.onClick ?
|
||||||
|
<button onClick={item.onClick}>
|
||||||
|
{item.name}
|
||||||
|
</button>
|
||||||
|
:
|
||||||
|
<Link href={item.link || ''}>
|
||||||
<a >
|
<a >
|
||||||
{item.name}
|
{item.name}
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>}
|
||||||
</li>)
|
</li>)
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
.formAuthenticate {
|
||||||
|
@apply overflow-hidden;
|
||||||
|
.inner {
|
||||||
|
@apply grid grid-cols-2 overflow-hidden transition-all duration-200;
|
||||||
|
width: 200%;
|
||||||
|
&.register {
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
import classNames from 'classnames'
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import ModalCommon from '../ModalCommon/ModalCommon'
|
||||||
|
import FormLogin from './components/FormLogin/FormLogin'
|
||||||
|
import FormRegister from './components/FormRegister/FormRegister'
|
||||||
|
import s from './ModalAuthenticate.module.scss'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visible: boolean,
|
||||||
|
closeModal: () => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
const ModalAuthenticate = ({ visible, closeModal }: Props) => {
|
||||||
|
const [isLogin, setIsLogin] = useState<boolean>(true)
|
||||||
|
|
||||||
|
const onSwitch = () => {
|
||||||
|
setIsLogin(!isLogin)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalCommon visible={visible} onClose={closeModal} title={isLogin ? 'Sign In' : 'Create Account'}>
|
||||||
|
<section className={s.formAuthenticate}>
|
||||||
|
<div className={classNames({
|
||||||
|
[s.inner]: true,
|
||||||
|
[s.register]: !isLogin,
|
||||||
|
})}>
|
||||||
|
<FormLogin isHide={!isLogin} onSwitch={onSwitch} />
|
||||||
|
<FormRegister isHide={isLogin} onSwitch={onSwitch} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</ModalCommon>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ModalAuthenticate
|
@ -0,0 +1,35 @@
|
|||||||
|
.formAuthen {
|
||||||
|
@apply bg-white w-full;
|
||||||
|
.inner {
|
||||||
|
@screen md {
|
||||||
|
max-width: 52rem;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
.body {
|
||||||
|
> div {
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-bottom: 1.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.others {
|
||||||
|
@apply font-bold text-center;
|
||||||
|
margin-top: 4rem;
|
||||||
|
|
||||||
|
span {
|
||||||
|
@apply text-active;
|
||||||
|
margin-right: 0.8rem;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
all: unset;
|
||||||
|
@apply text-primary cursor-pointer;
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 2px solid #000;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
.bottom {
|
||||||
|
@apply flex justify-between items-center;
|
||||||
|
margin: 4rem auto;
|
||||||
|
.forgotPassword {
|
||||||
|
@apply font-bold;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
import Link from 'next/link'
|
||||||
|
import React, { useRef, useEffect } from 'react'
|
||||||
|
import { Inputcommon, ButtonCommon } from 'src/components/common'
|
||||||
|
import { ROUTE } from 'src/utils/constanst.utils'
|
||||||
|
import SocialAuthen from '../SocialAuthen/SocialAuthen'
|
||||||
|
import s from '../FormAuthen.module.scss'
|
||||||
|
import styles from './FormLogin.module.scss'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import { CustomInputCommon } from 'src/utils/type.utils'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
isHide: boolean,
|
||||||
|
onSwitch: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const FormLogin = ({ onSwitch, isHide }: Props) => {
|
||||||
|
const emailRef = useRef<CustomInputCommon>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isHide) {
|
||||||
|
emailRef.current?.focus()
|
||||||
|
}
|
||||||
|
}, [isHide])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className={classNames({
|
||||||
|
[s.formAuthen]: true,
|
||||||
|
// [styles.hide]: isHide
|
||||||
|
})}>
|
||||||
|
<div className={s.inner}>
|
||||||
|
<div className={s.body}>
|
||||||
|
<Inputcommon placeholder='Email Address' type='email' ref={emailRef} />
|
||||||
|
<Inputcommon placeholder='Password' type='password' />
|
||||||
|
</div>
|
||||||
|
<div className={styles.bottom}>
|
||||||
|
<Link href={ROUTE.FORGOT_PASSWORD}>
|
||||||
|
<a href="" className={styles.forgotPassword}>
|
||||||
|
Forgot Password?
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
<ButtonCommon size='large'>Sign in</ButtonCommon>
|
||||||
|
</div>
|
||||||
|
<SocialAuthen />
|
||||||
|
<div className={s.others}>
|
||||||
|
<span>Don't have an account?</span>
|
||||||
|
<button onClick={onSwitch}>Create Account</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormLogin
|
@ -0,0 +1,15 @@
|
|||||||
|
@import "../../../../../styles/utilities";
|
||||||
|
|
||||||
|
.formRegister {
|
||||||
|
.passwordNote {
|
||||||
|
@apply text-center caption text-label;
|
||||||
|
margin-top: 0.8rem;
|
||||||
|
}
|
||||||
|
.bottom {
|
||||||
|
@apply flex justify-between items-center w-full;
|
||||||
|
margin: 4rem auto;
|
||||||
|
button {
|
||||||
|
@apply w-full;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
import React, { useEffect, useRef } from 'react'
|
||||||
|
import { ButtonCommon, Inputcommon } from 'src/components/common'
|
||||||
|
import s from '../FormAuthen.module.scss'
|
||||||
|
import styles from './FormRegister.module.scss'
|
||||||
|
import SocialAuthen from '../SocialAuthen/SocialAuthen'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import { CustomInputCommon } from 'src/utils/type.utils'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
isHide: boolean,
|
||||||
|
onSwitch: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const FormRegister = ({ onSwitch, isHide }: Props) => {
|
||||||
|
const emailRef = useRef<CustomInputCommon>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isHide) {
|
||||||
|
emailRef.current?.focus()
|
||||||
|
}
|
||||||
|
}, [isHide])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className={classNames({
|
||||||
|
[s.formAuthen]: true,
|
||||||
|
[styles.formRegister]: true,
|
||||||
|
// [styles.hide]: isHide
|
||||||
|
})}>
|
||||||
|
<div className={s.inner}>
|
||||||
|
<div className={s.body}>
|
||||||
|
<Inputcommon placeholder='Email Address' type='email' ref={emailRef}/>
|
||||||
|
<Inputcommon placeholder='Password' type='password' />
|
||||||
|
<div className={styles.passwordNote}>
|
||||||
|
Must contain 8 characters with at least 1 uppercase and 1 lowercase letter and either 1 number or 1 special character.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.bottom}>
|
||||||
|
<ButtonCommon size='large'>Create Account</ButtonCommon>
|
||||||
|
</div>
|
||||||
|
<SocialAuthen />
|
||||||
|
<div className={s.others}>
|
||||||
|
<span>Already an account?</span>
|
||||||
|
<button onClick={onSwitch}>Sign In</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormRegister
|
@ -0,0 +1,36 @@
|
|||||||
|
@import "../../../../../styles/utilities";
|
||||||
|
|
||||||
|
.socialAuthen {
|
||||||
|
.captionText {
|
||||||
|
@apply relative text-center;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
span {
|
||||||
|
@apply relative bg-white uppercase text-label caption;
|
||||||
|
padding: 0 0.8rem;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
&::after {
|
||||||
|
@apply absolute bg-line;
|
||||||
|
content: "";
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btns {
|
||||||
|
@apply grid grid-cols-3;
|
||||||
|
grid-gap: 1.6rem;
|
||||||
|
.buttonWithIcon {
|
||||||
|
@apply flex items-center;
|
||||||
|
.label {
|
||||||
|
@apply hidden;
|
||||||
|
@screen md {
|
||||||
|
@apply inline-block;
|
||||||
|
margin-left: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import ButtonCommon from 'src/components/common/ButtonCommon/ButtonCommon'
|
||||||
|
import { IconApple, IconFacebookColor, IconGoogleColor } from 'src/components/icons'
|
||||||
|
import s from './SocialAuthen.module.scss'
|
||||||
|
|
||||||
|
const SocialAuthen = () => {
|
||||||
|
return (
|
||||||
|
<section className={s.socialAuthen}>
|
||||||
|
<div className={s.captionText}>
|
||||||
|
<span>
|
||||||
|
OR CONTINUE WITH
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className={s.btns}>
|
||||||
|
<ButtonCommon type='light' size='large'>
|
||||||
|
<span className={s.buttonWithIcon}>
|
||||||
|
<IconFacebookColor /><span className={s.label}>Facebook</span>
|
||||||
|
</span>
|
||||||
|
</ButtonCommon>
|
||||||
|
<ButtonCommon type='light' size='large'>
|
||||||
|
<span className={s.buttonWithIcon}>
|
||||||
|
<IconApple />
|
||||||
|
<span className={s.label}>Apple</span>
|
||||||
|
</span>
|
||||||
|
</ButtonCommon>
|
||||||
|
<ButtonCommon type='light' size='large'>
|
||||||
|
<span className={s.buttonWithIcon}>
|
||||||
|
<IconGoogleColor />
|
||||||
|
<span className={s.label}>Google</span>
|
||||||
|
</span>
|
||||||
|
</ButtonCommon>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SocialAuthen
|
@ -1,3 +1,5 @@
|
|||||||
|
@import '../../../styles/utilities';
|
||||||
|
|
||||||
.background{
|
.background{
|
||||||
@apply fixed inset-0 overflow-y-auto;
|
@apply fixed inset-0 overflow-y-auto;
|
||||||
background: rgba(20, 20, 20, 0.65);
|
background: rgba(20, 20, 20, 0.65);
|
||||||
@ -10,10 +12,12 @@
|
|||||||
padding: 3.2rem;
|
padding: 3.2rem;
|
||||||
box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.24);
|
box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.24);
|
||||||
border-radius: 1.2rem;
|
border-radius: 1.2rem;
|
||||||
|
.top {
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
}
|
||||||
.title{
|
.title{
|
||||||
|
@apply font-heading heading-3;
|
||||||
padding: 0 0.8rem 0 0.8rem;
|
padding: 0 0.8rem 0 0.8rem;
|
||||||
font-size: 3.2rem;
|
|
||||||
line-height: 4rem;
|
|
||||||
}
|
}
|
||||||
.close{
|
.close{
|
||||||
@apply absolute;
|
@apply absolute;
|
||||||
|
23
src/components/hooks/useModalCommon.tsx
Normal file
23
src/components/hooks/useModalCommon.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
initialValue?: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useModalCommon = ({ initialValue = false }: Props) => {
|
||||||
|
const [visible, setVisible] = useState<boolean>(initialValue)
|
||||||
|
|
||||||
|
const openModal = (e?: any) => {
|
||||||
|
e && e.stopPropagation()
|
||||||
|
setVisible(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeModal = (e?: any) => {
|
||||||
|
e && e.stopPropagation()
|
||||||
|
setVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
visible, openModal, closeModal
|
||||||
|
}
|
||||||
|
};
|
18
src/components/icons/IconApple.tsx
Normal file
18
src/components/icons/IconApple.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const IconApple = () => {
|
||||||
|
return (
|
||||||
|
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clipPath="url(#clip0)">
|
||||||
|
<path d="M22.292 18.7033C21.929 19.5418 21.4994 20.3136 21.0016 21.0232C20.3231 21.9906 19.7676 22.6602 19.3395 23.032C18.6758 23.6424 17.9647 23.955 17.2032 23.9728C16.6566 23.9728 15.9973 23.8172 15.23 23.5017C14.4601 23.1876 13.7525 23.032 13.1056 23.032C12.4271 23.032 11.6994 23.1876 10.9211 23.5017C10.1415 23.8172 9.51355 23.9817 9.03342 23.9979C8.30322 24.0291 7.57539 23.7076 6.8489 23.032C6.38521 22.6276 5.80523 21.9343 5.11043 20.9521C4.36498 19.9033 3.75211 18.687 3.27198 17.3004C2.75777 15.8026 2.5 14.3523 2.5 12.9482C2.5 11.3398 2.84754 9.95259 3.54367 8.79011C4.09076 7.85636 4.81859 7.11979 5.72953 6.57906C6.64046 6.03834 7.62473 5.76279 8.68469 5.74516C9.26467 5.74516 10.0252 5.92457 10.9704 6.27715C11.9129 6.63091 12.5181 6.81032 12.7834 6.81032C12.9817 6.81032 13.654 6.60054 14.7937 6.18233C15.8714 5.79449 16.781 5.63391 17.5262 5.69716C19.5454 5.86012 21.0624 6.6561 22.0712 8.09013C20.2654 9.18432 19.3721 10.7169 19.3898 12.6829C19.4061 14.2142 19.9617 15.4886 21.0535 16.5004C21.5483 16.97 22.1009 17.333 22.7156 17.5907C22.5823 17.9774 22.4416 18.3477 22.292 18.7033ZM17.661 0.480137C17.661 1.68041 17.2225 2.8011 16.3484 3.8384C15.2937 5.07155 14.0179 5.78412 12.6343 5.67168C12.6167 5.52769 12.6065 5.37614 12.6065 5.21688C12.6065 4.06462 13.1081 2.83147 13.9989 1.82321C14.4436 1.3127 15.0092 0.888228 15.6951 0.549615C16.3796 0.216055 17.0269 0.031589 17.6358 0C17.6536 0.160458 17.661 0.320926 17.661 0.480121V0.480137Z" fill="black" />
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0">
|
||||||
|
<rect width="24" height="24" fill="white" transform="translate(0.5)" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default IconApple
|
19
src/components/icons/IconFacebookColor.tsx
Normal file
19
src/components/icons/IconFacebookColor.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const IconFacebookColor = () => {
|
||||||
|
return (
|
||||||
|
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clipPath="url(#clip0)">
|
||||||
|
<path d="M24.5 12C24.5 5.37258 19.1274 0 12.5 0C5.87258 0 0.5 5.37258 0.5 12C0.5 17.9895 4.8882 22.954 10.625 23.8542V15.4688H7.57812V12H10.625V9.35625C10.625 6.34875 12.4166 4.6875 15.1576 4.6875C16.4701 4.6875 17.8438 4.92188 17.8438 4.92188V7.875H16.3306C14.84 7.875 14.375 8.80008 14.375 9.75V12H17.7031L17.1711 15.4688H14.375V23.8542C20.1118 22.954 24.5 17.9895 24.5 12Z" fill="#1877F2" />
|
||||||
|
<path d="M17.1711 15.4688L17.7031 12H14.375V9.75C14.375 8.80102 14.84 7.875 16.3306 7.875H17.8438V4.92188C17.8438 4.92188 16.4705 4.6875 15.1576 4.6875C12.4166 4.6875 10.625 6.34875 10.625 9.35625V12H7.57812V15.4688H10.625V23.8542C11.8674 24.0486 13.1326 24.0486 14.375 23.8542V15.4688H17.1711Z" fill="white" />
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0">
|
||||||
|
<rect width="24" height="24" fill="white" transform="translate(0.5)" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default IconFacebookColor
|
21
src/components/icons/IconGoogleColor.tsx
Normal file
21
src/components/icons/IconGoogleColor.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const IconGoogleColor = () => {
|
||||||
|
return (
|
||||||
|
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clipPath="url(#clip0)">
|
||||||
|
<path d="M24.2663 12.2767C24.2663 11.461 24.2001 10.6409 24.059 9.83838H12.7402V14.4594H19.222C18.953 15.9497 18.0888 17.2681 16.8233 18.1059V21.1042H20.6903C22.9611 19.0142 24.2663 15.9277 24.2663 12.2767Z" fill="#4285F4" />
|
||||||
|
<path d="M12.7391 24.0008C15.9756 24.0008 18.705 22.9382 20.6936 21.1039L16.8266 18.1055C15.7507 18.8375 14.3618 19.252 12.7435 19.252C9.61291 19.252 6.95849 17.1399 6.00607 14.3003H2.01562V17.3912C4.05274 21.4434 8.20192 24.0008 12.7391 24.0008Z" fill="#34A853" />
|
||||||
|
<path d="M6.00277 14.3002C5.50011 12.8099 5.50011 11.196 6.00277 9.70569V6.61475H2.01674C0.314734 10.0055 0.314734 14.0004 2.01674 17.3912L6.00277 14.3002Z" fill="#FBBC04" />
|
||||||
|
<path d="M12.7391 4.74966C14.4499 4.7232 16.1034 5.36697 17.3425 6.54867L20.7685 3.12262C18.5991 1.0855 15.7198 -0.034466 12.7391 0.000808666C8.20192 0.000808666 4.05274 2.55822 2.01562 6.61481L6.00166 9.70575C6.94967 6.86173 9.6085 4.74966 12.7391 4.74966Z" fill="#EA4335" />
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0">
|
||||||
|
<rect width="24" height="24" fill="white" transform="translate(0.5)" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default IconGoogleColor
|
@ -9,6 +9,9 @@ export { default as IconHome } from './IconHome'
|
|||||||
export { default as IconShopping } from './IconShopping'
|
export { default as IconShopping } from './IconShopping'
|
||||||
export { default as IconHeart } from './IconHeart'
|
export { default as IconHeart } from './IconHeart'
|
||||||
export { default as IconVector } from './IconVector'
|
export { default as IconVector } from './IconVector'
|
||||||
|
export { default as IconFacebookColor } from './IconFacebookColor'
|
||||||
|
export { default as IconGoogleColor } from './IconGoogleColor'
|
||||||
|
export { default as IconApple } from './IconApple'
|
||||||
export { default as ArrowLeft } from './ArrowLeft'
|
export { default as ArrowLeft } from './ArrowLeft'
|
||||||
export { default as ArrowRight } from './ArrowRight'
|
export { default as ArrowRight } from './ArrowRight'
|
||||||
export { default as Close } from './Close'
|
export { default as Close } from './Close'
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
@import "../../../../styles/utilities";
|
@import "../../../../styles/utilities";
|
||||||
|
|
||||||
.homeFeature {
|
.homeFeature {
|
||||||
@apply spacing-horizontal-left grid grid-cols-1;
|
@apply spacing-horizontal;
|
||||||
background-color: #FFFFFF;
|
background-color: #ffffff;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
padding-top: 3.2rem;
|
margin: 3.2rem auto;
|
||||||
padding-bottom: 3.2rem;
|
|
||||||
|
|
||||||
@screen md {
|
@screen md {
|
||||||
@apply spacing-horizontal grid-cols-3;
|
@apply grid grid-cols-3;
|
||||||
margin-bottom: 6.4rem;
|
grid-gap: 2.4rem;
|
||||||
|
margin: 6.4rem auto;
|
||||||
|
}
|
||||||
|
@screen md {
|
||||||
|
grid-gap: 4rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,18 +1,16 @@
|
|||||||
@import '../../../../../../styles/utilities';
|
@import "../../../../../../styles/utilities";
|
||||||
|
|
||||||
.homeFeatureItem {
|
.homeFeatureItem {
|
||||||
@apply flex;
|
@apply flex items-center;
|
||||||
align-items: center;
|
|
||||||
vertical-align: middle;
|
|
||||||
height: fit-content;
|
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
@screen md {
|
@screen md {
|
||||||
@apply block;
|
@apply flex flex-col items-center justify-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
@screen lg {
|
@screen lg {
|
||||||
@apply flex;
|
@apply flex flex-row;
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemImg {
|
.itemImg {
|
||||||
@ -21,39 +19,38 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
&.firstImg {
|
&.firstImg {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
content:url("../../assets/10h30-11h-desktop.png");
|
content: url("../../assets/10h30-11h-desktop.png");
|
||||||
}
|
}
|
||||||
&.secondImg {
|
&.secondImg {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
content:url("../../assets/8h-desktop.png");
|
content: url("../../assets/8h-desktop.png");
|
||||||
}
|
}
|
||||||
&.thirdImg {
|
&.thirdImg {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
content:url("../../assets/green-desktop.png");
|
content: url("../../assets/green-desktop.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
@screen md {
|
@screen md {
|
||||||
@apply flex justify-center items-center;
|
@apply flex flex-col justify-center items-center;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
margin-top: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@screen lg {
|
@screen lg {
|
||||||
@apply flex float-left clear-both;
|
@apply flex float-left clear-both;
|
||||||
margin-right: 2.4rem;
|
margin-right: 2.4rem;
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemText {
|
.itemText {
|
||||||
@apply inline-block;
|
|
||||||
max-width: 28rem;
|
max-width: 28rem;
|
||||||
min-width: 12rem;
|
min-width: 12rem;
|
||||||
color: #000;
|
|
||||||
margin-right: 2.4rem;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
@screen md {
|
@screen md {
|
||||||
@apply flex;
|
@apply text-center;
|
||||||
|
}
|
||||||
|
@screen lg {
|
||||||
|
@apply text-left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -34,7 +34,7 @@
|
|||||||
--border-line: #ebebeb;
|
--border-line: #ebebeb;
|
||||||
--background: #fff;
|
--background: #fff;
|
||||||
--gray: #f8f8f8;
|
--gray: #f8f8f8;
|
||||||
--white: #fbfbfb;
|
--white: #fff;
|
||||||
--background-arrow:rgba(20, 20, 20, 0.05);
|
--background-arrow:rgba(20, 20, 20, 0.05);
|
||||||
--font-size: 1.6rem;
|
--font-size: 1.6rem;
|
||||||
--line-height: 2.4rem;
|
--line-height: 2.4rem;
|
||||||
|
@ -18,6 +18,7 @@ export const ROUTE = {
|
|||||||
TERM_CONDITION: '/term-condition',
|
TERM_CONDITION: '/term-condition',
|
||||||
PRIVACY_POLICY: '/privacy-policy',
|
PRIVACY_POLICY: '/privacy-policy',
|
||||||
BLOGS: '/blogs',
|
BLOGS: '/blogs',
|
||||||
|
FORGOT_PASSWORD: '/forgot-password'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ACCOUNT_TAB = {
|
export const ACCOUNT_TAB = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user