diff --git a/.gitignore b/.gitignore index 61386b73c..34232cff6 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,5 @@ yarn-error.log* # vercel .vercel + +.eslintrc diff --git a/codegen.bigcommerce.json b/codegen.bigcommerce.json deleted file mode 100644 index 1f14e88ac..000000000 --- a/codegen.bigcommerce.json +++ /dev/null @@ -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"] - } -} diff --git a/next.config.js b/next.config.js index d3ad64f4a..27bddfae6 100644 --- a/next.config.js +++ b/next.config.js @@ -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'], diff --git a/package.json b/package.json index 91a529d52..85d71c286 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pages/404.tsx b/pages/404.tsx index 8a357fb51..e5265afe0 100644 --- a/pages/404.tsx +++ b/pages/404.tsx @@ -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 (
- The requested page doesn't exist or you don't have access to it. +
) } - NotFound.Layout = Layout diff --git a/pages/account.tsx b/pages/account.tsx new file mode 100644 index 000000000..7da102c52 --- /dev/null +++ b/pages/account.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { Layout } from 'src/components/common'; +import { AccountPage } from 'src/components/modules/account'; + +const Account = () => { + return ( + + ); +}; + +Account.Layout = Layout + +export default Account; \ No newline at end of file diff --git a/pages/blog/[slug].tsx b/pages/blog/[slug].tsx new file mode 100644 index 000000000..8aaca04a9 --- /dev/null +++ b/pages/blog/[slug].tsx @@ -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 ( + <> + + + + + ) +} + +BlogDetailPage.Layout = Layout diff --git a/pages/blogs.tsx b/pages/blogs.tsx new file mode 100644 index 000000000..84e56b55d --- /dev/null +++ b/pages/blogs.tsx @@ -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( + <> + + + + + + ) +} +BlogsPage.Layout = Layout \ No newline at end of file diff --git a/pages/checkout.tsx b/pages/checkout.tsx new file mode 100644 index 000000000..f2bc93517 --- /dev/null +++ b/pages/checkout.tsx @@ -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 ( + <> + + + ) +} + +Checkout.Layout = Layout diff --git a/pages/index.tsx b/pages/index.tsx index cc77bafca..e7b5cab7d 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,22 +1,19 @@ import { Layout } from 'src/components/common'; import { HomeBanner, HomeCategories, HomeCollection, HomeCTA, HomeFeature, HomeRecipe, HomeSubscribe, HomeVideo } from 'src/components/modules/home'; -import Test from './test'; export default function Home() { return ( <> - - - {/* + - */} + - {/* // todo: uncomment */} + {/* // todo: uncomment {/* */} ) diff --git a/pages/privacy-policy.tsx b/pages/privacy-policy.tsx new file mode 100644 index 000000000..daf1b5fd0 --- /dev/null +++ b/pages/privacy-policy.tsx @@ -0,0 +1,12 @@ +import { Layout } from "src/components/common" +import { DeliveryAndPolicyContent, DeliveryAndPolicyBreadCrumb } from "src/components/modules/delivery-policy" + +export default function DeliveryAndPolicyPage () { + return ( + <> + + + + ) +} +DeliveryAndPolicyPage.Layout = Layout \ No newline at end of file diff --git a/pages/products.tsx b/pages/products.tsx new file mode 100644 index 000000000..ebc42d063 --- /dev/null +++ b/pages/products.tsx @@ -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 ( + <> + + + + ) +} + +Products.Layout = Layout diff --git a/pages/recipes.tsx b/pages/recipes.tsx new file mode 100644 index 000000000..a4acece13 --- /dev/null +++ b/pages/recipes.tsx @@ -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 ( + <> + + + + ) +} + +RecipeListPage.Layout = Layout diff --git a/pages/test.tsx b/pages/test.tsx index 95ea43aff..230177f0d 100644 --- a/pages/test.tsx +++ b/pages/test.tsx @@ -1,5 +1,73 @@ -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 = [ + { + 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`, + } + ]; + import CheckoutSuccess from 'src/components/modules/checkout/CheckoutSuccess/CheckoutSuccess' import LoadingCommon from 'src/components/common/LoadingCommon/LoadingCommon' diff --git a/public/assets/images/author.png b/public/assets/images/author.png new file mode 100644 index 000000000..70c922bc6 Binary files /dev/null and b/public/assets/images/author.png differ diff --git a/public/assets/images/image15.png b/public/assets/images/image15.png new file mode 100644 index 000000000..a4d0badbd Binary files /dev/null and b/public/assets/images/image15.png differ diff --git a/public/assets/images/image16.png b/public/assets/images/image16.png new file mode 100644 index 000000000..c5457090e Binary files /dev/null and b/public/assets/images/image16.png differ diff --git a/public/assets/images/image17.png b/public/assets/images/image17.png new file mode 100644 index 000000000..2dcb53d27 Binary files /dev/null and b/public/assets/images/image17.png differ diff --git a/public/assets/images/image20.png b/public/assets/images/image20.png new file mode 100644 index 000000000..548870b87 Binary files /dev/null and b/public/assets/images/image20.png differ diff --git a/public/assets/images/image21.png b/public/assets/images/image21.png new file mode 100644 index 000000000..6cb7b2b43 Binary files /dev/null and b/public/assets/images/image21.png differ diff --git a/public/assets/images/image22.png b/public/assets/images/image22.png new file mode 100644 index 000000000..c45a22c1c Binary files /dev/null and b/public/assets/images/image22.png differ diff --git a/public/assets/images/image23.png b/public/assets/images/image23.png new file mode 100644 index 000000000..928642628 Binary files /dev/null and b/public/assets/images/image23.png differ diff --git a/public/bg-products.svg b/public/bg-products.svg index 2118c3277..1eaa1df8b 100644 --- a/public/bg-products.svg +++ b/public/bg-products.svg @@ -1,7 +1,7 @@ - - - - + + + + diff --git a/report.20210908.160959.14332.0.001.json b/report.20210908.160959.14332.0.001.json new file mode 100644 index 000000000..dc9027da1 --- /dev/null +++ b/report.20210908.160959.14332.0.001.json @@ -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 >::operator<<+10873" + }, + { + "pc": "0x00007ff77aa05b7c", + "symbol": "std::basic_ostream >::operator<<+28316" + }, + { + "pc": "0x00007ff77aa04b38", + "symbol": "std::basic_ostream >::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" + ] +} \ No newline at end of file diff --git a/report.20210909.162411.14356.0.001.json b/report.20210909.162411.14356.0.001.json new file mode 100644 index 000000000..26661c6d8 --- /dev/null +++ b/report.20210909.162411.14356.0.001.json @@ -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 >::operator<<+10873" + }, + { + "pc": "0x00007ff7cdbe5b7c", + "symbol": "std::basic_ostream >::operator<<+28316" + }, + { + "pc": "0x00007ff7cdbe4b38", + "symbol": "std::basic_ostream >::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" + ] +} \ No newline at end of file diff --git a/src/components/common/Author/Author.module.scss b/src/components/common/Author/Author.module.scss index 0459a9fbb..8d903546f 100644 --- a/src/components/common/Author/Author.module.scss +++ b/src/components/common/Author/Author.module.scss @@ -1,3 +1,4 @@ +@import '../../../styles/utilities'; .authorWarper{ @apply flex flex-row items-center; diff --git a/src/components/common/Author/Author.tsx b/src/components/common/Author/Author.tsx index bbb389fbd..1cf8e52af 100644 --- a/src/components/common/Author/Author.tsx +++ b/src/components/common/Author/Author.tsx @@ -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 (
- +
{name}
) diff --git a/src/components/common/BreadcrumbCommon/BreadcrumbCommon.tsx b/src/components/common/BreadcrumbCommon/BreadcrumbCommon.tsx index 6ad2e6817..32ad88ab0 100644 --- a/src/components/common/BreadcrumbCommon/BreadcrumbCommon.tsx +++ b/src/components/common/BreadcrumbCommon/BreadcrumbCommon.tsx @@ -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' @@ -34,4 +35,4 @@ const BreadcrumbCommon = ({ crumbs, showHomePage = true }: BreadcrumbCommonProps ) } -export default BreadcrumbCommon +export default BreadcrumbCommon \ No newline at end of file diff --git a/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.tsx b/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.tsx index 13f980ea9..24f58a066 100644 --- a/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.tsx +++ b/src/components/common/BreadcrumbCommon/components/BreadcrumbItem/BreadcrumbItem.tsx @@ -15,4 +15,4 @@ const BreadcrumbItem = ({ text, href }: BreadcrumbItemProps) => { ) } -export default BreadcrumbItem +export default BreadcrumbItem \ No newline at end of file diff --git a/src/components/common/BreadcrumbCommon/components/BreadcrumbSeparator/BreadcrumbSeparator.tsx b/src/components/common/BreadcrumbCommon/components/BreadcrumbSeparator/BreadcrumbSeparator.tsx index 370c342d8..f84bc3a51 100644 --- a/src/components/common/BreadcrumbCommon/components/BreadcrumbSeparator/BreadcrumbSeparator.tsx +++ b/src/components/common/BreadcrumbCommon/components/BreadcrumbSeparator/BreadcrumbSeparator.tsx @@ -1,7 +1,7 @@ import React from 'react' interface BreadcrumbSeparatorProps { - children?: React.ReactNode + children?: React.ReactNode; } const BreadcrumbSeparator = ({ children }: BreadcrumbSeparatorProps) => { diff --git a/src/components/common/CardBlog/CardBlog.module.scss b/src/components/common/CardBlog/CardBlog.module.scss new file mode 100644 index 000000000..6e62ed5ff --- /dev/null +++ b/src/components/common/CardBlog/CardBlog.module.scss @@ -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; + } +} \ No newline at end of file diff --git a/src/components/common/CardBlog/CardBlog.tsx b/src/components/common/CardBlog/CardBlog.tsx new file mode 100644 index 000000000..314a6a1fd --- /dev/null +++ b/src/components/common/CardBlog/CardBlog.tsx @@ -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 ( +
+ + +
+ image cardblog +
+
+ + + +
{title}
+
+ +
{description}
+
+ ) +} + +export default CardBlog diff --git a/src/components/common/CardItemCheckout/CardItemCheckout.module.scss b/src/components/common/CardItemCheckout/CardItemCheckout.module.scss new file mode 100644 index 000000000..3617cb91f --- /dev/null +++ b/src/components/common/CardItemCheckout/CardItemCheckout.module.scss @@ -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); + } + } + } +} \ No newline at end of file diff --git a/src/components/common/CardItemCheckout/CardItemCheckout.tsx b/src/components/common/CardItemCheckout/CardItemCheckout.tsx new file mode 100644 index 000000000..e67057aa6 --- /dev/null +++ b/src/components/common/CardItemCheckout/CardItemCheckout.tsx @@ -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 ( +
+
+ image +
+
+
+ {`${name} (${weight})`} +
+
+ Quantity: +
+ {`${quantity} x ${price}`} +
+
+
+
+ ) +} + +export default CardItemCheckout diff --git a/src/components/common/CarouselCommon/CarouselCommon.tsx b/src/components/common/CarouselCommon/CarouselCommon.tsx index 136c323f3..3b5854ed4 100644 --- a/src/components/common/CarouselCommon/CarouselCommon.tsx +++ b/src/components/common/CarouselCommon/CarouselCommon.tsx @@ -28,7 +28,6 @@ const CarouselCommon = ({ option: { slideChanged,slidesPerView, ...sliderOption }, }: CarouselCommonProps) => { const [currentSlide, setCurrentSlide] = React.useState(0) - // const [dotActive, setDotActive] = React.useState(0) const [dotArr, setDotArr] = React.useState([]) const [sliderRef, slider] = useKeenSlider({ ...sliderOption, diff --git a/src/components/common/CheckboxCommon/CheckboxCommon.tsx b/src/components/common/CheckboxCommon/CheckboxCommon.tsx index d901f91f4..73c69bb24 100644 --- a/src/components/common/CheckboxCommon/CheckboxCommon.tsx +++ b/src/components/common/CheckboxCommon/CheckboxCommon.tsx @@ -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(true); @@ -31,7 +32,7 @@ const CheckboxCommon = ({onChange,defaultChecked = true,...props}: CheckboxProps
- +
) diff --git a/src/components/common/CheckoutCollapse/CheckoutCollapse.module.scss b/src/components/common/CheckoutCollapse/CheckoutCollapse.module.scss new file mode 100644 index 000000000..9e8e1f8e5 --- /dev/null +++ b/src/components/common/CheckoutCollapse/CheckoutCollapse.module.scss @@ -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; + } + } +} \ No newline at end of file diff --git a/src/components/common/CheckoutCollapse/CheckoutCollapse.tsx b/src/components/common/CheckoutCollapse/CheckoutCollapse.tsx new file mode 100644 index 000000000..077b94a79 --- /dev/null +++ b/src/components/common/CheckoutCollapse/CheckoutCollapse.tsx @@ -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 ( +
+
+
+
+ {isEdit?:id} +
+
+ {title} +
+
+ {isEdit &&
{'Edit'}
} +
+ {(!visible && isEdit) && (
{note}
) } +
{children}
+
+ ) +} + +export default CheckoutCollapse diff --git a/src/components/common/CollapseCommon/CollapseChild/CollapseChild.module.scss b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.module.scss new file mode 100644 index 000000000..839f4de65 --- /dev/null +++ b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.module.scss @@ -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; + } +} \ No newline at end of file diff --git a/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx new file mode 100644 index 000000000..408b0c397 --- /dev/null +++ b/src/components/common/CollapseCommon/CollapseChild/CollapseChild.tsx @@ -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( +
+
+

{title}

+
+
+
+ {content} +
+
+ ) +} + +export default CollapseChild \ No newline at end of file diff --git a/src/components/common/CollapseCommon/CollapseCommon.tsx b/src/components/common/CollapseCommon/CollapseCommon.tsx new file mode 100644 index 000000000..2e378abf9 --- /dev/null +++ b/src/components/common/CollapseCommon/CollapseCommon.tsx @@ -0,0 +1,19 @@ +import CollapseChild from './CollapseChild/CollapseChild' + +interface CollapseCommonProps{ + data: {title: string, content: string}[], +} + +const CollapseCommon = ({data}: CollapseCommonProps) => { + return ( +
+ { + data.map((item,index) => + + ) + } +
+ ) +} + +export default CollapseCommon diff --git a/src/components/common/CustomShapeSvg/CustomShapeSvg.tsx b/src/components/common/CustomShapeSvg/CustomShapeSvg.tsx new file mode 100644 index 000000000..573160b70 --- /dev/null +++ b/src/components/common/CustomShapeSvg/CustomShapeSvg.tsx @@ -0,0 +1,21 @@ + +const CustomShapeSvg = () => { + return ( + <> + + + + + + + + + + + + ) +} + +export default CustomShapeSvg \ No newline at end of file diff --git a/src/components/common/CustomShapeSvg/ViewAllItem.module.scss b/src/components/common/CustomShapeSvg/ViewAllItem.module.scss new file mode 100644 index 000000000..b4ec26872 --- /dev/null +++ b/src/components/common/CustomShapeSvg/ViewAllItem.module.scss @@ -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); + } + } +} diff --git a/src/components/common/DrawerCommon/DrawerCommon.module.scss b/src/components/common/DrawerCommon/DrawerCommon.module.scss index 3253eac50..d118d45e8 100644 --- a/src/components/common/DrawerCommon/DrawerCommon.module.scss +++ b/src/components/common/DrawerCommon/DrawerCommon.module.scss @@ -17,7 +17,7 @@ width: 100%; margin-right: 0; @screen md { - max-width: 55rem; + max-width: 52rem; } .top { @apply flex justify-between items-center; diff --git a/src/components/common/EmptyCommon/EmptyCommon.module.scss b/src/components/common/EmptyCommon/EmptyCommon.module.scss new file mode 100644 index 000000000..a31ba4374 --- /dev/null +++ b/src/components/common/EmptyCommon/EmptyCommon.module.scss @@ -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; + } +} diff --git a/src/components/common/EmptyCommon/EmptyCommon.tsx b/src/components/common/EmptyCommon/EmptyCommon.tsx new file mode 100644 index 000000000..8b5b3a132 --- /dev/null +++ b/src/components/common/EmptyCommon/EmptyCommon.tsx @@ -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 ( +
+
+ +
+ { + description &&
+ {description} +
+ } +
+ ) +} + +export default EmptyCommon \ No newline at end of file diff --git a/src/components/common/EmptyCommon/empty.png b/src/components/common/EmptyCommon/empty.png new file mode 100644 index 000000000..68d392d86 Binary files /dev/null and b/src/components/common/EmptyCommon/empty.png differ diff --git a/src/components/common/EmptyCommon/empty.svg b/src/components/common/EmptyCommon/empty.svg new file mode 100644 index 000000000..c62a71ab3 --- /dev/null +++ b/src/components/common/EmptyCommon/empty.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/common/Footer/Footer.tsx b/src/components/common/Footer/Footer.tsx index a830c60ea..bf16bd3d7 100644 --- a/src/components/common/Footer/Footer.tsx +++ b/src/components/common/Footer/Footer.tsx @@ -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, }, ] } diff --git a/src/components/common/Header/Header.module.scss b/src/components/common/Header/Header.module.scss index 3e40e067d..99cd29fe0 100644 --- a/src/components/common/Header/Header.module.scss +++ b/src/components/common/Header/Header.module.scss @@ -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; + 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; + } +} diff --git a/src/components/common/Header/Header.tsx b/src/components/common/Header/Header.tsx index a9926f765..5b42c6aaf 100644 --- a/src/components/common/Header/Header.tsx +++ b/src/components/common/Header/Header.tsx @@ -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(null) const [isFullHeader, setIsFullHeader] = useState(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 ( <> -
- +
+
- - +
+ + +
+ +
+ - + + ) }) diff --git a/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.module.scss b/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.module.scss index 9717fd29d..77e6aee82 100644 --- a/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.module.scss +++ b/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.module.scss @@ -3,37 +3,21 @@ .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); - .menu { - @apply flex items-center list-none; - padding: 0.8rem 0; - li { - &:not(:last-child) { - margin-right: 3.2rem; - } - a { - @appy no-underline; - } + @apply flex justify-between items-center spacing-horizontal bg-primary caption; + padding-top: 0.8rem; + padding-bottom: 0.8rem; + color: var(--white); + .menu { + @apply flex items-center list-none; + padding: 0.8rem 0; + li { + &:not(:last-child) { + margin-right: 3.2rem; + } + a { + @appy no-underline; } } } } } - -@keyframes showHeaderHightlight { - 0% { - transform: translateY(-4rem); - } - 100% { - transform: none; - } -} diff --git a/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.tsx b/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.tsx index a1759eede..d0d4eede7 100644 --- a/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.tsx +++ b/src/components/common/Header/components/HeaderHighLight/HeaderHighLight.tsx @@ -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 ( -
+
Free Shipping on order $49+ / Express $99+
diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss b/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss index 2832211c1..09f4dadbc 100644 --- a/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss +++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.module.scss @@ -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; } } } diff --git a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx index aa962605d..8037b357a 100644 --- a/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx +++ b/src/components/common/Header/components/HeaderMenu/HeaderMenu.tsx @@ -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,15 +40,24 @@ const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo }: Props) => { }, ], [openModalAuthen]) - return (
- +
+ { + FILTER_PAGE.includes(router.pathname) && ( + + ) + } + +
+
@@ -68,10 +82,20 @@ const HeaderMenu = memo(({ isFull, openModalAuthen, openModalInfo }: Props) => {
  • -
  • + + { + FILTER_PAGE.includes(router.pathname) && ( +
  • + +
  • + ) + }
    ) diff --git a/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.module.scss b/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.module.scss index 8a1d76c4d..3d8016c6b 100644 --- a/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.module.scss +++ b/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.module.scss @@ -3,38 +3,34 @@ .headerSubMenu { @apply hidden; @screen md { - transform: translateY(-10rem); - height: 0; - &.show { - @apply block; - padding-bottom: 2.4rem; - transform: none; - height: unset; + @apply block; + padding-bottom: 2.4rem; + transform: none; + height: unset; + @screen lg { + @apply flex justify-between items-center; + } + .menu { + @apply flex items-center list-none; + margin-bottom: 2.4rem; @screen lg { - @apply flex justify-between items-center; + margin-bottom: 0; } - .menu { - @apply flex items-center list-none; - margin-bottom: 2.4rem; - @screen lg { - margin-bottom: 0; + li { + &:not(:last-child) { + margin-right: 2.4rem; + @screen lg { + margin-right: 4rem; + } } - li { - &:not(:last-child) { - margin-right: 2.4rem; - @screen lg { - margin-right: 4rem; - } - } - a { - @appy no-underline; - } - &:hover { - @apply text-primary; - } - &.active { - @apply text-primary; - } + a { + @appy no-underline; + } + &:hover { + @apply text-primary; + } + &.active { + @apply text-primary; } } } diff --git a/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.tsx b/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.tsx index 6a02259b5..eb7d0a18a 100644 --- a/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.tsx +++ b/src/components/common/Header/components/HeaderSubMenu/HeaderSubMenu.tsx @@ -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 ( -
    +
      {/* todo: handle active item */}
    • diff --git a/src/components/common/ImgWithLink/ImgWithLink.module.scss b/src/components/common/ImgWithLink/ImgWithLink.module.scss index 413f96cdb..c454aaa4a 100644 --- a/src/components/common/ImgWithLink/ImgWithLink.module.scss +++ b/src/components/common/ImgWithLink/ImgWithLink.module.scss @@ -5,5 +5,8 @@ height: 100%; img { object-fit: cover; + background-size: contain !important; + background-position: center !important; + background-repeat: no-repeat; } } diff --git a/src/components/common/ImgWithLink/ImgWithLink.tsx b/src/components/common/ImgWithLink/ImgWithLink.tsx index 092322085..62a30fa45 100644 --- a/src/components/common/ImgWithLink/ImgWithLink.tsx +++ b/src/components/common/ImgWithLink/ImgWithLink.tsx @@ -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 (
      - {alt} + {alt}
      ) } diff --git a/src/components/common/InputCommon/InputCommon.module.scss b/src/components/common/InputCommon/InputCommon.module.scss index acfc07647..6b12d2bbd 100644 --- a/src/components/common/InputCommon/InputCommon.module.scss +++ b/src/components/common/InputCommon/InputCommon.module.scss @@ -15,9 +15,9 @@ .icon + .inputCommon { padding-left: 4.8rem; } - + .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, diff --git a/src/components/common/InputCommon/InputCommon.tsx b/src/components/common/InputCommon/InputCommon.tsx index 943b0a632..0389c99b3 100644 --- a/src/components/common/InputCommon/InputCommon.tsx +++ b/src/components/common/InputCommon/InputCommon.tsx @@ -6,6 +6,7 @@ import s from './InputCommon.module.scss'; type Ref = { focus: () => void + getValue: () => string | number } | null; interface Props { children?: React.ReactNode, diff --git a/src/components/common/Layout/Layout.module.scss b/src/components/common/Layout/Layout.module.scss index e495667eb..30e4a077d 100644 --- a/src/components/common/Layout/Layout.module.scss +++ b/src/components/common/Layout/Layout.module.scss @@ -6,3 +6,8 @@ flex: 1; } } +.filter{ + @screen xl { + display: none; + } +} \ No newline at end of file diff --git a/src/components/common/Layout/Layout.tsx b/src/components/common/Layout/Layout.tsx index 18fa73b33..8b93825b4 100644 --- a/src/components/common/Layout/Layout.tsx +++ b/src/components/common/Layout/Layout.tsx @@ -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,26 +17,25 @@ interface Props { // note: demo code const Layout: FC = ({ children }) => { const { locale = 'en-US' } = useRouter() - // const { visible: visibleCartDrawer, openModal, closeModal: closeCartDrawer } = useModalCommon({ initialValue: false }) - - // const toggle = () => { - // if (visibleCartDrawer) { - // closeCartDrawer() - // } else { - // openModal() - // } - // } + const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false }) + + const toggleFilter = () => { + if (visibleFilter) { + closeFilter() + } else { + openFilter() + } + } return ( -
      -
      -
      {children}
      - {/* */} - {/* */} -
      -
      +
      +
      +
      {children}
      + + +
      +
      +
      ) diff --git a/src/components/common/MenuDropdown/MenuDropdown.module.scss b/src/components/common/MenuDropdown/MenuDropdown.module.scss index ae5b76c3d..5332794ff 100644 --- a/src/components/common/MenuDropdown/MenuDropdown.module.scss +++ b/src/components/common/MenuDropdown/MenuDropdown.module.scss @@ -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; diff --git a/src/components/common/MenuFilter/MenuFilter.module.scss b/src/components/common/MenuFilter/MenuFilter.module.scss new file mode 100644 index 000000000..87a792297 --- /dev/null +++ b/src/components/common/MenuFilter/MenuFilter.module.scss @@ -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); + } + } + } + } +} diff --git a/src/components/common/MenuFilter/MenuFilter.tsx b/src/components/common/MenuFilter/MenuFilter.tsx new file mode 100644 index 000000000..454942734 --- /dev/null +++ b/src/components/common/MenuFilter/MenuFilter.tsx @@ -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(''); + + 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 ( +
      +

      {heading}

      +
        + { + categories.map(item =>
      • +
        handleClick(item.link)} className={classNames({ [s.active]: item.link === active? true: false })}> + {item.name} +
        +
      • ) + } +
      +
      + ) +} + +export default MenuFilter diff --git a/src/components/common/MenuNavigation/MenuNavigation.module.scss b/src/components/common/MenuNavigation/MenuNavigation.module.scss new file mode 100644 index 000000000..7535df707 --- /dev/null +++ b/src/components/common/MenuNavigation/MenuNavigation.module.scss @@ -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; + } + } + } + } + } +} diff --git a/src/components/common/MenuNavigation/MenuNavigation.tsx b/src/components/common/MenuNavigation/MenuNavigation.tsx new file mode 100644 index 000000000..4a8943051 --- /dev/null +++ b/src/components/common/MenuNavigation/MenuNavigation.tsx @@ -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 ( +
      +

      {heading}({categories.length})

      + +
      + ) +} + +export default MenuNavigation diff --git a/src/components/common/MenuNavigationProductList/MenuNavigationProductList.module.scss b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.module.scss new file mode 100644 index 000000000..042785c05 --- /dev/null +++ b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.module.scss @@ -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%; + } + } + } +} \ No newline at end of file diff --git a/src/components/common/MenuNavigationProductList/MenuNavigationProductList.tsx b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.tsx new file mode 100644 index 000000000..590368da4 --- /dev/null +++ b/src/components/common/MenuNavigationProductList/MenuNavigationProductList.tsx @@ -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( + <> +
      + + + +
      +
      +
      +
      +
      +

      FILTER

      +
      +
      + + + + +
      + {LANGUAGE.BUTTON_LABEL.CONFIRM} +
      +
      +
      +
      + + ) +} + +export default MenuNavigationProductList \ No newline at end of file diff --git a/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.module.scss b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.module.scss new file mode 100644 index 000000000..19bd605f8 --- /dev/null +++ b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.module.scss @@ -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; + } + } + } + } + } +} diff --git a/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.tsx b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.tsx new file mode 100644 index 000000000..2e66dfc83 --- /dev/null +++ b/src/components/common/MenuNavigationProductList/MenuSort/MenuSort.tsx @@ -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(''); + + 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 ( +
      +

      {heading}

      +
        + { + SORT.map(item =>
      • +
        handleClick(item.link)} className={classNames({ [s.active]: item.link === active? true: false })}> + {item.name} +
        +
      • ) + } +
      +
      + ) +} + +export default MenuSort diff --git a/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx b/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx index bedb993f4..b1059a441 100644 --- a/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx +++ b/src/components/common/ModalAuthenticate/components/FormLogin/FormLogin.tsx @@ -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' diff --git a/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx b/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx index d03dbc39e..66ec1f8a4 100644 --- a/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx +++ b/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx @@ -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' diff --git a/src/components/common/ModalCommon/ModalCommon.tsx b/src/components/common/ModalCommon/ModalCommon.tsx index 75222c162..7f9bc07d8 100644 --- a/src/components/common/ModalCommon/ModalCommon.tsx +++ b/src/components/common/ModalCommon/ModalCommon.tsx @@ -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 diff --git a/src/components/common/PaginationCommon/PaginationCommon.module.scss b/src/components/common/PaginationCommon/PaginationCommon.module.scss index e69de29bb..6470cd72f 100644 --- a/src/components/common/PaginationCommon/PaginationCommon.module.scss +++ b/src/components/common/PaginationCommon/PaginationCommon.module.scss @@ -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; + } + } +} \ No newline at end of file diff --git a/src/components/common/PaginationCommon/PaginationCommon.tsx b/src/components/common/PaginationCommon/PaginationCommon.tsx index 59bbd3baa..aed2473f3 100644 --- a/src/components/common/PaginationCommon/PaginationCommon.tsx +++ b/src/components/common/PaginationCommon/PaginationCommon.tsx @@ -1,15 +1,75 @@ -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 ( -
      - -
      - ) +const PaginationCommon = ({ + total, + pageSize=DEFAULT_PAGE_SIZE, + defaultCurrent, + onChange, +}: PaginationCommonProps) => { + const [pageNum, setPageNum] = useState(0) + const [currentPage, setCurrentPage] = useState(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 ( +
      +
      + +
      + {[...Array(pageNum).keys()].map((index) => { + return ( + + ) + })} +
      = pageNum - 1, + })} + onClick={onNextClick} + > + = pageNum} /> +
      +
      + ) } export default PaginationCommon diff --git a/src/components/common/PaginationCommon/components/PaginationItem.tsx b/src/components/common/PaginationCommon/components/PaginationItem.tsx new file mode 100644 index 000000000..e5f526bc4 --- /dev/null +++ b/src/components/common/PaginationCommon/components/PaginationItem.tsx @@ -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 ( +
      + {page+1} +
      + ) +} + +export default PaginationItem diff --git a/src/components/common/ProductCard/ProductCard.module.scss b/src/components/common/ProductCard/ProductCard.module.scss index 73be21ab1..cffbe063b 100644 --- a/src/components/common/ProductCard/ProductCard.module.scss +++ b/src/components/common/ProductCard/ProductCard.module.scss @@ -59,7 +59,8 @@ .cardBot{ min-height: 4rem; @apply flex justify-between items-center; - .cardButton{ + .cardIcon{ + margin-right: 0.8rem; } } } \ No newline at end of file diff --git a/src/components/common/ProductCard/ProductCard.tsx b/src/components/common/ProductCard/ProductCard.tsx index 4f1e3b329..a6022efa4 100644 --- a/src/components/common/ProductCard/ProductCard.tsx +++ b/src/components/common/ProductCard/ProductCard.tsx @@ -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 (
      - +
      image
      @@ -42,7 +43,7 @@ const ProductCard = ({
      - +
      {name}
      {weight}
      diff --git a/src/components/common/ProductList/ProductList.module.scss b/src/components/common/ProductList/ProductList.module.scss new file mode 100644 index 000000000..c49696ea5 --- /dev/null +++ b/src/components/common/ProductList/ProductList.module.scss @@ -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 ; + } +} \ No newline at end of file diff --git a/src/components/common/ProductList/ProductList.tsx b/src/components/common/ProductList/ProductList.tsx new file mode 100644 index 000000000..7428e3a63 --- /dev/null +++ b/src/components/common/ProductList/ProductList.tsx @@ -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 ( +
      +
      + { + data.slice(currentPage*20,(currentPage+1)*20).map((product,index)=>{ + return + }) + } +
      +
      + +
      +
      + ) +} + +export default ProductList diff --git a/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.module.scss b/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.module.scss new file mode 100644 index 000000000..6179a6aed --- /dev/null +++ b/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.module.scss @@ -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); + } + } + } + } +} diff --git a/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.tsx b/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.tsx new file mode 100644 index 000000000..396d42d07 --- /dev/null +++ b/src/components/common/RelevantBlogPosts/BlogPostCarousel/BlogPostCarousel.tsx @@ -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, '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 ( +
      + + data={data} + Component={BlogCard} + {...props} + option={{ ...OPTION_DEFAULT, ...option }} + /> +
      + ) +} + +export default BlogPostCarousel diff --git a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss new file mode 100644 index 000000000..ed232830f --- /dev/null +++ b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.module.scss @@ -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; + } + } + } +} diff --git a/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx new file mode 100644 index 000000000..1d71a6ca1 --- /dev/null +++ b/src/components/common/RelevantBlogPosts/RelevantBlogPosts.tsx @@ -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 ( +
      +
      +
      + {title} +
      +
      + +
      +
      +
      + +
      +
      + ) + } + + export default RelevantBlogPosts \ No newline at end of file diff --git a/src/components/common/SelectCommon/SelectCommon.module.scss b/src/components/common/SelectCommon/SelectCommon.module.scss index d91b1831e..4809a46bb 100644 --- a/src/components/common/SelectCommon/SelectCommon.module.scss +++ b/src/components/common/SelectCommon/SelectCommon.module.scss @@ -1,69 +1,90 @@ @import "../../../styles/utilities"; -.select{ +.select { background-color: var(--white); - &.base{ + .selectTrigger { + svg { + @apply transition-all duration-200; + } + } + &.base { width: 20.6rem; - .selectTrigger{ + .selectTrigger { width: 20.6rem; padding: 1.2rem 1.6rem; } } - &.large{ + &.large { width: 34.25rem; - .selectTrigger{ + .selectTrigger { width: 34.25rem; padding: 1.6rem 1.6rem; } } - &.default{ - .selectTrigger{ + &.default { + .selectTrigger { @apply border-solid border border-current; - } + } } - &.custom{ - .selectTrigger{ + &.custom { + .selectTrigger { @apply border-2; border-color: var(--border-line); color: var(--text-label); } } - &.isActive{ - .selectOptionWrapper{ + &:hover { + cursor: pointer; + .hoverWrapper { @apply block; + animation: SelectAnimation 0.2s ease-out; + } + .selectTrigger { + svg { + transform: rotate(180deg); + } } } } -.selectTrigger{ +.selectTrigger { @apply outline-none flex justify-between; color: var(--text-active); border-radius: 0.8rem; - } -.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; +.hoverWrapper { + @apply hidden outline-none absolute z-10; + padding-top: 0.6rem; + .selectOptionWrapper { + border-radius: 0.8rem; + background-color: var(--white); + padding: 0.4rem 0rem 0.4rem 0rem; + &.base { + width: 20.6rem; + } + &.large { + width: 34.25rem; + } + &.default { + @apply border-solid border border-current; + } + &.custom { + @apply border-2; + border-color: var(--border-line); + color: var(--text-label); + } } - &.large{ - width: 34.25rem; - } - &.default{ - @apply border-solid border border-current; - } - &.custom{ - @apply border-2; - 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; + } +} diff --git a/src/components/common/SelectCommon/SelectCommon.tsx b/src/components/common/SelectCommon/SelectCommon.tsx index 5bb3d15d6..9b8c88e24 100644 --- a/src/components/common/SelectCommon/SelectCommon.tsx +++ b/src/components/common/SelectCommon/SelectCommon.tsx @@ -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(null) - - 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 SelectCommon = ({ type = 'default', size = 'base', option, placeholder, onChange}: Props) => { + const [selectedName, setSelectedName] = useState(placeholder) + const [selectedValue, setSelectedValue] = useState('') - const changeActiveStatus = () => { - setActive(!isActive) - } - - const changeSelectedName = (item:string) => { + const changeSelectedName = (item:string, value: string) => { + setSelectedValue(value) setSelectedName(item) + onChange && onChange(value) } return( <> @@ -45,29 +27,29 @@ 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} >
      {selectedName}
      - -
      - { - option.map(item => - - ) - } + +
      +
      + { + option.map(item => + + ) + } +
      +
      ) diff --git a/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss b/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss index 5448f9879..ef504c112 100644 --- a/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss +++ b/src/components/common/SelectCommon/SelectOption/SelectOption.module.scss @@ -13,5 +13,9 @@ } &:hover{ background-color: var(--gray); + color: var(--primary); + } + &.isChoose{ + background-color: var(--gray); } } \ No newline at end of file diff --git a/src/components/common/SelectCommon/SelectOption/SelectOption.tsx b/src/components/common/SelectCommon/SelectOption/SelectOption.tsx index 54877d5fe..7e1968f9e 100644 --- a/src/components/common/SelectCommon/SelectOption/SelectOption.tsx +++ b/src/components/common/SelectCommon/SelectOption/SelectOption.tsx @@ -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(
      {itemName}
      diff --git a/src/components/common/StaticImage/StaticImage.module.scss b/src/components/common/StaticImage/StaticImage.module.scss new file mode 100644 index 000000000..4700c71cc --- /dev/null +++ b/src/components/common/StaticImage/StaticImage.module.scss @@ -0,0 +1,5 @@ +.staticImage { + img { + @apply w-full h-full; + } +} diff --git a/src/components/common/StaticImage/StaticImage.tsx b/src/components/common/StaticImage/StaticImage.tsx new file mode 100644 index 000000000..f744e492d --- /dev/null +++ b/src/components/common/StaticImage/StaticImage.tsx @@ -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 ( + {alt} + ) +} + +export default StaticImage \ No newline at end of file diff --git a/src/components/common/TabCommon/TabCommon.module.scss b/src/components/common/TabCommon/TabCommon.module.scss new file mode 100644 index 000000000..d8b5d0f9a --- /dev/null +++ b/src/components/common/TabCommon/TabCommon.module.scss @@ -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; + } + } + } +} diff --git a/src/components/common/TabCommon/TabCommon.tsx b/src/components/common/TabCommon/TabCommon.tsx new file mode 100644 index 000000000..7214361f7 --- /dev/null +++ b/src/components/common/TabCommon/TabCommon.tsx @@ -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(null) + const headerRef = useRef(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 ( +
      +
      +
        + {Children.map(children, (tab, index) => { + let item = tab as ReactElement> + return ( +
      • + + {item.props.tabName} + +
      • + ) + })} +
        +
      +
      +
      + {Children.map(children, (tab, index) => { + let item = tab as ReactElement> + return cloneElement(item, { active:index===active }); + }) + }
      +
      + ) + } + + export default TabCommon diff --git a/src/components/common/TabCommon/TabItem/TabItem.module.scss b/src/components/common/TabCommon/TabItem/TabItem.module.scss new file mode 100644 index 000000000..bdbb0b66a --- /dev/null +++ b/src/components/common/TabCommon/TabItem/TabItem.module.scss @@ -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; + } +} diff --git a/src/components/common/TabCommon/TabItem/TabItem.tsx b/src/components/common/TabCommon/TabItem/TabItem.tsx new file mode 100644 index 000000000..ab9eb69f9 --- /dev/null +++ b/src/components/common/TabCommon/TabItem/TabItem.tsx @@ -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 ( + + {children} + + ) +} + +export default TabItem; \ No newline at end of file diff --git a/src/components/common/TabCommon/components/TabItem/TabItem.module.scss b/src/components/common/TabCommon/components/TabItem/TabItem.module.scss new file mode 100644 index 000000000..159a38f57 --- /dev/null +++ b/src/components/common/TabCommon/components/TabItem/TabItem.module.scss @@ -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; + } +} diff --git a/src/components/common/TabCommon/components/TabItem/TabItem.tsx b/src/components/common/TabCommon/components/TabItem/TabItem.tsx new file mode 100644 index 000000000..49750dc55 --- /dev/null +++ b/src/components/common/TabCommon/components/TabItem/TabItem.tsx @@ -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 ( + + {children} + + ) +} + +export default TabItem diff --git a/src/components/common/TabCommon/components/TabPane/TabPane.module.scss b/src/components/common/TabCommon/components/TabPane/TabPane.module.scss new file mode 100644 index 000000000..380472828 --- /dev/null +++ b/src/components/common/TabCommon/components/TabPane/TabPane.module.scss @@ -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; + } +} \ No newline at end of file diff --git a/src/components/common/TabCommon/components/TabPane/TabPane.tsx b/src/components/common/TabCommon/components/TabPane/TabPane.tsx new file mode 100644 index 000000000..c0c7d2efa --- /dev/null +++ b/src/components/common/TabCommon/components/TabPane/TabPane.tsx @@ -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 ( +
      + {children} +
      + ) +} + +export default TabPane \ No newline at end of file diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 6fe49c9b1..7de333d3a 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -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' diff --git a/src/components/contexts/FilterContext.tsx b/src/components/contexts/FilterContext.tsx new file mode 100644 index 000000000..36a10ce9f --- /dev/null +++ b/src/components/contexts/FilterContext.tsx @@ -0,0 +1,43 @@ +import { createContext, ReactNode, useContext, useState } from "react"; +import { filterContextType } from "src/utils/types.utils"; + +const contextDefaultValues: filterContextType = { + visible: false, + open: () => {}, + close: () => {}, +}; + +const FilterContext = createContext(contextDefaultValues); + +export function useAuth() { + return useContext(FilterContext); +} + +type FilterProviderProps = { + children: ReactNode; +}; + +export function FilterProvider({ children }: FilterProviderProps) { + const [visible, setVisible] = useState(false); + + const open = () => { + setVisible(true); + }; + + const close = () => { + setVisible(false); + }; + + const value = { + visible, + open, + close, + }; + return ( + <> + + {children} + + + ); +} \ No newline at end of file diff --git a/src/utils/useClickOutSide.ts b/src/components/hooks/useClickOutSide.ts similarity index 92% rename from src/utils/useClickOutSide.ts rename to src/components/hooks/useClickOutSide.ts index d68e742fb..ff69007a8 100644 --- a/src/utils/useClickOutSide.ts +++ b/src/components/hooks/useClickOutSide.ts @@ -1,5 +1,5 @@ import { RefObject, useEffect } from 'react' -import { MouseAndTouchEvent } from './types.utils' +import { MouseAndTouchEvent } from '../../utils/types.utils' export function useOnClickOutside( ref: RefObject, diff --git a/src/components/icons/ArrowLeftSmall.tsx b/src/components/icons/ArrowLeftSmall.tsx new file mode 100644 index 000000000..7bb82665d --- /dev/null +++ b/src/components/icons/ArrowLeftSmall.tsx @@ -0,0 +1,18 @@ +const ArrowLeft = ({ ...props }) => { + return ( + + + + ) +} + +export default ArrowLeft diff --git a/src/components/icons/ArrowRightSmall.tsx b/src/components/icons/ArrowRightSmall.tsx new file mode 100644 index 000000000..36b4cd589 --- /dev/null +++ b/src/components/icons/ArrowRightSmall.tsx @@ -0,0 +1,18 @@ +const ArrowRight = ({ ...props }) => { + return ( + + + + ) +} + +export default ArrowRight diff --git a/src/components/icons/IconArrowUp.tsx b/src/components/icons/IconArrowUp.tsx index 3eac6391b..1f518d612 100644 --- a/src/components/icons/IconArrowUp.tsx +++ b/src/components/icons/IconArrowUp.tsx @@ -2,7 +2,7 @@ const ArrowUp = () => { return ( - + ) } diff --git a/src/components/icons/IconCirclePlus.tsx b/src/components/icons/IconCirclePlus.tsx new file mode 100644 index 000000000..c59766d89 --- /dev/null +++ b/src/components/icons/IconCirclePlus.tsx @@ -0,0 +1,20 @@ +import React from 'react' + +const IconCirclePlus = () => { + return ( + + + + ) +} + +export default IconCirclePlus diff --git a/src/components/icons/IconDoneCheckout.tsx b/src/components/icons/IconDoneCheckout.tsx new file mode 100644 index 000000000..418472d23 --- /dev/null +++ b/src/components/icons/IconDoneCheckout.tsx @@ -0,0 +1,20 @@ +import React from 'react' + +const IconDoneCheckout = () => { + return ( + + + + ) +} + +export default IconDoneCheckout diff --git a/src/components/icons/IconFilter.tsx b/src/components/icons/IconFilter.tsx new file mode 100644 index 000000000..2c06b9139 --- /dev/null +++ b/src/components/icons/IconFilter.tsx @@ -0,0 +1,22 @@ +import React from 'react' + +interface Props {} + +const IconFilter = (props: Props) => { + return ( + + + + ) +} + +export default IconFilter diff --git a/src/components/icons/IconHide.tsx b/src/components/icons/IconHide.tsx new file mode 100644 index 000000000..a977aff84 --- /dev/null +++ b/src/components/icons/IconHide.tsx @@ -0,0 +1,12 @@ +import React from 'react' + +const IconHide = () => { + return ( + + + + + ) +} + +export default IconHide diff --git a/src/components/icons/IconVectorDown.tsx b/src/components/icons/IconVectorDown.tsx index 019fc2806..0bb1cb8c1 100644 --- a/src/components/icons/IconVectorDown.tsx +++ b/src/components/icons/IconVectorDown.tsx @@ -1,5 +1,3 @@ - - const IconVectorDown = ({ ...props }) => { return ( { + return ( + + + + ) +} + +export default Shipping diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts index d773a0b03..7dd36b14f 100644 --- a/src/components/icons/index.ts +++ b/src/components/icons/index.ts @@ -15,11 +15,14 @@ export { default as IconGoogleColor } from './IconGoogleColor' export { default as IconApple } from './IconApple' export { default as ArrowLeft } from './ArrowLeft' export { default as ArrowRight } from './ArrowRight' +export { default as ArrowLeftSmall } from './ArrowLeftSmall' +export { default as ArrowRightSmall } from './ArrowRightSmall' export { default as Close } from './Close' export { default as IconPassword } from './IconPassword' export { default as IconPasswordCross } from './IconPasswordCross' export { default as IconError } from './IconError' export { default as IconCheck } from './IconCheck' +export { default as Shipping} from './Shipping' export { default as IconTime } from './IconTime' export { default as IconPeople } from './IconPeople' export { default as IconLocation } from './IconLocation' @@ -27,3 +30,6 @@ export { default as IconClose } from './IconClose' export { default as IconDelete } from './IconDelete' export { default as IconPlus } from './IconPlus' export { default as IconMinus } from './IconMinus' +export { default as IconCirclePlus } from './IconCirclePlus' +export { default as IconDoneCheckout } from './IconDoneCheckout' +export { default as IconFilter } from './IconFilter' diff --git a/src/components/modules/404/404Page/404Page.module.scss b/src/components/modules/404/404Page/404Page.module.scss new file mode 100644 index 000000000..b089a9ad3 --- /dev/null +++ b/src/components/modules/404/404Page/404Page.module.scss @@ -0,0 +1,36 @@ +@import '../../../../styles/utilities'; +.wrapper{ + @apply flex justify-center; + text-align: center; + height:100%; + + background-color: white; + .inner{ + height: 100vh; + .logo{ + margin-top: 2rem; + } + .text{ + @apply flex justify-center flex-col; + align-items: center; + width: 100%; + height:80%; + margin-top: 2rem; + h1{ + font-weight: bold; + font-size: 15rem; + color: var(--primary); + font-family: var(--font-heading); + text-shadow: 3px 5px 4px var(--primary); + height: 20%; + } + .description{ + @apply topline; + margin-top:1rem; + margin-bottom: 3rem; + color:var(--text-label); + } + } + } + +} \ No newline at end of file diff --git a/src/components/modules/404/404Page/404Page.tsx b/src/components/modules/404/404Page/404Page.tsx new file mode 100644 index 000000000..39eef34ca --- /dev/null +++ b/src/components/modules/404/404Page/404Page.tsx @@ -0,0 +1,28 @@ +import React from 'react' +import { ButtonCommon, Logo } from 'src/components/common' +import s from './404Page.module.scss' +import Link from 'next/link'; +interface Props { +} + +const NotFoundPage = ({ }: Props) => { + return ( + +
      +
      +
      +

      + 404 +

      +

      Opps! it seems we found an Error
      + We couldn't found what you're looking for +

      + + Return to Home Now +
      +
      +
      + ) +} + +export default NotFoundPage diff --git a/src/components/modules/404/index.tsx b/src/components/modules/404/index.tsx new file mode 100644 index 000000000..50990b601 --- /dev/null +++ b/src/components/modules/404/index.tsx @@ -0,0 +1 @@ +export {default as NotFoundPage} from './404Page/404Page'; \ No newline at end of file diff --git a/src/components/modules/account/AccountNavigation/AccountNavigation.module.scss b/src/components/modules/account/AccountNavigation/AccountNavigation.module.scss new file mode 100644 index 000000000..8bece6668 --- /dev/null +++ b/src/components/modules/account/AccountNavigation/AccountNavigation.module.scss @@ -0,0 +1,27 @@ +@import '../../../../styles/utilities'; + +.accountNavigation { + @apply flex; + width: 100%; + + .slider { + @apply inline-block; + width: 0.2rem; + height: 4.8rem; + border-radius: 3px; + background-color: var(--primary); + position: absolute; + left: 11.2rem; + transition: all .2s linear; + } + + .tabList { + margin-top: 3.8rem; + margin-right: 12.4rem; + } + + .tabBody { + margin-top: -4.7rem; + width: 100%; + } +} \ No newline at end of file diff --git a/src/components/modules/account/AccountNavigation/AccountNavigation.tsx b/src/components/modules/account/AccountNavigation/AccountNavigation.tsx new file mode 100644 index 000000000..013b4cbf1 --- /dev/null +++ b/src/components/modules/account/AccountNavigation/AccountNavigation.tsx @@ -0,0 +1,71 @@ +import React, { useRef, useEffect, Children, ReactElement, PropsWithChildren, useState, cloneElement } from "react" +import s from './AccountNavigation.module.scss' + +import AccountNavigationItem from './components/AccountNavigationItem' +import {TabPaneProps} from '../../../common/TabCommon/components/TabPane/TabPane' + +interface AccountNavigationProps { + defaultActiveIndex: number; + children: React.ReactNode +} + +const AccountNavigation = ({ defaultActiveIndex, children } : AccountNavigationProps) => { + const [active, setActive] = useState(defaultActiveIndex) + const sliderRef = useRef(null); + const headerRef = useRef(null) + + const onTabClick = (index: number) => { + setActive(index) + } + + function slide(index: number) { + const active = headerRef.current?.children.item(index)?.getBoundingClientRect() + const header = headerRef.current?.getBoundingClientRect() + const current = sliderRef.current + + if (current && active && header) { + const top = active.top; + current.style.top = top.toString()+"px"; + } + } + + useEffect(() => { + slide(active); + }, [active]) + + return ( +
      +
        + { + Children.map(children, (tab, index) => { + let item = tab as ReactElement> + return ( +
      • + + {item.props.tabName} + +
      • + ) + }) + } +
        +
      + +
      + { + Children.map(children, (tab, index) => { + let item = tab as ReactElement> + return cloneElement(item, { active: index === active }); + }) + } +
      +
      +
      + ) +} + +export default AccountNavigation \ No newline at end of file diff --git a/src/components/modules/account/AccountNavigation/components/AccountNavigationItem.module.scss b/src/components/modules/account/AccountNavigation/components/AccountNavigationItem.module.scss new file mode 100644 index 000000000..10037cdc7 --- /dev/null +++ b/src/components/modules/account/AccountNavigation/components/AccountNavigationItem.module.scss @@ -0,0 +1,17 @@ +@import '../../../../../styles/utilities'; + +.accountNavigationItem { + width: 28rem; + padding: 1.2rem 0 1.2rem 1.6rem; + margin-bottom: 1.2rem; + + + &:hover { + @apply cursor-pointer; + } + + &.active { + background-color: #FBFBFB; + border-radius: 0 1.6rem 1.6rem 0; + } +} \ No newline at end of file diff --git a/src/components/modules/account/AccountNavigation/components/AccountNavigationItem.tsx b/src/components/modules/account/AccountNavigation/components/AccountNavigationItem.tsx new file mode 100644 index 000000000..9f94fb1fc --- /dev/null +++ b/src/components/modules/account/AccountNavigation/components/AccountNavigationItem.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import classNames from "classnames"; +import s from './AccountNavigationItem.module.scss' + +interface AccountNavigationItemProps { + children?: string; + active?: boolean; + tabIndex: number + onClick: (index: number) => void; +} + +const AccountNavigationItem = ({ children, active, tabIndex, onClick } : AccountNavigationItemProps) => { + + const handleClick = () => { + onClick(tabIndex) + } + return ( +
      + {children} +
      + ) +} + +export default AccountNavigationItem \ No newline at end of file diff --git a/src/components/modules/account/AccountPage/AccountPage.module.scss b/src/components/modules/account/AccountPage/AccountPage.module.scss new file mode 100644 index 000000000..3f8307750 --- /dev/null +++ b/src/components/modules/account/AccountPage/AccountPage.module.scss @@ -0,0 +1,26 @@ +@import '../../../../styles/utilities'; + +.accountPage { + @apply spacing-horizontal; + background-color: #F5F4F2; + margin-top: -3.2rem; + padding-top: 3.2rem; + padding-bottom: 3.2rem; + + @screen md { + padding-left: 3.2rem; + padding-right: 3.2rem; + } + + @screen xl { + @apply spacing-horizontal + } + + .header { + margin-bottom: 1.2rem; + + @screen md { + margin-bottom: 3.8rem; + } + } +} \ No newline at end of file diff --git a/src/components/modules/account/AccountPage/AccountPage.tsx b/src/components/modules/account/AccountPage/AccountPage.tsx new file mode 100644 index 000000000..a5a0ef79d --- /dev/null +++ b/src/components/modules/account/AccountPage/AccountPage.tsx @@ -0,0 +1,86 @@ +import React, { useState } from "react" +import s from './AccountPage.module.scss' + +import AccountNavigation from '../AccountNavigation/AccountNavigation' +import HeadingCommon from '../../../common/HeadingCommon/HeadingCommon' +import AccountInfomation from "./components/AccountInfomation/AccountInfomation" +import OrderInfomation from './components/OrderInformation/OrderInformation' +import EditInfoModal from './components/EditInfoModal/EditInfoModal' +import TabPane from "src/components/common/TabCommon/components/TabPane/TabPane" + +const waiting = [ + { + id: "NO 123456", + products: ["Tomato", "Fish", "Pork", "Onion"], + totalPrice : 1000 + } +] + +const delivering = [ + { + id: "NO 123456", + products: ["Tomato", "Fish", "Pork", "Onion", "Tomato", "Fish", "Pork", "Onion"], + totalPrice : 1000 + } +] + +const delivered = [ + { + id: "NO 123456", + products: ["Tomato", "Fish", "Pork", "Onion", "Tomato", "Fish", "Pork", "Onion"], + totalPrice : 1000 + } +] + +let account = { + name: "vu duong", + email: "vuduong@gmail.com", + address: "234 Dien Bien Phu Bis, Dakao ward", + state: "District 1", + city: "HCMC", + postalCode: "700000", + phoneNumber: "(+84) 937 937 195" +} + +interface AccountPageProps { + defaultActiveContent?: "info" | "orders" | "favorites" +} + +const AccountPage = ({defaultActiveContent="orders"} : AccountPageProps) => { + + const [activeTab] = useState(defaultActiveContent==="info" ? 0 : defaultActiveContent==="orders" ? 1 : 2) + const [modalVisible, setModalVisible] = useState(false); + + function showModal() { + setModalVisible(true); + } + + function closeModal() { + setModalVisible(false); + } + + return ( + <> +
      +
      + Account +
      + + + + + + + + + + {/* */} + + +
      + + + ) +} + +export default AccountPage \ No newline at end of file diff --git a/src/components/modules/account/AccountPage/assets/avatar.png b/src/components/modules/account/AccountPage/assets/avatar.png new file mode 100644 index 000000000..b12cabed4 Binary files /dev/null and b/src/components/modules/account/AccountPage/assets/avatar.png differ diff --git a/src/components/modules/account/AccountPage/components/AccountInfomation/AccountInfomation.module.scss b/src/components/modules/account/AccountPage/components/AccountInfomation/AccountInfomation.module.scss new file mode 100644 index 000000000..442dae2eb --- /dev/null +++ b/src/components/modules/account/AccountPage/components/AccountInfomation/AccountInfomation.module.scss @@ -0,0 +1,67 @@ +@import '../../../../../../styles/utilities'; + +.accountInfomation { + @apply flex justify-center items-center; + text-align: center; + margin-top: 1.6rem; + + @screen md { + @apply block; + text-align: left; + margin-top: 0; + } + + .avatar { + height: 22rem; + width: 22rem; + border-radius: 50%; + margin: auto; + margin-bottom: 4rem; + + + @screen md { + margin-left: 0 + } + } + + .accountName { + @apply heading-3 font-heading; + } + + .horizontalSeparator{ + border: 1px solid var(--disabled); + max-width: 39.2rem; + min-width: 30rem; + margin-top: 2.4rem; + margin-bottom: 2.4rem; + } + + .shippingInfo { + @apply heading-3 font-heading; + } + + .accountAddress { + max-width: 31rem; + min-width: none; + } + + .editInfoBtn { + @apply text-center font-bold custom-border-radius; + margin: auto; + margin-top: 2.4rem; + margin-bottom: 2.4rem; + padding: .8rem 1.6rem; + color: #141414; + border: 1px solid #141414; + max-width: 8.8rem; + + &:hover { + @apply cursor-pointer; + background-color: #FBFBFB; + } + + @screen md { + margin-left: 0; + } + } +} \ No newline at end of file diff --git a/src/components/modules/account/AccountPage/components/AccountInfomation/AccountInfomation.tsx b/src/components/modules/account/AccountPage/components/AccountInfomation/AccountInfomation.tsx new file mode 100644 index 000000000..f24b36216 --- /dev/null +++ b/src/components/modules/account/AccountPage/components/AccountInfomation/AccountInfomation.tsx @@ -0,0 +1,56 @@ +import React from "react" +import s from './AccountInfomation.module.scss' + +import Image from "next/image" +import avatar from '../../assets/avatar.png'; + +interface AccountProps { + name: string, email: string, address: string, state: string, city: string, postalCode: string, phoneNumber: string +} + +interface AccountInfomationProps { + account: AccountProps; + onClick: () => void; +} + +const AccountInfomation = ({ account, onClick } : AccountInfomationProps) => { + + // need to handle call back when edit account information + + const showEditForm = () => onClick() + + return ( +
      + { +
      +
      + avatar +
      + +
      + {account.name} +
      +
      + {account.email} +
      + +
      + +
      Shipping Infomation
      + +
      + {account.address + `, ${account.state}, ${account.city}, ${account.postalCode}`} +
      + +
      + {account.phoneNumber} +
      + +
      Edit
      +
      + } +
      + ) +} + +export default AccountInfomation \ No newline at end of file diff --git a/src/components/modules/account/AccountPage/components/EditInfoModal/EditInfoModal.module.scss b/src/components/modules/account/AccountPage/components/EditInfoModal/EditInfoModal.module.scss new file mode 100644 index 000000000..be1384ab7 --- /dev/null +++ b/src/components/modules/account/AccountPage/components/EditInfoModal/EditInfoModal.module.scss @@ -0,0 +1,81 @@ +@import '../../../../../../styles/utilities'; + +.editInfoModal { + .input { + @apply bg-white; + margin-bottom: 1.6rem; + width: 100%; + border: 2px solid #EBEBEB; + border-radius: .8rem; + padding: 1.6rem; + } + + .inputDisable { + margin-bottom: 1.6rem; + width: 100%; + border: 2px solid #EBEBEB; + border-radius: .8rem; + padding: 1.6rem; + background-color: #EBEBEB; + color: #CCCCCC; + } + + .inputStateWrapper { + @apply bg-white; + margin-bottom: 1.6rem; + margin-right: 1.6rem; + border: 2px solid #EBEBEB; + border-radius: .8rem; + padding: 1.6rem; + + .inputState { + @apply bg-white cursor-pointer; + border: white; + } + } + + .inputPostalCode { + @apply bg-white; + margin-bottom: 1.6rem; + border: 2px solid #EBEBEB; + border-radius: .8rem; + padding: 1.6rem; + } + + .inputPhoneNumber { + @apply bg-white; + margin-bottom: 4rem; + width: 100%; + border: 2px solid #EBEBEB; + border-radius: .8rem; + padding: 1.6rem; + } + + .buttons { + @apply flex; + + .buttonCancel { + @apply bg-white text-center font-bold custom-border-radius-lg; + color: #141414; + border: 1px solid #141414; + padding: 1.6rem; + margin-right: 1.6rem; + width: 100%; + + &:hover { + @apply cursor-pointer; + } + } + + .buttonSave { + @apply text-center font-bold custom-border-radius-lg; + background-color: var(--primary); + color: white; + padding: 1.6rem; + width: 100%; + &:hover { + @apply cursor-pointer; + } + } + } +} \ No newline at end of file diff --git a/src/components/modules/account/AccountPage/components/EditInfoModal/EditInfoModal.tsx b/src/components/modules/account/AccountPage/components/EditInfoModal/EditInfoModal.tsx new file mode 100644 index 000000000..d2be8b1a1 --- /dev/null +++ b/src/components/modules/account/AccountPage/components/EditInfoModal/EditInfoModal.tsx @@ -0,0 +1,83 @@ +import classNames from "classnames" +import React, { useState } from "react" +import s from './EditInfoModal.module.scss' + +import {ModalCommon, MenuDropdown} from '../../../../../common' + +import {ButtonCommon} from '../../../../../common' + +interface EditInfoModalProps { + accountInfo: {name: string, email: string, address: string, state: string, city: string, postalCode: string, phoneNumber: string}; + visible: boolean; + closeModal: () => void; +} + +const EditInfoModal = ({ accountInfo, visible = false, closeModal }: EditInfoModalProps) => { + + const [name, setName] = useState(accountInfo.name); + const [email, setEmail] = useState(accountInfo.email); + const [address, setAddress] = useState(accountInfo.address); + const [state, setState] = useState(accountInfo.state); + const [city, setCity] = useState(accountInfo.city); + const [postalCode, setPostalCode] = useState(accountInfo.postalCode); + const [phoneNumber, setPhoneNumber] = useState(accountInfo.phoneNumber); + + function saveInfo() { + console.log("saved !!!"); + + closeModal(); + } + + const states = [ + {name: "D1", onClick: () => {setState("D1")}}, + {name: "D2", onClick: () => {setState("D2")}}, + {name: "D3", onClick: () => {setState("D3")}} + ] + + return ( + +
      +
      + {setName(e.target.value)}} /> +
      +
      + {setEmail(e.target.value)}} /> +
      +
      + {setAddress(e.target.value)}}/> +
      +
      + {setCity(e.target.value)}} /> +
      + +
      +
      + + + +
      + + {setPostalCode(e.target.value)}} /> +
      + +
      + {setPhoneNumber(e.target.value)}} /> +
      + +
      +
      Cancel
      +
      Save
      +
      +
      +
      + ) +} + +export default EditInfoModal \ No newline at end of file diff --git a/src/components/modules/account/AccountPage/components/OrderInformation/OrderInformation.module.scss b/src/components/modules/account/AccountPage/components/OrderInformation/OrderInformation.module.scss new file mode 100644 index 000000000..0096a67d7 --- /dev/null +++ b/src/components/modules/account/AccountPage/components/OrderInformation/OrderInformation.module.scss @@ -0,0 +1,16 @@ +@import '../../../../../../styles/utilities'; + +.orderInformation { + .title { + @apply heading-3 font-heading; + margin-top: 1.6rem; + } + + .tabs { + margin-top: 3.2rem; + + .blank { + margin-bottom: 2.4rem; + } + } +} \ No newline at end of file diff --git a/src/components/modules/account/AccountPage/components/OrderInformation/OrderInformation.tsx b/src/components/modules/account/AccountPage/components/OrderInformation/OrderInformation.tsx new file mode 100644 index 000000000..76985b9fd --- /dev/null +++ b/src/components/modules/account/AccountPage/components/OrderInformation/OrderInformation.tsx @@ -0,0 +1,66 @@ +import React from "react" +import s from './OrderInformation.module.scss' + +import { TabCommon } from '../../../../../common' +import TabPane from 'src/components/common/TabCommon/components/TabPane/TabPane' +import DeliveryItem from '../../../DeliveryItem/DeliveryItem' + + +interface OrderInformationProps { + waiting: {id: string, products: string[], totalPrice: number}[], + delivering: {id: string, products: string[], totalPrice: number}[], + delivered: {id: string, products: string[], totalPrice: number}[], + // active?: boolean +} + +const OrderInformation = ({ waiting, delivering, delivered} : OrderInformationProps) => { + + return ( +
      + { +
      +
      Order Information
      + +
      + + +
      + { + waiting.map((order, i) => { + return ( + + ) + }) + } +
      + + +
      + { + delivering.map((order, i) => { + return ( + + ) + }) + } +
      + + +
      + { + delivered.map((order, i) => { + return ( + + ) + }) + } +
      +
      +
      +
      + } +
      + ) +} + +export default OrderInformation \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/DeliveryItem.module.scss b/src/components/modules/account/DeliveryItem/DeliveryItem.module.scss new file mode 100644 index 000000000..b83b77fd3 --- /dev/null +++ b/src/components/modules/account/DeliveryItem/DeliveryItem.module.scss @@ -0,0 +1,26 @@ +@import '../../../../styles/utilities'; + +.deliveryItem { + @apply flex bg-white items-center custom-border-radius; + margin-bottom: 1.6rem; + border: 1px solid var(--primary) +} + +.separator { + border-left: 2px dashed #EBEBEB; + max-height: 9.2rem; + min-height: 8.6rem; + + margin-left: .6rem; + margin-right: .6rem; + + @screen md { + margin-left: .8rem; + margin-right: .8rem; + } + + @screen lg { + margin-left: 2.4rem; + margin-right: 2.4rem; + } +} \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/DeliveryItem.tsx b/src/components/modules/account/DeliveryItem/DeliveryItem.tsx new file mode 100644 index 000000000..fe8f5cdef --- /dev/null +++ b/src/components/modules/account/DeliveryItem/DeliveryItem.tsx @@ -0,0 +1,30 @@ +import React from "react" +import s from './DeliveryItem.module.scss' + +import IdAndStatus from './components/IdAndStatus/IdAndStatus' +import Products from './components/Products/Products' +import TotalPrice from './components/TotalPrice/TotalPrice' +import ReOrder from './components/ReOrder/ReOrder' + + +interface DeliveryItemProps { + id: string; + status: "waiting" | "delivering" | "delivered"; + products: string[]; + totalPrice: number; + reOrderLink?: string; +} + +const DeliveryItem = ({ id, status, products, totalPrice, reOrderLink } : DeliveryItemProps) => { + return ( +
      + +
      + + + +
      + ) +} + +export default DeliveryItem \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/components/IdAndStatus/IdAndStatus.module.scss b/src/components/modules/account/DeliveryItem/components/IdAndStatus/IdAndStatus.module.scss new file mode 100644 index 000000000..d50ecd115 --- /dev/null +++ b/src/components/modules/account/DeliveryItem/components/IdAndStatus/IdAndStatus.module.scss @@ -0,0 +1,75 @@ +@import '../../../../../../styles/utilities'; + +.idAndStatus { + @apply items-center; + padding: 2.4rem 0 2.4rem 1rem; + + @screen md { + padding: 2.4rem 0 2.4rem 1.2rem; + } + + @screen lg { + padding: 2.4rem 0 2.4rem 2.4rem; + } + + .id { + @apply font-bold; + margin-bottom: .8rem; + } + + .deliveryStatus { + @apply font-bold text-white; + font-size: 1.2rem; + line-height: 2rem; + padding: 0 .8rem; + border-radius: 0.5rem; + width: fit-content; + + &.waiting { + background-color: #D9A645; + } + &.delivering { + background-color: var(--info-dark); + } + &.delivered { + background-color: var(--primary); + } + } +}@import '../../../../../../styles/utilities'; + +.idAndStatus { + @apply items-center; + padding: 2.4rem 0 2.4rem 1rem; + + @screen md { + padding: 2.4rem 0 2.4rem 1.2rem; + } + + @screen lg { + padding: 2.4rem 0 2.4rem 2.4rem; + } + + .id { + @apply font-bold; + margin-bottom: .8rem; + } + + .deliveryStatus { + @apply font-bold text-white; + font-size: 1.2rem; + line-height: 2rem; + padding: 0 .8rem; + border-radius: 0.5rem; + width: fit-content; + + &.waiting { + background-color: #D9A645; + } + &.delivering { + background-color: var(--info-dark); + } + &.delivered { + background-color: var(--primary); + } + } +} \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/components/IdAndStatus/IdAndStatus.tsx b/src/components/modules/account/DeliveryItem/components/IdAndStatus/IdAndStatus.tsx new file mode 100644 index 000000000..841dd530f --- /dev/null +++ b/src/components/modules/account/DeliveryItem/components/IdAndStatus/IdAndStatus.tsx @@ -0,0 +1,25 @@ +import classNames from "classnames" +import React from "react" +import s from './IdAndStatus.module.scss' + + +interface IdAndStatusProps { + id?: string; + status: "waiting" | "delivering" | "delivered"; +} + +const IdAndStatus = ({ id, status="waiting" } : IdAndStatusProps) => { + return ( +
      +
      + {id} +
      +
      {status} +
      +
      + ) +} + +export default IdAndStatus \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/components/Products/Products.module.scss b/src/components/modules/account/DeliveryItem/components/Products/Products.module.scss new file mode 100644 index 000000000..f05d6395b --- /dev/null +++ b/src/components/modules/account/DeliveryItem/components/Products/Products.module.scss @@ -0,0 +1,12 @@ +@import '../../../../../../styles/utilities'; + +.products { + margin-top: .8rem; + max-width: 32%; + min-width: none; + + @screen lg { + margin-top: 0; + margin-bottom: 0; + } +} \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/components/Products/Products.tsx b/src/components/modules/account/DeliveryItem/components/Products/Products.tsx new file mode 100644 index 000000000..fdbba2c73 --- /dev/null +++ b/src/components/modules/account/DeliveryItem/components/Products/Products.tsx @@ -0,0 +1,29 @@ +import React from "react" +import s from './Products.module.scss' + +interface ProductsProps { + products: string[]; +} + +const Products = ({ products } : ProductsProps) => { + + function toString(products:string[]): string { + let strProducts = ""; + products.map((prod, i) => { + if (i === 0) { + strProducts += prod; + } else { + strProducts += `, ${prod}` + } + }); + return strProducts; + } + + return ( +
      + {toString(products)} +
      + ) +} + +export default Products \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/components/ReOrder/ReOrder.module.scss b/src/components/modules/account/DeliveryItem/components/ReOrder/ReOrder.module.scss new file mode 100644 index 000000000..b46b528e1 --- /dev/null +++ b/src/components/modules/account/DeliveryItem/components/ReOrder/ReOrder.module.scss @@ -0,0 +1,27 @@ +@import '../../../../../../styles/utilities'; + +.reOrder { + @apply text-white custom-border-radius hidden font-bold; + padding: .4rem .6rem; + margin-right: 1rem; + background-color: var(--primary); + + @screen md { + padding: .4rem .6rem; + margin-right: 1.2rem; + } + + @screen lg { + padding: .8rem 1.2rem; + margin-right: 2.4rem; + } + + &.show { + @apply block; + } + + &:hover { + @apply cursor-pointer; + } + +} \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/components/ReOrder/ReOrder.tsx b/src/components/modules/account/DeliveryItem/components/ReOrder/ReOrder.tsx new file mode 100644 index 000000000..2fbc546f4 --- /dev/null +++ b/src/components/modules/account/DeliveryItem/components/ReOrder/ReOrder.tsx @@ -0,0 +1,23 @@ +import classNames from "classnames" +import React from "react" +import s from './ReOrder.module.scss' +import Link from 'next/link' + +interface ReOrderProps { + show: boolean; + href?: string; +} + +const ReOrder = ({ show=false, href="#" } : ReOrderProps) => { + return ( +
      + + Re-Order + +
      + ) +} + +export default ReOrder \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/components/TotalPrice/TotalPrice.module.scss b/src/components/modules/account/DeliveryItem/components/TotalPrice/TotalPrice.module.scss new file mode 100644 index 000000000..9a4f795b3 --- /dev/null +++ b/src/components/modules/account/DeliveryItem/components/TotalPrice/TotalPrice.module.scss @@ -0,0 +1,26 @@ +@import '../../../../../../styles/utilities'; + +.totalPrice { + margin-left: auto; + margin-right: 1rem; + + @screen md { + margin-right: 1.2rem; + } + + @screen lg { + margin-right: 2.4rem; + } + + .price { + @apply font-bold ; + + @screen md { + @apply topline + } + + @screen lg { + @apply sub-headline; + } + } +} \ No newline at end of file diff --git a/src/components/modules/account/DeliveryItem/components/TotalPrice/TotalPrice.tsx b/src/components/modules/account/DeliveryItem/components/TotalPrice/TotalPrice.tsx new file mode 100644 index 000000000..153149e85 --- /dev/null +++ b/src/components/modules/account/DeliveryItem/components/TotalPrice/TotalPrice.tsx @@ -0,0 +1,18 @@ +import React from "react" +import s from './TotalPrice.module.scss' + + +interface TotalPriceProps { + totalPrice: number; +} + +const TotalPrice = ({ totalPrice } : TotalPriceProps) => { + return ( +
      +
      Total
      +
      Rp {totalPrice}
      +
      + ) +} + +export default TotalPrice \ No newline at end of file diff --git a/src/components/modules/account/index.ts b/src/components/modules/account/index.ts new file mode 100644 index 000000000..42753b0b5 --- /dev/null +++ b/src/components/modules/account/index.ts @@ -0,0 +1,3 @@ +export { default as AccountNavigation } from './AccountNavigation/AccountNavigation' +export { default as DeliveryItem } from './DeliveryItem/DeliveryItem' +export { default as AccountPage } from './AccountPage/AccountPage' \ No newline at end of file diff --git a/src/components/modules/blog-detail/BlogContent/BlogContent.module.scss b/src/components/modules/blog-detail/BlogContent/BlogContent.module.scss new file mode 100644 index 000000000..e081b5f15 --- /dev/null +++ b/src/components/modules/blog-detail/BlogContent/BlogContent.module.scss @@ -0,0 +1,55 @@ +@import "../../../../styles/_utilities"; + +.blogContentWrapper{ + width: 100%; + padding: 0 2rem; + @screen md { + width: 90%; + margin:0 auto; + } + @screen xl{ + width: 63%; + margin:0 auto; + } + + h1{ + @apply heading-2; + } + h2{ + @apply heading-3; + } + h3{ + @apply heading-3; + } + + h1,h2,h3,h4{ + color:var(--text-base); + font-family: var(--font-heading); + } + + .author{ + padding: 2rem 0; + } + .content{ + + + + img{ + width: 100%; + border-radius: 2.4rem; + } + } + .boxShare{ + @apply flex font-bold; + margin: 4rem 0; + color: var(--text-active); + .listIcon{ + ul{ + @apply flex; + li{ + margin: 0px 1.6rem; + } + } + } + } +} \ No newline at end of file diff --git a/src/components/modules/blog-detail/BlogContent/BlogContent.tsx b/src/components/modules/blog-detail/BlogContent/BlogContent.tsx new file mode 100644 index 000000000..17d8555ae --- /dev/null +++ b/src/components/modules/blog-detail/BlogContent/BlogContent.tsx @@ -0,0 +1,80 @@ +import React from 'react'; +import { Author, DateTime } from "src/components/common"; +import IconFacebook from 'src/components/icons/IconFacebook'; +import IconInstagram from 'src/components/icons/IconInstagram'; +import IconTwitter from 'src/components/icons/IconTwitter'; +import s from './BlogContent.module.scss'; +import imageAuthor from '../../../common/Author/img/author.png'; +import Link from 'next/link'; +interface BlogContentProps { + className?: string + children?: any, +} +const BlogContent = ({}:BlogContentProps) => { + return ( + <> +
      + +

      The Best Sesame Soy Broccoli Salad

      +
      + +
      +
      + +

      When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces. +
      +
      + + Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to. +
      +
      + This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing. +

      + +
      +
      + +

      What is broccoli salad

      +
      +

      When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces. +
      +
      + + Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to. +
      +
      + This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing. +

      + +
      +
      + +

      What about broccoli stems?

      +
      +

      + You can eat broccoli stems. In fact, they are delicious. Just use a peeler to peel off the outsides and then trim the stalks into small 1/4”-1/2” cubes. +

      +
      + blog-detail + +
      + +
      +
      + Share to: +
      +
      + +
      +
      +
      + + + ) +} + +export default BlogContent diff --git a/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.module.scss b/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.module.scss new file mode 100644 index 000000000..98206b439 --- /dev/null +++ b/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.module.scss @@ -0,0 +1,21 @@ +.beadcrumb{ + padding-left: 3.2rem; + padding-bottom: 3.2rem; +} +.image{ + width: 100%; + padding: 0 2rem; + margin-bottom: 2rem; + border-radius: 2.4rem; + @screen md { + width: 90%; + margin:0 auto; + margin-bottom: 4rem; + } + @screen xl{ + width: 63%; + margin:0 auto; + margin-bottom: 4rem; + } + +} \ No newline at end of file diff --git a/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.tsx b/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.tsx new file mode 100644 index 000000000..b7eb6aaef --- /dev/null +++ b/src/components/modules/blog-detail/BlogDetailImg/BlogDetailImg.tsx @@ -0,0 +1,27 @@ + +import React from 'react'; +import BreadcrumbCommon from 'src/components/common/BreadcrumbCommon/BreadcrumbCommon'; +import s from './BlogDetailImg.module.scss'; +interface Props { + className?: string + children?: any +} + +const CRUMBS =[ + { + name:"Blog", + link:"/blog" + } +] +const BlogDetailImg = ({}:Props ) => { + return ( + <> +
      + +
      + Ảnh đại diện + + ) +} + +export default BlogDetailImg diff --git a/src/components/modules/blog-detail/BlogDetailImg/img/blogdetail.png b/src/components/modules/blog-detail/BlogDetailImg/img/blogdetail.png new file mode 100644 index 000000000..ad200ac46 Binary files /dev/null and b/src/components/modules/blog-detail/BlogDetailImg/img/blogdetail.png differ diff --git a/src/components/modules/blog-detail/index.ts b/src/components/modules/blog-detail/index.ts new file mode 100644 index 000000000..45d532145 --- /dev/null +++ b/src/components/modules/blog-detail/index.ts @@ -0,0 +1,2 @@ +export { default as BlogContent } from './BlogContent/BlogContent'; +export { default as BlogDetailImg } from './BlogDetailImg/BlogDetailImg'; \ No newline at end of file diff --git a/src/components/modules/blogs/BlogBreadcrumb/BlogBreadCrumb.module.scss b/src/components/modules/blogs/BlogBreadcrumb/BlogBreadCrumb.module.scss new file mode 100644 index 000000000..d347ad872 --- /dev/null +++ b/src/components/modules/blogs/BlogBreadcrumb/BlogBreadCrumb.module.scss @@ -0,0 +1,7 @@ +@import "../../../../styles/utilities"; +.breadCrumbWrapper { + @apply py-12 spacing-horizontal; + @screen lg { + padding-left: 3.2rem; + } +} \ No newline at end of file diff --git a/src/components/modules/blogs/BlogBreadcrumb/BlogBreadcrumb.tsx b/src/components/modules/blogs/BlogBreadcrumb/BlogBreadcrumb.tsx new file mode 100644 index 000000000..bb2ea19ef --- /dev/null +++ b/src/components/modules/blogs/BlogBreadcrumb/BlogBreadcrumb.tsx @@ -0,0 +1,16 @@ +import { BreadcrumbCommon } from "src/components/common" +import s from './BlogBreadCrumb.module.scss' + +const BLOG_DATA = [ + {link: "/blogs", name: "Blog"}, +]; + +const BlogBreadCrumb = () => { + return ( +
      + +
      + ) +} + +export default BlogBreadCrumb \ No newline at end of file diff --git a/src/components/modules/blogs/BlogHeading/BlogHeading.module.scss b/src/components/modules/blogs/BlogHeading/BlogHeading.module.scss new file mode 100644 index 000000000..d562ce2ae --- /dev/null +++ b/src/components/modules/blogs/BlogHeading/BlogHeading.module.scss @@ -0,0 +1,9 @@ +@import "../../../../styles/utilities"; + +.headingWrapper { + @apply flex spacing-horizontal-left pb-16 justify-center; + .heading{ + max-width: 121.6rem; + flex-grow: 1; + } +} \ No newline at end of file diff --git a/src/components/modules/blogs/BlogHeading/BlogHeading.tsx b/src/components/modules/blogs/BlogHeading/BlogHeading.tsx new file mode 100644 index 000000000..e3f60c980 --- /dev/null +++ b/src/components/modules/blogs/BlogHeading/BlogHeading.tsx @@ -0,0 +1,18 @@ +import { HeadingCommon } from "src/components/common" +import s from './BlogHeading.module.scss' + +interface BlogHeadingProps { + children?: React.ReactNode, + heading?: string, +} + +const BlogHeading = ({heading = "BLOG"}: BlogHeadingProps) => { + return ( +
      +
      + {heading} +
      +
      + ) +} +export default BlogHeading \ No newline at end of file diff --git a/src/components/modules/blogs/BlogsList/BlogsList.module.scss b/src/components/modules/blogs/BlogsList/BlogsList.module.scss new file mode 100644 index 000000000..295cabc5a --- /dev/null +++ b/src/components/modules/blogs/BlogsList/BlogsList.module.scss @@ -0,0 +1,23 @@ +@import "../../../../styles/utilities"; + +.wrapper { + @apply flex flex-col spacing-horizontal items-center; + padding-bottom: 16.8rem; + .list { + @apply grid grid-cols-1 gap-8; + max-width: 121.6rem; + @screen md { + @apply grid-cols-2; + } + @screen lg { + @apply grid-cols-3; + } + } + .card { + @apply pb-16; + } + .pagination { + @apply flex justify-center items-center ; + padding-top: 0.8rem; + } +} \ No newline at end of file diff --git a/src/components/modules/blogs/BlogsList/BlogsList.tsx b/src/components/modules/blogs/BlogsList/BlogsList.tsx new file mode 100644 index 000000000..536aa4afd --- /dev/null +++ b/src/components/modules/blogs/BlogsList/BlogsList.tsx @@ -0,0 +1,157 @@ +import React, { useState } from 'react' +import CardBlog, { BlogCardProps } from 'src/components/common/CardBlog/CardBlog' +import PaginationCommon from 'src/components/common/PaginationCommon/PaginationCommon' +import s from "./BlogsList.module.scss" +import { DEFAULT_BLOG_PAGE_SIZE } from 'src/utils/constanst.utils' +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 image21 from '../../../../../public/assets/images/image21.png' +import image22 from '../../../../../public/assets/images/image22.png' +import image23 from '../../../../../public/assets/images/image23.png' + +interface BlogsListProps { + data?: BlogCardProps[], +} + +const BLOGSLIST_DATA = [ + { + imageSrc: image15.src, + title: "1", + description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...", + slug: "happy-diet" + }, + { + imageSrc: image16.src, + title: "2", + description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...", + slug: "happy-diet" + }, + { + imageSrc: image17.src, + title: "3", + description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...", + slug: "happy-diet" + }, + { + imageSrc: image21.src, + title: "4", + description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...", + slug: "happy-diet" + }, + { + imageSrc: image22.src, + title: "5", + description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...", + slug: "happy-diet" + }, + { + imageSrc: image23.src, + title: "6", + description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...", + slug: "happy-diet" + }, + { + imageSrc: image15.src, + title: "7", + description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...", + slug: "happy-diet" + }, + { + imageSrc: image16.src, + title: "8", + description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...", + slug: "happy-diet" + }, + { + imageSrc: image17.src, + title: "9", + description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...", + slug: "happy-diet" + }, + { + imageSrc: image23.src, + title: "10", + description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...", + slug: "happy-diet" + }, + { + imageSrc: image21.src, + title: "11", + description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...", + slug: "happy-diet" + }, + { + imageSrc: image22.src, + title: "12", + description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...", + slug: "happy-diet" + }, + { + imageSrc: image15.src, + title: "13", + description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...", + slug: "happy-diet" + }, + { + imageSrc: image16.src, + title: "14", + description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...", + slug: "happy-diet" + }, + { + imageSrc: image17.src, + title: "15", + description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...", + slug: "happy-diet" + }, + { + imageSrc: image21.src, + title: "16", + description: "The DEBM diet stands for "+"Delicious Happy Fun Diet"+". This diet was popularized by Robert...", + slug: "happy-diet" + }, + { + imageSrc: image23.src, + title: "17", + description: "Dragon fruit is a type of fruit that is a favorite for many people because of its delicious and fresh...", + slug: "happy-diet" + }, + { + imageSrc: image22.src, + title: "18", + description: "Aloe vera or aloe vera is a green plant, has thorns on the side of the skin with yellowish patches and...", + slug: "happy-diet" + }, + + ] + +const BlogsList = ({ data = BLOGSLIST_DATA }:BlogsListProps) => { + const [currentPage, setCurrentPage] = useState(0) + const onPageChange = (page:number) => { + setCurrentPage(page) + } + + return ( +
      +
      +
      + { + data.slice(currentPage*DEFAULT_BLOG_PAGE_SIZE,(currentPage+1)*DEFAULT_BLOG_PAGE_SIZE).map((product,index)=> { + return( +
      + +
      + ) + }) + } +
      +
      + +
      +
      +
      + ) +} + +export default BlogsList \ No newline at end of file diff --git a/src/components/modules/blogs/FeaturedCardBlog/FeaturedCardBlog.module.scss b/src/components/modules/blogs/FeaturedCardBlog/FeaturedCardBlog.module.scss new file mode 100644 index 000000000..6fb16450c --- /dev/null +++ b/src/components/modules/blogs/FeaturedCardBlog/FeaturedCardBlog.module.scss @@ -0,0 +1,34 @@ +@import "../../../../styles/utilities"; + +.featuredCard { + @apply flex flex-row justify-center spacing-horizontal pb-16; + .featuredCardWrapper { + @apply flex flex-col; + @screen lg { + @apply flex-row justify-between; + } + max-width: 121.6rem; + } +} +.left { + max-width: 59.8rem; + img { + border-radius: 2.4rem; + } +} +.right { + flex-shrink: 3; + @screen lg { + margin-left: 6.4rem; + } +} +.titleWrapper { + @apply flex flex-col items-start font-heading heading-3; + margin-bottom: 1.6rem; + .title { + margin-top: 0.4rem; + } +} +.content { + margin-top: 1.6rem +} \ No newline at end of file diff --git a/src/components/modules/blogs/FeaturedCardBlog/FeaturedCardBlog.tsx b/src/components/modules/blogs/FeaturedCardBlog/FeaturedCardBlog.tsx new file mode 100644 index 000000000..2bd158d79 --- /dev/null +++ b/src/components/modules/blogs/FeaturedCardBlog/FeaturedCardBlog.tsx @@ -0,0 +1,52 @@ +import s from './FeaturedCardBlog.module.scss' +import { Author, DateTime } from 'src/components/common' +import Image from "next/image"; +import image20 from '../../../../../public/assets/images/image20.png' +import author from '../../../../../public/assets/images/author.png' + +interface FeaturedCardBlogProps{ + title?: string, + content?: string, + imgSrc?: any, + imgAuthor?: any, + date?: string, + authorName?: string, +} + +const FEATURED_DATA = { + title: "Flammekueche with green asparagus", + content: "Traditionally, the Flammekueche is made with rapeseed oil, which, contrary to popular belief, is indeed an oil that can be cooked hot and is not limited to seasoning. It is important to vary the oils in the kitchen to take advantage of the benefits of each. Rapeseed oil is an oil rich in omega 3 which participate in the proper functioning of the cardiovascular system as well as in vitamins E which contributes to the protection of cells against oxidative stress. In short, oils are your friends 😉", + imgSrc: image20, + imgAuthor: author.src, + date: "APRIL 30, 2021", + author: "Alessandro Del Piero" +} + +const FeaturedCardBlog = ({ + title = FEATURED_DATA.title, + content = FEATURED_DATA.content, + imgSrc = FEATURED_DATA.imgSrc, + imgAuthor = FEATURED_DATA.imgAuthor, + date = FEATURED_DATA.date, + authorName = FEATURED_DATA.author +}: FeaturedCardBlogProps) => { + return ( +
      +
      +
      + image feature card +
      +
      +
      + + {title} +
      + +
      {content}
      +
      +
      +
      + ) +} + +export default FeaturedCardBlog \ No newline at end of file diff --git a/src/components/modules/blogs/index.tsx b/src/components/modules/blogs/index.tsx new file mode 100644 index 000000000..0f8e1b281 --- /dev/null +++ b/src/components/modules/blogs/index.tsx @@ -0,0 +1,4 @@ +export { default as FeaturedCardBlog } from './FeaturedCardBlog/FeaturedCardBlog' +export { default as BlogsList } from './BlogsList/BlogsList' +export { default as BlogHeading } from './BlogHeading/BlogHeading' +export { default as BlogBreadCrumb } from './BlogBreadcrumb/BlogBreadcrumb' \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutBill/CheckoutBill.module.scss b/src/components/modules/checkout/CheckoutBill/CheckoutBill.module.scss new file mode 100644 index 000000000..403bdb76b --- /dev/null +++ b/src/components/modules/checkout/CheckoutBill/CheckoutBill.module.scss @@ -0,0 +1,38 @@ +.warpper { + padding: 3.2rem; + min-width: 100%; + @screen lg { + max-width: 56.3rem; + @apply flex justify-between flex-col border-l-2 border-solid border-line; + } + .title { + display: none; + font-weight: bold; + font-size: 2rem; + line-height: 2.8rem; + @screen md { + display: block; + } + } + .list { + min-height: 52.8rem; + } + .bot { + .promo { + // padding: 3.2rem; + @apply bg-gray flex justify-between items-center; + min-height: 6.4rem; + } + .price { + margin-top: 3.2rem; + .line { + @apply flex justify-between items-center text-label; + .total { + font-weight: bold; + font-size: 2rem; + line-height: 2.8rem; + } + } + } + } +} diff --git a/src/components/modules/checkout/CheckoutBill/CheckoutBill.tsx b/src/components/modules/checkout/CheckoutBill/CheckoutBill.tsx new file mode 100644 index 000000000..259397980 --- /dev/null +++ b/src/components/modules/checkout/CheckoutBill/CheckoutBill.tsx @@ -0,0 +1,46 @@ +import React from 'react' +import s from './CheckoutBill.module.scss' +import { CardItemCheckout } from '../../../common' +import { CardItemCheckoutProps } from '../../../common/CardItemCheckout/CardItemCheckout' +import { IconCirclePlus } from 'src/components/icons' + +interface CheckoutBillProps { + data: CardItemCheckoutProps[] +} + +const CheckoutBill = ({ data }: CheckoutBillProps) => { + return ( +
      +
      + Your cart ({data.length}) +
      +
      + {data.map((item) => { + return + })} +
      +
      +
      + Apply Promotion Code + +
      +
      +
      + Subtotal +
      RP 120.500
      +
      +
      + Shipping +
      Free
      +
      +
      + Estimated Total +
      RP 120.500
      +
      +
      +
      +
      + ) +} + +export default CheckoutBill diff --git a/src/components/modules/checkout/CheckoutInfo/CheckoutInfo.module.scss b/src/components/modules/checkout/CheckoutInfo/CheckoutInfo.module.scss new file mode 100644 index 000000000..cadf9f684 --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/CheckoutInfo.module.scss @@ -0,0 +1,17 @@ +.warpper{ + @apply w-full; + padding: 3.2rem; + .title{ + margin-bottom: 3.2rem; + @apply flex justify-between items-center; + .viewCart{ + margin-right: 5.6rem; + @apply text-primary font-bold; + display: block; + cursor: pointer; + @screen lg { + display: none; + } + } + } +} \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutInfo/CheckoutInfo.tsx b/src/components/modules/checkout/CheckoutInfo/CheckoutInfo.tsx new file mode 100644 index 000000000..423f92635 --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/CheckoutInfo.tsx @@ -0,0 +1,94 @@ +import React, { useState } from 'react' +import { Logo } from 'src/components/common' +import CheckoutCollapse from 'src/components/common/CheckoutCollapse/CheckoutCollapse' +import { removeItem } from 'src/utils/funtion.utils' +import { CheckOutForm } from 'src/utils/types.utils' +import s from './CheckoutInfo.module.scss' +import CustomerInfoForm from './components/CustomerInfoForm/CustomerInfoForm' +import PaymentInfoForm from './components/PaymentInfoForm/PaymentInfoForm' +import ShippingInfoForm from './components/ShippingInfoForm/ShippingInfoForm' +interface CheckoutInfoProps { + onViewCart:()=>void +} + +const CheckoutInfo = ({onViewCart}: CheckoutInfoProps) => { + const [active, setActive] = useState(1) + const [done, setDone] = useState([]) + const [info, setInfo] = useState({}) + + const onEdit = (id:number) => { + setActive(id) + setDone(removeItem(done,id)) + } + + const onConfirm = (id:number,formInfo:CheckOutForm) => { + if(id+1>formList.length){ + console.log({...info,...formInfo}) + }else{ + if(done.length>0){ + for (let i = id+1; i <= formList.length; i++) { + if(!done.includes(i)){ + setActive(i) + } + } + }else{ + setActive(id+1) + } + setDone([...done,id]) + } + setInfo({...info,...formInfo}) + } + + const getNote = (id:number) => { + switch (id) { + case 1: + return `${info.name}, ${info.email}` + case 2: + return `${info.address}, ${info.state}, ${info.city}, ${info.code}, ${info.phone}, ` + default: + return "" + } + } + + const formList = [ + { + id: 1, + title: 'Customer Information', + form: , + }, + { + id: 2, + title: 'Shipping Information', + form: , + }, + { + id: 3, + title: 'Payment Information', + form: , + }, + ] + return ( +
      +
      + +
      View cart
      +
      + {formList.map((item) => { + let note = getNote(item.id) + return + {item.form} + + })} +
      + ) +} + +export default CheckoutInfo diff --git a/src/components/modules/checkout/CheckoutInfo/components/BankTransfer/BankTransfer.module.scss b/src/components/modules/checkout/CheckoutInfo/components/BankTransfer/BankTransfer.module.scss new file mode 100644 index 000000000..44ac98048 --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/BankTransfer/BankTransfer.module.scss @@ -0,0 +1,15 @@ +.warpper{ + .info{ + .line{ + @apply flex justify-start items-center; + .title{ + margin-right: 3.2rem; + min-width: 19.4rem; + @apply text-label; + } + .hightlight{ + @apply text-active; + } + } + } +} \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutInfo/components/BankTransfer/BankTransfer.tsx b/src/components/modules/checkout/CheckoutInfo/components/BankTransfer/BankTransfer.tsx new file mode 100644 index 000000000..7de11245c --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/BankTransfer/BankTransfer.tsx @@ -0,0 +1,26 @@ +import React from 'react' +import s from './BankTransfer.module.scss' +interface BankTransferProps {} + +const BankTransfer = ({}: BankTransferProps) => { + return ( +
      +
      +
      +
      Account Name:
      +
      Duong Dinh Vu
      +
      +
      +
      Account Number:
      +
      1234 1234 1234 1234
      +
      +
      +
      Bank Name:
      +
      Techcombank - HCMC
      +
      +
      +
      + ) +} + +export default BankTransfer diff --git a/src/components/modules/checkout/CheckoutInfo/components/CreditCardForm/CreditCardForm.module.scss b/src/components/modules/checkout/CheckoutInfo/components/CreditCardForm/CreditCardForm.module.scss new file mode 100644 index 000000000..62dbbc8d3 --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/CreditCardForm/CreditCardForm.module.scss @@ -0,0 +1,12 @@ +@import "../../../../../../styles/utilities"; +.warpper{ + @apply u-form; + .line{ + >div{ + width: 50%; + } + } + .checkbox{ + margin-top: 1.6rem; + } +} \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutInfo/components/CreditCardForm/CreditCardForm.tsx b/src/components/modules/checkout/CheckoutInfo/components/CreditCardForm/CreditCardForm.tsx new file mode 100644 index 000000000..d289165e0 --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/CreditCardForm/CreditCardForm.tsx @@ -0,0 +1,27 @@ +import React, { useRef } from 'react' +import { CheckboxCommon, Inputcommon } from 'src/components/common' +import { CustomInputCommon } from 'src/utils/type.utils' +import s from "./CreditCardForm.module.scss" +interface CreditCardFormProps { + +} + +const CreditCardForm = ({}: CreditCardFormProps) => { + const cardNumberRef = useRef(null) + const dateRef = useRef(null) + const cvsRef = useRef(null) + return ( +
      +
      + +
      + + +
      +
      +
      +
      + ) +} + +export default CreditCardForm diff --git a/src/components/modules/checkout/CheckoutInfo/components/CustomerInfoForm/CustomerInfoForm.module.scss b/src/components/modules/checkout/CheckoutInfo/components/CustomerInfoForm/CustomerInfoForm.module.scss new file mode 100644 index 000000000..b0ecf8144 --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/CustomerInfoForm/CustomerInfoForm.module.scss @@ -0,0 +1,15 @@ +@import "../../../../../../styles/utilities"; +.warpper{ + @apply u-form; + @screen md { + padding: 0 5.6rem; + } + .bottom{ + margin-top: 2.4rem; + @apply flex justify-between items-center; + .note{ + font-size: 1.2rem; + line-height: 2rem; + } + } +} \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutInfo/components/CustomerInfoForm/CustomerInfoForm.tsx b/src/components/modules/checkout/CheckoutInfo/components/CustomerInfoForm/CustomerInfoForm.tsx new file mode 100644 index 000000000..8496b119d --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/CustomerInfoForm/CustomerInfoForm.tsx @@ -0,0 +1,54 @@ +import Link from 'next/link' +import React, { useRef } from 'react' +import { ButtonCommon, Inputcommon } from 'src/components/common' +import InputCommon from 'src/components/common/InputCommon/InputCommon' +import { CheckOutForm } from 'src/utils/types.utils' +import s from './CustomerInfoForm.module.scss' +interface CustomerInfoFormProps { + onConfirm?: (id: number, formInfo: CheckOutForm) => void + id: number +} + +const CustomerInfoForm = ({ id, onConfirm }: CustomerInfoFormProps) => { + const nameRef = useRef>(null) + const emailRef = useRef>(null) + + const handleConfirmClick = () => { + onConfirm && + onConfirm(id, { + name: nameRef?.current?.getValue().toString(), + email: emailRef.current?.getValue().toString(), + }) + } + + return ( +
      +
      + + +
      +
      +
      + By clicking continue you agree to Casper's{' '} + { + + terms and conditions + + }{' '} + and{' '} + { + + privacy policy + + } + . +
      + + Continue to Shipping + +
      +
      + ) +} + +export default CustomerInfoForm diff --git a/src/components/modules/checkout/CheckoutInfo/components/PaymentInfoForm/PaymentInfoForm.module.scss b/src/components/modules/checkout/CheckoutInfo/components/PaymentInfoForm/PaymentInfoForm.module.scss new file mode 100644 index 000000000..15a70659c --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/PaymentInfoForm/PaymentInfoForm.module.scss @@ -0,0 +1,16 @@ +.wrapper{ + @screen md { + padding: 0 5.6rem; + } + .inner{ + padding: 4rem 0; + } + .bottom{ + margin-top: 2.4rem; + @apply flex justify-between items-center; + .note{ + font-size: 1.2rem; + line-height: 2rem; + } + } +} \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutInfo/components/PaymentInfoForm/PaymentInfoForm.tsx b/src/components/modules/checkout/CheckoutInfo/components/PaymentInfoForm/PaymentInfoForm.tsx new file mode 100644 index 000000000..dc84fec38 --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/PaymentInfoForm/PaymentInfoForm.tsx @@ -0,0 +1,55 @@ +import React from 'react' +import { ButtonCommon, TabCommon, TabPane } from 'src/components/common' +import { CheckOutForm } from 'src/utils/types.utils' +import BankTransfer from '../BankTransfer/BankTransfer' +import Link from 'next/link' + +import s from './PaymentInfoForm.module.scss' +import CreditCardForm from '../CreditCardForm/CreditCardForm' +interface PaymentInfoFormProps { + onConfirm?: (id: number, formInfo: CheckOutForm) => void + id: number +} + +const PaymentInfoForm = ({onConfirm,id}: PaymentInfoFormProps) => { + const handleConfirmClick = () => { + onConfirm && onConfirm(id,{}) + } + return ( +
      + + +
      +
      + +
      +
      + +
      +
      +
      +
      +
      + By clicking continue you agree to Casper's{' '} + { + + terms and conditions + + }{' '} + and{' '} + { + + privacy policy + + } + . +
      + + Submit Order + +
      +
      + ) +} + +export default PaymentInfoForm diff --git a/src/components/modules/checkout/CheckoutInfo/components/ShippingInfoForm/ShippingInfoForm.module.scss b/src/components/modules/checkout/CheckoutInfo/components/ShippingInfoForm/ShippingInfoForm.module.scss new file mode 100644 index 000000000..c0c8b2795 --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/ShippingInfoForm/ShippingInfoForm.module.scss @@ -0,0 +1,39 @@ +@import "../../../../../../styles/utilities"; + +.warpper{ + @apply u-form; + @screen md { + padding: 0 5.6rem; + } + .bottom{ + margin-top: 2.4rem; + @apply flex justify-between items-center; + .note{ + font-size: 1.2rem; + line-height: 2rem; + } + } + .line{ + >div{ + width: 50%; + } + } + .method{ + width: 100%; + height: 5.6rem; + padding: 1.6rem; + border-radius: 0.8rem; + @apply flex justify-between items-center border border-solid border-line bg-gray; + .left{ + @apply flex; + .name{ + margin-left: 1.6rem; + color: var(--text-active); + } + } + .price{ + font-weight: bold; + color: var(--text-active); + } + } +} \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutInfo/components/ShippingInfoForm/ShippingInfoForm.tsx b/src/components/modules/checkout/CheckoutInfo/components/ShippingInfoForm/ShippingInfoForm.tsx new file mode 100644 index 000000000..ac4bc8af5 --- /dev/null +++ b/src/components/modules/checkout/CheckoutInfo/components/ShippingInfoForm/ShippingInfoForm.tsx @@ -0,0 +1,97 @@ +import React, { useRef } from 'react' +import { ButtonCommon, Inputcommon, SelectCommon } from 'src/components/common' +import s from './ShippingInfoForm.module.scss' +import Link from 'next/link' +import { CustomInputCommon } from 'src/utils/type.utils' +import { Shipping } from 'src/components/icons' +import { CheckOutForm } from 'src/utils/types.utils' + +interface ShippingInfoFormProps { + onConfirm?: (id:number,formInfo:CheckOutForm)=>void + id:number +} + +const option = [ + { + name: 'Hồ Chí Minh', + }, + { + name: 'Hà Nội', + }, +] + +const ShippingInfoForm = ({onConfirm,id}: ShippingInfoFormProps) => { + const addressRef = useRef(null) + const cityRef = useRef(null) + const stateRef = useRef(null) + const codeRef = useRef(null) + const phoneRef = useRef(null) + const handleConfirmClick = () => { + onConfirm && onConfirm(id,{ + address: addressRef?.current?.getValue().toString(), + city: cityRef.current?.getValue().toString(), + state: stateRef?.current?.getValue().toString(), + code: Number(codeRef.current?.getValue()), + phone: Number(phoneRef?.current?.getValue()), + }) + } + + return ( +
      +
      + + +
      + State + +
      + +
      +
      +
      + +
      +
      + Standard Delivery Method +
      +
      +
      +
      + Free +
      +
      +
      +
      +
      +
      + By clicking continue you agree to Casper's{' '} + { + + terms and conditions + + }{' '} + and{' '} + { + + privacy policy + + } + . +
      + + Continue to Payment + +
      +
      + ) +} + +export default ShippingInfoForm diff --git a/src/components/modules/checkout/CheckoutPage/CheckoutPage.module.scss b/src/components/modules/checkout/CheckoutPage/CheckoutPage.module.scss new file mode 100644 index 000000000..1661f243c --- /dev/null +++ b/src/components/modules/checkout/CheckoutPage/CheckoutPage.module.scss @@ -0,0 +1,56 @@ +@import "../../../../styles/utilities"; +.warrper{ + @apply flex; + .right{ + display: none; + @screen lg { + display: block; + min-width: 45rem; + } + @screen xl { + min-width: 56.3rem; + } + } + .left{ + @apply w-full; + } + .mobile{ + @apply hidden; + &.isShow{ + @apply block; + @screen lg { + @apply hidden; + } + } + .modal{ + background: rgba(0, 0, 0, 0.5); + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + z-index: 10000; + .content{ + @apply spacing-horizontal; + margin-top: 3rem; + padding-top: 6.4rem ; + padding-bottom: 5rem; + background-color: white; + overflow: auto; + height: 100%; + border-radius: 2.4rem 2.4rem 0 0; + .head{ + @apply flex justify-between; + h3{ + @apply heading-3 font-bold; + color:var(--text-base); + } + } + button{ + margin-top: 2rem; + width: 100%; + } + } + } + } +} \ No newline at end of file diff --git a/src/components/modules/checkout/CheckoutPage/CheckoutPage.tsx b/src/components/modules/checkout/CheckoutPage/CheckoutPage.tsx new file mode 100644 index 000000000..8cfcc31f3 --- /dev/null +++ b/src/components/modules/checkout/CheckoutPage/CheckoutPage.tsx @@ -0,0 +1,37 @@ +import classNames from 'classnames' +import React, { useState } from 'react' +import IconHide from 'src/components/icons/IconHide' +import { CHECKOUT_BILL_DATA } from 'src/utils/demo-data' +import { CheckoutBill, CheckoutInfo } from '..' +import s from "./CheckoutPage.module.scss" +interface CheckoutPageProps { +} + +const CheckoutPage = ({}: CheckoutPageProps) => { + const [isShow, setIsShow] = useState(false) + const onClose = () => { + setIsShow(false) + } + const onViewCart =() => { + setIsShow(true) + } + return ( +
      +
      +
      +
      +
      +
      +
      +

      Your Cart({CHECKOUT_BILL_DATA.length})

      +
      +
      + +
      +
      +
      +
      + ) +} + +export default CheckoutPage diff --git a/src/components/modules/checkout/index.ts b/src/components/modules/checkout/index.ts new file mode 100644 index 000000000..736375e4c --- /dev/null +++ b/src/components/modules/checkout/index.ts @@ -0,0 +1,3 @@ +export { default as CheckoutInfo } from './CheckoutInfo/CheckoutInfo' +export { default as CheckoutPage } from './CheckoutPage/CheckoutPage' +export { default as CheckoutBill } from './CheckoutBill/CheckoutBill' diff --git a/src/components/modules/delivery-policy/DeliveryAndPolicyBreadCrumb/DeliveryAndPolicyBreadCrumb.module.scss b/src/components/modules/delivery-policy/DeliveryAndPolicyBreadCrumb/DeliveryAndPolicyBreadCrumb.module.scss new file mode 100644 index 000000000..abf7ef84f --- /dev/null +++ b/src/components/modules/delivery-policy/DeliveryAndPolicyBreadCrumb/DeliveryAndPolicyBreadCrumb.module.scss @@ -0,0 +1,8 @@ +@import "../../../../styles/utilities"; + +.breadCrumb { + @apply absolute z-10 pt-12 spacing-horizontal; + @screen lg{ + padding-left: 3.2rem; + } +} \ No newline at end of file diff --git a/src/components/modules/delivery-policy/DeliveryAndPolicyBreadCrumb/DeliveryAndPolicyBreadCrumb.tsx b/src/components/modules/delivery-policy/DeliveryAndPolicyBreadCrumb/DeliveryAndPolicyBreadCrumb.tsx new file mode 100644 index 000000000..992370ce5 --- /dev/null +++ b/src/components/modules/delivery-policy/DeliveryAndPolicyBreadCrumb/DeliveryAndPolicyBreadCrumb.tsx @@ -0,0 +1,17 @@ +import { BreadcrumbCommon } from 'src/components/common' +import s from './DeliveryAndPolicyBreadCrumb.module.scss' + +const CRUMB_DATA = [ + { + link: "/delivery-policy", + name: "Delivery And Policy" + } +] +const DeliveryAndPolicyBreadCrumb = () => { + return ( +
      + +
      + ) +} +export default DeliveryAndPolicyBreadCrumb \ No newline at end of file diff --git a/src/components/modules/delivery-policy/DeliveryAndPolicyContent/DeliveryAndPolicyContent.module.scss b/src/components/modules/delivery-policy/DeliveryAndPolicyContent/DeliveryAndPolicyContent.module.scss new file mode 100644 index 000000000..be88621b5 --- /dev/null +++ b/src/components/modules/delivery-policy/DeliveryAndPolicyContent/DeliveryAndPolicyContent.module.scss @@ -0,0 +1,26 @@ +@import "../../../../styles/utilities"; + +.wrapper { + @apply flex justify-center pt-20 pb-28 spacing-horizontal; + .deliveryAndPolicyContentWrapper { + max-width: 80.4rem; + min-height: 4rem; + .titleWrapper { + @apply flex flex-col items-start; + .date { + @apply inline flex flex-row; + margin-bottom: 0.4rem; + .update { + @apply uppercase leading-8; + color:var(--text-label); + font-size: 1.2rem; + letter-spacing: 0.01em; + } + } + } + .content { + @apply pb-16 whitespace-pre-line; + padding-top: 1.6rem; + } + } +} diff --git a/src/components/modules/delivery-policy/DeliveryAndPolicyContent/DeliveryAndPolicyContent.tsx b/src/components/modules/delivery-policy/DeliveryAndPolicyContent/DeliveryAndPolicyContent.tsx new file mode 100644 index 000000000..6045288f6 --- /dev/null +++ b/src/components/modules/delivery-policy/DeliveryAndPolicyContent/DeliveryAndPolicyContent.tsx @@ -0,0 +1,81 @@ +import { CollapseCommon, DateTime, HeadingCommon } from 'src/components/common' +import s from './DeliveryAndPolicyContent.module.scss' + +interface DeliveryAndPolicyContentProps{ + title?: string, + date?: string, + content?: string, +} +const HEADER_CONTENT = +`When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces. + +Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to. + +This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.`; + +const DELIVERYANDPOLICY_DATA = [ + { + title: "This is a subtitle", + content: `When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces. + + Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to. + + This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.`, + }, + { + title: "This is a subtitle", + content: `When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces. + + Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to. + + This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.`, + }, + { + title: "This is a subtitle", + content: `When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces. + + Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to. + + This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.`, + }, + { + title: "This is a subtitle", + content: `When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces. + + Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to. + + This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.`, + }, + { + title: "This is a subtitle", + content: `When you’re trying to eat healthier but want something more substantial than a leafy green salad, broccoli salad is there for you. I love the crunch and heft of broccoli, especially when it’s cut up into bite size spoonable pieces. + + Some people aren’t into raw broccoli, but I love it! I always go for the raw broccoli on those vegetable platters that seem to be at every potluck/party you go to. + + This is a simple broccoli salad: you have the bulk of it, raw broccoli; crunchy red onions for a bit of acidity and raw crunch, craisins for sweetness, almonds for a nutty counter point; and a sweet and tangy soy-rice vinegar-sesame dressing.`, + }, +] + +const DeliveryAndPolicyContent = ( { title="Delivery & Policy", date="APRIL 30, 2021", content = HEADER_CONTENT } : DeliveryAndPolicyContentProps) => { + return ( +
      + +
      +
      +
      +
      LASTEST UPDATED: 
      + +
      + {title} +
      +
      + {content} +
      + +
      + +
      + ) +} + +export default DeliveryAndPolicyContent \ No newline at end of file diff --git a/src/components/modules/delivery-policy/index.tsx b/src/components/modules/delivery-policy/index.tsx new file mode 100644 index 000000000..bb23bd6c8 --- /dev/null +++ b/src/components/modules/delivery-policy/index.tsx @@ -0,0 +1,2 @@ +export { default as DeliveryAndPolicyContent } from './DeliveryAndPolicyContent/DeliveryAndPolicyContent' +export { default as DeliveryAndPolicyBreadCrumb } from './DeliveryAndPolicyBreadCrumb/DeliveryAndPolicyBreadCrumb' \ No newline at end of file diff --git a/src/components/modules/error/ErrorPage/ErrorPage.tsx b/src/components/modules/error/ErrorPage/ErrorPage.tsx new file mode 100644 index 000000000..0e550b766 --- /dev/null +++ b/src/components/modules/error/ErrorPage/ErrorPage.tsx @@ -0,0 +1,29 @@ +import Link from 'next/link'; +import React from 'react'; +import { ButtonCommon } from 'src/components/common'; +import s from './ErrorPage.module.scss'; + +interface Props { +} + +const ErrorPage = ({ }: Props) => { + return ( + +
      +
      +
      +

      + ERROR +

      +

      Oh no, Something went wrong
      + We're doing our best and we'll back soon +

      + + Return to Home Now +
      +
      +
      + ) +} + +export default ErrorPage diff --git a/src/components/modules/error/ErrorPage/Errorpage.module.scss b/src/components/modules/error/ErrorPage/Errorpage.module.scss new file mode 100644 index 000000000..562a20f8b --- /dev/null +++ b/src/components/modules/error/ErrorPage/Errorpage.module.scss @@ -0,0 +1,36 @@ +@import '../../../../styles/utilities'; +.wrapper{ + @apply flex justify-center; + text-align: center; + height:100%; + + background-color: white; + .inner{ + height: 100vh; + .logo{ + margin-top: 2rem; + } + .text{ + @apply flex justify-center flex-col; + align-items: center; + width: 100%; + height:80%; + margin-top: 2rem; + h1{ + font-weight: bold; + font-size: 15rem; + color: var(--negative); + font-family: var(--font-heading); + text-shadow: 3px 5px 4px var(--negative); + height: 20%; + } + .description{ + @apply topline; + margin-top:1rem; + margin-bottom: 3rem; + color:var(--text-label); + } + } + } + +} \ No newline at end of file diff --git a/src/components/modules/error/index.tsx b/src/components/modules/error/index.tsx new file mode 100644 index 000000000..4fadf1398 --- /dev/null +++ b/src/components/modules/error/index.tsx @@ -0,0 +1 @@ +export {default as ErrorPage} from './ErrorPage/ErrorPage'; \ No newline at end of file diff --git a/src/components/modules/home/HomeBanner/HomeBanner.module.scss b/src/components/modules/home/HomeBanner/HomeBanner.module.scss index 507558cad..fdba411c0 100644 --- a/src/components/modules/home/HomeBanner/HomeBanner.module.scss +++ b/src/components/modules/home/HomeBanner/HomeBanner.module.scss @@ -11,11 +11,19 @@ @apply grid; grid-template-columns: 1fr 1.8fr; .left { - @apply flex items-end justify-center custom-border-radius-lg; + @apply relative flex items-end justify-center custom-border-radius-lg; margin-right: 1.6rem; - background-image: url('./assets/home_banner.png'); - background-repeat: no-repeat; - background-size: cover; + .imgWrap { + @apply absolute w-full h-full; + top: 0; + left: 0; + > div { + @apply w-full h-full custom-border-radius-lg; + } + img { + object-fit: cover; + } + } .text { @apply relative font-heading text-center; diff --git a/src/components/modules/home/HomeBanner/HomeBanner.tsx b/src/components/modules/home/HomeBanner/HomeBanner.tsx index 2a3a632fb..18432ec82 100644 --- a/src/components/modules/home/HomeBanner/HomeBanner.tsx +++ b/src/components/modules/home/HomeBanner/HomeBanner.tsx @@ -1,8 +1,9 @@ import React from 'react' import { Banner } from 'src/components/common' -import s from './HomeBanner.module.scss' import BannerImgRight from './assets/banner_full.png' -import BannerImgRight2 from './assets/banner_product.png' +import HomeBannerImg from './assets/home_banner.png' +import s from './HomeBanner.module.scss' +import Image from 'next/image' interface Props { className?: string @@ -13,6 +14,9 @@ const HomeBanner = ({ }: Props) => { return (
      +
      + +
      Freshness
      guaranteed
      @@ -28,10 +32,10 @@ const HomeBanner = ({ }: Props) => { { title: "Save 15% on your first order 2", subtitle: "Last call! Shop deep deals on 100+ bulk picks while you can.", - imgLink: BannerImgRight2.src, + imgLink: BannerImgRight.src, size: "small", } - ] + ] } />
      diff --git a/src/components/modules/home/HomeBanner/assets/banner_product.png b/src/components/modules/home/HomeBanner/assets/banner_product.png deleted file mode 100644 index 82f1b7fee..000000000 Binary files a/src/components/modules/home/HomeBanner/assets/banner_product.png and /dev/null differ diff --git a/src/components/modules/home/HomeVideo/assets/bg_left.svg b/src/components/modules/home/HomeVideo/assets/bg_left.svg index d730f777d..74b215ae0 100644 --- a/src/components/modules/home/HomeVideo/assets/bg_left.svg +++ b/src/components/modules/home/HomeVideo/assets/bg_left.svg @@ -1,19 +1,19 @@ - - + + - - + + - - + + diff --git a/src/components/modules/home/HomeVideo/assets/bg_right.svg b/src/components/modules/home/HomeVideo/assets/bg_right.svg index e89652a3a..346d14e31 100644 --- a/src/components/modules/home/HomeVideo/assets/bg_right.svg +++ b/src/components/modules/home/HomeVideo/assets/bg_right.svg @@ -1,21 +1,21 @@ - - + + - - + + - - + + diff --git a/src/components/modules/product-list/ProductListBanner/ProductListBanner.module.scss b/src/components/modules/product-list/ProductListBanner/ProductListBanner.module.scss new file mode 100644 index 000000000..a3452e797 --- /dev/null +++ b/src/components/modules/product-list/ProductListBanner/ProductListBanner.module.scss @@ -0,0 +1,8 @@ +@import "../../../../styles/_utilities"; + +.productListBanner{ + @apply spacing-horizontal; + @screen md { + padding:0 3.2rem; + } +} \ No newline at end of file diff --git a/src/components/modules/product-list/ProductListBanner/ProductListBanner.tsx b/src/components/modules/product-list/ProductListBanner/ProductListBanner.tsx new file mode 100644 index 000000000..17d48d637 --- /dev/null +++ b/src/components/modules/product-list/ProductListBanner/ProductListBanner.tsx @@ -0,0 +1,27 @@ +import React from 'react' +import { Banner } from 'src/components/common' +import BannerRight from './assets/bannerrecipes.png' +import s from './ProductListBanner.module.scss' + +interface Props { +} + +const ProductListBanner = ({ }: Props) => { + return ( +
      + +
      + ) +} + +export default ProductListBanner diff --git a/src/components/modules/product-list/ProductListBanner/assets/bannerrecipes.png b/src/components/modules/product-list/ProductListBanner/assets/bannerrecipes.png new file mode 100644 index 000000000..91271cbd2 Binary files /dev/null and b/src/components/modules/product-list/ProductListBanner/assets/bannerrecipes.png differ diff --git a/src/components/modules/product-list/ProductListFilter/ProductListFilter.module.scss b/src/components/modules/product-list/ProductListFilter/ProductListFilter.module.scss new file mode 100644 index 000000000..b30b9e1a6 --- /dev/null +++ b/src/components/modules/product-list/ProductListFilter/ProductListFilter.module.scss @@ -0,0 +1,88 @@ +@import "../../../../styles/_utilities"; + +.warpper { + @apply spacing-horizontal; + @screen md{ + padding:0 3.2rem; + padding-bottom:5.6rem; + } + .breadcrumb{ + padding:1rem 0; + } + .main{ + @screen md { + @apply flex; + } + .categories{ + @apply hidden; + @screen md { + @apply hidden; + } + @screen xl{ + @apply block; + width:25%; + } + } + .list{ + @screen md { + @apply flex justify-between flex-wrap w-full; + margin: 1rem 0; + } + @screen xl { + width:75%; + } + .inner{ + @screen md { + @apply flex flex-col items-center justify-center; + } + .boxItem { + @screen md { + @apply flex justify-between flex-wrap; + margin: 1rem 0; + } + .item { + @screen md { + width: calc(97% / 2); + margin-top:1rem; + } + @screen lg{ + width: calc(97% / 3); + margin-top:1rem; + } + } + } + } + + .boxSelect{ + @apply w-auto; + // padding: 2.5rem 0; + display: none; + + @screen xl { + @apply block; + width: auto; + padding:0; + } + .categorySelectCate{ + @screen xl { + @apply hidden; + } + } + label{ + @apply font-bold topline ; + color:var(--text-active); + @screen xl { + @apply hidden; + } + } + .select{ + margin-top: 1rem; + } + } + + } + + } + + +} diff --git a/src/components/modules/product-list/ProductListFilter/ProductListFilter.tsx b/src/components/modules/product-list/ProductListFilter/ProductListFilter.tsx new file mode 100644 index 000000000..5315283dc --- /dev/null +++ b/src/components/modules/product-list/ProductListFilter/ProductListFilter.tsx @@ -0,0 +1,66 @@ +import React from 'react' +import { HeadingCommon, ProductList, SelectCommon } from 'src/components/common' +import BreadcrumbCommon from 'src/components/common/BreadcrumbCommon/BreadcrumbCommon' +import MenuNavigation from 'src/components/common/MenuNavigation/MenuNavigation' +import { BRAND, CATEGORY, FEATURED} from 'src/utils/constanst.utils' +import { PRODUCT_DATA_TEST_PAGE } from 'src/utils/demo-data' +import s from './ProductListFilter.module.scss' + +interface ProductListFilterProps {} + +const BREADCRUMB = [ + { + name: 'Products', + link: `#`, + }, +] +const OPTIONSLECT = [ + { + name: 'Most Viewed', + value: 'most-viewed', + }, + { + name: 'Lastest Products', + value: 'lastest-products', + }, + { + name: 'Recent Products', + value: 'recent-products', + }, +] + +const onModalClose = () => { + +} + +const ProductListFilter = (props: ProductListFilterProps) => { + return ( +
      +
      + +
      +
      +
      + + + +
      + +
      + SPECIAL RECIPES + +
      +
      +
      + +
      +
      +
      + +
      +
      +
      + ) +} + +export default ProductListFilter diff --git a/src/components/modules/recipes-list/RecipeListBanner/RecipeListBanner.module.scss b/src/components/modules/recipes-list/RecipeListBanner/RecipeListBanner.module.scss new file mode 100644 index 000000000..2e5f65a1c --- /dev/null +++ b/src/components/modules/recipes-list/RecipeListBanner/RecipeListBanner.module.scss @@ -0,0 +1,8 @@ +@import "../../../../styles/_utilities"; + +.recipeListBanner{ + @apply spacing-horizontal; + @screen md { + padding:0 3.2rem; + } +} \ No newline at end of file diff --git a/src/components/modules/recipes-list/RecipeListBanner/RecipeListBanner.tsx b/src/components/modules/recipes-list/RecipeListBanner/RecipeListBanner.tsx new file mode 100644 index 000000000..0db63d2e3 --- /dev/null +++ b/src/components/modules/recipes-list/RecipeListBanner/RecipeListBanner.tsx @@ -0,0 +1,27 @@ +import React from 'react' +import { Banner } from 'src/components/common' +import BannerRight from './assets/bannerrecipes.png' +import s from './RecipeListBanner.module.scss' + +interface Props { +} + +const RecipeListBanner = ({ }: Props) => { + return ( +
      + +
      + ) +} + +export default RecipeListBanner diff --git a/src/components/modules/recipes-list/RecipeListBanner/assets/bannerrecipes.png b/src/components/modules/recipes-list/RecipeListBanner/assets/bannerrecipes.png new file mode 100644 index 000000000..91271cbd2 Binary files /dev/null and b/src/components/modules/recipes-list/RecipeListBanner/assets/bannerrecipes.png differ diff --git a/src/components/modules/recipes-list/RecipesList/RecipesItem/RecipesItem.module.scss b/src/components/modules/recipes-list/RecipesList/RecipesItem/RecipesItem.module.scss new file mode 100644 index 000000000..2f70eb3ca --- /dev/null +++ b/src/components/modules/recipes-list/RecipesList/RecipesItem/RecipesItem.module.scss @@ -0,0 +1,60 @@ +@import "../../../../../styles/_utilities"; + +.recipesItem { + @apply flex justify-between; + margin: 1.5rem 0; + + @screen md{ + @apply block; + } + + .recipesItemImage { + @apply transition-all duration-200; + width: 31%; + img { + @apply block object-cover; + width: 100%; + min-height: 12.5rem; + border-radius: 1.5rem; + } + + @screen md { + @apply object-cover cursor-pointer; + width: 100%; + margin: 0 auto; + img{ + height:100%; + border-radius: 2.4rem; + } + } + } + .recipesItemText { + width: 65%; + .recipesItemName{ + @apply topline font-bold cursor-pointer; + + display: -webkit-box; + -webkit-line-clamp: 1; + overflow: hidden; + -webkit-box-orient: vertical; + font-feature-settings: "salt" on; + color:var(--text-active); + margin-top: 1.6rem; + &:hover { + color: var(--primary); + } + } + @screen md { + width: 100%; + } + } + + .recipesItemDescription{ + color:var(--text-label); + display: -webkit-box; + -webkit-line-clamp: 2; + overflow: hidden; + -webkit-box-orient: vertical; + } + +} diff --git a/src/components/modules/recipes-list/RecipesList/RecipesItem/RecipesItem.tsx b/src/components/modules/recipes-list/RecipesList/RecipesItem/RecipesItem.tsx new file mode 100644 index 000000000..f43227d5a --- /dev/null +++ b/src/components/modules/recipes-list/RecipesList/RecipesItem/RecipesItem.tsx @@ -0,0 +1,31 @@ +import Link from 'next/link'; +import React from 'react'; +import s from './RecipesItem.module.scss'; +interface RecipesItem { + image:string, + name: string, + description:string, + link: string +} + +const RecipesItem = ({ image, name,description, link }: RecipesItem) => { + return ( + + ) +} + +export default RecipesItem diff --git a/src/components/modules/recipes-list/RecipesList/RecipesList.module.scss b/src/components/modules/recipes-list/RecipesList/RecipesList.module.scss new file mode 100644 index 000000000..5f9ded191 --- /dev/null +++ b/src/components/modules/recipes-list/RecipesList/RecipesList.module.scss @@ -0,0 +1,94 @@ +@import "../../../../styles/_utilities"; + +.recipesListWrapper { + @apply spacing-horizontal; + @screen md{ + padding:0 3.2rem; + padding-bottom:5.6rem; + } + .breadcrumb{ + padding:1rem 0; + } + .recipesListPageMain{ + @screen md { + @apply flex; + } + .categories{ + @apply hidden; + @screen md { + @apply hidden; + } + @screen xl{ + @apply block; + width:25%; + } + } + .recipesList{ + @screen md { + @apply flex justify-between flex-wrap w-full; + margin: 1rem 0; + } + @screen xl { + width:75%; + } + .inner{ + @screen md { + @apply flex flex-col items-center justify-center; + } + .boxItem { + @screen md { + @apply flex justify-between flex-wrap; + margin: 1rem 0; + } + .item { + @screen md { + width: calc(97% / 2); + margin-top:1rem; + } + @screen lg{ + width: calc(97% / 3); + margin-top:1rem; + } + } + } + } + .recipesPagination{ + @apply flex justify-center w-full; + margin: 3rem 0; + @screen md { + @apply flex justify-center ; + margin:2rem 0; + } + } + .boxSelect{ + @apply flex justify-between w-full; + padding: 2.5rem 0; + + @screen xl { + @apply block; + width: auto; + padding:0; + } + .categorySelectCate{ + @screen xl { + @apply hidden; + } + } + label{ + @apply font-bold topline ; + color:var(--text-active); + @screen xl { + @apply hidden; + } + } + .select{ + margin-top: 1rem; + } + } + + } + + } + + +} diff --git a/src/components/modules/recipes-list/RecipesList/RecipesList.tsx b/src/components/modules/recipes-list/RecipesList/RecipesList.tsx new file mode 100644 index 000000000..c061b9edb --- /dev/null +++ b/src/components/modules/recipes-list/RecipesList/RecipesList.tsx @@ -0,0 +1,228 @@ +import React from 'react'; +import { SelectCommon } from 'src/components/common'; +import BreadcrumbCommon from 'src/components/common/BreadcrumbCommon/BreadcrumbCommon'; +import MenuNavigation from 'src/components/common/MenuNavigation/MenuNavigation'; +import PaginationCommon from 'src/components/common/PaginationCommon/PaginationCommon'; +import { RecipeCardProps } from 'src/components/common/RecipeCard/RecipeCard'; +import { OPTION_ALL, QUERY_KEY, ROUTE } from 'src/utils/constanst.utils'; +import HeadingCommon from "../../../common/HeadingCommon/HeadingCommon"; +import RecipesItem from './RecipesItem/RecipesItem'; +import s from './RecipesList.module.scss'; + +const recipe:RecipeCardProps[] = [ +{ + title: "Special Recipe of Vietnamese Phở", + description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png', + slug: "special-recipe-of-vietnamese-pho" +}, +{ + title: "Original Recipe of Curry", + description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png', + slug:"original-recipe-of-curry" +}, +{ + title: "The Best Recipe of Beef Noodle Soup", + description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png', + slug:"the-best-recipe-of-beef-noodle-soup" +}, +{ + title: "Special Recipe of Vietnamese Phở", + description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png', + slug: "special-recipe-of-vietnamese-pho" +}, +{ + title: "Original Recipe of Curry", + description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png', + slug:"original-recipe-of-curry" +}, +{ + title: "The Best Recipe of Beef Noodle Soup", + description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png', + slug:"the-best-recipe-of-beef-noodle-soup" +},]; +const DEFAULT_PAGESIZE_RECIPELIST = 6; + +const BREADCRUMB = [ + { + name: 'Special Recipes', + link: `#`, + }, +]; + +const CATEGORY = [ + { + name: 'All', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=${OPTION_ALL}`, + }, + { + name: 'Malaysian', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=malaysia`, + }, + { + name: 'Vietnamese', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=vietnamese`, + }, + { + name: 'Thailand', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=thailand`, + }, + { + name: 'Indian', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=indian`, + }, + { + name: 'Lao', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=lao`, + }, + { + name: 'Chinese', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=chinese`, + }, + { + name: 'Korean', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=korean`, + }, + { + name: 'Japanese', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=japanese`, + }, + { + name: 'Western', + link: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=western`, + }, + ]; + +const CATEGORYSELECT = [ +{ + name: 'All', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=${OPTION_ALL}`, +}, +{ + name: 'Malaysian', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=malaysia`, +}, +{ + name: 'Vietnamese', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=vietnamese`, +}, +{ + name: 'Thailand', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=thailand`, +}, +{ + name: 'Indian', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=indian`, +}, +{ + name: 'Lao', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=lao`, +}, +{ + name: 'Chinese', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=chinese`, +}, +{ + name: 'Korean', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=korean`, +}, +{ + name: 'Japanese', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=japanese`, +}, +{ + name: 'Western', + value: `${ROUTE.RECIPES}/?${QUERY_KEY.RECIPES}=western`, +}, +]; + +const OPTIONSLECT=[ + { + name:"Most Viewed", + value:"most-viewed" + }, + { + name:"Lastest Blogs", + value:"lastest-blogs" + }, + { + name:"Recent Blogs", + value:"recent-blogs" + }, +]; + +interface Props{ + data?: RecipeCardProps[], + recipes?:{ + id:string, + title:string, + image:string, + description:string, + link:string + }[], +} + + +const RecipesList = ({ data =recipe}:Props) => { + return ( + <> +
      +
      + +
      +
      + +
      + +
      + +
      + SPECIAL RECIPES + +
      +
      + +
      + +
      +
      +
      + +
      + +
      +
      +
      + +
      +
      + {data?.map((item,index) => ( +
      + +
      + ))} +
      +
      +
      + +
      +
      + +
      + +
      + + ) +} + +export default RecipesList diff --git a/src/components/modules/recipes-list/index.ts b/src/components/modules/recipes-list/index.ts new file mode 100644 index 000000000..dc665674c --- /dev/null +++ b/src/components/modules/recipes-list/index.ts @@ -0,0 +1,2 @@ +export { default as RecipeListBanner } from './RecipeListBanner/RecipeListBanner' +export { default as RecipesList} from './RecipesList/RecipesList' diff --git a/src/styles/_utilities.scss b/src/styles/_utilities.scss index cc13ea3cf..c73526a27 100644 --- a/src/styles/_utilities.scss +++ b/src/styles/_utilities.scss @@ -112,6 +112,60 @@ border-radius: 60% 2% 2% 2%/ 6% 50% 50% 50%; } + .shape-common { + position: relative; + $border: 2px; + margin: $border; + clip-path: url(#svg-custom-shape); + } + + .shape-common-border { + position: relative; + $border: 2px; + margin: $border; + + .inner { + background: var(--white); + clip-path: url(#svg-custom-shape); + } + &::before { + position: absolute; + content: ""; + width: calc(100% + #{$border} * 2); + height: calc(100% + #{$border} * 2); + background-color: var(--primary); + top: calc(#{$border} * -1); + left: calc(#{$border} * -1); + clip-path: url(#svg-custom-shape); + } + } + + .shape-common-lg { + clip-path: url(#svg-custom-shape-lg); + padding: 2rem; + } + + .shape-common-lg-border { + position: relative; + $border: 2px; + margin: $border; + + .inner { + padding: 2rem; + clip-path: url(#svg-custom-shape-lg); + } + &::before { + position: absolute; + content: ""; + width: calc(100% + #{$border} * 2); + height: calc(100% + #{$border} * 2); + background-color: var(--primary); + top: calc(#{$border} * -1); + left: calc(#{$border} * -1); + clip-path: url(#svg-custom-shape-lg); + } + } + .font-heading { font-family: var(--font-heading); } @@ -135,7 +189,7 @@ &::-webkit-scrollbar-thumb { border-radius: 10px; - background-color: var(--primary) + background-color: var(--primary); } } @@ -149,6 +203,7 @@ .line { @apply flex justify-between items-center; > div { + flex: 1; &:not(:last-child) { margin-right: 1.6rem; } diff --git a/src/utils/constanst.utils.ts b/src/utils/constanst.utils.ts index f680fa39c..3757feb1e 100644 --- a/src/utils/constanst.utils.ts +++ b/src/utils/constanst.utils.ts @@ -1,3 +1,5 @@ +export const BLUR_DATA_IMG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMMAAADDCAMAAAAIoVWYAAAAgVBMVEUAAABYl3BZl3RZn3Bbm3RbmnRamXNbmnVbmnNamnRamXRbmnNYlnJbm3RamnRamXNamnRcmXRZmXNamnNcmXP///9bmnTr8+6YwKjB2cv1+fdvp4VloHyEs5e308KixrHW5txwpoWtzLnh7eaEs5bM4NSOup/W5t16rY6tzbrC2cuKR9FTAAAAFXRSTlMAIEAQv+9g35+AcN8wz5Cgr4BQn1CCHGjpAAAJqklEQVR42uya25aaMBSGEcRT1U6nzZEEEAS17/+AnUraiAmEbkGcLr47kYX87PNGb2JiYmJiYmJiYmJiYmLifyaYfRB4n5XtZrULccXube17nw1/H+J73hbeJ2Ixx1aWq5n3cvx2d1PBEjfzUipmm9Wy8pdwvn8PdBjMcSvLjfcaBOv7O50rZ9/gOtEH4u7UVzBFsA5tD/hDRXArTSYFQVd4Gpfi5szxc9QmbHITX0fC+cJRnYLqM9feqMzm2I1MkQVCX0PEtpZ0RBRF2EDEqAFyeAER21BHa5JW7pIX9FAzAkHNXLBinIKnJZjewrSKBLWSqzPDkbLTbGkoMFRkSOHyp+U4reAfCVlzxP5EqKuIvTcCe1zRdJ/sIFokaHJVK0YoEzMtoQGSo078VAXbezo7fCVGj5OMZAgfX6GoB7gYxxBVfT4Q1AfxUw0RbBfr1Wo+X+ErDPVDlZu+e8OzXc/rDd4BAbHX63DoGhFszPaOop7gwuFMww0JBPUFrUbT98Vi4W+HMccixBYk6g2Gb9mt9Dg78JDAUG9wc13Qq2P5S6wRZcJYmrI4SyhB/XHGBvP+VGzwzUiZo4FIhlzdfDNGykEo7DP5olcJ56EU6IAQ55JSelRu1duU+q7nsYFJCUcKXlCBFY/PFbNQRXKKngtnh75ELLFu7Z4Mv/TjTt/GkGCubt4fH9XEvYSco6dAelh6rOyjWi4kssPKJGOn/qzGVYp6g7fa9uaUCIyTtkKV9W8JH2wGazCQqPk+ad9tFEqNfQEkGjLrfeICoAHC5SFDLKxmYHol49Qw/r5gbo2GqG0lk9i+4ziSksZjjKkBvpJbzZC17SeozaXPcEPAF+M/rFN/ZBw1m8/IJlsiKAl857Fufqa4aJ/GTuiWEtAzmr+59AC82Xw7cfjFsTIERxpi6IKNqQF4n3qyTYzMtbA7E32IgjZRpv9uwS0rQTXwFeIKQBwxog4kj2+iSnBQ4ys2s4pOI6XMGGOJwIbsUw7YPfWjQft25MoiJln9GkLScTRoOzh+0eRgPoenaAhtri865JiLKYGYaYbfJTQhy4zxlnh4B8d0buROd3NNjrhGyS1p5mR7OHnL+swH1wdmfcbEVZboobaVcta8XHuuCbw+7G3lleP7IsYzuwPkLKGUJow01BDBTZeXLXU6hLfe0hpfuoiRM5awukuNuaqhGY7hzffMGntEKEsUlREgrdDxPt/y0nBR4/Rw44ETU2w8FUVU0rPO/oD5EsuT+nxureVYsQYHhOxSxArgjlvIkkqBFcTxB6EV+A30yV3EKAesXDQOa5JSiwB2rtJVxEQMWbkYlKiRGO5Om6bRmR2wBvQ2iBiWoJ00/3NgB6G5qlQwdQ/RhUBH/YNpS7fmcAY0hLT6dMpYQRAcwo5/IzvmXUNoDoiIYd+f5GnBUoK6wA9Ab/L/pozxIQK4aNq8kIgYmpvmuCLhrZU3R31jueIR2PwFX3BFRJoVSJ27oJiXPJkHoevj2RdHIeDUIRGiwJ5IjnrjBxURWVTwTGg7OcklR25Y09QeK2cCilBIVhuNY4kVnUTEApfdt8SnPv/lFOzxDecyi9kHGY1wjcgR2PwqOO48YMRNX2w8CIsv2IXz/tLI3rm4XwFoYhUQIGZfsYPmsNc7y7ahOTYCgjZNTzvPG1RFplUYka9I7Ino1EED0UENVdHsUcmNLXK7As1PU0E9J1Ct1TqXeo/gf93hW5Z7v+rPWSFugjs5cd3extIVN8ndriRXA65DA5zA36xXv1kv/N/tV+Viyf1oJqSklMqowePMlKktEauPHKQBvoaK1IjalehXe1fYnCgMRAFR0aIHdx1CAIHTAvX+/w+8cViNS1ICTjPdzPA+2naGJ2+zydvdtFMa/mnTlCfpYGecw0p4EixNdDiuRbYctZnVvToZxPR3wxcSH2EBSgvfn+V25k3DOe9UXgm4tC+srS/bUK3IpDKKqu6z05sTqH6cyV7Jv5HkF307Bw/t0EpJ+W1ZP7gdN+r8jrwSWKJUaA0N04H7ccFV/fA3ajNgIKWteo6x12Fx1x0fq5DCns9IQKCv6s+gzYD3UoohI5Z4IQamWVN9fKRlrTNqDbS0xyggaji598JPUZhEojrH20LKF1qkyJ4xFxAgJugR50hKkOT5o8py+zuI6glg5sYyISAY+sp9ZGWXalcynfci0l6QICWTAVHiYJWb6pkqs10mj0gEjgkc0dfLZJ0z5V6pRqdDrZoY7L1cxwTecdU8Tx7o5C/87/CZ1hP90NbopPUK7zNT6XlzlWhSiPPVelJIXBND0QDYIh+iHEbvRRXQHJ7JneaHXl9pm369XesyLNOlaDeKleTBEWRcTllrfGZ/Jx4BjSdlkpT4QEk7vR8Kloix9KYuxxe4wlaPKGnowp2Z2hIxGAwAV70wcSnG2eBXXL0fWvdtXBA7CCYXphwns0JW0hWUpPZDyy67GwrnJ0PBN/cW5N6/HCVpLo81shyUJLDC9lXxeTrlgrzR+wZwDybmwAcnu4INAnqjvfNFYG1sUVX3OiEpMdlVgo+CGU7iceWYxq9nDrVaSqfhdtXV+KGacUWjHEokpRytSdJr0Puh29j4OwAOcgAwnBy49jUAwn10EDeW7TWvwBCH/DmdpdLBJ8snHANcz/NCzeOb59CBbrCSRIBQuMELwX/e4l0VEc2H/krgUAPOD1WRnBiK6EryV37+DrIhvjLbGShJPtg71BB+VVDORILGUqJ3zyPaeyNchwWdhmhEO9HXxzDeprXsEUUOOeDztAwLpORJIa1zfeldQxtMH4A7w7GYHMAent7qTeWuUElKbAqHAsbEqGGGlC5Q1ySHGVLiRMNhM0NKFZzuqSECP2x6SP92iMGdMwHxSTOkN3NGWolmOH/GSCujuSy5c6aja5rL0n6OlBqaHA76YprcFkkLLiqy6Xd8P36J9OtSAlQkOSApaZFSPADdpWQzB5Tg9GgpbjX8eSNPHwTtsRUkOJs53HvFbOYAvWJWc+hPcI3NHELwlWzmsAczwGYO0ANnNQewWa3mAIaG1Ry2cznk9GoPfTycreYQ40qVHgU9WyPUDlmqJ2FIwRckrHWM3TWQ4BbbGvtZl2xUNDsE4gSQn+2tJ8aJYKF+F+SbTYAEIO30ffMHhyDCt0QgxzRwrzBRKclj7knRlvLk7m00l2izCcCNpGmxqmw6dkPXlNXn7SOqPT8PeH4yAjL/dVA7IW49hVtcbDQv442wkATcERrrmNSGdRTezl/LBALPHgY9wvf90fe3NxyiYLchmJsXLFiwYMGCBQsWLFgwH/8BQqjRKhB614AAAAAASUVORK5CYII=' + export const SOCIAL_LINKS = { FB: 'FB', TWITTER: 'TWITTER', @@ -10,9 +12,9 @@ export const ROUTE = { PRODUCTS: '/products', PRODUCT_DETAIL: '/product', ABOUT: '/about', + BLOG_DETAIL: '/blog', ACCOUNT: '/account', RECIPES: '/recipes', - BUSSINESS: '/bussiness', CONTACT: '/contact', FAQ: '/faq', @@ -33,7 +35,9 @@ export const QUERY_KEY = { TAB: 'tab', CATEGORY: 'category', BRAND: 'brand', - FEATURED: 'feature' + FEATURED: 'feature', + SORTBY:'sortby', + RECIPES:'recipes' } export enum ProductFeature { @@ -41,10 +45,75 @@ export enum ProductFeature { Sales = 'Sales', NewItem = 'New Item', Viewed = 'Viewed', - } export const KEY = { ENTER: 'Enter', } +export const OPTION_ALL = 'all'; +export const DEFAULT_PAGE_SIZE=20; + + +export const CATEGORY = [ + { + name: 'All', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=${OPTION_ALL}`, + }, + { + name: 'Veggie', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=veggie`, + }, + { + name: 'Seafood', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=seafood`, + }, + { + name: 'Frozen', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=frozen`, + }, + { + name: 'Coffee Bean', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=coffee_bean`, + }, + { + name: 'Sauce', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.CATEGORY}=sauce`, + }, + ] + + export const BRAND = [ + { + name: 'Maggi', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=maggi`, + }, + { + name: 'Chomilex', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=chomilex`, + }, + { + name: 'Chinsu', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.BRAND}=chinsu`, + }, + ] + +export const FEATURED = [ + { + name: 'Best Sellers', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=best_sellers`, + }, + { + name: 'Sales', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=sales`, + }, + { + name: 'New Item', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=new_item`, + }, + { + name: 'Viewed', + link: `${ROUTE.PRODUCTS}/?${QUERY_KEY.FEATURED}=viewed`, + }, + ] + +export const DEFAULT_BLOG_PAGE_SIZE=6; diff --git a/src/utils/demo-data.ts b/src/utils/demo-data.ts index 64c8128ae..aad6653b5 100644 --- a/src/utils/demo-data.ts +++ b/src/utils/demo-data.ts @@ -1,3 +1,5 @@ +import { BlogCardProps } from "src/components/common/CardBlog/CardBlog" +import { CardItemCheckoutProps } from "src/components/common/CardItemCheckout/CardItemCheckout" import { RecipeCardProps } from "src/components/common/RecipeCard/RecipeCard" export const PRODUCT_DATA_TEST = [ @@ -185,31 +187,108 @@ export const RECIPE_DATA_TEST: RecipeCardProps[] = [ { title: "Special Recipe of Vietnamese Phở", description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:", - imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png' + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png', + slug: "special-recipe-of-vietnamese-pho" }, { title: "Original Recipe of Curry", description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...", - imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png' + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png', + slug:"original-recipe-of-curry" }, { title: "The Best Recipe of Beef Noodle Soup", description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...", - imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png' + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png', + slug:"the-best-recipe-of-beef-noodle-soup" }, { title: "Special Recipe of Vietnamese Phở", description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:", - imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png' + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png', + slug: "special-recipe-of-vietnamese-pho" }, { title: "Original Recipe of Curry", description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...", - imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png' + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png', + slug:"original-recipe-of-curry" }, { title: "The Best Recipe of Beef Noodle Soup", description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...", - imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png' + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png', + slug:"the-best-recipe-of-beef-noodle-soup" }, -] \ No newline at end of file +] + + + +export const BLOGS_DATA_TEST: BlogCardProps[] = [ + { + title: "Special Recipe of Vietnamese Phở", + description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png', + slug: "special-recipe-of-vietnamese-pho" + }, + { + title: "Original Recipe of Curry", + description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png', + slug:"original-recipe-of-curry" + }, + { + title: "The Best Recipe of Beef Noodle Soup", + description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png', + slug:"the-best-recipe-of-beef-noodle-soup" + }, + { + title: "Special Recipe of Vietnamese Phở", + description: "Alright, before we get to the actual recipe, let’s chat for a sec about the ingredients. To make this pho soup recipe, you will need:", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159257-f92574c7-d00d-4142-8ea7-0ca9515fb737.png', + slug: "special-recipe-of-vietnamese-pho" + }, + { + title: "Original Recipe of Curry", + description: "Chicken curry is common to several countries including India, countries in Asia and the Caribbean. My favorite of them though is this aromatic Indian...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159259-ae4c986d-ab53-4758-9137-d06bafdd15d0.png', + slug:"original-recipe-of-curry" + }, + { + title: "The Best Recipe of Beef Noodle Soup", + description: "The broth for Bun Bo Hue is prepared by slowly simmering various types of beef and pork bones (ox tail, beef shank, pork neck bones, pork feet,...", + imageSrc: 'https://user-images.githubusercontent.com/76729908/132159262-f28a9fb9-4852-47e6-80b5-d600521b548a.png', + slug:"the-best-recipe-of-beef-noodle-soup" + }, +]; +export const CHECKOUT_BILL_DATA:CardItemCheckoutProps[] = [ + { + name: 'Tomato', + slug: "tomato", + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646227-b5705e64-3b45-47a3-9433-9f4b5ee8d40c.png", + quantity:10 + }, + { + name: 'Carrot', + slug: "carrot", + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646217-23b86160-45c9-4845-8dcc-b3e1a4483edd.png", + quantity:1 + }, + { + name: 'Salad', + slug:"salad", + weight: '250g', + category: 'VEGGIE', + price: 'Rp 27.500', + imageSrc: "https://user-images.githubusercontent.com/76729908/131646221-aaa1d48d-bb80-470f-9400-ae2aa47285b6.png", + quantity:2 + }, + ] +export const PRODUCT_DATA_TEST_PAGE = [...PRODUCT_DATA_TEST, ...PRODUCT_DATA_TEST, ...PRODUCT_DATA_TEST, ...PRODUCT_DATA_TEST, ...PRODUCT_DATA_TEST] diff --git a/src/utils/funtion.utils.ts b/src/utils/funtion.utils.ts index b1e7b5536..619e9ae30 100644 --- a/src/utils/funtion.utils.ts +++ b/src/utils/funtion.utils.ts @@ -1,3 +1,11 @@ export function isMobile() { return window.innerWidth <= 768 +} + +export function removeItem(arr: Array, value: T): Array { + const index = arr.indexOf(value); + if (index > -1) { + arr.splice(index, 1); + } + return [...arr]; } \ No newline at end of file diff --git a/src/utils/language.utils.ts b/src/utils/language.utils.ts index 191215aaa..8b3d8f8d5 100644 --- a/src/utils/language.utils.ts +++ b/src/utils/language.utils.ts @@ -2,6 +2,7 @@ export const LANGUAGE = { BUTTON_LABEL: { BUY_NOW: 'Buy now', SHOP_NOW: 'Shop now', + CONFIRM:'Confirm', ADD_TO_CARD: 'Add to Cart', PREORDER: 'Pre-Order Now', }, diff --git a/src/utils/types.utils.ts b/src/utils/types.utils.ts index c87305f2b..e2ce516d4 100644 --- a/src/utils/types.utils.ts +++ b/src/utils/types.utils.ts @@ -20,8 +20,34 @@ export interface FeaturedProductProps { export interface RecipeProps { title: string + slug: string description: string imageSrc: string } -export type MouseAndTouchEvent = MouseEvent | TouchEvent \ No newline at end of file +export interface BlogProps { + title: string + slug: string + description: string + imageSrc: string +} + +export interface CheckOutForm { + name?: string + email?:string + address?: string + city?:string + state?:string + code?:number + phone?:number + method?:string + shipping_fee?:number +} + +export type MouseAndTouchEvent = MouseEvent | TouchEvent + +export type filterContextType = { + visible: boolean; + open: () => void; + close: () => void; +}; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 6a08e59f8..316d817b7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,6 @@ "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, - "isolatedModules": true, "jsx": "preserve", "incremental": true, "noUnusedLocals": true, @@ -26,7 +25,8 @@ "@commerce/*": ["framework/commerce/*"], "@framework": ["framework/vendure"], "@framework/*": ["framework/vendure/*"] - } + }, + "isolatedModules": true }, "include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"], "exclude": [