Merge branch 'common' into m6-sonnguyen

This commit is contained in:
sonnguyenkieio
2021-09-13 15:49:17 +07:00
committed by GitHub
205 changed files with 6718 additions and 330 deletions

2
.gitignore vendored
View File

@@ -35,3 +35,5 @@ yarn-error.log*
# vercel
.vercel
.eslintrc

View File

@@ -1,27 +0,0 @@
{
"schema": {
"https://buybutton.store/graphql": {
"headers": {
"Authorization": "Bearer xzy"
}
}
},
"documents": [
{
"./framework/bigcommerce/api/**/*.ts": {
"noRequire": true
}
}
],
"generates": {
"./framework/bigcommerce/schema.d.ts": {
"plugins": ["typescript", "typescript-operations"]
},
"./framework/bigcommerce/schema.graphql": {
"plugins": ["schema-ast"]
}
},
"hooks": {
"afterAllFileWrite": ["prettier --write"]
}
}

View File

@@ -13,6 +13,16 @@ const isVendure = provider === 'vendure'
module.exports = withCommerceConfig({
commerce,
typescript: { // todo: remove it
// !! WARN !!
// Dangerously allow production builds to successfully complete even if
// your project has type errors.
// !! WARN !!
ignoreBuildErrors: true,
},
eslint: {
ignoreDuringBuilds: true,
},
images: {
// todo: replace domains for images
domains: ['user-images.githubusercontent.com'],

View File

@@ -5,7 +5,7 @@
"dev": "NODE_OPTIONS='--inspect' PORT=3005 next dev",
"dev-windows": "set NODE_OPTIONS='--inspect' && set PORT=3005 && next dev",
"build": "next build",
"start": "next start",
"start": "PORT=3005 next start",
"analyze": "BUNDLE_ANALYZE=both yarn build",
"prettier-fix": "prettier --write .",
"find:unused": "npx next-unused",
@@ -27,6 +27,8 @@
"classnames": "^2.3.1",
"cookie": "^0.4.1",
"email-validator": "^2.0.4",
"eslint": "^7.32.0",
"eslint-config-next": "^11.1.2",
"immutability-helper": "^3.1.1",
"js-cookie": "^2.2.1",
"keen-slider": "^5.5.1",
@@ -66,6 +68,7 @@
"@types/node": "^15.12.4",
"@types/react": "^17.0.8",
"deepmerge": "^4.2.2",
"eslint-config-prettier": "^8.3.0",
"graphql": "^15.5.1",
"husky": "^6.0.0",
"lint-staged": "^11.0.0",

View File

@@ -1,11 +1,11 @@
import { Layout } from "src/components/common"
import { Layout } from 'src/components/common'
import { NotFoundPage } from "src/components/modules/404"
export default function NotFound() {
return (
<div>
The requested page doesn't exist or you don't have access to it.
<NotFoundPage/>
</div>
)
}
NotFound.Layout = Layout

13
pages/account.tsx Normal file
View File

@@ -0,0 +1,13 @@
import React from 'react';
import { Layout } from 'src/components/common';
import { AccountPage } from 'src/components/modules/account';
const Account = () => {
return (
<AccountPage/>
);
};
Account.Layout = Layout
export default Account;

17
pages/blog/[slug].tsx Normal file
View File

@@ -0,0 +1,17 @@
import { Layout, RelevantBlogPosts } from 'src/components/common';
import BlogContent from 'src/components/modules/blog-detail/BlogContent/BlogContent';
import BlogDetailImg from 'src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg';
import { BLOGS_DATA_TEST } from 'src/utils/demo-data'
export default function BlogDetailPage() {
return (
<>
<BlogDetailImg/>
<BlogContent/>
<RelevantBlogPosts data={BLOGS_DATA_TEST} title="You will like also" bgcolor="cream"/>
</>
)
}
BlogDetailPage.Layout = Layout

14
pages/blogs.tsx Normal file
View File

@@ -0,0 +1,14 @@
import { Layout } from 'src/components/common';
import { BlogsList, FeaturedCardBlog, BlogHeading, BlogBreadCrumb } from 'src/components/modules/blogs';
export default function BlogsPage() {
return(
<>
<BlogBreadCrumb />
<BlogHeading />
<FeaturedCardBlog />
<BlogsList />
</>
)
}
BlogsPage.Layout = Layout

13
pages/checkout.tsx Normal file
View File

@@ -0,0 +1,13 @@
import { Layout } from 'src/components/common';
import { CheckoutPage } from 'src/components/modules/checkout';
import { HomeBanner, HomeCategories, HomeCollection, HomeCTA, HomeFeature, HomeRecipe, HomeSubscribe, HomeVideo } from 'src/components/modules/home';
export default function Checkout() {
return (
<>
<CheckoutPage/>
</>
)
}
Checkout.Layout = Layout

View File

@@ -16,7 +16,7 @@ export default function Home() {
<HomeRecipe />
<HomeSubscribe /> */}
{/* // todo: uncomment */}
{/* // todo: uncomment
{/* <ModalCreateUserInfo/> */}
</>
)

12
pages/privacy-policy.tsx Normal file
View File

@@ -0,0 +1,12 @@
import { Layout } from "src/components/common"
import { DeliveryAndPolicyContent, DeliveryAndPolicyBreadCrumb } from "src/components/modules/delivery-policy"
export default function DeliveryAndPolicyPage () {
return (
<>
<DeliveryAndPolicyBreadCrumb />
<DeliveryAndPolicyContent />
</>
)
}
DeliveryAndPolicyPage.Layout = Layout

17
pages/products.tsx Normal file
View File

@@ -0,0 +1,17 @@
import { Layout } from 'src/components/common';
import ProductListFilter from 'src/components/modules/product-list/ProductListFilter/ProductListFilter';
import RecipeListBanner from 'src/components/modules/recipes-list/RecipeListBanner/RecipeListBanner';
import RecipesList from 'src/components/modules/recipes-list/RecipesList/RecipesList';
import ProductListBanner from '../src/components/modules/product-list/ProductListBanner/ProductListBanner';
export default function Products() {
return (
<>
<ProductListBanner />
<ProductListFilter/>
</>
)
}
Products.Layout = Layout

15
pages/recipes.tsx Normal file
View File

@@ -0,0 +1,15 @@
import { Layout } from 'src/components/common';
import RecipeListBanner from 'src/components/modules/recipes-list/RecipeListBanner/RecipeListBanner';
import RecipesList from 'src/components/modules/recipes-list/RecipesList/RecipesList';
export default function RecipeListPage() {
return (
<>
<RecipeListBanner />
<RecipesList/>
</>
)
}
RecipeListPage.Layout = Layout

View File

@@ -1,13 +1,90 @@
import { useState } from 'react'
import { ButtonCommon, Layout } from 'src/components/common'
import {
CartDrawer,
Layout
} from 'src/components/common';
import MenuNavigationProductList from 'src/components/common/MenuNavigationProductList/MenuNavigationProductList';
// import { RecipeListPage } from 'src/components/modules/recipes';
import { OPTION_ALL, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils';
import { useModalCommon } from 'src/components/hooks';
const CATEGORY = [
{
name: 'All',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=${OPTION_ALL}`,
},
{
name: 'Veggie',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=veggie`,
},
{
name: 'Seafood',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=seafood`,
},
{
name: 'Frozen',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=frozen`,
},
{
name: 'Coffee Bean',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=coffee-bean`,
},
{
name: 'Sauce',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=sauce`,
},
]
const BRAND = [
import CheckoutSuccess from 'src/components/modules/checkout/CheckoutSuccess/CheckoutSuccess'
{
name: 'Maggi',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=veggie`,
},
{
name: 'Cholimes',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=seafood`,
},
{
name: 'Chinsu',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=frozen`,
}
];
const FEATURED = [
{
name: 'Best Sellers',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=veggie`,
},
{
name: 'Sales',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=seafood`,
},
{
name: 'New Item',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=frozen`,
},
{
name: 'Viewed',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=viewed`,
}
];
export default function Test() {
const { visible: visibleMenuFilter, openModal, closeModal: closeMenuFilter } = useModalCommon({ initialValue: false })
const toggle = () => {
if (visibleMenuFilter) {
closeMenuFilter()
} else {
openModal()
}
}
return (
<>
<CheckoutSuccess />
{/* <BlogDetailPage /> */}
{/* <RecipeListPage/> */}
{/*<MenuNavigation heading="CATEGORIES" categories={CATEGORY}/>*/}
<button onClick={toggle}>toggle menu : {visibleMenuFilter.toString()}</button>
<MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleMenuFilter} onClose={closeMenuFilter}/>
{/* <CartDrawer /> */}
</>
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

View File

@@ -1,7 +1,7 @@
<svg width="48" height="46" viewBox="0 0 48 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<line opacity="0.1" x1="9.41421" y1="8" x2="21" y2="19.5858" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<line opacity="0.1" x1="1" y1="-1" x2="17.3848" y2="-1" transform="matrix(-0.707107 0.707107 0.707107 0.707107 40 8)" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<line opacity="0.1" x1="1" y1="-1" x2="17.3848" y2="-1" transform="matrix(0.707107 -0.707107 -0.707107 -0.707107 8 38)" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<line opacity="0.1" x1="38.5858" y1="38" x2="27" y2="26.4142" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<line opacity="0.1" x1="9.41421" y1="8" x2="21" y2="19.5858" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<line opacity="0.1" x1="1" y1="-1" x2="17.3848" y2="-1" transform="matrix(-0.707107 0.707107 0.707107 0.707107 40 8)" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<line opacity="0.1" x1="1" y1="-1" x2="17.3848" y2="-1" transform="matrix(0.707107 -0.707107 -0.707107 -0.707107 8 38)" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
<line opacity="0.1" x1="38.5858" y1="38" x2="27" y2="26.4142" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 797 B

After

Width:  |  Height:  |  Size: 785 B

View File

@@ -0,0 +1,646 @@
{
"header": {
"reportVersion": 1,
"event": "Allocation failed - JavaScript heap out of memory",
"trigger": "FatalError",
"filename": "report.20210908.160959.14332.0.001.json",
"dumpEventTime": "2021-09-08T16:09:59Z",
"dumpEventTimeStamp": "1631092199677",
"processId": 14332,
"cwd": "G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce",
"commandLine": [
"node",
"G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce\\node_modules\\.bin\\\\..\\next\\dist\\bin\\next",
"dev"
],
"nodejsVersion": "v12.15.0",
"wordSize": 64,
"arch": "x64",
"platform": "win32",
"componentVersions": {
"node": "12.15.0",
"v8": "7.7.299.13-node.16",
"uv": "1.33.1",
"zlib": "1.2.11",
"brotli": "1.0.7",
"ares": "1.15.0",
"modules": "72",
"nghttp2": "1.40.0",
"napi": "5",
"llhttp": "2.0.4",
"http_parser": "2.9.3",
"openssl": "1.1.1d",
"cldr": "35.1",
"icu": "64.2",
"tz": "2019c",
"unicode": "12.1"
},
"release": {
"name": "node",
"lts": "Erbium",
"headersUrl": "https://nodejs.org/download/release/v12.15.0/node-v12.15.0-headers.tar.gz",
"sourceUrl": "https://nodejs.org/download/release/v12.15.0/node-v12.15.0.tar.gz",
"libUrl": "https://nodejs.org/download/release/v12.15.0/win-x64/node.lib"
},
"osName": "Windows_NT",
"osRelease": "10.0.19043",
"osVersion": "Windows 10 Pro",
"osMachine": "x86_64",
"cpus": [
{
"model": "Intel(R) Core(TM) i3-3110M CPU @ 2.40GHz",
"speed": 2395,
"user": 67605265,
"nice": 0,
"sys": 33647953,
"idle": 255172281,
"irq": 3598359
},
{
"model": "Intel(R) Core(TM) i3-3110M CPU @ 2.40GHz",
"speed": 2395,
"user": 68803843,
"nice": 0,
"sys": 25225015,
"idle": 262396453,
"irq": 602640
},
{
"model": "Intel(R) Core(TM) i3-3110M CPU @ 2.40GHz",
"speed": 2395,
"user": 76698718,
"nice": 0,
"sys": 25995390,
"idle": 253731187,
"irq": 321484
},
{
"model": "Intel(R) Core(TM) i3-3110M CPU @ 2.40GHz",
"speed": 2395,
"user": 77662531,
"nice": 0,
"sys": 24450312,
"idle": 254312468,
"irq": 266531
}
],
"networkInterfaces": [
{
"name": "Wi-Fi",
"internal": false,
"mac": "a4:17:31:1d:cc:e5",
"address": "2402:800:6318:9d24:f937:34a5:8214:a074",
"netmask": "ffff:ffff:ffff:ffff::",
"family": "IPv6",
"scopeid": 0
},
{
"name": "Wi-Fi",
"internal": false,
"mac": "a4:17:31:1d:cc:e5",
"address": "2402:800:6318:9d24:69cf:fc3d:74:1b08",
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
"family": "IPv6",
"scopeid": 0
},
{
"name": "Wi-Fi",
"internal": false,
"mac": "a4:17:31:1d:cc:e5",
"address": "fe80::f937:34a5:8214:a074",
"netmask": "ffff:ffff:ffff:ffff::",
"family": "IPv6",
"scopeid": 21
},
{
"name": "Wi-Fi",
"internal": false,
"mac": "a4:17:31:1d:cc:e5",
"address": "192.168.1.10",
"netmask": "255.255.255.0",
"family": "IPv4"
},
{
"name": "Loopback Pseudo-Interface 1",
"internal": true,
"mac": "00:00:00:00:00:00",
"address": "::1",
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
"family": "IPv6",
"scopeid": 0
},
{
"name": "Loopback Pseudo-Interface 1",
"internal": true,
"mac": "00:00:00:00:00:00",
"address": "127.0.0.1",
"netmask": "255.0.0.0",
"family": "IPv4"
}
],
"host": "DESKTOP-TILU55O"
},
"javascriptStack": {
"message": "No stack.",
"stack": [
"Unavailable."
]
},
"nativeStack": [
{
"pc": "0x00007ff77aa01759",
"symbol": "std::basic_ostream<char,std::char_traits<char> >::operator<<+10873"
},
{
"pc": "0x00007ff77aa05b7c",
"symbol": "std::basic_ostream<char,std::char_traits<char> >::operator<<+28316"
},
{
"pc": "0x00007ff77aa04b38",
"symbol": "std::basic_ostream<char,std::char_traits<char> >::operator<<+24152"
},
{
"pc": "0x00007ff77aaf446b",
"symbol": "v8::base::CPU::has_sse+37723"
},
{
"pc": "0x00007ff77b2f8d9e",
"symbol": "v8::Isolate::ReportExternalAllocationLimitReached+94"
},
{
"pc": "0x00007ff77b2e0de1",
"symbol": "v8::SharedArrayBuffer::Externalize+833"
},
{
"pc": "0x00007ff77b1ae6ac",
"symbol": "v8::internal::Heap::EphemeronKeyWriteBarrierFromCode+1436"
},
{
"pc": "0x00007ff77b1b9a50",
"symbol": "v8::internal::Heap::ProtectUnprotectedMemoryChunks+1312"
},
{
"pc": "0x00007ff77b1b6584",
"symbol": "v8::internal::Heap::PageFlagsAreConsistent+3204"
},
{
"pc": "0x00007ff77b1abe13",
"symbol": "v8::internal::Heap::CollectGarbage+1283"
},
{
"pc": "0x00007ff77b1aa5e4",
"symbol": "v8::internal::Heap::AddRetainedMap+2356"
},
{
"pc": "0x00007ff77b1c46ee",
"symbol": "v8::internal::Factory::AllocateRawFixedArray+94"
},
{
"pc": "0x00007ff77b1cba84",
"symbol": "v8::internal::Factory::NewFixedArrayWithFiller+52"
},
{
"pc": "0x00007ff77b1cba41",
"symbol": "v8::internal::Factory::NewUninitializedFixedArray+65"
},
{
"pc": "0x00007ff77b0ac86f",
"symbol": "v8::Object::GetIsolate+6767"
},
{
"pc": "0x00007ff77af5feaa",
"symbol": "v8::internal::OrderedHashMap::ValueAt+61274"
},
{
"pc": "0x00007ff77b724d3d",
"symbol": "v8::internal::SetupIsolateDelegate::SetupHeap+567949"
},
{
"pc": "0x0000004163e2d61e",
"symbol": ""
}
],
"javascriptHeap": {
"totalMemory": 2197684224,
"totalCommittedMemory": 2197684224,
"usedMemory": 2099361840,
"availableMemory": 89682992,
"memoryLimit": 2197815296,
"heapSpaces": {
"read_only_space": {
"memorySize": 262144,
"committedMemory": 262144,
"capacity": 261872,
"used": 32296,
"available": 229576
},
"new_space": {
"memorySize": 33554432,
"committedMemory": 33554432,
"capacity": 16759808,
"used": 9024016,
"available": 7735792
},
"old_space": {
"memorySize": 1753329664,
"committedMemory": 1753329664,
"capacity": 1750360832,
"used": 1685534088,
"available": 64826744
},
"code_space": {
"memorySize": 5144576,
"committedMemory": 5144576,
"capacity": 4347712,
"used": 4347712,
"available": 0
},
"map_space": {
"memorySize": 8916992,
"committedMemory": 8916992,
"capacity": 4381920,
"used": 4381920,
"available": 0
},
"large_object_space": {
"memorySize": 395280384,
"committedMemory": 395280384,
"capacity": 394944560,
"used": 394944560,
"available": 0
},
"code_large_object_space": {
"memorySize": 1196032,
"committedMemory": 1196032,
"capacity": 1097248,
"used": 1097248,
"available": 0
},
"new_large_object_space": {
"memorySize": 0,
"committedMemory": 0,
"capacity": 16759808,
"used": 0,
"available": 16759808
}
}
},
"resourceUsage": {
"userCpuSeconds": 2420.01,
"kernelCpuSeconds": 114.859,
"cpuConsumptionPercent": 11.0361,
"maxRss": 2818129920,
"pageFaults": {
"IORequired": 14395451,
"IONotRequired": 0
},
"fsActivity": {
"reads": 46029,
"writes": 640054
}
},
"libuv": [
],
"environmentVariables": {
"=G:": "G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce",
"ALLUSERSPROFILE": "C:\\ProgramData",
"ANDROID_HOME": "G:\\ASDK",
"ANDROID_SDK_ROOT": "G:\\ASDK",
"APPDATA": "C:\\Users\\nhan\\AppData\\Roaming",
"ChocolateyInstall": "C:\\ProgramData\\chocolatey",
"ChocolateyLastPathUpdate": "132608575831335062",
"CHROME_CRASHPAD_PIPE_NAME": "\\\\.\\pipe\\crashpad_17244_MSJZWZVAYBLFIPJS",
"CLASSPATH": "C:\\Program Files\\Java\\jdk1.8.0_231\\bin",
"COLORTERM": "truecolor",
"COMMERCE_CUSTOMERAUTH_ENABLED": "true",
"COMMERCE_PROVIDER": "vendure",
"CommonProgramFiles": "C:\\Program Files\\Common Files",
"CommonProgramFiles(x86)": "C:\\Program Files (x86)\\Common Files",
"CommonProgramW6432": "C:\\Program Files\\Common Files",
"COMPUTERNAME": "DESKTOP-TILU55O",
"ComSpec": "C:\\WINDOWS\\system32\\cmd.exe",
"dp0": "G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce\\node_modules\\.bin\\",
"DriverData": "C:\\Windows\\System32\\Drivers\\DriverData",
"FPS_BROWSER_APP_PROFILE_STRING": "Internet Explorer",
"FPS_BROWSER_USER_PROFILE_STRING": "Default",
"GIT_ASKPASS": "c:\\Users\\nhan\\AppData\\Local\\Programs\\Microsoft VS Code\\resources\\app\\extensions\\git\\dist\\askpass.sh",
"GIT_LFS_PATH": "C:\\Program Files\\Git LFS",
"HOME": "C:\\Users\\nhan",
"HOMEDRIVE": "C:",
"HOMEPATH": "\\Users\\nhan",
"INIT_CWD": "G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce",
"JAVA_HOME": "C:\\Program Files\\Java\\jdk1.8.0_281",
"LANG": "en_US.UTF-8",
"LOCALAPPDATA": "C:\\Users\\nhan\\AppData\\Local",
"LOGONSERVER": "\\\\DESKTOP-TILU55O",
"NEXT_PUBLIC_VENDURE_LOCAL_URL": "/vendure-shop-api",
"NEXT_PUBLIC_VENDURE_SHOP_API_URL": "https://demo.vendure.io/shop-api",
"NODE": "C:\\Program Files\\nodejs\\node.exe",
"NODE_ENV": "development",
"NODE_EXE": "C:\\Program Files\\nodejs\\\\node.exe",
"NODE_OPTIONS": "'--inspect' ",
"NPM_CLI_JS": "C:\\Program Files\\nodejs\\\\node_modules\\npm\\bin\\npm-cli.js",
"npm_config_access": "",
"npm_config_allow_same_version": "",
"npm_config_also": "",
"npm_config_always_auth": "",
"npm_config_argv": "{\"remain\":[],\"cooked\":[\"run\",\"dev-windows\"],\"original\":[\"run\",\"dev-windows\"]}",
"npm_config_audit": "true",
"npm_config_audit_level": "low",
"npm_config_auth_type": "legacy",
"npm_config_before": "",
"npm_config_bin_links": "true",
"npm_config_browser": "",
"npm_config_ca": "",
"npm_config_cache": "C:\\Users\\nhan\\AppData\\Roaming\\npm-cache",
"npm_config_cache_lock_retries": "10",
"npm_config_cache_lock_stale": "60000",
"npm_config_cache_lock_wait": "10000",
"npm_config_cache_max": "Infinity",
"npm_config_cache_min": "10",
"npm_config_cafile": "",
"npm_config_cert": "",
"npm_config_cidr": "",
"npm_config_color": "true",
"npm_config_commit_hooks": "true",
"npm_config_depth": "Infinity",
"npm_config_description": "true",
"npm_config_dev": "",
"npm_config_dry_run": "",
"npm_config_editor": "notepad.exe",
"npm_config_engine_strict": "",
"npm_config_fetch_retries": "2",
"npm_config_fetch_retry_factor": "10",
"npm_config_fetch_retry_maxtimeout": "60000",
"npm_config_fetch_retry_mintimeout": "10000",
"npm_config_force": "",
"npm_config_format_package_lock": "true",
"npm_config_fund": "true",
"npm_config_git": "git",
"npm_config_git_tag_version": "true",
"npm_config_global": "",
"npm_config_globalconfig": "C:\\Users\\nhan\\AppData\\Roaming\\npm\\etc\\npmrc",
"npm_config_globalignorefile": "C:\\Users\\nhan\\AppData\\Roaming\\npm\\etc\\npmignore",
"npm_config_global_style": "",
"npm_config_group": "",
"npm_config_ham_it_up": "",
"npm_config_heading": "npm",
"npm_config_https_proxy": "",
"npm_config_if_present": "",
"npm_config_ignore_prepublish": "",
"npm_config_ignore_scripts": "",
"npm_config_init_author_email": "",
"npm_config_init_author_name": "",
"npm_config_init_author_url": "",
"npm_config_init_license": "ISC",
"npm_config_init_module": "C:\\Users\\nhan\\.npm-init.js",
"npm_config_init_version": "1.0.0",
"npm_config_json": "",
"npm_config_key": "",
"npm_config_legacy_bundling": "",
"npm_config_link": "",
"npm_config_local_address": "",
"npm_config_loglevel": "notice",
"npm_config_logs_max": "10",
"npm_config_long": "",
"npm_config_maxsockets": "50",
"npm_config_message": "%s",
"npm_config_metrics_registry": "https://registry.npmjs.org/",
"npm_config_node_gyp": "C:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js",
"npm_config_node_options": "",
"npm_config_node_version": "12.15.0",
"npm_config_noproxy": "",
"npm_config_offline": "",
"npm_config_onload_script": "",
"npm_config_only": "",
"npm_config_optional": "true",
"npm_config_otp": "",
"npm_config_package_lock": "true",
"npm_config_package_lock_only": "",
"npm_config_parseable": "",
"npm_config_prefer_offline": "",
"npm_config_prefer_online": "",
"npm_config_prefix": "C:\\Users\\nhan\\AppData\\Roaming\\npm",
"npm_config_preid": "",
"npm_config_production": "",
"npm_config_progress": "true",
"npm_config_proxy": "",
"npm_config_read_only": "",
"npm_config_rebuild_bundle": "true",
"npm_config_registry": "https://registry.npmjs.org/",
"npm_config_rollback": "true",
"npm_config_save": "true",
"npm_config_save_bundle": "",
"npm_config_save_dev": "",
"npm_config_save_exact": "",
"npm_config_save_optional": "",
"npm_config_save_prefix": "^",
"npm_config_save_prod": "",
"npm_config_scope": "",
"npm_config_scripts_prepend_node_path": "warn-only",
"npm_config_script_shell": "",
"npm_config_searchexclude": "",
"npm_config_searchlimit": "20",
"npm_config_searchopts": "",
"npm_config_searchstaleness": "900",
"npm_config_send_metrics": "",
"npm_config_shell": "C:\\WINDOWS\\system32\\cmd.exe",
"npm_config_shrinkwrap": "true",
"npm_config_sign_git_commit": "",
"npm_config_sign_git_tag": "",
"npm_config_sso_poll_frequency": "500",
"npm_config_sso_type": "oauth",
"npm_config_strict_ssl": "true",
"npm_config_tag": "latest",
"npm_config_tag_version_prefix": "v",
"npm_config_timing": "",
"npm_config_tmp": "C:\\Users\\nhan\\AppData\\Local\\Temp",
"npm_config_umask": "0000",
"npm_config_unicode": "",
"npm_config_unsafe_perm": "true",
"npm_config_update_notifier": "true",
"npm_config_usage": "",
"npm_config_user": "",
"npm_config_userconfig": "C:\\Users\\nhan\\.npmrc",
"npm_config_user_agent": "npm/6.13.4 node/v12.15.0 win32 x64",
"npm_config_version": "",
"npm_config_versions": "",
"npm_config_viewer": "browser",
"npm_execpath": "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js",
"npm_lifecycle_event": "dev-windows",
"npm_lifecycle_script": "set NODE_OPTIONS='--inspect' && set PORT=3005 && next dev",
"npm_node_execpath": "C:\\Program Files\\nodejs\\node.exe",
"npm_package_dependencies_autoprefixer": "^10.2.6",
"npm_package_dependencies_body_scroll_lock": "^3.1.5",
"npm_package_dependencies_classnames": "^2.3.1",
"npm_package_dependencies_cookie": "^0.4.1",
"npm_package_dependencies_email_validator": "^2.0.4",
"npm_package_dependencies_eslint": "^7.32.0",
"npm_package_dependencies_eslint_config_next": "^11.1.2",
"npm_package_dependencies_immutability_helper": "^3.1.1",
"npm_package_dependencies_js_cookie": "^2.2.1",
"npm_package_dependencies_keen_slider": "^5.5.1",
"npm_package_dependencies_lodash_debounce": "^4.0.8",
"npm_package_dependencies_lodash_random": "^3.2.0",
"npm_package_dependencies_lodash_throttle": "^4.1.1",
"npm_package_dependencies_next": "^11.0.0",
"npm_package_dependencies_next_seo": "^4.26.0",
"npm_package_dependencies_next_themes": "^0.0.14",
"npm_package_dependencies_postcss": "^8.3.5",
"npm_package_dependencies_postcss_nesting": "^8.0.1",
"npm_package_dependencies_react": "^17.0.2",
"npm_package_dependencies_react_dom": "^17.0.2",
"npm_package_dependencies_react_fast_marquee": "^1.1.4",
"npm_package_dependencies_react_merge_refs": "^1.1.0",
"npm_package_dependencies_react_player": "^2.9.0",
"npm_package_dependencies_react_use_measure": "^2.0.4",
"npm_package_dependencies_sass": "^1.38.0",
"npm_package_dependencies_swell_js": "^4.0.0-next.0",
"npm_package_dependencies_swr": "^0.5.6",
"npm_package_dependencies_tabbable": "^5.2.0",
"npm_package_dependencies_tailwindcss": "^2.2.2",
"npm_package_dependencies_uuidv4": "^6.2.10",
"npm_package_dependencies__react_spring_web": "^9.2.1",
"npm_package_dependencies__vercel_fetch": "^6.1.0",
"npm_package_description": "[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fcommerce&project-name=commerce&repo-name=commerce&demo-title=Next.js%20Commerce&demo-description=An%20all-in-one%20starter%20kit%20for%20high-performance%20e-commerce%20sites.&demo-url=https%3A%2F%2Fdemo.vercel.store&demo-image=https%3A%2F%2Fbigcommerce-demo-asset-ksvtgfvnd.vercel.app%2Fbigcommerce.png&integration-ids=oac_MuWZiE4jtmQ2ejZQaQ7ncuDT)",
"npm_package_devDependencies_deepmerge": "^4.2.2",
"npm_package_devDependencies_eslint_config_prettier": "^8.3.0",
"npm_package_devDependencies_graphql": "^15.5.1",
"npm_package_devDependencies_husky": "^6.0.0",
"npm_package_devDependencies_lint_staged": "^11.0.0",
"npm_package_devDependencies_postcss_flexbugs_fixes": "^5.0.2",
"npm_package_devDependencies_postcss_import": "^14.0.2",
"npm_package_devDependencies_postcss_preset_env": "^6.7.0",
"npm_package_devDependencies_prettier": "^2.3.0",
"npm_package_devDependencies_typescript": "4.3.4",
"npm_package_devDependencies__graphql_codegen_cli": "^1.21.5",
"npm_package_devDependencies__graphql_codegen_schema_ast": "^1.18.3",
"npm_package_devDependencies__graphql_codegen_typescript": "^1.22.2",
"npm_package_devDependencies__graphql_codegen_typescript_operations": "^1.18.1",
"npm_package_devDependencies__next_bundle_analyzer": "^10.2.3",
"npm_package_devDependencies__types_body_scroll_lock": "^2.6.1",
"npm_package_devDependencies__types_cookie": "^0.4.0",
"npm_package_devDependencies__types_js_cookie": "^2.2.6",
"npm_package_devDependencies__types_lodash_debounce": "^4.0.6",
"npm_package_devDependencies__types_lodash_random": "^3.2.6",
"npm_package_devDependencies__types_lodash_throttle": "^4.1.6",
"npm_package_devDependencies__types_node": "^15.12.4",
"npm_package_devDependencies__types_react": "^17.0.8",
"npm_package_engines_node": ">=14.x",
"npm_package_gitHead": "16ca52162bc58204b405a3732a141f014a9573e2",
"npm_package_license": "MIT",
"npm_package_lint_staged_______js_jsx_ts_tsx__0": "prettier --write",
"npm_package_lint_staged_______js_jsx_ts_tsx__1": "git add",
"npm_package_lint_staged_______md_mdx_json__0": "prettier --write",
"npm_package_lint_staged_______md_mdx_json__1": "git add",
"npm_package_name": "nextjs-commerce",
"npm_package_next_unused_alias__assets___0": "assets/*",
"npm_package_next_unused_alias__components___0": "components/*",
"npm_package_next_unused_alias__config___0": "config/*",
"npm_package_next_unused_alias__lib___0": "lib/*",
"npm_package_next_unused_alias__utils___0": "utils/*",
"npm_package_next_unused_debug": "true",
"npm_package_next_unused_entrypoints_0": "pages",
"npm_package_next_unused_include_0": "components",
"npm_package_next_unused_include_1": "lib",
"npm_package_next_unused_include_2": "pages",
"npm_package_readmeFilename": "README.md",
"npm_package_scripts_analyze": "BUNDLE_ANALYZE=both yarn build",
"npm_package_scripts_build": "next build",
"npm_package_scripts_dev": "NODE_OPTIONS='--inspect' PORT=3005 next dev",
"npm_package_scripts_dev_windows": "set NODE_OPTIONS='--inspect' && set PORT=3005 && next dev",
"npm_package_scripts_find_unused": "npx next-unused",
"npm_package_scripts_generate": "graphql-codegen",
"npm_package_scripts_generate_definitions": "node framework/bigcommerce/scripts/generate-definitions.js",
"npm_package_scripts_generate_shopify": "DOTENV_CONFIG_PATH=./.env.local graphql-codegen -r dotenv/config --config framework/shopify/codegen.json",
"npm_package_scripts_generate_vendure": "graphql-codegen --config framework/vendure/codegen.json",
"npm_package_scripts_prettier_fix": "prettier --write .",
"npm_package_scripts_start": "next start",
"npm_package_sideEffects": "false",
"npm_package_version": "1.0.0",
"NPM_PREFIX_NPM_CLI_JS": "C:\\Users\\nhan\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js",
"NUMBER_OF_PROCESSORS": "4",
"OneDrive": "C:\\Users\\nhan\\OneDrive",
"OneDriveConsumer": "C:\\Users\\nhan\\OneDrive",
"OPENSSL_CONF": "C:\\Program Files\\PostgreSQL\\psqlODBC\\etc\\openssl.cnf",
"ORIGINAL_XDG_CURRENT_DESKTOP": "undefined",
"OS": "Windows_NT",
"Path": "C:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\npm-lifecycle\\node-gyp-bin;G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce\\node_modules\\.bin;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Program Files\\Java\\jdk1.8.0_231\\bin;C:\\Program Files\\nodejs\\;C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin;C:\\Program Files\\Git\\cmd;C:\\Program Files\\MongoDB\\Server\\4.2\\bin;;C:\\Program Files\\Git LFS;D:\\hoc-fpt\\code-tren-lop\\php\\xampp3\\php;C:\\ProgramData\\ComposerSetup\\bin;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\AdoptOpenJDK\\jdk8u192-b12\\bin;C:\\Program Files\\Java\\jdk1.8.0_211\\bin;C:\\Android\\android-sdk\\tools;C:\\Android\\android-sdk\\platform-tools;C:\\Android\\android-sdk\\tools\\bin;C:\\Program Files\\MySQL\\MySQL Shell 8.0\\bin\\;C:\\Program Files\\Java\\jdk1.8.0_231\\bin;C:\\Users\\nhan\\AppData\\Local\\Programs\\Microsoft VS Code\\bin;C:\\Users\\nhan\\AppData\\Roaming\\npm;C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin;C:\\Program Files\\heroku\\bin;C:\\Users\\nhan\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\nhan\\AppData\\Roaming\\Composer\\vendor\\bin",
"PATHEXT": ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JSE;.WSF;.WSH;.MSC;.CPL",
"PORT": "3005 ",
"PROCESSOR_ARCHITECTURE": "AMD64",
"PROCESSOR_IDENTIFIER": "Intel64 Family 6 Model 58 Stepping 9, GenuineIntel",
"PROCESSOR_LEVEL": "6",
"PROCESSOR_REVISION": "3a09",
"ProgramData": "C:\\ProgramData",
"ProgramFiles": "C:\\Program Files",
"ProgramFiles(x86)": "C:\\Program Files (x86)",
"ProgramW6432": "C:\\Program Files",
"PROMPT": "$P$G",
"PSModulePath": "C:\\Users\\nhan\\Documents\\WindowsPowerShell\\Modules;C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules",
"PUBLIC": "C:\\Users\\Public",
"SESSIONNAME": "Console",
"SystemDrive": "C:",
"SystemRoot": "C:\\WINDOWS",
"TEMP": "C:\\Users\\nhan\\AppData\\Local\\Temp",
"TERM_PROGRAM": "vscode",
"TERM_PROGRAM_VERSION": "1.60.0",
"TMP": "C:\\Users\\nhan\\AppData\\Local\\Temp",
"TRACE_ID": "69c5adcb5945384d",
"USERDOMAIN": "DESKTOP-TILU55O",
"USERDOMAIN_ROAMINGPROFILE": "DESKTOP-TILU55O",
"USERNAME": "nhan",
"USERPROFILE": "C:\\Users\\nhan",
"VSCODE_GIT_ASKPASS_MAIN": "c:\\Users\\nhan\\AppData\\Local\\Programs\\Microsoft VS Code\\resources\\app\\extensions\\git\\dist\\askpass-main.js",
"VSCODE_GIT_ASKPASS_NODE": "C:\\Users\\nhan\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe",
"VSCODE_GIT_IPC_HANDLE": "\\\\.\\pipe\\vscode-git-d5d8071aa9-sock",
"windir": "C:\\WINDOWS",
"_prog": "node",
"__NEXT_PROCESSED_ENV": "true"
},
"sharedObjects": [
"C:\\Program Files\\nodejs\\node.exe",
"C:\\WINDOWS\\SYSTEM32\\ntdll.dll",
"C:\\WINDOWS\\System32\\KERNEL32.DLL",
"C:\\WINDOWS\\System32\\KERNELBASE.dll",
"C:\\WINDOWS\\System32\\WS2_32.dll",
"C:\\WINDOWS\\System32\\RPCRT4.dll",
"C:\\WINDOWS\\System32\\ADVAPI32.dll",
"C:\\WINDOWS\\System32\\msvcrt.dll",
"C:\\WINDOWS\\System32\\sechost.dll",
"C:\\WINDOWS\\System32\\USER32.dll",
"C:\\WINDOWS\\System32\\win32u.dll",
"C:\\WINDOWS\\System32\\GDI32.dll",
"C:\\WINDOWS\\System32\\gdi32full.dll",
"C:\\WINDOWS\\System32\\msvcp_win.dll",
"C:\\WINDOWS\\System32\\ucrtbase.dll",
"C:\\WINDOWS\\System32\\PSAPI.DLL",
"C:\\WINDOWS\\System32\\CRYPT32.dll",
"C:\\WINDOWS\\System32\\bcrypt.dll",
"C:\\WINDOWS\\SYSTEM32\\dbghelp.dll",
"C:\\WINDOWS\\SYSTEM32\\IPHLPAPI.DLL",
"C:\\WINDOWS\\SYSTEM32\\USERENV.dll",
"C:\\WINDOWS\\SYSTEM32\\WINMM.dll",
"C:\\WINDOWS\\System32\\IMM32.DLL",
"C:\\WINDOWS\\SYSTEM32\\powrprof.dll",
"C:\\WINDOWS\\SYSTEM32\\UMPDC.dll",
"C:\\WINDOWS\\SYSTEM32\\CRYPTBASE.DLL",
"C:\\WINDOWS\\system32\\uxtheme.dll",
"C:\\WINDOWS\\System32\\combase.dll",
"C:\\WINDOWS\\system32\\mswsock.dll",
"C:\\WINDOWS\\SYSTEM32\\kernel.appcore.dll",
"C:\\WINDOWS\\System32\\bcryptprimitives.dll",
"C:\\WINDOWS\\System32\\NSI.dll",
"C:\\WINDOWS\\SYSTEM32\\dhcpcsvc6.DLL",
"C:\\WINDOWS\\SYSTEM32\\dhcpcsvc.DLL",
"C:\\WINDOWS\\SYSTEM32\\DNSAPI.dll",
"C:\\WINDOWS\\system32\\napinsp.dll",
"C:\\WINDOWS\\system32\\pnrpnsp.dll",
"C:\\WINDOWS\\system32\\wshbth.dll",
"C:\\WINDOWS\\system32\\NLAapi.dll",
"C:\\WINDOWS\\System32\\winrnr.dll",
"C:\\Windows\\System32\\rasadhlp.dll",
"C:\\WINDOWS\\System32\\fwpuclnt.dll"
]
}

View File

@@ -0,0 +1,634 @@
{
"header": {
"reportVersion": 1,
"event": "Allocation failed - JavaScript heap out of memory",
"trigger": "FatalError",
"filename": "report.20210909.162411.14356.0.001.json",
"dumpEventTime": "2021-09-09T16:24:11Z",
"dumpEventTimeStamp": "1631179451642",
"processId": 14356,
"cwd": "G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce",
"commandLine": [
"node",
"G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce\\node_modules\\.bin\\\\..\\next\\dist\\bin\\next",
"dev"
],
"nodejsVersion": "v12.15.0",
"wordSize": 64,
"arch": "x64",
"platform": "win32",
"componentVersions": {
"node": "12.15.0",
"v8": "7.7.299.13-node.16",
"uv": "1.33.1",
"zlib": "1.2.11",
"brotli": "1.0.7",
"ares": "1.15.0",
"modules": "72",
"nghttp2": "1.40.0",
"napi": "5",
"llhttp": "2.0.4",
"http_parser": "2.9.3",
"openssl": "1.1.1d",
"cldr": "35.1",
"icu": "64.2",
"tz": "2019c",
"unicode": "12.1"
},
"release": {
"name": "node",
"lts": "Erbium",
"headersUrl": "https://nodejs.org/download/release/v12.15.0/node-v12.15.0-headers.tar.gz",
"sourceUrl": "https://nodejs.org/download/release/v12.15.0/node-v12.15.0.tar.gz",
"libUrl": "https://nodejs.org/download/release/v12.15.0/win-x64/node.lib"
},
"osName": "Windows_NT",
"osRelease": "10.0.19043",
"osVersion": "Windows 10 Pro",
"osMachine": "x86_64",
"cpus": [
{
"model": "Intel(R) Core(TM) i3-3110M CPU @ 2.40GHz",
"speed": 2395,
"user": 77383734,
"nice": 0,
"sys": 38262234,
"idle": 289301562,
"irq": 4023859
},
{
"model": "Intel(R) Core(TM) i3-3110M CPU @ 2.40GHz",
"speed": 2395,
"user": 78754296,
"nice": 0,
"sys": 28849546,
"idle": 297343500,
"irq": 670015
},
{
"model": "Intel(R) Core(TM) i3-3110M CPU @ 2.40GHz",
"speed": 2395,
"user": 87811078,
"nice": 0,
"sys": 29829109,
"idle": 287307140,
"irq": 361687
},
{
"model": "Intel(R) Core(TM) i3-3110M CPU @ 2.40GHz",
"speed": 2395,
"user": 88812562,
"nice": 0,
"sys": 27906453,
"idle": 288228328,
"irq": 299734
}
],
"networkInterfaces": [
{
"name": "Wi-Fi",
"internal": false,
"mac": "a4:17:31:1d:cc:e5",
"address": "2402:800:6318:9d24:f937:34a5:8214:a074",
"netmask": "ffff:ffff:ffff:ffff::",
"family": "IPv6",
"scopeid": 0
},
{
"name": "Wi-Fi",
"internal": false,
"mac": "a4:17:31:1d:cc:e5",
"address": "2402:800:6318:9d24:e935:47df:3dd7:735f",
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
"family": "IPv6",
"scopeid": 0
},
{
"name": "Wi-Fi",
"internal": false,
"mac": "a4:17:31:1d:cc:e5",
"address": "fe80::f937:34a5:8214:a074",
"netmask": "ffff:ffff:ffff:ffff::",
"family": "IPv6",
"scopeid": 21
},
{
"name": "Wi-Fi",
"internal": false,
"mac": "a4:17:31:1d:cc:e5",
"address": "192.168.1.11",
"netmask": "255.255.255.0",
"family": "IPv4"
},
{
"name": "Loopback Pseudo-Interface 1",
"internal": true,
"mac": "00:00:00:00:00:00",
"address": "::1",
"netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
"family": "IPv6",
"scopeid": 0
},
{
"name": "Loopback Pseudo-Interface 1",
"internal": true,
"mac": "00:00:00:00:00:00",
"address": "127.0.0.1",
"netmask": "255.0.0.0",
"family": "IPv4"
}
],
"host": "DESKTOP-TILU55O"
},
"javascriptStack": {
"message": "No stack.",
"stack": [
"Unavailable."
]
},
"nativeStack": [
{
"pc": "0x00007ff7cdbe1759",
"symbol": "std::basic_ostream<char,std::char_traits<char> >::operator<<+10873"
},
{
"pc": "0x00007ff7cdbe5b7c",
"symbol": "std::basic_ostream<char,std::char_traits<char> >::operator<<+28316"
},
{
"pc": "0x00007ff7cdbe4b38",
"symbol": "std::basic_ostream<char,std::char_traits<char> >::operator<<+24152"
},
{
"pc": "0x00007ff7cdcd446b",
"symbol": "v8::base::CPU::has_sse+37723"
},
{
"pc": "0x00007ff7ce4d8d9e",
"symbol": "v8::Isolate::ReportExternalAllocationLimitReached+94"
},
{
"pc": "0x00007ff7ce4c0de1",
"symbol": "v8::SharedArrayBuffer::Externalize+833"
},
{
"pc": "0x00007ff7ce38e6ac",
"symbol": "v8::internal::Heap::EphemeronKeyWriteBarrierFromCode+1436"
},
{
"pc": "0x00007ff7ce399a50",
"symbol": "v8::internal::Heap::ProtectUnprotectedMemoryChunks+1312"
},
{
"pc": "0x00007ff7ce396584",
"symbol": "v8::internal::Heap::PageFlagsAreConsistent+3204"
},
{
"pc": "0x00007ff7ce38be13",
"symbol": "v8::internal::Heap::CollectGarbage+1283"
},
{
"pc": "0x00007ff7ce38a5e4",
"symbol": "v8::internal::Heap::AddRetainedMap+2356"
},
{
"pc": "0x00007ff7ce3ab8b5",
"symbol": "v8::internal::Factory::NewFillerObject+53"
},
{
"pc": "0x00007ff7ce117b89",
"symbol": "v8::internal::interpreter::JumpTableTargetOffsets::iterator::operator=+4057"
},
{
"pc": "0x00007ff7ce904d3d",
"symbol": "v8::internal::SetupIsolateDelegate::SetupHeap+567949"
},
{
"pc": "0x000003ec3249fceb",
"symbol": ""
}
],
"javascriptHeap": {
"totalMemory": 2151399424,
"totalCommittedMemory": 2151399424,
"usedMemory": 2073679128,
"availableMemory": 51804896,
"memoryLimit": 2197815296,
"heapSpaces": {
"read_only_space": {
"memorySize": 262144,
"committedMemory": 262144,
"capacity": 261872,
"used": 32296,
"available": 229576
},
"new_space": {
"memorySize": 2097152,
"committedMemory": 2097152,
"capacity": 1047488,
"used": 97208,
"available": 950280
},
"old_space": {
"memorySize": 1644802048,
"committedMemory": 1644802048,
"capacity": 1577839984,
"used": 1574678304,
"available": 3161680
},
"code_space": {
"memorySize": 5144576,
"committedMemory": 5144576,
"capacity": 4272640,
"used": 4272640,
"available": 0
},
"map_space": {
"memorySize": 8130560,
"committedMemory": 8130560,
"capacity": 4150160,
"used": 4150160,
"available": 0
},
"large_object_space": {
"memorySize": 489766912,
"committedMemory": 489766912,
"capacity": 489351272,
"used": 489351272,
"available": 0
},
"code_large_object_space": {
"memorySize": 1196032,
"committedMemory": 1196032,
"capacity": 1097248,
"used": 1097248,
"available": 0
},
"new_large_object_space": {
"memorySize": 0,
"committedMemory": 0,
"capacity": 1047488,
"used": 0,
"available": 1047488
}
}
},
"resourceUsage": {
"userCpuSeconds": 3948.5,
"kernelCpuSeconds": 161.609,
"cpuConsumptionPercent": 15.0548,
"maxRss": 3016343552,
"pageFaults": {
"IORequired": 18788222,
"IONotRequired": 0
},
"fsActivity": {
"reads": 42626,
"writes": 632648
}
},
"libuv": [
],
"environmentVariables": {
"=G:": "G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce",
"ALLUSERSPROFILE": "C:\\ProgramData",
"ANDROID_HOME": "G:\\ASDK",
"ANDROID_SDK_ROOT": "G:\\ASDK",
"APPDATA": "C:\\Users\\nhan\\AppData\\Roaming",
"ChocolateyInstall": "C:\\ProgramData\\chocolatey",
"ChocolateyLastPathUpdate": "132608575831335062",
"CHROME_CRASHPAD_PIPE_NAME": "\\\\.\\pipe\\crashpad_16216_SBAEYTWYVPQDZSNO",
"CLASSPATH": "C:\\Program Files\\Java\\jdk1.8.0_231\\bin",
"COLORTERM": "truecolor",
"COMMERCE_CUSTOMERAUTH_ENABLED": "true",
"COMMERCE_PROVIDER": "vendure",
"CommonProgramFiles": "C:\\Program Files\\Common Files",
"CommonProgramFiles(x86)": "C:\\Program Files (x86)\\Common Files",
"CommonProgramW6432": "C:\\Program Files\\Common Files",
"COMPUTERNAME": "DESKTOP-TILU55O",
"ComSpec": "C:\\WINDOWS\\system32\\cmd.exe",
"dp0": "G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce\\node_modules\\.bin\\",
"DriverData": "C:\\Windows\\System32\\Drivers\\DriverData",
"FPS_BROWSER_APP_PROFILE_STRING": "Internet Explorer",
"FPS_BROWSER_USER_PROFILE_STRING": "Default",
"GIT_ASKPASS": "c:\\Users\\nhan\\AppData\\Local\\Programs\\Microsoft VS Code\\resources\\app\\extensions\\git\\dist\\askpass.sh",
"GIT_LFS_PATH": "C:\\Program Files\\Git LFS",
"HOME": "C:\\Users\\nhan",
"HOMEDRIVE": "C:",
"HOMEPATH": "\\Users\\nhan",
"INIT_CWD": "G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce",
"JAVA_HOME": "C:\\Program Files\\Java\\jdk1.8.0_281",
"LANG": "en_US.UTF-8",
"LOCALAPPDATA": "C:\\Users\\nhan\\AppData\\Local",
"LOGONSERVER": "\\\\DESKTOP-TILU55O",
"NEXT_PUBLIC_VENDURE_LOCAL_URL": "/vendure-shop-api",
"NEXT_PUBLIC_VENDURE_SHOP_API_URL": "https://demo.vendure.io/shop-api",
"NODE": "C:\\Program Files\\nodejs\\node.exe",
"NODE_ENV": "development",
"NODE_EXE": "C:\\Program Files\\nodejs\\\\node.exe",
"NODE_OPTIONS": "'--inspect' ",
"NPM_CLI_JS": "C:\\Program Files\\nodejs\\\\node_modules\\npm\\bin\\npm-cli.js",
"npm_config_access": "",
"npm_config_allow_same_version": "",
"npm_config_also": "",
"npm_config_always_auth": "",
"npm_config_argv": "{\"remain\":[],\"cooked\":[\"run\",\"dev-windows\"],\"original\":[\"run\",\"dev-windows\"]}",
"npm_config_audit": "true",
"npm_config_audit_level": "low",
"npm_config_auth_type": "legacy",
"npm_config_before": "",
"npm_config_bin_links": "true",
"npm_config_browser": "",
"npm_config_ca": "",
"npm_config_cache": "C:\\Users\\nhan\\AppData\\Roaming\\npm-cache",
"npm_config_cache_lock_retries": "10",
"npm_config_cache_lock_stale": "60000",
"npm_config_cache_lock_wait": "10000",
"npm_config_cache_max": "Infinity",
"npm_config_cache_min": "10",
"npm_config_cafile": "",
"npm_config_cert": "",
"npm_config_cidr": "",
"npm_config_color": "true",
"npm_config_commit_hooks": "true",
"npm_config_depth": "Infinity",
"npm_config_description": "true",
"npm_config_dev": "",
"npm_config_dry_run": "",
"npm_config_editor": "notepad.exe",
"npm_config_engine_strict": "",
"npm_config_fetch_retries": "2",
"npm_config_fetch_retry_factor": "10",
"npm_config_fetch_retry_maxtimeout": "60000",
"npm_config_fetch_retry_mintimeout": "10000",
"npm_config_force": "",
"npm_config_format_package_lock": "true",
"npm_config_fund": "true",
"npm_config_git": "git",
"npm_config_git_tag_version": "true",
"npm_config_global": "",
"npm_config_globalconfig": "C:\\Users\\nhan\\AppData\\Roaming\\npm\\etc\\npmrc",
"npm_config_globalignorefile": "C:\\Users\\nhan\\AppData\\Roaming\\npm\\etc\\npmignore",
"npm_config_global_style": "",
"npm_config_group": "",
"npm_config_ham_it_up": "",
"npm_config_heading": "npm",
"npm_config_https_proxy": "",
"npm_config_if_present": "",
"npm_config_ignore_prepublish": "",
"npm_config_ignore_scripts": "",
"npm_config_init_author_email": "",
"npm_config_init_author_name": "",
"npm_config_init_author_url": "",
"npm_config_init_license": "ISC",
"npm_config_init_module": "C:\\Users\\nhan\\.npm-init.js",
"npm_config_init_version": "1.0.0",
"npm_config_json": "",
"npm_config_key": "",
"npm_config_legacy_bundling": "",
"npm_config_link": "",
"npm_config_local_address": "",
"npm_config_loglevel": "notice",
"npm_config_logs_max": "10",
"npm_config_long": "",
"npm_config_maxsockets": "50",
"npm_config_message": "%s",
"npm_config_metrics_registry": "https://registry.npmjs.org/",
"npm_config_node_gyp": "C:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js",
"npm_config_node_options": "",
"npm_config_node_version": "12.15.0",
"npm_config_noproxy": "",
"npm_config_offline": "",
"npm_config_onload_script": "",
"npm_config_only": "",
"npm_config_optional": "true",
"npm_config_otp": "",
"npm_config_package_lock": "true",
"npm_config_package_lock_only": "",
"npm_config_parseable": "",
"npm_config_prefer_offline": "",
"npm_config_prefer_online": "",
"npm_config_prefix": "C:\\Users\\nhan\\AppData\\Roaming\\npm",
"npm_config_preid": "",
"npm_config_production": "",
"npm_config_progress": "true",
"npm_config_proxy": "",
"npm_config_read_only": "",
"npm_config_rebuild_bundle": "true",
"npm_config_registry": "https://registry.npmjs.org/",
"npm_config_rollback": "true",
"npm_config_save": "true",
"npm_config_save_bundle": "",
"npm_config_save_dev": "",
"npm_config_save_exact": "",
"npm_config_save_optional": "",
"npm_config_save_prefix": "^",
"npm_config_save_prod": "",
"npm_config_scope": "",
"npm_config_scripts_prepend_node_path": "warn-only",
"npm_config_script_shell": "",
"npm_config_searchexclude": "",
"npm_config_searchlimit": "20",
"npm_config_searchopts": "",
"npm_config_searchstaleness": "900",
"npm_config_send_metrics": "",
"npm_config_shell": "C:\\WINDOWS\\system32\\cmd.exe",
"npm_config_shrinkwrap": "true",
"npm_config_sign_git_commit": "",
"npm_config_sign_git_tag": "",
"npm_config_sso_poll_frequency": "500",
"npm_config_sso_type": "oauth",
"npm_config_strict_ssl": "true",
"npm_config_tag": "latest",
"npm_config_tag_version_prefix": "v",
"npm_config_timing": "",
"npm_config_tmp": "C:\\Users\\nhan\\AppData\\Local\\Temp",
"npm_config_umask": "0000",
"npm_config_unicode": "",
"npm_config_unsafe_perm": "true",
"npm_config_update_notifier": "true",
"npm_config_usage": "",
"npm_config_user": "",
"npm_config_userconfig": "C:\\Users\\nhan\\.npmrc",
"npm_config_user_agent": "npm/6.13.4 node/v12.15.0 win32 x64",
"npm_config_version": "",
"npm_config_versions": "",
"npm_config_viewer": "browser",
"npm_execpath": "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js",
"npm_lifecycle_event": "dev-windows",
"npm_lifecycle_script": "set NODE_OPTIONS='--inspect' && set PORT=3005 && next dev",
"npm_node_execpath": "C:\\Program Files\\nodejs\\node.exe",
"npm_package_dependencies_autoprefixer": "^10.2.6",
"npm_package_dependencies_body_scroll_lock": "^3.1.5",
"npm_package_dependencies_classnames": "^2.3.1",
"npm_package_dependencies_cookie": "^0.4.1",
"npm_package_dependencies_email_validator": "^2.0.4",
"npm_package_dependencies_eslint": "^7.32.0",
"npm_package_dependencies_eslint_config_next": "^11.1.2",
"npm_package_dependencies_immutability_helper": "^3.1.1",
"npm_package_dependencies_js_cookie": "^2.2.1",
"npm_package_dependencies_keen_slider": "^5.5.1",
"npm_package_dependencies_lodash_debounce": "^4.0.8",
"npm_package_dependencies_lodash_random": "^3.2.0",
"npm_package_dependencies_lodash_throttle": "^4.1.1",
"npm_package_dependencies_next": "^11.0.0",
"npm_package_dependencies_next_seo": "^4.26.0",
"npm_package_dependencies_next_themes": "^0.0.14",
"npm_package_dependencies_postcss": "^8.3.5",
"npm_package_dependencies_postcss_nesting": "^8.0.1",
"npm_package_dependencies_react": "^17.0.2",
"npm_package_dependencies_react_dom": "^17.0.2",
"npm_package_dependencies_react_fast_marquee": "^1.1.4",
"npm_package_dependencies_react_merge_refs": "^1.1.0",
"npm_package_dependencies_react_player": "^2.9.0",
"npm_package_dependencies_react_use_measure": "^2.0.4",
"npm_package_dependencies_sass": "^1.38.0",
"npm_package_dependencies_swell_js": "^4.0.0-next.0",
"npm_package_dependencies_swr": "^0.5.6",
"npm_package_dependencies_tabbable": "^5.2.0",
"npm_package_dependencies_tailwindcss": "^2.2.2",
"npm_package_dependencies_uuidv4": "^6.2.10",
"npm_package_dependencies__react_spring_web": "^9.2.1",
"npm_package_dependencies__vercel_fetch": "^6.1.0",
"npm_package_description": "[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fcommerce&project-name=commerce&repo-name=commerce&demo-title=Next.js%20Commerce&demo-description=An%20all-in-one%20starter%20kit%20for%20high-performance%20e-commerce%20sites.&demo-url=https%3A%2F%2Fdemo.vercel.store&demo-image=https%3A%2F%2Fbigcommerce-demo-asset-ksvtgfvnd.vercel.app%2Fbigcommerce.png&integration-ids=oac_MuWZiE4jtmQ2ejZQaQ7ncuDT)",
"npm_package_devDependencies_deepmerge": "^4.2.2",
"npm_package_devDependencies_eslint_config_prettier": "^8.3.0",
"npm_package_devDependencies_graphql": "^15.5.1",
"npm_package_devDependencies_husky": "^6.0.0",
"npm_package_devDependencies_lint_staged": "^11.0.0",
"npm_package_devDependencies_postcss_flexbugs_fixes": "^5.0.2",
"npm_package_devDependencies_postcss_import": "^14.0.2",
"npm_package_devDependencies_postcss_preset_env": "^6.7.0",
"npm_package_devDependencies_prettier": "^2.3.0",
"npm_package_devDependencies_typescript": "4.3.4",
"npm_package_devDependencies__graphql_codegen_cli": "^1.21.5",
"npm_package_devDependencies__graphql_codegen_schema_ast": "^1.18.3",
"npm_package_devDependencies__graphql_codegen_typescript": "^1.22.2",
"npm_package_devDependencies__graphql_codegen_typescript_operations": "^1.18.1",
"npm_package_devDependencies__next_bundle_analyzer": "^10.2.3",
"npm_package_devDependencies__types_body_scroll_lock": "^2.6.1",
"npm_package_devDependencies__types_cookie": "^0.4.0",
"npm_package_devDependencies__types_js_cookie": "^2.2.6",
"npm_package_devDependencies__types_lodash_debounce": "^4.0.6",
"npm_package_devDependencies__types_lodash_random": "^3.2.6",
"npm_package_devDependencies__types_lodash_throttle": "^4.1.6",
"npm_package_devDependencies__types_node": "^15.12.4",
"npm_package_devDependencies__types_react": "^17.0.8",
"npm_package_engines_node": ">=14.x",
"npm_package_gitHead": "d6a0c41e9987f3d0af8a69c4404152e0ddc1345f",
"npm_package_license": "MIT",
"npm_package_lint_staged_______js_jsx_ts_tsx__0": "prettier --write",
"npm_package_lint_staged_______js_jsx_ts_tsx__1": "git add",
"npm_package_lint_staged_______md_mdx_json__0": "prettier --write",
"npm_package_lint_staged_______md_mdx_json__1": "git add",
"npm_package_name": "nextjs-commerce",
"npm_package_next_unused_alias__assets___0": "assets/*",
"npm_package_next_unused_alias__components___0": "components/*",
"npm_package_next_unused_alias__config___0": "config/*",
"npm_package_next_unused_alias__lib___0": "lib/*",
"npm_package_next_unused_alias__utils___0": "utils/*",
"npm_package_next_unused_debug": "true",
"npm_package_next_unused_entrypoints_0": "pages",
"npm_package_next_unused_include_0": "components",
"npm_package_next_unused_include_1": "lib",
"npm_package_next_unused_include_2": "pages",
"npm_package_readmeFilename": "README.md",
"npm_package_scripts_analyze": "BUNDLE_ANALYZE=both yarn build",
"npm_package_scripts_build": "next build",
"npm_package_scripts_dev": "NODE_OPTIONS='--inspect' PORT=3005 next dev",
"npm_package_scripts_dev_windows": "set NODE_OPTIONS='--inspect' && set PORT=3005 && next dev",
"npm_package_scripts_find_unused": "npx next-unused",
"npm_package_scripts_generate": "graphql-codegen",
"npm_package_scripts_generate_definitions": "node framework/bigcommerce/scripts/generate-definitions.js",
"npm_package_scripts_generate_shopify": "DOTENV_CONFIG_PATH=./.env.local graphql-codegen -r dotenv/config --config framework/shopify/codegen.json",
"npm_package_scripts_generate_vendure": "graphql-codegen --config framework/vendure/codegen.json",
"npm_package_scripts_prettier_fix": "prettier --write .",
"npm_package_scripts_start": "next start",
"npm_package_sideEffects": "false",
"npm_package_version": "1.0.0",
"NPM_PREFIX_NPM_CLI_JS": "C:\\Users\\nhan\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js",
"NUMBER_OF_PROCESSORS": "4",
"OneDrive": "C:\\Users\\nhan\\OneDrive",
"OneDriveConsumer": "C:\\Users\\nhan\\OneDrive",
"OPENSSL_CONF": "C:\\Program Files\\PostgreSQL\\psqlODBC\\etc\\openssl.cnf",
"ORIGINAL_XDG_CURRENT_DESKTOP": "undefined",
"OS": "Windows_NT",
"Path": "C:\\Program Files\\nodejs\\node_modules\\npm\\node_modules\\npm-lifecycle\\node-gyp-bin;G:\\hoc-fpt-2\\làm việc\\kie\\work\\grocery-vercel-commerce\\node_modules\\.bin;C:\\Program Files (x86)\\Common Files\\Oracle\\Java\\javapath;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Program Files\\Java\\jdk1.8.0_231\\bin;C:\\Program Files\\nodejs\\;C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin;C:\\Program Files\\Git\\cmd;C:\\Program Files\\MongoDB\\Server\\4.2\\bin;;C:\\Program Files\\Git LFS;D:\\hoc-fpt\\code-tren-lop\\php\\xampp3\\php;C:\\ProgramData\\ComposerSetup\\bin;C:\\ProgramData\\chocolatey\\bin;C:\\Program Files\\AdoptOpenJDK\\jdk8u192-b12\\bin;C:\\Program Files\\Java\\jdk1.8.0_211\\bin;C:\\Android\\android-sdk\\tools;C:\\Android\\android-sdk\\platform-tools;C:\\Android\\android-sdk\\tools\\bin;C:\\Program Files\\MySQL\\MySQL Shell 8.0\\bin\\;C:\\Program Files\\Java\\jdk1.8.0_231\\bin;C:\\Users\\nhan\\AppData\\Local\\Programs\\Microsoft VS Code\\bin;C:\\Users\\nhan\\AppData\\Roaming\\npm;C:\\Program Files\\MySQL\\MySQL Server 8.0\\bin;C:\\Program Files\\heroku\\bin;C:\\Users\\nhan\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\nhan\\AppData\\Roaming\\Composer\\vendor\\bin",
"PATHEXT": ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JSE;.WSF;.WSH;.MSC;.CPL",
"PORT": "3005 ",
"PROCESSOR_ARCHITECTURE": "AMD64",
"PROCESSOR_IDENTIFIER": "Intel64 Family 6 Model 58 Stepping 9, GenuineIntel",
"PROCESSOR_LEVEL": "6",
"PROCESSOR_REVISION": "3a09",
"ProgramData": "C:\\ProgramData",
"ProgramFiles": "C:\\Program Files",
"ProgramFiles(x86)": "C:\\Program Files (x86)",
"ProgramW6432": "C:\\Program Files",
"PROMPT": "$P$G",
"PSModulePath": "C:\\Users\\nhan\\Documents\\WindowsPowerShell\\Modules;C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules",
"PUBLIC": "C:\\Users\\Public",
"SESSIONNAME": "Console",
"SystemDrive": "C:",
"SystemRoot": "C:\\WINDOWS",
"TEMP": "C:\\Users\\nhan\\AppData\\Local\\Temp",
"TERM_PROGRAM": "vscode",
"TERM_PROGRAM_VERSION": "1.60.0",
"TMP": "C:\\Users\\nhan\\AppData\\Local\\Temp",
"TRACE_ID": "9bcaa92ba218c9e0",
"USERDOMAIN": "DESKTOP-TILU55O",
"USERDOMAIN_ROAMINGPROFILE": "DESKTOP-TILU55O",
"USERNAME": "nhan",
"USERPROFILE": "C:\\Users\\nhan",
"VSCODE_GIT_ASKPASS_MAIN": "c:\\Users\\nhan\\AppData\\Local\\Programs\\Microsoft VS Code\\resources\\app\\extensions\\git\\dist\\askpass-main.js",
"VSCODE_GIT_ASKPASS_NODE": "C:\\Users\\nhan\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe",
"VSCODE_GIT_IPC_HANDLE": "\\\\.\\pipe\\vscode-git-d5d8071aa9-sock",
"windir": "C:\\WINDOWS",
"_prog": "node",
"__NEXT_PROCESSED_ENV": "true"
},
"sharedObjects": [
"C:\\Program Files\\nodejs\\node.exe",
"C:\\WINDOWS\\SYSTEM32\\ntdll.dll",
"C:\\WINDOWS\\System32\\KERNEL32.DLL",
"C:\\WINDOWS\\System32\\KERNELBASE.dll",
"C:\\WINDOWS\\System32\\WS2_32.dll",
"C:\\WINDOWS\\System32\\RPCRT4.dll",
"C:\\WINDOWS\\System32\\ADVAPI32.dll",
"C:\\WINDOWS\\System32\\msvcrt.dll",
"C:\\WINDOWS\\System32\\sechost.dll",
"C:\\WINDOWS\\System32\\USER32.dll",
"C:\\WINDOWS\\System32\\win32u.dll",
"C:\\WINDOWS\\System32\\GDI32.dll",
"C:\\WINDOWS\\System32\\gdi32full.dll",
"C:\\WINDOWS\\System32\\msvcp_win.dll",
"C:\\WINDOWS\\System32\\ucrtbase.dll",
"C:\\WINDOWS\\System32\\PSAPI.DLL",
"C:\\WINDOWS\\System32\\CRYPT32.dll",
"C:\\WINDOWS\\System32\\bcrypt.dll",
"C:\\WINDOWS\\SYSTEM32\\dbghelp.dll",
"C:\\WINDOWS\\SYSTEM32\\IPHLPAPI.DLL",
"C:\\WINDOWS\\SYSTEM32\\USERENV.dll",
"C:\\WINDOWS\\SYSTEM32\\WINMM.dll",
"C:\\WINDOWS\\System32\\IMM32.DLL",
"C:\\WINDOWS\\SYSTEM32\\powrprof.dll",
"C:\\WINDOWS\\SYSTEM32\\UMPDC.dll",
"C:\\WINDOWS\\SYSTEM32\\CRYPTBASE.DLL",
"C:\\WINDOWS\\system32\\uxtheme.dll",
"C:\\WINDOWS\\System32\\combase.dll",
"C:\\WINDOWS\\system32\\mswsock.dll",
"C:\\WINDOWS\\SYSTEM32\\kernel.appcore.dll",
"C:\\WINDOWS\\System32\\bcryptprimitives.dll",
"C:\\WINDOWS\\System32\\NSI.dll",
"C:\\WINDOWS\\SYSTEM32\\dhcpcsvc6.DLL",
"C:\\WINDOWS\\SYSTEM32\\dhcpcsvc.DLL",
"C:\\WINDOWS\\SYSTEM32\\DNSAPI.dll",
"C:\\WINDOWS\\system32\\napinsp.dll",
"C:\\WINDOWS\\system32\\pnrpnsp.dll",
"C:\\WINDOWS\\system32\\wshbth.dll",
"C:\\WINDOWS\\system32\\NLAapi.dll",
"C:\\WINDOWS\\System32\\winrnr.dll",
"C:\\Windows\\System32\\rasadhlp.dll",
"C:\\WINDOWS\\System32\\fwpuclnt.dll"
]
}

View File

@@ -1,3 +1,4 @@
@import '../../../styles/utilities';
.authorWarper{
@apply flex flex-row items-center;

View File

@@ -2,9 +2,8 @@ import React from 'react';
import s from './Author.module.scss';
import classNames from 'classnames';
import Image from "next/image";
interface Props {
image:any,
image:string,
name: string
}
@@ -12,7 +11,7 @@ const Author = ({image,name}:Props) =>{
return (
<div className={classNames(s.authorWarper)}>
<Image className={classNames(s.authorImage)} src={image} alt=""/>
<img className={classNames(s.authorImage)} src={image} alt=""/>
<div className={classNames(s.authorName)}>{name}</div>
</div>
)

View File

@@ -1,6 +1,7 @@
import React from 'react'
import { ROUTE } from 'src/utils/constanst.utils'
import s from './BreadcrumbCommon.module.scss'
import BreadcrumbItem from './components/BreadcrumbItem/BreadcrumbItem'
import BreadcrumbSeparator from './components/BreadcrumbSeparator/BreadcrumbSeparator'

View File

@@ -1,7 +1,7 @@
import React from 'react'
interface BreadcrumbSeparatorProps {
children?: React.ReactNode
children?: React.ReactNode;
}
const BreadcrumbSeparator = ({ children }: BreadcrumbSeparatorProps) => {

View File

@@ -0,0 +1,36 @@
@import "../../../styles/utilities";
.cardBlogWarpper {
@apply inline-flex flex-col justify-start;
max-width: 39.2rem;
.image {
width: 100%;
max-height: 22rem;
border-radius: 2.4rem;
&:hover {
cursor: pointer;
}
img{
border-radius: 2.4rem;
}
}
.title {
padding: 1.6rem 0.8rem 0.4rem 0.8rem;
@apply font-bold;
font-size: 2rem;
line-height: 2.8rem;
letter-spacing: -0.01em;
color: var(--text-active);
&:hover {
cursor: pointer;
}
}
.description {
padding: 0 0.8rem;
@apply overflow-hidden overflow-ellipsis ;
color: var(--text-label);
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
}

View File

@@ -0,0 +1,31 @@
import Link from 'next/link'
import React from 'react'
import { ROUTE } from 'src/utils/constanst.utils'
import { BlogProps } from 'src/utils/types.utils'
import s from './CardBlog.module.scss'
export interface BlogCardProps extends BlogProps {
// todo: edit when intergrate API
}
const CardBlog = ({ imageSrc, title, description, slug }: BlogCardProps) => {
return (
<div className={s.cardBlogWarpper}>
<Link href={`${ROUTE.BLOG_DETAIL}/${slug}`}>
<a>
<div className={s.image}>
<img src={imageSrc} alt="image cardblog" />
</div>
</a>
</Link>
<Link href={`${ROUTE.BLOG_DETAIL}/${slug}`}>
<a>
<div className={s.title}>{title}</div>
</a>
</Link>
<div className={s.description}>{description}</div>
</div>
)
}
export default CardBlog

View File

@@ -0,0 +1,31 @@
.warpper{
max-height: 12rem;
padding:1.6rem 0;
@apply flex items-center;
@screen lg {
max-width: 49.9rem;
}
.image{
width: 13.3rem;
height: 8.8rem;
margin: 0.8rem;
@apply flex justify-center items-center;
img{
max-width: 100%;
max-height: 100%;
}
}
.right{
width: 100%;
.name{
color: var(--text-active);
margin-bottom: 0.5erm;
}
.quantity {
@apply flex justify-between text-label;
.price{
color: var(--text-base);
}
}
}
}

View File

@@ -0,0 +1,29 @@
import React from 'react'
import s from "./CardItemCheckout.module.scss"
import { ProductProps } from 'src/utils/types.utils'
export interface CardItemCheckoutProps extends ProductProps {
quantity:number
}
const CardItemCheckout = ({imageSrc,name,price,weight,quantity,category}: CardItemCheckoutProps) => {
return (
<div className={s.warpper}>
<div className={s.image}>
<img src={imageSrc} alt="image" />
</div>
<div className={s.right}>
<div className={s.name}>
{`${name} (${weight})`}
</div>
<div className={s.quantity}>
Quantity:
<div className={s.price}>
{`${quantity} x ${price}`}
</div>
</div>
</div>
</div>
)
}
export default CardItemCheckout

View File

@@ -28,7 +28,6 @@ const CarouselCommon = <T,>({
option: { slideChanged,slidesPerView, ...sliderOption },
}: CarouselCommonProps<T>) => {
const [currentSlide, setCurrentSlide] = React.useState(0)
// const [dotActive, setDotActive] = React.useState<number>(0)
const [dotArr, setDotArr] = React.useState<number[]>([])
const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({
...sliderOption,

View File

@@ -8,9 +8,10 @@ interface CheckboxProps extends Omit<
>{
onChange?: (value: boolean) => void,
defaultChecked?: boolean
text?:string
}
const CheckboxCommon = ({onChange,defaultChecked = true,...props}: CheckboxProps) =>{
const CheckboxCommon = ({onChange,defaultChecked = true,text="Billing address is same as shipping", ...props}: CheckboxProps) =>{
const [value, setValue] = useState<boolean>(true);
@@ -31,7 +32,7 @@ const CheckboxCommon = ({onChange,defaultChecked = true,...props}: CheckboxProps
<span className={s.checkMark}></span>
</label>
<div className={classNames(s.checkboxText)}>
<label htmlFor="check"> Billing address is same as shipping </label>
<label htmlFor="check"> {text} </label>
</div>
</div>
)

View File

@@ -0,0 +1,51 @@
.warpper{
padding: 2.4rem 0;
@apply border-b border-solid border-line;
.note{
font-size: 1.2rem;
line-height: 2rem;
letter-spacing: 0.01em;
color: var(--text-label);
padding: 0 5.6rem;
}
.header{
@apply flex justify-between;
.left{
@apply flex items-center;
.number{
width: 3.2rem;
height: 3.2rem;
border-radius: 100%;
border: 1px solid var(--text-active);
color: var(--text-active);
@apply flex justify-center items-center font-bold;
&.visible{
background-color: var(--text-active);
border: none;
color: var(--white);
}
&.done{
@apply border-2 border-solid border-primary;
}
}
.title{
padding-left: 2.4rem;
@apply font-bold select-none cursor-pointer;
color: var(--text-active);
}
}
.edit{
@apply font-bold cursor-pointer;
text-decoration-line: underline;
margin-right: 5.6rem;
}
}
.body{
height: 0;
@apply overflow-hidden;
&.show{
margin-top: 3.2rem;
height: initial;
}
}
}

View File

@@ -0,0 +1,59 @@
import classNames from 'classnames'
import { divide } from 'lodash'
import React from 'react'
import { IconDoneCheckout } from 'src/components/icons'
import { CheckOutForm } from 'src/utils/types.utils'
import s from './CheckoutCollapse.module.scss'
interface CheckoutCollapseProps {
visible: boolean
id: number
children: React.ReactNode
title: string
isEdit: boolean
onClose?: (id:number) => void
onOpen?: (id:number) => void
onEditClick?:(id:number) => void
note?:string
}
const CheckoutCollapse = ({
children,
id,
title,
isEdit,
visible,
note,
onOpen,
onClose,
onEditClick
}: CheckoutCollapseProps) => {
const handleTitleClick = () => {
if(visible){
onClose && onClose(id)
}else{
onOpen && onOpen(id)
}
}
const handleEdit = () => {
onEditClick && onEditClick(id)
}
return (
<div className={s.warpper}>
<div className={s.header}>
<div className={s.left}>
<div className={classNames(s.number, { [s.visible]: visible, [s.done]:isEdit })}>
{isEdit?<IconDoneCheckout/>:id}
</div>
<div className={s.title} onClick={handleTitleClick}>
{title}
</div>
</div>
{isEdit && <div className={s.edit} onClick={handleEdit}>{'Edit'}</div>}
</div>
{(!visible && isEdit) && (<div className={s.note}>{note}</div>) }
<div className={classNames(s.body, { [`${s.show}`]: visible })}>{children}</div>
</div>
)
}
export default CheckoutCollapse

View File

@@ -0,0 +1,67 @@
@import "../../../../styles/utilities";
.collapseWrapper {
@apply border-t border-b;
border-color: var(--border-line);
max-width: 80.4rem;
min-height: 4rem;
&.isActive {
.title {
@apply pb-0;
}
.contentContainer {
@apply block;
animation: ContentAnimationIn 0.5s ease-out;
}
.toggle {
&:before {
transform: rotate(180deg);
}
&:after {
transform: rotate(180deg);
}
}
}
&:hover {
cursor: pointer;
}
}
.title {
@apply outline-none flex justify-between font-heading items-center pt-16 pb-16;
font-size: 3.2rem;
line-height: 4rem;
letter-spacing: -0.01em;
.toggle {
height: 2.2rem;
width: 2.2rem;
position: relative;
&:before,
&:after {
@apply absolute h-2;
content: "";
border-radius: 0.8rem;
background: var(--text-active);
top: 40%;
width: 2.2rem;
transition: transform 500ms ease;
}
&:before {
transform-origin: center;
transform: rotate(90deg);
}
}
}
.contentContainer {
@apply hidden pb-16 whitespace-pre-line;
padding-top: 1.6rem;
}
@keyframes ContentAnimationIn {
0% {
opacity: 0;
transform: translateY(-1.6rem);
}
100% {
opacity: 1;
transform: none;
}
}

View File

@@ -0,0 +1,34 @@
import s from './CollapseChild.module.scss'
import { useState } from 'react'
import classNames from 'classnames'
interface CollapseProps{
title?: string,
content: string,
isToggle?: boolean,
}
const CollapseChild = ({title, content, isToggle=false}: CollapseProps) => {
const [isActive, changeActive] = useState(isToggle)
const handleToggle = () => {
changeActive(!isActive)
}
return(
<div className={classNames({
[s.collapseWrapper] : true,
[s.isActive] : isActive
})}
onClick = { handleToggle }
>
<div className={s.title}>
<h4>{title}</h4>
<div className={s.toggle}></div>
</div>
<div className={s.contentContainer}>
{content}
</div>
</div>
)
}
export default CollapseChild

View File

@@ -0,0 +1,19 @@
import CollapseChild from './CollapseChild/CollapseChild'
interface CollapseCommonProps{
data: {title: string, content: string}[],
}
const CollapseCommon = ({data}: CollapseCommonProps) => {
return (
<section>
{
data.map((item,index) =>
<CollapseChild key={`${item.title}-${index}`} title={item.title} content={item.content} />
)
}
</section>
)
}
export default CollapseCommon

View File

@@ -0,0 +1,21 @@
const CustomShapeSvg = () => {
return (
<>
<svg width="0" height="0" viewBox="0 0 1 1" fill="none" xmlns="http://www.w3.org/2000/svg">
<clipPath id="svg-custom-shape" clipPathUnits="objectBoundingBox">
<path
d="M0.0172975 0.136181C0.0343229 -0.030626 0.360144 0.00272041 0.510753 0.00272041C0.640763 0.00272041 0.779987 0.0273237 0.944182 0.0678791C0.966966 0.0735065 0.986 0.126214 0.990073 0.19938C0.994835 0.284918 1 0.404512 1 0.520863C1 0.736726 0.993726 0.834689 0.982222 0.886228C0.943784 1.05844 0.733836 0.983992 0.493833 0.983992C0.30975 0.983992 0.127708 0.957276 0.052872 0.944826C0.0312385 0.941228 0.0126875 0.895116 0.00839312 0.826023C0.00415553 0.757843 0 0.662594 0 0.551233C0 0.345672 0.000272106 0.302988 0.0172975 0.136181Z"
fill="#B5B5B5" />
</clipPath>
</svg>
<svg width="0" height="0" viewBox="0 0 1 1" fill="none" xmlns="http://www.w3.org/2000/svg">
<clipPath id="svg-custom-shape-lg" clipPathUnits="objectBoundingBox">
<path d="M0.00309475 0.648049L0.016817 0.981984H0.165017L0.368106 0.987044C0.428484 0.985357 0.660022 0.997877 0.750058 0.998542C0.845065 0.999243 0.83562 1.00172 0.881179 0.998007C0.938818 0.993313 0.955418 0.966805 0.96914 0.941507C0.982862 0.916209 0.99209 0.790258 0.99384 0.76948C0.995632 0.748196 1.00207 0.572154 0.999329 0.425425C0.996584 0.278696 0.977373 0.0408933 0.96914 0.0257144C0.960907 0.0105355 0.546495 0.000416471 0.532773 0.000416471C0.519051 0.000416471 0.329256 -0.00466047 0.156356 0.0206377C-0.0165445 0.0459358 0.0135012 0.0186561 0.00526778 0.180564C-0.00116735 0.30711 -0.00147933 0.563722 0.00309475 0.648049Z" fill="#C4C4C4" />
</clipPath>
</svg>
</>
)
}
export default CustomShapeSvg

View File

@@ -0,0 +1,16 @@
@import "../../../styles/utilities";
.viewAll {
display: flex;
.content {
color: var(--primary);
margin: 0.8rem 0.8rem 0.8rem 0;
font-weight: bold;
}
.vector {
margin: 0.8rem 0rem 0.8rem 0rem;
svg path {
fill: var(--primary);
}
}
}

View File

@@ -17,7 +17,7 @@
width: 100%;
margin-right: 0;
@screen md {
max-width: 55rem;
max-width: 52rem;
}
.top {
@apply flex justify-between items-center;

View File

@@ -0,0 +1,16 @@
@import "../../../styles/utilities";
.empty {
padding: 1.6rem;
margin: auto;
.imgWrap {
min-width: 10rem;
text-align: center;
}
.description {
color: var(--disabled);
text-align: center;
margin-top: .8rem;
}
}

View File

@@ -0,0 +1,25 @@
import { StaticImage } from '..';
import EmptyImg from './empty.png';
import s from './EmptyCommon.module.scss';
interface Props {
description?: string
}
const EmptyCommon = ({ description = "No data to display" }: Props) => {
return (
<div className={s.empty}>
<div className={s.imgWrap}>
<StaticImage src={EmptyImg} alt="empty" />
</div>
{
description && <div className={s.description}>
{description}
</div>
}
</div>
)
}
export default EmptyCommon

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -48,11 +48,11 @@ const FOOTER_COLUMNS = [
},
{
name: 'Privacy Policy',
link: ROUTE.TERM_CONDITION,
link: ROUTE.PRIVACY_POLICY,
},
{
name: 'Blog',
link: ROUTE.TERM_CONDITION,
link: ROUTE.BLOGS,
},
]
}

View File

@@ -1,10 +1,14 @@
@import "../../../styles/utilities";
.header {
@apply sticky bg-white shadow-md;
@apply sticky bg-white;
top: 0;
left: 0;
z-index: 9999;
margin-bottom: 3.2rem;
@screen md {
@apply relative;
}
&.full {
@apply shadow-none;
border: 1px solid var(--border-line);
@@ -17,3 +21,27 @@
@apply font-logo;
}
}
.headerSticky {
@apply sticky bg-white shadow-md;
display: none;
padding-left: 3.2rem;
padding-right: 3.2rem;
top: 0;
left: 0;
z-index: 10000;
transition: all 0.2s;
&.show {
display: block;
animation: showHeaderSticky 0.2s;
}
}
@keyframes showHeaderSticky {
0% {
transform: translateY(-7rem);
}
100% {
transform: none;
}
}

View File

@@ -1,7 +1,8 @@
import classNames from 'classnames'
import React, { memo, useEffect, useState } from 'react'
import React, { memo, useEffect, useMemo, useRef, useState } from 'react'
import { useModalCommon } from 'src/components/hooks'
import { isMobile } from 'src/utils/funtion.utils'
import { CartDrawer } from '..'
import ModalAuthenticate from '../ModalAuthenticate/ModalAuthenticate'
import ModalCreateUserInfo from '../ModalCreateUserInfo/ModalCreateUserInfo'
import HeaderHighLight from './components/HeaderHighLight/HeaderHighLight'
@@ -9,43 +10,78 @@ import HeaderMenu from './components/HeaderMenu/HeaderMenu'
import HeaderSubMenu from './components/HeaderSubMenu/HeaderSubMenu'
import HeaderSubMenuMobile from './components/HeaderSubMenuMobile/HeaderSubMenuMobile'
import s from './Header.module.scss'
interface props {
toggleFilter: () => void
}
const Header = memo(() => {
const Header = memo(({ toggleFilter }: props) => {
const headeFullRef = useRef<HTMLDivElement>(null)
const [isFullHeader, setIsFullHeader] = useState<boolean>(true)
const { visible: visibleModalAuthen, closeModal: closeModalAuthen, openModal: openModalAuthen } = useModalCommon({ initialValue: false })
const { visible: visibleModalInfo, closeModal: closeModalInfo, openModal: openModalInfo } = useModalCommon({ initialValue: false })
const { visible: visibleCartDrawer, openModal: openCartDrawer, closeModal: closeCartDrawer } = useModalCommon({ initialValue: false })
const toggleCart = () => {
if (visibleCartDrawer) {
closeCartDrawer()
} else {
openCartDrawer()
}
}
const headerHeight = useMemo(() => {
return headeFullRef.current?.offsetHeight
}, [headeFullRef.current])
useEffect(() => {
const handleScroll = () => {
if (!isMobile()) {
if (!headerHeight || window.scrollY > headerHeight) {
setIsFullHeader(false)
} else {
setIsFullHeader(true)
}
}
}
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
}, [headerHeight])
const handleScroll = () => {
if (!isMobile()) {
if (window.scrollY === 0) {
setIsFullHeader(true)
} else {
setIsFullHeader(false)
}
}
}
return (
<>
<header className={classNames({ [s.header]: true, [s.full]: isFullHeader })}>
<HeaderHighLight isShow={isFullHeader} />
<header ref={headeFullRef} className={classNames({ [s.header]: true, [s.full]: isFullHeader })}>
<HeaderHighLight />
<div className={s.menu}>
<HeaderMenu isFull={isFullHeader}
<HeaderMenu
toggleFilter={toggleFilter}
toggleCart={toggleCart}
isFull={isFullHeader}
openModalAuthen={openModalAuthen}
openModalInfo={openModalInfo} />
<HeaderSubMenu isShow={isFullHeader} />
<HeaderSubMenu />
</div>
</header>
<div className={classNames({
[s.headerSticky]: true,
[s.show]: !isFullHeader
})}>
<HeaderMenu isFull={isFullHeader}
toggleFilter={toggleFilter}
toggleCart={toggleCart}
openModalAuthen={openModalAuthen}
openModalInfo={openModalInfo} />
</div>
<HeaderSubMenuMobile />
<ModalAuthenticate visible={visibleModalAuthen} closeModal={closeModalAuthen} />
<ModalCreateUserInfo demoVisible={visibleModalInfo} demoCloseModal={closeModalInfo} />
<CartDrawer
visible={visibleCartDrawer}
onClose={closeCartDrawer} />
</>
)
})

View File

@@ -3,13 +3,7 @@
.headerHighLight {
@apply hidden;
@screen md {
transform: translateY(-10rem);
height: 0;
&.show {
@apply flex justify-between items-center spacing-horizontal bg-primary caption;
animation: showHeaderHightlight 0.2s;
height: unset;
transform: none;
padding-top: 0.8rem;
padding-bottom: 0.8rem;
color: var(--white);
@@ -27,13 +21,3 @@
}
}
}
}
@keyframes showHeaderHightlight {
0% {
transform: translateY(-4rem);
}
100% {
transform: none;
}
}

View File

@@ -1,6 +1,5 @@
import classNames from 'classnames'
import Link from 'next/link'
import { memo, useEffect, useRef } from 'react'
import { memo } from 'react'
import { ROUTE } from 'src/utils/constanst.utils'
import s from './HeaderHighLight.module.scss'
@@ -19,14 +18,9 @@ const MENU = [
},
]
interface Props {
children?: any,
isShow: boolean,
}
const HeaderHighLight = memo(({ isShow }: Props) => {
const HeaderHighLight = memo(() => {
return (
<section className={classNames({ [s.headerHighLight]: true, [s.show]: isShow })}>
<section className={s.headerHighLight}>
<div>
Free Shipping on order $49+ / Express $99+
</div>

View File

@@ -15,7 +15,16 @@
.left {
.top {
@apply flex justify-between items-center;
.iconGroup{
@apply flex justify-between items-center;
}
.iconCart {
margin-left: 1.6rem;
}
.iconFilter{
@screen md {
display: none;
}
}
}
.inputSearch {
@@ -42,7 +51,7 @@
@apply hidden;
@screen md {
@apply flex items-center list-none;
li {
> li {
@apply flex justify-center items-center w-full;
&:not(:last-child) {
margin-right: 4.8rem;
@@ -53,7 +62,7 @@
a {
@appy no-underline;
&:hover {
opacity: .8;
opacity: 0.8;
}
&.iconFavourite {
svg path {
@@ -61,7 +70,24 @@
}
}
}
.btnCart {
all: unset;
cursor: pointer;
&:focus-visible {
outline: 2px solid #000;
}
&:hover {
svg path {
fill: var(--primary);
opacity: 0.8;
}
}
}
}
}
@screen xl {
.iconFilterDesk {
display:none;
}
}
}

View File

@@ -3,19 +3,24 @@ import Link from 'next/link'
import { memo, useMemo } from 'react'
import InputSearch from 'src/components/common/InputSearch/InputSearch'
import MenuDropdown from 'src/components/common/MenuDropdown/MenuDropdown'
import { IconBuy, IconHeart, IconHistory, IconUser } from 'src/components/icons'
import { IconBuy, IconFilter, IconHeart, IconHistory, IconUser } from 'src/components/icons'
import { ACCOUNT_TAB, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'
import Logo from '../../../Logo/Logo'
import s from './HeaderMenu.module.scss'
import { useRouter } from 'next/router'
interface Props {
children?: any,
isFull: boolean,
openModalAuthen: () => void,
openModalInfo: () => void,
toggleFilter:() => void,
toggleCart:() => void,
}
const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo }: Props) => {
const FILTER_PAGE = [ROUTE.HOME,ROUTE.PRODUCTS]
const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo, toggleFilter, toggleCart }: Props) => {
const router = useRouter()
const optionMenu = useMemo(() => [
{
onClick: openModalAuthen,
@@ -35,16 +40,25 @@ const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo }: Props) => {
},
], [openModalAuthen])
return (
<section className={classNames({ [s.headerMenu]: true, [s.full]: isFull })}>
<div className={s.left}>
<div className={s.top}>
<Logo/>
<div className={s.iconGroup}>
{
FILTER_PAGE.includes(router.pathname) && (
<button className={s.iconFilter} onClick={toggleFilter}>
<IconFilter/>
</button>
)
}
<button className={s.iconCart}>
<IconBuy />
</button>
</div>
</div>
<div className={s.inputSearch}>
<InputSearch />
</div>
@@ -68,10 +82,20 @@ const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo }: Props) => {
<MenuDropdown options={optionMenu} isHasArrow={false}><IconUser /></MenuDropdown>
</li>
<li>
<button>
<button className={s.btnCart} onClick={toggleCart}>
<IconBuy />
</button>
</li>
{
FILTER_PAGE.includes(router.pathname) && (
<li className={s.iconFilterDesk}>
<button className={s.iconFilter} onClick={toggleFilter}>
<IconFilter/>
</button>
</li>
)
}
</ul>
</section>
)

View File

@@ -3,9 +3,6 @@
.headerSubMenu {
@apply hidden;
@screen md {
transform: translateY(-10rem);
height: 0;
&.show {
@apply block;
padding-bottom: 2.4rem;
transform: none;
@@ -39,4 +36,3 @@
}
}
}
}

View File

@@ -53,16 +53,12 @@ const CATEGORY = [
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=sauce`,
},
]
interface Props {
children?: any,
isShow: boolean,
}
const HeaderSubMenu = memo(({ isShow }: Props) => {
const HeaderSubMenu = memo(() => {
const router = useRouter()
return (
<section className={classNames({ [s.headerSubMenu]: true, [s.show]: isShow })}>
<section className={s.headerSubMenu}>
<ul className={s.menu}>
{/* todo: handle active item */}
<li>

View File

@@ -5,5 +5,8 @@
height: 100%;
img {
object-fit: cover;
background-size: contain !important;
background-position: center !important;
background-repeat: no-repeat;
}
}

View File

@@ -1,6 +1,7 @@
import React from 'react'
import s from './ImgWithLink.module.scss'
import Image from 'next/image'
import { BLUR_DATA_IMG } from 'src/utils/constanst.utils'
export interface ImgWithLinkProps {
src: string,
@@ -10,7 +11,12 @@ export interface ImgWithLinkProps {
const ImgWithLink = ({ src, alt }: ImgWithLinkProps) => {
return (
<div className={s.imgWithLink}>
<Image src={src} alt={alt} layout="fill" className={s.imgWithLink} />
<Image src={src} alt={alt}
layout="fill"
className={s.imgWithLink}
placeholder="blur"
blurDataURL={BLUR_DATA_IMG}
/>
</div>
)
}

View File

@@ -17,7 +17,7 @@
}
.inputCommon {
@apply block w-full transition-all duration-200 rounded;
@apply block w-full transition-all duration-200 rounded bg-white;
padding: 1.2rem 1.6rem;
border: 1px solid var(--border-line);
&:hover,

View File

@@ -6,6 +6,7 @@ import s from './InputCommon.module.scss';
type Ref = {
focus: () => void
getValue: () => string | number
} | null;
interface Props {
children?: React.ReactNode,

View File

@@ -6,3 +6,8 @@
flex: 1;
}
}
.filter{
@screen xl {
display: none;
}
}

View File

@@ -2,9 +2,11 @@ import { CommerceProvider } from '@framework'
import { useRouter } from 'next/router'
import { FC } from 'react'
import { useModalCommon } from 'src/components/hooks'
import { CartDrawer } from '..'
import { BRAND, CATEGORY, FEATURED } from 'src/utils/constanst.utils'
import { CustomShapeSvg } from '..'
import Footer from '../Footer/Footer'
import Header from '../Header/Header'
import MenuNavigationProductList from '../MenuNavigationProductList/MenuNavigationProductList'
import s from './Layout.module.scss'
interface Props {
@@ -15,24 +17,23 @@ interface Props {
// note: demo code
const Layout: FC<Props> = ({ children }) => {
const { locale = 'en-US' } = useRouter()
// const { visible: visibleCartDrawer, openModal, closeModal: closeCartDrawer } = useModalCommon({ initialValue: false })
const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false })
// const toggle = () => {
// if (visibleCartDrawer) {
// closeCartDrawer()
// } else {
// openModal()
// }
// }
const toggleFilter = () => {
if (visibleFilter) {
closeFilter()
} else {
openFilter()
}
}
return (
<CommerceProvider locale={locale}>
<div className={s.mainLayout}>
<Header />
<Header toggleFilter={toggleFilter}/>
<main >{children}</main>
{/* <button onClick={toggle}>toggle card: {visibleCartDrawer.toString()}</button> */}
{/* <CartDrawer
visible={visibleCartDrawer}
onClose={closeCartDrawer} /> */}
<CustomShapeSvg/>
<div className={s.filter}><MenuNavigationProductList categories={CATEGORY} brands={BRAND} featured={FEATURED} visible={visibleFilter} onClose={closeFilter}/> </div>
<Footer />
</div>
</CommerceProvider>

View File

@@ -3,9 +3,6 @@
.menuDropdown {
@apply relative cursor-pointer;
width: fit-content;
.label {
all: unset;
}
&:hover {
.label {
color: var(--primary);
@@ -20,10 +17,21 @@
}
.label {
all: unset;
@apply flex justify-end items-center transition-all duration-200;
svg path {
width: fit-content;
}
&:focus,
&:active {
color: var(--primary);
svg path {
fill: currentColor;
}
}
&:focus-visible {
outline: 2px solid #000;
}
}
&.arrow {
@@ -66,18 +74,9 @@
@apply rounded list-none bg-white;
border: 1px solid var(--text-active);
margin-top: 0.4rem;
li {
> li {
@apply block w-full transition-all duration-200 cursor-pointer text-active;
word-wrap: break-word;
-webkit-hyphens: auto;
-ms-hyphens: auto;
-moz-hyphens: auto;
hyphens: auto;
overflow-x: hidden;
position: relative;
max-width: 15rem;
white-space: nowrap;
text-overflow: ellipsis;
button {
all: unset;
color: currentColor;

View File

@@ -0,0 +1,38 @@
@import "../../../styles/utilities";
.menuFilterWrapper{
@apply spacing-horizontal;
.menuFilterHeading{
@apply sub-headline font-bold ;
color: var(--text-active);
font-feature-settings: 'salt' on;
margin: 0.8rem 0;
}
.menuFilterList{
@apply flex flex-wrap justify-start relative;
margin-bottom: 3rem;
box-sizing: border-box;
&::after{
@apply absolute;
bottom: -1rem;
content: "";
width: 100%;
border-bottom: 1px solid var(--border-line);
}
li{
margin: 1rem 0;
padding:0;
div{
padding: 0.8rem 1.6rem;
margin-right: 0.8rem;
background-color: var(--gray);
border-radius: 0.8rem;
&.active {
color:white;
background-color: var(--primary);
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
import classNames from 'classnames'
import { useEffect, useState } from 'react';
import s from './MenuFilter.module.scss'
interface Props {
children?: any,
heading?:string,
categories:{name:string,link:string}[],
type:string,
onChangeValue?: (value: Object) => void
}
const MenuFilter = ({heading,categories,type,onChangeValue}:Props)=> {
const [active, setActive] = useState<string>('');
function handleClick(link:string){
setActive(link);
if(active === link){
setActive('');
}
}
useEffect(()=>{
let href = active?.split("=");
const linkValue = href[1];
onChangeValue && onChangeValue({[type]:linkValue});
},[active])
return (
<section className={s.menuFilterWrapper}>
<h2 className={s.menuFilterHeading}>{heading}</h2>
<ul className={s.menuFilterList}>
{
categories.map(item => <li key={item.name}>
<div onClick={()=> handleClick(item.link)} className={classNames({ [s.active]: item.link === active? true: false })}>
{item.name}
</div>
</li>)
}
</ul>
</section>
)
}
export default MenuFilter

View File

@@ -0,0 +1,29 @@
@import "../../../styles/utilities";
.menuNavigationWrapper{
.menuNavigationHeading{
@screen md {
@apply sub-headline font-bold ;
color: var(--text-active);
font-feature-settings: 'salt' on;
margin: 1.6rem 0;
}
}
.menuNavigationList{
@screen md {
li{
margin: 0.8rem 0;
a{
display:block;
width:100%;
color:var(--text-base);
&:hover {
@apply text-primary;
}
&.active {
@apply text-primary;
}
}
}
}
}
}

View File

@@ -0,0 +1,34 @@
import classNames from 'classnames'
import Link from 'next/link'
import { useRouter } from 'next/router'
import s from './MenuNavigation.module.scss'
interface Props {
children?: any,
heading:string,
categories:{name:string,link:string}[]
}
const MenuNavigation = ({heading,categories}:Props)=> {
const router = useRouter()
return (
<section className={s.menuNavigationWrapper}>
<h2 className={s.menuNavigationHeading}>{heading}({categories.length})</h2>
<ul className={s.menuNavigationList}>
{
categories.map(item => <li key={item.name}
>
<Link href={item.link}>
<a className={classNames({ [s.active]: router.asPath === item.link})}>
{item.name}
</a>
</Link>
</li>)
}
</ul>
</section>
)
}
export default MenuNavigation

View File

@@ -0,0 +1,79 @@
@import "../../../styles/utilities";
.menuNavigationProductListDesktop{
@screen sm {
@apply hidden;
}
@screen xl {
@apply block;
}
}
.menuNavigationProductListMobile{
@apply relative transition-all duration-100;
&.isShow{
&::after{
content: "";
background: rgba(0, 0, 0, 0.5);
left: 0;
top: 0;
bottom: 0;
width: 100%;
height: 100vh;
position: fixed;
z-index: 9999;
}
}
.menuNavigationProductModal{
@apply transition-all duration-200;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100vh;
z-index: 10000;
transform: translateY(100%);
&.animation{
transform: translateY(0%)
}
.content{
@apply relative w-full h-full;
margin-top: 3rem;
padding-top: 8rem ;
padding-bottom: 10rem;
background-color: white;
overflow-y: auto;
height: 100vh;
border-radius: 2.4rem 2.4rem 0 0;
.head{
@apply flex justify-between fixed;
top:0;
left:0;
margin-top: 3rem;
border-radius: 2.4rem 2.4rem 0 0;
padding: 3rem 2rem 1rem 2rem;
width: 100%;
background-color: white;
z-index: 10000;
h3{
@apply heading-3 font-bold;
color:var(--text-base);
}
}
.foot{
@apply fixed;
bottom: 0;
left:0;
width: 100%;
background-color: white;
padding: 0 1rem 2rem 1rem;
}
button{
margin-top: 2rem;
width: 100%;
}
}
}
}

View File

@@ -0,0 +1,57 @@
import React, { useState } from 'react';
import {ButtonCommon} from 'src/components/common';
import s from './MenuNavigationProductList.module.scss';
import MenuSort from './MenuSort/MenuSort';
import {LANGUAGE} from 'src/utils/language.utils';
import classNames from 'classnames'
import MenuFilter from '../MenuFilter/MenuFilter';
import MenuNavigation from '../MenuNavigation/MenuNavigation';
import IconHide from 'src/components/icons/IconHide';
interface Props{
categories:{name:string,link:string}[],
brands:{name:string,link:string}[],
featured:{name:string,link:string}[],
visible: boolean,
onClose: () => void
}
const MenuNavigationProductList = ({categories,brands,featured,visible,onClose}:Props)=>{
const [dataSort,setDataSort] = useState({});
function handleValue(value:Object){
setDataSort({...dataSort,...value});
}
function filter(){
console.log(dataSort)
}
return(
<>
<div className={s.menuNavigationProductListDesktop}>
<MenuNavigation categories={categories} heading="Categories"/>
<MenuNavigation categories={brands} heading="Brands"/>
<MenuNavigation categories={featured} heading="Featured"/>
</div>
<div className={classNames({ [s.menuNavigationProductListMobile] :true,[s.isShow]: visible})}>
<div className={classNames({ [s.menuNavigationProductModal] :true,[s.animation]: visible})}>
<div className={s.content}>
<div className={s.head}>
<h3>FILTER</h3>
<div onClick={onClose}><IconHide/></div>
</div>
<MenuFilter categories={categories} heading="Categories" type="category" onChangeValue={handleValue}/>
<MenuFilter categories={brands} heading="Brand" type="brand" onChangeValue={handleValue}/>
<MenuFilter categories={featured} heading="Featured" type="featured" onChangeValue={handleValue}/>
<MenuSort heading="SORT BY" type="sort" onChangeValue={handleValue}/>
<div className={s.foot}>
<ButtonCommon size="large" onClick={filter}>{LANGUAGE.BUTTON_LABEL.CONFIRM}</ButtonCommon>
</div>
</div>
</div>
</div>
</>
)
}
export default MenuNavigationProductList

View File

@@ -0,0 +1,39 @@
@import "../../../../styles/utilities";
.menuSortWrapper{
@apply spacing-horizontal;
.menuSortHeading{
@apply sub-headline font-bold ;
color: var(--text-active);
font-feature-settings: 'salt' on;
margin: 0.8rem 0;
}
.menuSortList{
margin-bottom: 2rem;
box-sizing: border-box;
li{
div{
height: 4.8rem;
line-height: 4.8rem;
padding: 0 1.6rem;
margin-right: 0.8rem;
border-radius: 0.8rem;
&.active {
@apply font-bold relative;
color:var(--text-active);
background-color: var(--primary-lightest);
&::after{
@apply absolute;
content:"";
background-image: url('/assets/svg/check.svg');
right: 1.6rem;
top: calc(50% - 24px/2);
width: 2.4rem;
height: 2.4rem;
}
}
}
}
}
}

View File

@@ -0,0 +1,67 @@
import classNames from 'classnames';
import { useEffect, useState } from 'react';
import { QUERY_KEY, ROUTE } from 'src/utils/constanst.utils';
import s from './MenuSort.module.scss';
interface Props {
children?: any,
heading:string,
type:string,
onChangeValue?: (value: Object) => void
}
const SORT = [
{
name: 'By Name',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=by-name`,
},
{
name: 'Price(High to Low)',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=high-to-low`,
},
{
name: 'Price (Low to High)',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=low-to-high`,
},
{
name: 'On Sale',
link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.SORTBY}=on-sale`,
},
];
const MenuSort = ({heading,type,onChangeValue}:Props)=> {
const [active, setActive] = useState<string>('');
function handleClick(link:string){
setActive(link);
if(active === link){
setActive('');
}
}
useEffect(()=>{
let href = active?.split("=");
const linkValue = href[1];
onChangeValue && onChangeValue({[type]:linkValue});
},[active])
return (
<section className={classNames(s.menuSortWrapper)}>
<h2 className={classNames(s.menuSortHeading)}>{heading}</h2>
<ul className={s.menuSortList}>
{
SORT.map(item => <li key={item.name}>
<div onClick={()=> handleClick(item.link)} className={classNames({ [s.active]: item.link === active? true: false })}>
{item.name}
</div>
</li>)
}
</ul>
</section>
)
}
export default MenuSort

View File

@@ -1,7 +1,6 @@
import Link from 'next/link'
import React, { useEffect, useRef } from 'react'
import { ButtonCommon, Inputcommon } from 'src/components/common'
import InputPassword from 'src/components/common/InputPassword/InputPassword'
import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common'
import { ROUTE } from 'src/utils/constanst.utils'
import { CustomInputCommon } from 'src/utils/type.utils'
import s from '../FormAuthen.module.scss'

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useRef } from 'react'
import { ButtonCommon, Inputcommon } from 'src/components/common'
import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common'
import s from '../FormAuthen.module.scss'
import styles from './FormRegister.module.scss'
import SocialAuthen from '../SocialAuthen/SocialAuthen'

View File

@@ -1,6 +1,6 @@
import React, { useRef } from 'react'
import { Close } from 'src/components/icons'
import { useOnClickOutside } from 'src/utils/useClickOutSide'
import { useOnClickOutside } from 'src/components/hooks/useClickOutSide'
import s from './ModalCommon.module.scss'
export interface ModalCommonProps {
onClose: () => void

View File

@@ -0,0 +1,22 @@
.warpper{
.item{
@apply inline-flex items-center justify-center cursor-pointer;
background-color: var(--gray);
margin: 0 0.4rem;
width: 3.2rem;
height: 3.2rem;
&.active{
@apply border border-solid;
border-color: var(--text-active);
background-color: var(--white);
}
&.disable{
svg{
path{
fill: var(--disabled)
}
}
@apply text-disabled cursor-not-allowed;
}
}
}

View File

@@ -1,13 +1,73 @@
import React from 'react'
import classNames from 'classnames'
import React, { useEffect, useState } from 'react'
import { ArrowLeftSmall, ArrowRightSmall } from 'src/components/icons'
import { DEFAULT_PAGE_SIZE } from 'src/utils/constanst.utils'
import PaginationItem from './components/PaginationItem'
import s from './PaginationCommon.module.scss'
interface PaginationCommonProps {
defaultCurrent?: number
pageSize?: number
total: number
onChange?: (page: number, pageSize: number) => void
}
const PaginationCommon = (props: PaginationCommonProps) => {
return (
<div>
const PaginationCommon = ({
total,
pageSize=DEFAULT_PAGE_SIZE,
defaultCurrent,
onChange,
}: PaginationCommonProps) => {
const [pageNum, setPageNum] = useState<number>(0)
const [currentPage, setCurrentPage] = useState<number>(0)
useEffect(() => {
setPageNum(Math.ceil(total / pageSize))
}, [total, pageSize])
useEffect(() => {
if (defaultCurrent) {
setCurrentPage(defaultCurrent)
}
}, [defaultCurrent])
const onPageClick = (page: number) => {
setCurrentPage(page)
onChange && onChange(page, pageSize)
}
const onPrevClick = () => {
setCurrentPage(currentPage - 1 < 0 ? 0 : currentPage - 1)
}
const onNextClick = () => {
setCurrentPage((currentPage + 1) > (pageNum - 1) ? (pageNum - 1) : currentPage + 1)
}
return (
<div className={s.warpper}>
<div
className={classNames(s.item, { [`${s.disable}`]: currentPage <= 0 })}
onClick={onPrevClick}
>
<ArrowLeftSmall disable={currentPage <= 0} />
</div>
{[...Array(pageNum).keys()].map((index) => {
return (
<PaginationItem
page={index}
onClick={onPageClick}
key={index}
active={index === currentPage}
/>
)
})}
<div
className={classNames(s.item, {
[s.disable]: currentPage >= pageNum - 1,
})}
onClick={onNextClick}
>
<ArrowRightSmall disable={currentPage >= pageNum} />
</div>
</div>
)
}

View File

@@ -0,0 +1,21 @@
import classNames from 'classnames'
import React from 'react'
import s from "../PaginationCommon.module.scss"
interface PaginationItemProps {
onClick:(page:number)=>void
page:number
active:boolean
}
const PaginationItem = ({onClick, page, active}: PaginationItemProps) => {
const onPageClick = () => {
onClick && onClick(page)
}
return (
<div onClick={onPageClick} className={classNames(s.item,{[`${s.active}`]:active})}>
{page+1}
</div>
)
}
export default PaginationItem

View File

@@ -59,7 +59,8 @@
.cardBot{
min-height: 4rem;
@apply flex justify-between items-center;
.cardButton{
.cardIcon{
margin-right: 0.8rem;
}
}
}

View File

@@ -1,5 +1,6 @@
import Link from 'next/link'
import React from 'react'
import { ROUTE } from 'src/utils/constanst.utils'
import { ProductProps } from 'src/utils/types.utils'
import ButtonCommon from '../ButtonCommon/ButtonCommon'
import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy'
@@ -31,7 +32,7 @@ const ProductCard = ({
return (
<div className={s.productCardWarpper}>
<div className={s.cardTop}>
<Link href="#">
<Link href={`${ROUTE.PRODUCT_DETAIL}/test`}>
<div className={s.productImage}>
<img src={imageSrc} alt="image" />
</div>
@@ -42,7 +43,7 @@ const ProductCard = ({
</div>
<div className={s.cardMid}>
<div className={s.cardMidTop}>
<Link href="#">
<Link href={`${ROUTE.PRODUCT_DETAIL}/test`}>
<div className={s.productname}>{name} </div>
</Link>
<div className={s.productWeight}>{weight}</div>

View File

@@ -0,0 +1,11 @@
.wrapper{
.list{
// max-width: 109.4rem;
@apply flex flex-wrap justify-around;
}
.pagination{
padding-top: 4.8rem;
// max-width: 109.4rem;
@apply flex justify-center items-center ;
}
}

View File

@@ -0,0 +1,30 @@
import React, { useState } from 'react'
import PaginationCommon from '../PaginationCommon/PaginationCommon'
import ProductCard, { ProductCardProps } from '../ProductCard/ProductCard'
import s from "./ProductList.module.scss"
interface ProductListProps {
data: ProductCardProps[]
}
const ProductList = ({data}: ProductListProps) => {
const [currentPage, setCurrentPage] = useState(0)
const onPageChange = (page:number) => {
setCurrentPage(page)
}
return (
<div className={s.wrapper}>
<div className={s.list}>
{
data.slice(currentPage*20,(currentPage+1)*20).map((product,index)=>{
return <ProductCard {...product} key={index}/>
})
}
</div>
<div className={s.pagination}>
<PaginationCommon total={data.length} pageSize={20} onChange={onPageChange}/>
</div>
</div>
)
}
export default ProductList

View File

@@ -0,0 +1,16 @@
@import '../../../../styles/utilities';
.blogCardWarpper {
@apply spacing-horizontal;
@screen xl {
:global(.customArrow) {
@screen lg {
&:global(.leftArrow) {
left: calc(-6.4rem - 2rem);
}
&:global(.rightArrow) {
right: calc(-6.4rem - 2rem);
}
}
}
}
}

View File

@@ -0,0 +1,46 @@
import { TOptionsEvents } from 'keen-slider'
import React from 'react'
import CarouselCommon, {
CarouselCommonProps,
} from '../../CarouselCommon/CarouselCommon'
import BlogCard, { BlogCardProps } from 'src/components/common/CardBlog/CardBlog'
import s from "./BlogPostCarousel.module.scss"
interface BlogPostCarouselProps
extends Omit<CarouselCommonProps<BlogCardProps>, 'Component'|"option"> {
option?:TOptionsEvents
}
const OPTION_DEFAULT: TOptionsEvents = {
slidesPerView: 1.25,
mode: 'free',
spacing:24,
breakpoints: {
'(min-width: 640px)': {
slidesPerView: 2,
},
'(min-width: 1024px)': {
slidesPerView: 2.5,
},
'(min-width: 1440px)': {
slidesPerView: 3,
},
'(min-width: 1536px)': {
slidesPerView: 3.5,
},
},
}
const BlogPostCarousel = ({ option, data, ...props }: BlogPostCarouselProps) => {
return (
<div className={s.blogCardWarpper}>
<CarouselCommon<BlogCardProps>
data={data}
Component={BlogCard}
{...props}
option={{ ...OPTION_DEFAULT, ...option }}
/>
</div>
)
}
export default BlogPostCarousel

View File

@@ -0,0 +1,19 @@
@import '../../../styles/utilities';
.blogPostWarpper {
&.cream{
background-color: #F5F4F2;
}
padding-top: 5.6rem;
padding-bottom: 5.2rem;
@apply flex flex-col;
.top {
@apply spacing-horizontal flex w-full justify-between;
padding-bottom: 3.2rem;
@screen xl {
.right {
margin-right: 2.476rem;
}
}
}
}

View File

@@ -0,0 +1,75 @@
import image15 from '../../../../public/assets/images/image15.png'
import image16 from '../../../../public/assets/images/image16.png'
import image17 from '../../../../public/assets/images/image17.png'
import classNames from 'classnames'
import React from 'react'
import { HeadingCommon, ViewAllItem } from 'src/components/common'
import { BlogCardProps } from 'src/components/common/CardBlog/CardBlog'
import BlogPostCarousel from './BlogPostCarousel/BlogPostCarousel'
import s from './RelevantBlogPosts.module.scss'
import { ROUTE } from 'src/utils/constanst.utils';
interface RelevantProps {
data?: BlogCardProps[],
itemKey?: string,
title?: string,
viewAllLink?: string,
bgcolor?: "default" | "cream"
}
const recipe:BlogCardProps[] = [
{
title: "Want to Lose Weight? Here are 10 DEBM Diet Guidelines for Beginners",
slug: 'have-a-nice-lunch',
description:"The DEBM diet stands for "+'"Delicious Happy Fun Diet"'+". This diet was popularized by Robert...",
imageSrc: image15.src,
},{
title: "9 Ways to Make an Aloe Vera Mask at Home",
slug: 'have-a-nice-lunch',
description:"Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
imageSrc: image16.src,
},{
title: "Don't Buy Wrong, Here Are 7 Ways to Choose a Ripe Dragon Fruit",
slug: 'have-a-nice-lunch',
description:"Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
imageSrc: image17.src,
},{
title: "Want to Lose Weight? Here are 10 DEBM Diet Guidelines for Beginners",
slug: 'have-a-nice-lunch',
description:"The DEBM diet stands for "+'"Delicious Happy Fun Diet"'+". This diet was popularized by Robert...",
imageSrc: image15.src,
},{
title: "9 Ways to Make an Aloe Vera Mask at Home",
slug: 'have-a-nice-lunch',
description:"Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...",
imageSrc: image16.src,
},{
title: "Don't Buy Wrong, Here Are 7 Ways to Choose a Ripe Dragon Fruit",
slug: 'have-a-nice-lunch',
description:"Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...",
imageSrc: image17.src,
}]
const RelevantBlogPosts = ({ data = recipe, itemKey="detail-relevant", title="Relevant Blog Posts", bgcolor = "default" }: RelevantProps) => {
return (
<div className={classNames({
[s.blogPostWarpper] : true,
[s[bgcolor]] : bgcolor,
})}
>
<div className={s.top}>
<div className={s.left}>
<HeadingCommon>{title}</HeadingCommon>
</div>
<div className={s.right}>
<ViewAllItem link={ROUTE.BLOGS}/>
</div>
</div>
<div className={s.bot}>
<BlogPostCarousel data={data} itemKey={itemKey} />
</div>
</div>
)
}
export default RelevantBlogPosts

View File

@@ -2,6 +2,11 @@
.select {
background-color: var(--white);
.selectTrigger {
svg {
@apply transition-all duration-200;
}
}
&.base {
width: 20.6rem;
.selectTrigger {
@@ -28,9 +33,16 @@
color: var(--text-label);
}
}
&.isActive{
.selectOptionWrapper{
&:hover {
cursor: pointer;
.hoverWrapper {
@apply block;
animation: SelectAnimation 0.2s ease-out;
}
.selectTrigger {
svg {
transform: rotate(180deg);
}
}
}
}
@@ -38,14 +50,14 @@
@apply outline-none flex justify-between;
color: var(--text-active);
border-radius: 0.8rem;
}
.hoverWrapper {
@apply hidden outline-none absolute z-10;
padding-top: 0.6rem;
.selectOptionWrapper {
@apply outline-none hidden z-10 absolute;
border-radius: 0.8rem;
background-color: var(--white);
padding: 0.4rem 0rem 0.4rem 0rem;
margin-top: 0.6rem;
&.base {
width: 20.6rem;
}
@@ -60,10 +72,19 @@
border-color: var(--border-line);
color: var(--text-label);
}
&.active{
@apply hidden;
}
&:hover {
@apply block;
}
}
@keyframes SelectAnimation {
0% {
opacity: 0;
transform: translateY(1.6rem);
}
100% {
opacity: 1;
transform: none;
}
}

View File

@@ -1,43 +1,25 @@
import s from './SelectCommon.module.scss'
import classNames from 'classnames'
import { useState, useRef, useEffect } from 'react'
import { useState } from 'react'
import { IconVectorDown } from 'src/components/icons'
import SelectOption from './SelectOption/SelectOption'
interface Props {
children? : React.ReactNode,
placeholder? : string,
size?: 'base' | 'large',
type?: 'default' | 'custom',
option: {name: string}[],
option: {name: string, value: string}[],
onChange?: (value: string) => void,
}
const SelectCommon = ({ type = 'default', size = 'base', option, children }: Props) => {
const [isActive, setActive] = useState(false)
const [selectedName, setSelectedName] = useState(children)
const ref = useRef<HTMLDivElement>(null)
const SelectCommon = ({ type = 'default', size = 'base', option, placeholder, onChange}: Props) => {
const [selectedName, setSelectedName] = useState(placeholder)
const [selectedValue, setSelectedValue] = useState('')
useEffect(() => {
const handleClick = (event: MouseEvent) => {
const { target } = event;
if (!ref?.current || ref?.current.contains(target as Node)) {
return
}
else{
setActive(false)
}
}
document.addEventListener('click', handleClick)
return () => {
document.removeEventListener('click', handleClick)
}
}, [ref])
const changeActiveStatus = () => {
setActive(!isActive)
}
const changeSelectedName = (item:string) => {
const changeSelectedName = (item:string, value: string) => {
setSelectedValue(value)
setSelectedName(item)
onChange && onChange(value)
}
return(
<>
@@ -45,10 +27,7 @@ const SelectCommon = ({ type = 'default', size = 'base', option, children }: Pro
[s.select] : true,
[s[size]] : !!size,
[s[type]] : !!type,
[s.isActive] : isActive,
})}
onClick = { changeActiveStatus }
ref = {ref}
>
<div className={classNames({
[s.selectTrigger] : true,
@@ -56,6 +35,7 @@ const SelectCommon = ({ type = 'default', size = 'base', option, children }: Pro
})}
>{selectedName}<IconVectorDown /></div>
<div className={s.hoverWrapper}>
<div className={classNames({
[s.selectOptionWrapper] : true,
[s[type]] : !!type,
@@ -64,11 +44,13 @@ const SelectCommon = ({ type = 'default', size = 'base', option, children }: Pro
>
{
option.map(item =>
<SelectOption itemName={item.name} onClick={changeSelectedName} size={size} />
<SelectOption key={item.value} itemName={item.name} value={item.value} onClick={changeSelectedName} size={size} selected={(selectedValue === item.value)} />
)
}
</div>
</div>
</div>
</>
)
}

View File

@@ -13,5 +13,9 @@
}
&:hover{
background-color: var(--gray);
color: var(--primary);
}
&.isChoose{
background-color: var(--gray);
}
}

View File

@@ -2,20 +2,22 @@ import s from './SelectOption.module.scss'
import classNames from 'classnames'
interface Props{
onClick: (value: string) => void,
onClick: (name: string, value: string) => void,
itemName: string,
size: 'base' | 'large',
value: string,
selected?: boolean,
}
const SelectOption = ({onClick, itemName, size}: Props) => {
const SelectOption = ({onClick, itemName, size, value, selected} : Props) => {
const changeName = () => {
onClick(itemName)
onClick(itemName, value)
}
return(
<div className={classNames({
[s.selectOption] : true,
[s[size]] : !!size,
[s.isChoose] : selected ,
})}
onClick = {changeName}
>{itemName}</div>

View File

@@ -0,0 +1,5 @@
.staticImage {
img {
@apply w-full h-full;
}
}

View File

@@ -0,0 +1,16 @@
import React from 'react'
import s from './StaticImage.module.scss'
import Image from 'next/image'
export interface Props {
src: StaticImageData,
alt?: string,
}
const StaticImage = ({ src, alt }: Props) => {
return (
<Image src={src} alt={alt} placeholder='blur' className={s.staticImage}/>
)
}
export default StaticImage

View File

@@ -0,0 +1,28 @@
@import '../../../styles/utilities';
.tabWapper{
@apply flex flex-col w-full;
.tabHeader{
@apply flex;
.tabList {
@apply flex;
position: relative;
border-bottom: 2px solid #FBFBFB;
padding: 0.8rem 0;
&.center{
margin: auto;
}
.slider {
@apply inline-block;
height: .2rem;
border-radius: 3px;
background-color: var(--primary);
position: absolute;
z-index: 1200;
bottom: 0;
transition: all .25s linear;
}
}
}
}

View File

@@ -0,0 +1,85 @@
import React, {
Children,
PropsWithChildren,
ReactElement,
useEffect,
useRef,
useState,
cloneElement,
} from 'react'
import s from './TabCommon.module.scss'
import TabItem from './components/TabItem/TabItem'
import { TabPaneProps } from './components/TabPane/TabPane'
import classNames from 'classnames'
interface TabCommonProps {
defaultActiveTab?: number
children: React.ReactNode
center?:boolean
}
const TabCommon = ({
defaultActiveTab = 0,
children,
center
}: TabCommonProps) => {
const [active, setActive] = useState(0)
const slider = useRef<HTMLDivElement>(null)
const headerRef = useRef<HTMLUListElement>(null)
useEffect(() => {
setActive(defaultActiveTab)
}, [])
useEffect(() => {
slide(active)
}, [active])
function slide(index: number) {
const active = headerRef.current?.children
.item(index)
?.getBoundingClientRect()
const header = headerRef.current?.getBoundingClientRect()
const current = slider.current
if (current && active && header) {
let width = active.width - 24 <= 0 ? 24 : active.width - 24
let left = active.left - header.left
current.style.width = width.toString() + 'px'
current.style.left = left.toString() + 'px'
}
}
const onTabClick = (index: number) => {
setActive(index)
}
return (
<section className={s.tabWapper}>
<div className={s.tabHeader}>
<ul className={classNames(s.tabList,{[s.center]:center})} ref={headerRef}>
{Children.map(children, (tab, index) => {
let item = tab as ReactElement<PropsWithChildren<TabPaneProps>>
return (
<li key={item.props.tabName}>
<TabItem
active={active === index}
onClick={onTabClick}
tabIndex={index}
>
{item.props.tabName}
</TabItem>
</li>
)
})}
<div ref={slider} className={s.slider}></div>
</ul>
</div>
<div className={s.tabBody}>
{Children.map(children, (tab, index) => {
let item = tab as ReactElement<PropsWithChildren<TabPaneProps>>
return cloneElement(item, { active:index===active });
})
}</div>
</section>
)
}
export default TabCommon

View File

@@ -0,0 +1,22 @@
@import '../../../../styles/utilities';
.tabItem {
margin-right: 4.8rem;
padding-top: 1.6rem;
padding-bottom: 1.6rem;
&:hover {
@apply cursor-pointer;
}
}
.tabItemActive {
@apply font-bold;
margin-right: 4.8rem;
padding-top: 1.6rem;
padding-bottom: 1.6rem;
&:hover {
@apply cursor-pointer;
}
}

View File

@@ -0,0 +1,19 @@
import React from "react"
import s from './TabItem.module.scss'
interface TabItemProps {
active: boolean;
children: string;
onClick: (tabIndex: number, tabPane?: string) => void;
}
const TabItem = ({ active = false, children, onClick } : TabItemProps) => {
return (
<span onClick={onClick} className={active ? s.tabItemActive : s.tabItem} >
{children}
</span>
)
}
export default TabItem;

View File

@@ -0,0 +1,13 @@
@import '../../../../../styles/utilities';
.tabItem {
margin-right:2.4rem;
padding: 0.8rem 0;
min-width: 2.4rem;
&:hover {
@apply cursor-pointer;
}
&.tabItemActive {
@apply font-bold;
}
}

View File

@@ -0,0 +1,31 @@
import classNames from 'classnames'
import React from 'react'
import s from './TabItem.module.scss'
interface TabItemProps {
active: boolean
children: string
onClick?: (tabIndex: number) => void
tabIndex: number
}
const TabItem = ({
active = false,
children,
onClick,
tabIndex,
}: TabItemProps) => {
const handleClick = () => {
onClick && onClick(tabIndex)
}
return (
<span
onClick={handleClick}
className={classNames(s.tabItem, {[s.tabItemActive]:active})}
>
{children}
</span>
)
}
export default TabItem

View File

@@ -0,0 +1,23 @@
@import "../../../../../styles/utilities";
.tabPane {
@apply hidden;
transition: all 0.6s;
// animation-duration: 0.6s;
// animation-name: appear;
// @keyframes appear {
// from {
// margin-left: 100%;
// width: 200%;
// }
// to {
// margin-left: 0%;
// width: 100%;
// }
// }
&.active {
@apply block;
}
}

View File

@@ -0,0 +1,21 @@
import classNames from "classnames"
import React from "react"
import s from './TabPane.module.scss'
export interface TabPaneProps {
active?: boolean;
children?: React.ReactNode;
tabName: string
}
const TabPane = ({ active, children } : TabPaneProps) => {
return (
<section className={classNames(s.tabPane, {
[s.active] : active
})}>
{children}
</section>
)
}
export default TabPane

View File

@@ -30,8 +30,19 @@ export { default as SelectCommon} from './SelectCommon/SelectCommon'
export { default as ModalCommon} from './ModalCommon/ModalCommon'
export { default as ModalConfirm} from "./ModalConfirm/ModalConfirm"
export { default as ModalInfo} from "./ModalInfo/ModalInfo"
export { default as ProductList} from "./ProductList/ProductList"
export { default as ModalCreateUserInfo} from './ModalCreateUserInfo/ModalCreateUserInfo'
export { default as CardItemCheckout} from './CardItemCheckout/CardItemCheckout'
export { default as CardBlog} from './CardBlog/CardBlog'
export { default as RelevantBlogPosts} from './RelevantBlogPosts/RelevantBlogPosts'
export { default as CollapseCommon} from './CollapseCommon/CollapseCommon'
export { default as BreadcrumbCommon } from './BreadcrumbCommon/BreadcrumbCommon'
export { default as ImgWithLink} from './ImgWithLink/ImgWithLink'
export { default as RecipeDetail} from './RecipeDetail/RecipeDetail'
export { default as DrawerCommon} from './DrawerCommon/DrawerCommon'
export { default as CartDrawer} from './CartDrawer/CartDrawer'
export { default as TabPane} from './TabCommon/components/TabPane/TabPane'
export { default as TabCommon} from './TabCommon/TabCommon'
export { default as StaticImage} from './StaticImage/StaticImage'
export { default as EmptyCommon} from './EmptyCommon/EmptyCommon'
export { default as CustomShapeSvg} from './CustomShapeSvg/CustomShapeSvg'

Some files were not shown because too many files have changed in this diff Show More