Merge pull request #14 from KieIO/m2-quangnhan

M2: home categories
This commit is contained in:
lytrankieio123 2021-08-27 11:18:36 +07:00 committed by GitHub
commit ad575d097b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 440 additions and 11904 deletions

@ -0,0 +1 @@
Subproject commit 3c7aa8e862bfd8d44719be44c6c0a31ab01524a3

11905
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,12 @@
import { Layout } from 'src/components/common';
import { HomeBanner, HomeCTA, HomeSubscribe, HomeVideo } from 'src/components/modules/home';
import { HomeBanner, HomeCategories, HomeCTA, HomeSubscribe, HomeVideo } from 'src/components/modules/home';
export default function Home() {
return (
<>
<HomeBanner />
<HomeCategories/>
<HomeVideo />
<HomeCTA />
<HomeSubscribe />

View File

@ -0,0 +1 @@
<svg width="10" height="8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.194 1.006a.625.625 0 00-.888 0L3.65 5.67 1.694 3.706a.639.639 0 00-.888.919l2.4 2.4a.625.625 0 00.888 0l5.1-5.1a.625.625 0 000-.919z" fill="#FBFBFB"/></svg>

After

Width:  |  Height:  |  Size: 242 B

View File

@ -0,0 +1,17 @@
.authorWarper{
@apply flex flex-row items-center;
.authorImage{
width:3.2rem;
height:3.2rem;
border-radius:3.2rem;
}
.authorName{
margin-left:1rem;
color:var(--text-label);
font-family: var(--font-sans);
font-size: 1.2rem;
line-height: 2rem;
font-feature-settings: 'salt' on;
}
}

View File

@ -0,0 +1,21 @@
import React from 'react';
import s from './Author.module.scss';
import classNames from 'classnames';
import Image from "next/image";
interface Props {
image:any,
name: string
}
const Author = ({image,name}:Props) =>{
return (
<div className={classNames(s.authorWarper)}>
<Image className={classNames(s.authorImage)} src={image} alt=""/>
<div className={classNames(s.authorName)}>{name}</div>
</div>
)
}
export default Author;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -88,8 +88,6 @@
}
}
&.preserve {
flex-direction: row-reverse;
.icon {

View File

@ -0,0 +1,71 @@
@import '../../../styles/utilities';
.checkboxCommonWarper{
@apply flex flex-col;
.checkboxItem{
display: block;
position: relative;
cursor: pointer;
border-radius: 0.4rem;
width:50%;
&:hover .checkboxInput ~ .checkMark {
background-color: #ccc;
}
.checkboxInput{
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
&:checked ~ .checkMark:after {
display: block;
}
}
.checkMark {
border-radius: 0.4rem;
position: absolute;
top: 0;
left: 0;
height: 2rem;
width: 2rem;
background-color:var(--positive);
&:after {
left: 25.74%;
bottom: 34.6%;
width: 0.878rem;
height: 0.7rem;
color:white;
content: "";
background-image:url('/assets/svg/checkmark.svg');
background-size:cover;
background-repeat: no-repeat;
position: absolute;
display: none;
}
}
&~ .checkMark{
background-color: #ccc;
}
&:checked ~ .checkMark {
background-color: #2196F3;
}
&:checked ~ .checkMark:after {
display: block;
}
&:hover .checkboxInput ~ .checkMark {
background-color: #ccc;
}
}
.checkboxText{
margin-left:3rem;
font-size:1.2rem;
line-height: 2rem;
font-family: var(--font-sans);
color:var(--text-base);
letter-spacing: 0.01em;
}
}

View File

@ -0,0 +1,40 @@
import React,{ChangeEvent,useState,useEffect} from 'react';
import s from './CheckboxCommon.module.scss';
import classNames from 'classnames';
interface CheckboxProps extends Omit<
React.InputHTMLAttributes<HTMLInputElement>,
'onChange'
>{
onChange?: (value: boolean) => void,
defaultChecked?: boolean
}
const CheckboxCommon = ({onChange,defaultChecked = true,...props}: CheckboxProps) =>{
const [value, setValue] = useState<boolean>(true);
useEffect(()=>{
onChange && onChange(value)
},[value])
const onValueChange = (e: ChangeEvent<HTMLInputElement>)=>{
let value =e.target.checked;
setValue(value);
}
return (
<div className={classNames(s.checkboxCommonWarper)}>
<label className={classNames(s.checkboxItem)}>
<input id="check" defaultChecked={defaultChecked} className={s.checkboxInput} type="checkbox" onChange={onValueChange}/>
<span className={s.checkMark}></span>
</label>
<div className={classNames(s.checkboxText)}>
<label htmlFor="check"> Billing address is same as shipping </label>
</div>
</div>
)
}
export default CheckboxCommon;

View File

@ -0,0 +1,9 @@
.dateTime{
color:var(--text-label);
text-transform: uppercase;
font-size: 1.2rem;
line-height: 2rem;
letter-spacing: 0.01em;
font-feature-settings: 'salt' on;
font-family: var(--font-sans);
}

View File

@ -0,0 +1,15 @@
import React from 'react';
import s from './DateTime.module.scss';
import classNames from 'classnames';
interface Props {
date:string,
}
const DateTime = ({date}:Props) =>{
return (
<div className={classNames(s.dateTime)}>{date}</div>
)
}
export default DateTime;

View File

@ -13,4 +13,7 @@
padding-left: 3.2rem;
padding-right: 3.2rem;
}
.logo {
@apply font-logo;
}
}

View File

@ -38,7 +38,6 @@ const InputCommon = forwardRef<Ref, Props>(({ value, placeholder, type, styleTyp
const handleKeyDown = (e: any) => {
if (e.key === KEY.ENTER && onEnter) {
console.log("on enter***")
const value = inputElementRef.current?.value || ''
onEnter(value)
}

View File

@ -1,15 +1,15 @@
@import '../../../styles/utilities';
.logo{
.logo {
display: flex;
.eclipse{
.eclipse {
width: 3.2rem;
height: 3.2rem;
background-color: var(--primary);
border-radius: 50%;
margin-right: 1.2rem;
}
.content{
.content {
@apply font-logo;
font-size: 16px;
line-height: 32px;

View File

@ -8,6 +8,9 @@ export { default as ViewAllItem} from './ViewAllItem/ViewAllItem'
export { default as ItemWishList} from './ItemWishList/ItemWishList'
export { default as Logo} from './Logo/Logo'
export { default as Inputcommon} from './InputCommon/InputCommon'
export { default as CheckboxCommon} from './CheckboxCommon/CheckboxCommon'
export { default as Author} from './Author/Author'
export { default as DateTime} from './DateTime/DateTime'
export { default as HeadingCommon } from './HeadingCommon/HeadingCommon'
export { default as CollectionHeading } from './CollectionHeading/CollectionHeading'
export { default as ScrollToTop } from './ScrollToTop/ScrollToTop'

View File

@ -0,0 +1,20 @@
const Vector = ({ ...props }) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M20.16 4.99992C19.1 3.93713 17.6948 3.28846 16.1984 3.17109C14.7019 3.05372 13.2128 3.47539 12 4.35992C10.7277 3.41356 9.14402 2.98443 7.56795 3.15896C5.99188 3.33348 4.54047 4.0987 3.506 5.30051C2.47154 6.50231 1.93085 8.05144 1.99283 9.63594C2.05481 11.2204 2.71485 12.7226 3.84003 13.8399L10.05 20.0599C10.57 20.5717 11.2704 20.8585 12 20.8585C12.7296 20.8585 13.43 20.5717 13.95 20.0599L20.16 13.8399C21.3276 12.6652 21.983 11.0762 21.983 9.41992C21.983 7.76365 21.3276 6.17465 20.16 4.99992ZM18.75 12.4599L12.54 18.6699C12.4694 18.7413 12.3853 18.7979 12.2926 18.8366C12.1999 18.8752 12.1005 18.8951 12 18.8951C11.8996 18.8951 11.8002 18.8752 11.7075 18.8366C11.6148 18.7979 11.5307 18.7413 11.46 18.6699L5.25003 12.4299C4.46579 11.6283 4.02664 10.5514 4.02664 9.42992C4.02664 8.30846 4.46579 7.23158 5.25003 6.42992C6.04919 5.64091 7.127 5.19849 8.25003 5.19849C9.37306 5.19849 10.4509 5.64091 11.25 6.42992C11.343 6.52365 11.4536 6.59804 11.5755 6.64881C11.6973 6.69958 11.828 6.72572 11.96 6.72572C12.092 6.72572 12.2227 6.69958 12.3446 6.64881C12.4665 6.59804 12.5771 6.52365 12.67 6.42992C13.4692 5.64091 14.547 5.19849 15.67 5.19849C16.7931 5.19849 17.8709 5.64091 18.67 6.42992C19.4651 7.22107 19.9186 8.29211 19.9336 9.41361C19.9485 10.5351 19.5237 11.6179 18.75 12.4299V12.4599Z"
fill={props.color}
/>
</svg>
)
}
export default Vector

View File

@ -0,0 +1,20 @@
const Vector = ({ ...props }) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M14.8299 11.2899L10.5899 7.04995C10.497 6.95622 10.3864 6.88183 10.2645 6.83106C10.1427 6.78029 10.012 6.75415 9.87994 6.75415C9.74793 6.75415 9.61723 6.78029 9.49537 6.83106C9.37351 6.88183 9.26291 6.95622 9.16994 7.04995C8.98369 7.23731 8.87915 7.49076 8.87915 7.75495C8.87915 8.01913 8.98369 8.27259 9.16994 8.45995L12.7099 11.9999L9.16994 15.5399C8.98369 15.7273 8.87915 15.9808 8.87915 16.2449C8.87915 16.5091 8.98369 16.7626 9.16994 16.9499C9.26338 17.0426 9.3742 17.116 9.49604 17.1657C9.61787 17.2155 9.74834 17.2407 9.87994 17.2399C10.0115 17.2407 10.142 17.2155 10.2638 17.1657C10.3857 17.116 10.4965 17.0426 10.5899 16.9499L14.8299 12.7099C14.9237 12.617 14.9981 12.5064 15.0488 12.3845C15.0996 12.2627 15.1257 12.132 15.1257 11.9999C15.1257 11.8679 15.0996 11.7372 15.0488 11.6154C14.9981 11.4935 14.9237 11.3829 14.8299 11.2899Z"
fill="#5B9A74"
/>
</svg>
)
}
export default Vector

View File

@ -0,0 +1,31 @@
@import "../../../../../styles/_utilities";
.categoryItem {
.categoryItemImage {
@apply transition-all duration-200;
width: 10.6rem;
margin: 0 auto;
max-height: 14rem;
object-fit: cover;
cursor: pointer;
@screen md {
width: 100%;
}
img {
width: 100%;
height: 100%;
}
&:hover {
transform: scale(1.05);
}
}
.categoryItemText {
@apply sub-headline;
text-align: center;
font-feature-settings: "salt" on;
cursor: pointer;
&:hover {
color: var(--primary);
}
}
}

View File

@ -0,0 +1,33 @@
import React from 'react';
import s from './CategoryItem.module.scss'
import classNames from 'classnames';
import Image from "next/image";
import Link from 'next/link';
interface CategoryItem {
image: StaticImageData,
name: string,
link: string
}
const CategoryItem = ({ image, name, link }: CategoryItem) => {
return (
<div className={classNames(s.categoryItem)}>
<div className={classNames(s.categoryItemImage)}>
<Link href={link}>
<a>
<Image src={image} />
</a>
</Link>
</div>
<Link href={link}>
<a>
<div className={classNames(s.categoryItemText)}>{name}</div>
</a>
</Link>
</div >
)
}
export default CategoryItem

View File

@ -0,0 +1,54 @@
@import "../../../../styles/_utilities";
.homeCategoriesWrapper {
@apply flex flex-col items-center justify-center;
margin: 3rem auto;
.inner {
@apply relative spacing-horizontal;
padding-top: 1.6rem;
padding-bottom: 1.6rem;
z-index: 10;
@screen md {
@apply bg-gray;
}
}
@screen md {
@apply relative;
margin: 5.6rem auto;
&::before,
&::after {
@apply absolute w-full;
content: "";
height: 6rem;
z-index: 0;
background-repeat: no-repeat;
background-size: 115%;
}
&::before {
top: -4rem;
background-image: url("./img/bg_top.svg");
background-position: top center;
}
&::after {
bottom: -4rem;
background-image: url("./img/bg_bottom.svg");
background-position: bottom center;
}
}
.homeCategoryList {
@apply flex justify-start items-center flex-wrap;
margin: 1rem 0;
@screen md {
@apply flex-nowrap;
}
.homeCategoriesItem {
width: calc(100% / 3);
@screen md {
margin-top: 2rem;
width: 100%;
}
}
}
}

View File

@ -0,0 +1,68 @@
import classNames from 'classnames';
import React from 'react';
import { QUERY_KEY, ROUTE } from 'src/utils/constanst.utils';
import HeadingCommon from "../../../common/HeadingCommon/HeadingCommon";
import CategoryItem from './CategoriesItem/CategoryItem';
import s from './HomeCategories.module.scss';
import coffeebean from './img/coffeebean.png';
import frozen from './img/frozen.png';
import sauce from './img/sauce.png';
import seafood from './img/seafood.png';
import veggle from './img/veggle.png';
const categories = [
{
id: 1,
image: veggle,
name: "Veggie",
link: `${ROUTE.PRODUCTS}?${QUERY_KEY.CATEGORY}=veggie`
}, {
id: 2,
image: seafood,
name: "Seafood",
link: `${ROUTE.PRODUCTS}?${QUERY_KEY.CATEGORY}=seafood`
}
, {
id: 3,
image: frozen,
name: "Frozen",
link: `${ROUTE.PRODUCTS}?${QUERY_KEY.CATEGORY}=frozen`
}
, {
id: 4,
image: coffeebean,
name: "Coffe Bean",
link: `${ROUTE.PRODUCTS}?${QUERY_KEY.CATEGORY}=coffee-bean`
}
, {
id: 5,
image: sauce,
name: "Sauce",
link: `${ROUTE.PRODUCTS}?${QUERY_KEY.CATEGORY}=sauce`,
}
]
const HomeCategories = () => {
return (
<div className={classNames(s.homeCategoriesWrapper)}>
<div className={s.inner}>
<HeadingCommon align='center'>CATEGORIES</HeadingCommon>
<div className={classNames(s.homeCategoryList)}>
{categories?.map(item => (
<div key={item.name} className={classNames(s.homeCategoriesItem)}>
<CategoryItem
name={item.name}
image={item.image}
link={item.link}
/>
</div>
))}
</div>
</div>
</div>
)
}
export default HomeCategories

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -1,4 +1,5 @@
export { default as HomeBanner } from './HomeBanner/HomeBanner'
export { default as HomeCategories } from './HomeCategories/HomeCategories'
export { default as HomeCTA } from './HomeCTA/HomeCTA'
export { default as HomeSubscribe } from './HomeSubscribe/HomeSubscribe'
export { default as HomeVideo } from './HomeVideo/HomeVideo'

View File

@ -51,7 +51,6 @@ module.exports = {
gray: 'var(--gray)',
disabled: 'var(--text-disabled)',
'background-arrow':'var(--background-arrow)',
// @deprecated (NOT use these variables)
'primary-2': 'var(--primary-2)',