Merge branch 'common' of github.com:KieIO/grocery-vercel-commerce into fixbug-13/9/2021-datnguyen

This commit is contained in:
unknown
2021-09-17 10:27:04 +07:00
36 changed files with 963 additions and 295 deletions

View File

@@ -103,6 +103,20 @@
}
}
}
&.small {
.inner {
padding: .5rem 1rem;
&.onlyIcon {
padding: 1rem;
}
@screen md {
padding: .8rem 1.6rem;
&.onlyIcon {
padding: .8rem;
}
}
}
}
&.large {
.inner {

View File

@@ -5,7 +5,7 @@ import s from './ButtonCommon.module.scss'
interface Props {
children?: React.ReactNode,
type?: 'primary' | 'light' | 'ghost' | 'lightBorderNone',
size?: 'default' | 'large',
size?: 'default' | 'large' | 'small',
icon?: React.ReactNode,
isIconSuffix?: boolean,
loading?: boolean,

View File

@@ -3,14 +3,14 @@ import { IconBuy } from 'src/components/icons'
import ButtonCommon from '../ButtonCommon/ButtonCommon'
interface Props {
type?: 'primary' | 'light' | 'ghost',
size?: 'default' | 'large',
type?: 'primary' | 'light' | 'ghost' | 'lightBorderNone',
size?: 'default' | 'large' | 'small',
loading?: boolean,
disabled?: boolean,
onClick?: () => void,
}
const ButtonIconBuy = memo(({ type = 'light', size = 'default', loading = false, disabled, onClick }: Props) => {
const ButtonIconBuy = memo(({ type = 'light', size = 'small', loading = false, disabled, onClick }: Props) => {
return (
<ButtonCommon
type={type}

View File

@@ -3,7 +3,7 @@
// min-width: 30.2rem;
height: 14.4rem;
padding: 2.4rem;
@apply bg-primary-light inline-flex justify-start items-center custom-border-radius ;
@apply bg-primary-light inline-flex justify-start items-center shape-common ;
@screen md {
// min-width: 598px;
height: 28.8rem;
@@ -15,18 +15,18 @@
padding: 2.4rem 4rem 2.4rem 2.4rem;
}
.left{
max-width: 10rem;
max-height: 10rem;
width: 10rem;
height: 10rem;
@screen md {
max-width: 24rem;
max-height: 24rem;
width: 24rem;
height: 24rem;
}
}
.right{
margin-left: 1.2rem;
// min-width: 27rem;
max-width: 16.6rem;
ma-height: 10rem;
max-height: 10rem;
@apply flex justify-between flex-col;
@screen md {
margin-left: 2.4rem;
@@ -60,70 +60,34 @@
}
}
.priceWrapper{
@apply flex justify-start;
@apply flex justify-start sm-headline;
.price{
@apply font-bold;
font-size: 1.2rem;
line-height: 1.6rem;
letter-spacing: -0.01em;
@apply font-bold sm-headline;
color: var(--text-active);
@screen md {
font-size: 2rem;
line-height: 2.8rem;
}
}
.originPrice{
@apply sm-headline;
font-weight: normal;
margin-left: 0.8rem;
font-size: 1.2rem;
line-height: 1.6rem;
color: var(--text-label);
text-decoration-line: line-through;
@screen md {
font-size: 2rem;
line-height: 2.8rem;
}
}
}
}
.buttonWarpper{
@apply flex;
.icon{
max-width: 3.2rem;
max-height: 3.2rem;
@screen sm-only{
button{
padding: 1rem;
svg{
width: 1.1rem;
height: 1.1rem;
}
button {
>div {
@apply bg-primary-light;
}
}
@screen md {
max-width: 5.6rem;
max-height: 5.6rem;
}
}
.button{
margin-left: 0.8rem;
min-width: 12.5rem;
max-height: 3.2rem;
button{
width: 100%;
height: 100%;
}
@screen sm-only {
button{
padding:0.9rem;
}
}
@screen md {
min-width: 20.6rem;
button{
height: initial;
}
max-height: 5.6rem;
flex: 1;
button {
@apply w-full;
}
}
}

View File

@@ -4,7 +4,8 @@ import s from './FeaturedProductCard.module.scss'
import { LANGUAGE } from '../../../utils/language.utils'
import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy'
import ButtonCommon from '../ButtonCommon/ButtonCommon'
export interface FeaturedProductCardProps extends FeaturedProductProps {
import { ImgWithLink } from '..'
interface FeaturedProductCardProps extends FeaturedProductProps {
buttonText?: string
}
@@ -19,7 +20,7 @@ const FeaturedProductCard = ({
return (
<div className={s.featuredProductCardWarpper}>
<div className={s.left}>
<img src={imageSrc} alt="image" />
<ImgWithLink src={imageSrc} alt={title}/>
</div>
<div className={s.right}>
<div className={s.rightTop}>
@@ -32,7 +33,7 @@ const FeaturedProductCard = ({
</div>
<div className={s.buttonWarpper}>
<div className={s.icon}>
<ButtonIconBuy />
<ButtonIconBuy size='default'/>
</div>
<div className={s.button}>
<ButtonCommon>{buttonText}</ButtonCommon>

View File

@@ -2,15 +2,22 @@
display: flex;
flex-direction: column;
min-height: 100vh;
> main {
.wrapperWithBg {
@apply bg-background-gray;
width: 100%;
margin-top: -3.2rem;
}
> main,
.wrapperWithBg > main {
flex: 1;
width: 100%;
max-width: min( 100%, 1536px);
max-width: min(100%, 1536px);
margin: auto;
}
}
.filter{
.filter {
@screen xl {
display: none;
}
}
}

View File

@@ -2,7 +2,7 @@ import { CommerceProvider } from '@framework'
import { useRouter } from 'next/router'
import { FC } from 'react'
import { useModalCommon } from 'src/components/hooks'
import { BRAND, CATEGORY, FEATURED, FILTER_PAGE } from 'src/utils/constanst.utils'
import { BRAND, CATEGORY, FEATURED, FILTER_PAGE, ROUTE } from 'src/utils/constanst.utils'
import { ScrollToTop } from '..'
import Footer from '../Footer/Footer'
import Header from '../Header/Header'
@@ -19,6 +19,8 @@ const Layout: FC<Props> = ({ children }) => {
const { locale = 'en-US', pathname } = useRouter()
const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false })
const router = useRouter()
const toggleFilter = () => {
if (visibleFilter) {
closeFilter()
@@ -26,11 +28,18 @@ const Layout: FC<Props> = ({ children }) => {
openFilter()
}
}
return (
<CommerceProvider locale={locale}>
<div className={s.mainLayout}>
<Header toggleFilter={toggleFilter} visibleFilter={visibleFilter} />
<main >{children}</main>
{
router.pathname === ROUTE.ACCOUNT ?
<section className={s.wrapperWithBg}>
<main>{children}</main>
</section> :
<main>{children}</main>
}
<div className={s.filter}><MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleFilter} onClose={closeFilter} /> </div>
<ScrollToTop visibilityHeight={1500} />
{

View File

@@ -28,6 +28,7 @@
margin-right: 0.8rem;
background-color: var(--gray);
border-radius: 0.8rem;
cursor: pointer;
&.active {
color:white;
background-color: var(--primary);

View File

@@ -20,7 +20,7 @@
width: 100%;
height: 100vh;
position: fixed;
z-index: 9999;
z-index: 9999999;
}
}
.menuNavigationProductModal{
@@ -30,7 +30,7 @@
top: 0;
width: 100%;
height: 100vh;
z-index: 10000;
z-index: 99999999;
transform: translateY(100%);
&.animation{

View File

@@ -19,6 +19,7 @@
padding: 0 1.6rem;
margin-right: 0.8rem;
border-radius: 0.8rem;
cursor: pointer;
&.active {
@apply font-bold relative;
color:var(--text-active);

View File

@@ -63,15 +63,15 @@ const ProductCard = ({
{
isSingleButton ?
<div className={s.cardButton}>
<ButtonCommon type="light" icon={<IconBuy />}>Add to cart</ButtonCommon>
<ButtonCommon type="light" icon={<IconBuy />} size='small'>Add to cart</ButtonCommon>
</div>
:
<>
<div className={s.cardIcon}>
<ButtonIconBuy />
<ButtonIconBuy/>
</div>
<div className={s.cardButton}>
<ButtonCommon type="light">{buttonText}</ButtonCommon>
<ButtonCommon type="light" size='small'>{buttonText}</ButtonCommon>
</div>
</>
}

View File

@@ -1,10 +1,23 @@
@import '../../../styles/utilities';
.quanittyInputWarper{
border-color: theme("textColor.active");
@apply border border-solid inline-flex justify-between items-center custom-border-radius;
.quanittyInputWarper {
@apply shape-common-border;
&::before{
height: 100%;
top: 1px;
background-color: var(--text-active);
}
.inner {
@apply inline-flex justify-between items-center;
margin: 0;
}
.plusIcon, .minusIcon{
@apply flex justify-center items-center;
min-height: 2rem;
&:hover{
cursor: pointer;
svg path {
fill: var(--primary);
}
}
}
&.default{

View File

@@ -4,8 +4,8 @@ import classNames from 'classnames'
import { IconMinus, IconPlus } from '../../icons'
interface QuanittyInputProps
extends Omit<
React.InputHTMLAttributes<HTMLInputElement>,
'onChange' | 'min' | 'max' | 'step' | "type" | "size"
React.InputHTMLAttributes<HTMLInputElement>,
'onChange' | 'min' | 'max' | 'step' | "type" | "size"
> {
size?: 'default' | 'small'
onChange?: (value: number) => void
@@ -63,18 +63,20 @@ const QuanittyInput = ({
return (
<div className={classNames(s.quanittyInputWarper, { [s[size]]: size })}>
<div className={s.minusIcon} onClick={onMinusClick}>
<IconMinus />
</div>
<input
{...props}
type="number"
value={value}
onChange={onValueChange}
className={s.quanittyInput}
/>
<div className={s.plusIcon} onClick={onPlusClick}>
<IconPlus />
<div className={s.inner}>
<div className={s.minusIcon} onClick={onMinusClick}>
<IconMinus />
</div>
<input
{...props}
type="number"
value={value}
onChange={onValueChange}
className={s.quanittyInput}
/>
<div className={s.plusIcon} onClick={onPlusClick}>
<IconPlus />
</div>
</div>
</div>
)

View File

@@ -4,7 +4,6 @@
@apply inline-flex flex-col justify-start;
.image{
width: 100%;
max-height: 22rem;
border-radius: 2.4rem;
img {
border-radius: 2.4rem;
@@ -12,14 +11,20 @@
&:hover{
cursor: pointer;
}
@screen md{
max-height: 22rem;
}
}
.title{
padding: 1.6rem 0.8rem 0.4rem 0.8rem;
@apply font-bold;
@apply font-bold overflow-hidden overflow-ellipsis ;
font-size: 2rem;
line-height: 2.8rem;
letter-spacing: -0.01em;
color: var(--text-active);
display: -webkit-box;
-webkit-line-clamp: 2; /* number of lines to show */
-webkit-box-orient: vertical;
&:hover{
cursor: pointer;
}
@@ -30,5 +35,9 @@
display: -webkit-box;
-webkit-line-clamp: 3; /* number of lines to show */
-webkit-box-orient: vertical;
margin-bottom: 3rem;
@screen md{
margin-bottom: 0;
}
}
}

View File

@@ -1,4 +1,4 @@
const IconMinus = ({ ...props }) => {
const IconMinus = () => {
return (
<svg
width="12"

View File

@@ -1,4 +1,4 @@
const IconPlus = ({ ...props }) => {
const IconPlus = () => {
return (
<svg
width="12"

View File

@@ -1,23 +1,26 @@
@import '../../../../styles/utilities';
.accountPage {
@apply spacing-horizontal;
background-color: #F5F4F2;
margin-top: -3.2rem;
padding-top: 3.2rem;
padding-bottom: 3.2rem;
@apply bg-background-gray;
padding: 3.2rem 2rem;
min-height: 70rem;
@screen md {
padding-left: 3.2rem;
padding-right: 3.2rem;
padding-left: 2.8rem;
padding-right: 2.8rem;
padding: 5.4rem 2rem;
}
@screen lg {
padding-left: 6.4rem;
padding-right: 6.4rem;
}
@screen xl {
@apply spacing-horizontal
padding-left: 11.2rem;
padding-right: 11.2rem;
}
.header {
margin-bottom: 1.2rem;

View File

@@ -16,7 +16,6 @@
margin: auto;
margin-bottom: 4rem;
@screen md {
margin-left: 0
}
@@ -56,22 +55,16 @@
}
.editInfoBtn {
@apply text-center font-bold custom-border-radius;
margin: auto;
@apply flex items-center justify-center;
margin-top: 2.4rem;
margin-bottom: 2.4rem;
padding: .8rem 1.6rem;
color: #141414;
border: 1px solid #141414;
max-width: 8.8rem;
&:hover {
@apply cursor-pointer;
background-color: #FBFBFB;
button div {
background-color: #F5F4F2 !important;
}
@screen md {
margin-left: 0;
@apply block;
}
}
}

View File

@@ -4,6 +4,8 @@ import s from './AccountInfomation.module.scss'
import Image from "next/image"
import avatar from '../../assets/avatar.png';
import { ButtonCommon } from 'src/components/common'
interface AccountProps {
name: string, email: string, address: string, state: string, city: string, postalCode: string, phoneNumber: string
}
@@ -44,7 +46,9 @@ const AccountInfomation = ({ account, onClick } : AccountInfomationProps) => {
{account.phoneNumber}
</div>
<div onClick={showEditForm} className={s.editInfoBtn}>Edit</div>
<div className={s.editInfoBtn}>
<ButtonCommon onClick={showEditForm} type="light" size="small">Edit</ButtonCommon>
</div>
</section>
)
}

View File

@@ -25,7 +25,7 @@ const OrderInformation = ({ waiting, delivering, delivered} : OrderInformationPr
{
waiting.map((order, i) => {
return (
<DeliveryItem key={order.id} id={order.id} status="Waiting" products={order.products} totalPrice={order.totalPrice} />
<DeliveryItem key={order.id} id={order.id} status="waiting" products={order.products} totalPrice={order.totalPrice} />
)
})
}
@@ -36,7 +36,7 @@ const OrderInformation = ({ waiting, delivering, delivered} : OrderInformationPr
{
delivering.map((order, i) => {
return (
<DeliveryItem key={order.id} id={order.id} status="Delivering" products={order.products} totalPrice={order.totalPrice} />
<DeliveryItem key={order.id} id={order.id} status="delivering" products={order.products} totalPrice={order.totalPrice} />
)
})
}
@@ -47,7 +47,7 @@ const OrderInformation = ({ waiting, delivering, delivered} : OrderInformationPr
{
delivered.map((order, i) => {
return (
<DeliveryItem key={order.id} id={order.id} status="Delivered" products={order.products} totalPrice={order.totalPrice} />
<DeliveryItem key={order.id} id={order.id} status="delivered" products={order.products} totalPrice={order.totalPrice} />
)
})
}

View File

@@ -9,7 +9,7 @@ import ReOrder from './components/ReOrder/ReOrder'
interface DeliveryItemProps {
id: string;
status: "Waiting" | "Delivering" | "Delivered";
status: "waiting" | "delivering" | "delivered";
products: string[];
totalPrice: number;
}
@@ -21,7 +21,7 @@ const DeliveryItem = ({ id, status, products, totalPrice } : DeliveryItemProps)
<div className={s.separator}></div>
<Products products={products} />
<TotalPrice totalPrice={totalPrice} />
<ReOrder show={status === "Delivered" ? true : false}/>
<ReOrder visible={status === "delivered" ? true : false}/>
</section>
)
}

View File

@@ -5,10 +5,10 @@ import s from './IdAndStatus.module.scss'
interface IdAndStatusProps {
id?: string;
status: "Waiting" | "Delivering" | "Delivered";
status: "waiting" | "delivering" | "delivered";
}
const IdAndStatus = ({ id, status="Waiting" } : IdAndStatusProps) => {
const IdAndStatus = ({ id, status="waiting" } : IdAndStatusProps) => {
return (
<div className={s.idAndStatus}>
<div className={s.id}>

View File

@@ -1,9 +1,21 @@
@import '../../../../../../styles/utilities';
.reOrder {
@apply hidden;
@apply hidden shape-common text-white font-bold;
background-color: var(--primary);
margin-right: 1.2rem;
&.show {
padding: .4rem .6rem;
@screen lg {
padding: .8rem 1.2rem;
margin-right: 2.4rem;
}
&.visible {
@apply block;
}
&:hover {
@apply cursor-pointer;
}
}

View File

@@ -1,18 +1,22 @@
import classNames from "classnames"
import React from "react"
import { ButtonCommon } from "src/components/common"
import Link from 'next/link'
import s from './ReOrder.module.scss'
interface ReOrderProps {
show: boolean;
visible: boolean;
href?: string;
}
const ReOrder = ({ show=false } : ReOrderProps) => {
const ReOrder = ({ visible=false, href="#" } : ReOrderProps) => {
return (
<div className={classNames(s.reOrder, {
[s.show]: show
[s.visible]: visible
})}>
<ButtonCommon>Re-Order</ButtonCommon>
<Link href={href}>
<a>Re-Order</a>
</Link>
</div>
)
}

View File

@@ -1,11 +1,12 @@
@import "../../../../styles/_utilities";
.beadcrumb{
padding-left: 3.2rem;
padding-bottom: 3.2rem;
}
.image{
@apply spacing-horizontal;
div{
width: 100%;
padding: 0 2rem;
margin-bottom: 2rem;
border-radius: 2.4rem;
min-height: 45.2rem;

View File

@@ -16,20 +16,5 @@
padding-top: 3.2rem;
padding-bottom: 3.2rem;
@apply flex justify-start spacing-horizontal;
.tab{
font-family: var(--font-heading);
padding: 1.6rem 1.6rem 0.8rem 1.6rem;
font-size: 2.4rem;
line-height: 2.8rem;
@screen md{
font-size: 3.2rem;
line-height: 4rem;
}
outline: none;
&.active{
@apply text-background custom-border-radius bg-primary;
}
}
}
}

View File

@@ -1,4 +1,4 @@
import React from 'react'
import React, { useState } from 'react'
import { HeadingCommon, ViewAllItem } from 'src/components/common'
import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard'
import RecipeCarousel from 'src/components/common/RecipeCarousel/RecipeCarousel'
@@ -7,6 +7,7 @@ import classNames from 'classnames';
import image13 from "../../../../../public/assets/images/image13.png"
import image14 from "../../../../../public/assets/images/image14.png"
import image12 from "../../../../../public/assets/images/image12.png"
import HomeRecipeTab from './HomeRecipeTab/HomeRecipeTab'
interface HomeRecipeProps {
data?: RecipeCardProps[]
@@ -44,7 +45,28 @@ const recipe:RecipeCardProps[] = [{
}]
const TABS = [
{
name: 'Noodle',
value: 'Noodle',
},
{
name: 'Curry',
value: 'Curry',
},
{
name: 'Special Recipes',
value: 'Special Recipes',
}
]
const HomeRecipe = ({ data =recipe, itemKey="home-recipe", title="Special Recipes" }: HomeRecipeProps) => {
const [activeTab, setActiveTab] = useState<string>(TABS[0].value)
const onTabChanged = (value: string) => {
setActiveTab(value)
}
return (
<div className={s.homeRecipeWarpper}>
<div className={s.top}>
@@ -56,9 +78,14 @@ const HomeRecipe = ({ data =recipe, itemKey="home-recipe", title="Special Recipe
</div>
</div>
<div className={s.mid}>
<button className={classNames(s.tab,s.active)}>Noodle</button>
<button className={s.tab}>Curry</button>
<button className={s.tab}>Special Recipes</button>
{
TABS.map(item => <HomeRecipeTab
key={item.value}
activeValue={activeTab}
name={item.name}
value={item.value}
onClick={onTabChanged} />)
}
</div>
<div className={s.bot}>
<RecipeCarousel data={data} itemKey={itemKey} />

View File

@@ -0,0 +1,17 @@
@import "../../../../../styles/utilities";
.tab {
all: unset;
@apply heading-3 font-heading cursor-pointer outline-none;
padding: 1.6rem;
&:focus {
outline: none;
filter: brightness(1.05);
}
&:focus-visible {
outline: 2px solid var(--text-active);
}
&.active {
@apply text-background shape-common bg-primary;
}
}

View File

@@ -0,0 +1,26 @@
import classNames from 'classnames';
import React from 'react';
import s from './HomeRecipeTab.module.scss'
interface Props {
activeValue: string
name: string
value: string
onClick: (value: string) => void
}
const HomeRecipeTab = ({ activeValue, name, value, onClick }: Props) => {
const handleClick = () => {
onClick(value)
}
return (
<button onClick={handleClick} className={classNames(s.tab, {
[s.active]: activeValue === value
})}>{name}</button>
);
};
export default HomeRecipeTab;

View File

@@ -1,61 +0,0 @@
@import "../../../../../styles/_utilities";
.recipesItem {
@apply flex justify-between;
margin: 1.5rem 0;
@screen md{
@apply block;
}
.recipesItemImage {
@apply transition-all duration-200;
width: 31%;
a{
div{
@apply object-cover;
min-height: 19.6rem;
border-radius: 1.5rem;
}
}
@screen md {
@apply object-cover cursor-pointer;
width: 100%;
margin: 0 auto;
img{
height:100%;
border-radius: 2.4rem;
}
}
}
.recipesItemText {
width: 65%;
.recipesItemName{
@apply topline font-bold cursor-pointer;
display: -webkit-box;
-webkit-line-clamp: 1;
overflow: hidden;
-webkit-box-orient: vertical;
font-feature-settings: "salt" on;
color:var(--text-active);
margin-top: 1.6rem;
&:hover {
color: var(--primary);
}
}
@screen md {
width: 100%;
}
}
.recipesItemDescription{
color:var(--text-label);
display: -webkit-box;
-webkit-line-clamp: 2;
overflow: hidden;
-webkit-box-orient: vertical;
}
}

View File

@@ -1,32 +0,0 @@
import Link from 'next/link';
import React from 'react';
import { ImgWithLink } from 'src/components/common';
import s from './RecipesItem.module.scss';
interface RecipesItem {
image:string,
name: string,
description:string,
link: string
}
const RecipesItem = ({ image, name,description, link }: RecipesItem) => {
return (
<div className={s.recipesItem}>
<div className={s.recipesItemImage}>
<Link href={link}>
<a>
<ImgWithLink src={image} alt="author" />
</a>
</Link>
</div>
<Link href={link}>
<a className={s.recipesItemText}>
<div className={s.recipesItemName}>{name}</div>
<div className={s.recipesItemDescription}>{description}</div>
</a>
</Link>
</div >
)
}
export default RecipesItem

View File

@@ -6,6 +6,10 @@
padding:0 3.2rem;
padding-bottom:5.6rem;
}
div{
max-width: 100%;
max-height: 100%;
}
.breadcrumb{
padding:1rem 0;
}
@@ -39,11 +43,16 @@
@screen md {
@apply flex justify-between flex-wrap;
margin: 1rem 0;
}
.item {
img{
width: 100%;
}
@screen md {
width: calc(97% / 2);
margin-top:1rem;
}
@screen lg{
width: calc(97% / 3);
@@ -63,7 +72,9 @@
.boxSelect{
@apply flex justify-between w-full;
padding: 2.5rem 0;
div{
max-width: 17.6rem;
}
@screen xl {
@apply block;
width: auto;

View File

@@ -3,7 +3,7 @@
:root {
--primary: #5b9a74;
--primary-light: #e0f6e8;
--primary-light: #e3f2e9;
--primary-lightest: #effaf4;
--info-dark: #00317a;

View File

@@ -25,7 +25,7 @@
}
.heading-3 {
font-size: 24px;
line-height: 32px;
line-height: 28px;
letter-spacing: -0.01em;
font-weight: bold;
text-transform: uppercase;
@@ -114,8 +114,6 @@
.shape-common {
position: relative;
$border: 2px;
margin: $border;
clip-path: url(#svg-custom-shape);
}