diff --git a/.gitignore b/.gitignore index 1437c53..9a4fa09 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,8 @@ yarn-error.log* # vercel .vercel + +# next-pwa + +**/public/workbox-*.js +**/public/sw.js \ No newline at end of file diff --git a/README.md b/README.md index 2bfcda2..1abc546 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,12 @@ All network requests are proxied via CORS Anywhere helps with accessing data from other websites that is normally forbidden by the same origin policy of web browsers -SWR - state management -SSR - NextJS -PWA - next-pwa -recharts - Charting library -idb-keyval - IndexedDB +- SWR - state management +- SSR - NextJS +- PWA - next-pwa +- recharts - Charting library +- idb-keyval - IndexedDB +App works Offline after initial load Demo : https://comparecart.vercel.app/ \ No newline at end of file diff --git a/components/Analytics/Chart.tsx b/components/Analytics/Chart.tsx index 45edc76..bf0d396 100644 --- a/components/Analytics/Chart.tsx +++ b/components/Analytics/Chart.tsx @@ -18,7 +18,7 @@ export const Chart = ({ items, title, colour, name }: chartProps) => { {name} - + ); diff --git a/components/SideBar/MenuOptions.ts b/components/SideBar/MenuOptions.ts index 685a245..4f7a71a 100644 --- a/components/SideBar/MenuOptions.ts +++ b/components/SideBar/MenuOptions.ts @@ -1,12 +1,11 @@ export interface MenuOptions { - 'my store': Item[]; - 'Research Products': Item[]; - 'Learn': Item[]; - 'Settings': Item[]; + id: number; + name: string; + options: Option[]; } -export interface Item { - id: number; +export interface Option { + id: number; icon: string; name: string; -} +} \ No newline at end of file diff --git a/components/SideBar/OptionsList.tsx b/components/SideBar/OptionsList.tsx index da7d2a1..62de7dc 100644 --- a/components/SideBar/OptionsList.tsx +++ b/components/SideBar/OptionsList.tsx @@ -1,10 +1,10 @@ import React from 'react'; import OptionsListItem from './OptionsListItem'; import OptionsListHeading from './OptionsListHeading'; -import { MenuOptions, Item } from './MenuOptions'; +import { MenuOptions, Option } from './MenuOptions'; interface Iprops { - menuOptions: MenuOptions; + menuOptions: MenuOptions[]; } const OptionsList = ({ menuOptions }: Iprops) => { @@ -15,15 +15,15 @@ const OptionsList = ({ menuOptions }: Iprops) => { ); }; -const renderOptions = (menuOptions: MenuOptions): React.ReactNode => { - return Object.entries(menuOptions).map(([heading, options]) => { +const renderOptions = (menuOptions: MenuOptions[]): React.ReactNode => { + return menuOptions.map((option: MenuOptions) => { return ( - <> - - {options.map((option: Item) => ( +
+ + {option.options.map((option: Option) => ( ))} - +
); }); }; diff --git a/components/SideBar/OptionsListItem.tsx b/components/SideBar/OptionsListItem.tsx index f566a19..09a3f9f 100644 --- a/components/SideBar/OptionsListItem.tsx +++ b/components/SideBar/OptionsListItem.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import { Item } from './MenuOptions'; +import { Option } from './MenuOptions'; interface Iprops { - item: Item; + item: Option; } const OptionsListItem = ({ item }: Iprops) => { diff --git a/components/SideBar/index.tsx b/components/SideBar/index.tsx index c132c4f..d795f18 100644 --- a/components/SideBar/index.tsx +++ b/components/SideBar/index.tsx @@ -1,82 +1,6 @@ import React from 'react'; import OptionsList from './OptionsList'; -import { MenuOptions } from './MenuOptions'; - -const MenuItems: MenuOptions = { - 'my store': [ - { - id: 1, - icon: 'some.svg', - name: 'Item Name', - }, - { - id: 2, - icon: 'some.svg', - name: 'Item Name', - }, - { - id: 3, - icon: 'some.svg', - name: 'Item Name', - }, - { - id: 4, - icon: 'some.svg', - name: 'Item Name', - }, - ], - 'Research Products': [ - { - id: 5, - icon: 'some.svg', - name: 'Item Name', - }, - { - id: 6, - icon: 'some.svg', - name: 'Item Name', - }, - { - id: 7, - icon: 'some.svg', - name: 'Item Name', - }, - { - id: 8, - icon: 'some.svg', - name: 'Item Name', - }, - ], - Learn: [ - { - id: 9, - icon: 'some.svg', - name: 'Item Name', - }, - { - id: 10, - icon: 'some.svg', - name: 'Item Name', - }, - ], - Settings: [ - { - id: 11, - icon: 'some.svg', - name: 'Item Name', - }, - { - id: 12, - icon: 'some.svg', - name: 'Item Name', - }, - { - id: 13, - icon: 'some.svg', - name: 'Item Name', - }, - ], -}; +import { MenuItems } from 'services/globals'; const SideBar = () => { return ( diff --git a/next.config.js b/next.config.js index f4182bc..cc89d50 100644 --- a/next.config.js +++ b/next.config.js @@ -1,10 +1,10 @@ -// const isProd = process.env.NODE_ENV === "production"; +const isProd = process.env.NODE_ENV === "production"; const withPWA = require("next-pwa") module.exports = withPWA({ pwa: { - // disable: !isProd, + disable: !isProd, dest: "public" } }) \ No newline at end of file diff --git a/pages/_app.js b/pages/_app.js deleted file mode 100644 index d56d9bf..0000000 --- a/pages/_app.js +++ /dev/null @@ -1,7 +0,0 @@ -import '../styles/index.css' - -function MyApp({ Component, pageProps }) { - return -} - -export default MyApp diff --git a/pages/_app.tsx b/pages/_app.tsx new file mode 100644 index 0000000..df56e13 --- /dev/null +++ b/pages/_app.tsx @@ -0,0 +1,19 @@ +import '../styles/index.css'; +import Head from 'next/head'; + +import { AppProps } from 'next/app'; + +function MyApp({ Component, pageProps }: AppProps) { + return ( + <> + + CompareCart + + + + + + ); +} + +export default MyApp; diff --git a/pages/_document.tsx b/pages/_document.tsx index 8dfe227..6f9c0fb 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -16,9 +16,7 @@ class MyDocument extends Document { return ( - CompareCart - - + {"require"!==e&&(e+=".js");let s=Promise.resolve();return a[e]||(s=new Promise(async s=>{if("document"in self){const a=document.createElement("script");a.src=e,document.head.appendChild(a),a.onload=s}else importScripts(e),s()})),s.then(()=>{if(!a[e])throw new Error(`Module ${e} didn’t register its module`);return a[e]})},s=(s,a)=>{Promise.all(s.map(e)).then(e=>a(1===e.length?e[0]:e))},a={require:Promise.resolve(s)};self.define=(s,c,n)=>{a[s]||(a[s]=Promise.resolve().then(()=>{let a={};const r={uri:location.origin+s.slice(1)};return Promise.all(c.map(s=>{switch(s){case"exports":return a;case"module":return r;default:return e(s)}})).then(e=>{const s=n(...e);return a.default||(a.default=s),a})}))}}define("./sw.js",["./workbox-432e0d0b"],(function(e){"use strict";importScripts(),e.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/static/_z1b1eyAg2XYXFIevCejJ/_buildManifest.js",revision:"0ded160ec5c758936e4f8c9f2afb7e3d"},{url:"/_next/static/_z1b1eyAg2XYXFIevCejJ/_ssgManifest.js",revision:"abee47769bf307639ace4945f9cfd4ff"},{url:"/_next/static/chunks/commons.a6380e44e1e61e829588.js",revision:"3b70f12312b2ed6cf89e85a45d56004a"},{url:"/_next/static/chunks/f6078781a05fe1bcb0902d23dbbb2662c8d200b3.967c64c909a544bf93bf.js",revision:"5d7dc9f159fe02619aa43e93ada855d0"},{url:"/_next/static/chunks/framework.a5d4ffe593e18b49243e.js",revision:"1c8c47501f8a83e7cbef6220665aa75a"},{url:"/_next/static/chunks/main-fdbc5bac9bf812c50bef.js",revision:"84b77c59bd96553fcc574e47bc03fb95"},{url:"/_next/static/chunks/pages/_app-6ef0e7c22cdf6864df33.js",revision:"554e6e9d58cba924b58c1723716dac02"},{url:"/_next/static/chunks/pages/_error-f50b9ee345909a909d63.js",revision:"c1ac48d476390b75889e187f7dfb5c0a"},{url:"/_next/static/chunks/pages/index-ecf861fc46980e4163c4.js",revision:"cbffd35cf4860616aeb7e0f818102750"},{url:"/_next/static/chunks/polyfills-b4c9a36a8d9b649404fa.js",revision:"a48d4613d0d8a928054ac053d572d8b2"},{url:"/_next/static/chunks/webpack-488dc228921f1fdbc0e7.js",revision:"8c19f623e8389f11131a054a7e17ff95"},{url:"/_next/static/css/2344944d8f6b3174d57a.css",revision:"8eca0cf6505d0ee7506a729c5607c762"},{url:"/favicon.ico",revision:"e78c7079ca7b991b283c29e6a7af106c"},{url:"/logo.png",revision:"de6a4582054cceb76b892e513a205b41"},{url:"/logo192.png",revision:"43b0d8380e5d43a391ff2e5eff8f3b07"},{url:"/logo512.png",revision:"8fdd769467795f5b19240873f36a06de"},{url:"/manifest.webmanifest",revision:"c8c820d4b0f0400b857d85796a30025c"},{url:"/maskable_logo1024.png",revision:"366a56da8c3d06dadcfb31e8f6559b79"},{url:"/robots.txt",revision:"fa1ded1ed7c11438a9b0385b1e112850"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[new e.ExpirationPlugin({maxEntries:1,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis|gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\/api\/.*$/i,new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/.*/i,new e.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET")})); +if(!self.define){const e=e=>{"require"!==e&&(e+=".js");let s=Promise.resolve();return a[e]||(s=new Promise(async s=>{if("document"in self){const a=document.createElement("script");a.src=e,document.head.appendChild(a),a.onload=s}else importScripts(e),s()})),s.then(()=>{if(!a[e])throw new Error(`Module ${e} didn’t register its module`);return a[e]})},s=(s,a)=>{Promise.all(s.map(e)).then(e=>a(1===e.length?e[0]:e))},a={require:Promise.resolve(s)};self.define=(s,n,c)=>{a[s]||(a[s]=Promise.resolve().then(()=>{let a={};const r={uri:location.origin+s.slice(1)};return Promise.all(n.map(s=>{switch(s){case"exports":return a;case"module":return r;default:return e(s)}})).then(e=>{const s=c(...e);return a.default||(a.default=s),a})}))}}define("./sw.js",["./workbox-432e0d0b"],(function(e){"use strict";importScripts(),e.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/static/chunks/commons.018269f306026a28effd.js",revision:"b92f128b6452f72687c89afdab3d3cb1"},{url:"/_next/static/chunks/f6078781a05fe1bcb0902d23dbbb2662c8d200b3.967c64c909a544bf93bf.js",revision:"5d7dc9f159fe02619aa43e93ada855d0"},{url:"/_next/static/chunks/framework.a5d4ffe593e18b49243e.js",revision:"1c8c47501f8a83e7cbef6220665aa75a"},{url:"/_next/static/chunks/main-756fc0fb2b0b72df46ff.js",revision:"f16182661e4de00cba30ecc847e30db0"},{url:"/_next/static/chunks/pages/_app-87369ed04ece7eedecb2.js",revision:"35b5637479f42d20acc4f6b232dd8f6d"},{url:"/_next/static/chunks/pages/_error-0d8b37c31ac76a3f5ea0.js",revision:"a02826061cd180a6339ec2e9aac36fb1"},{url:"/_next/static/chunks/pages/index-846a92beeac57f29902e.js",revision:"9a526fcf67327289e66c8247482079e3"},{url:"/_next/static/chunks/polyfills-b4c9a36a8d9b649404fa.js",revision:"a48d4613d0d8a928054ac053d572d8b2"},{url:"/_next/static/chunks/webpack-488dc228921f1fdbc0e7.js",revision:"8c19f623e8389f11131a054a7e17ff95"},{url:"/_next/static/css/2344944d8f6b3174d57a.css",revision:"8eca0cf6505d0ee7506a729c5607c762"},{url:"/_next/static/v7cbzS0pDN_lHwaZqAT0f/_buildManifest.js",revision:"a36f7600d378fb855ec6d65a2bfe2531"},{url:"/_next/static/v7cbzS0pDN_lHwaZqAT0f/_ssgManifest.js",revision:"abee47769bf307639ace4945f9cfd4ff"},{url:"/favicon.ico",revision:"e78c7079ca7b991b283c29e6a7af106c"},{url:"/logo.png",revision:"de6a4582054cceb76b892e513a205b41"},{url:"/logo192.png",revision:"43b0d8380e5d43a391ff2e5eff8f3b07"},{url:"/logo512.png",revision:"8fdd769467795f5b19240873f36a06de"},{url:"/manifest.webmanifest",revision:"c8c820d4b0f0400b857d85796a30025c"},{url:"/maskable_logo1024.png",revision:"366a56da8c3d06dadcfb31e8f6559b79"},{url:"/robots.txt",revision:"fa1ded1ed7c11438a9b0385b1e112850"}],{ignoreURLParametersMatching:[]}),e.cleanupOutdatedCaches(),e.registerRoute("/",new e.NetworkFirst({cacheName:"start-url",plugins:[new e.ExpirationPlugin({maxEntries:1,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/^https:\/\/fonts\.(?:googleapis|gstatic)\.com\/.*/i,new e.CacheFirst({cacheName:"google-fonts",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:31536e3,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,new e.StaleWhileRevalidate({cacheName:"static-font-assets",plugins:[new e.ExpirationPlugin({maxEntries:4,maxAgeSeconds:604800,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,new e.StaleWhileRevalidate({cacheName:"static-image-assets",plugins:[new e.ExpirationPlugin({maxEntries:64,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:js)$/i,new e.StaleWhileRevalidate({cacheName:"static-js-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:css|less)$/i,new e.StaleWhileRevalidate({cacheName:"static-style-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\.(?:json|xml|csv)$/i,new e.NetworkFirst({cacheName:"static-data-assets",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/\/api\/.*$/i,new e.NetworkFirst({cacheName:"apis",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:16,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET"),e.registerRoute(/.*/i,new e.NetworkFirst({cacheName:"others",networkTimeoutSeconds:10,plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:86400,purgeOnQuotaError:!0})]}),"GET")})); diff --git a/services/globals.ts b/services/globals.ts index 89e354a..e798000 100644 --- a/services/globals.ts +++ b/services/globals.ts @@ -1,3 +1,5 @@ +import { MenuOptions } from "components/SideBar/MenuOptions"; + export const BOL_SERVER = 'https://api.bol.com'; export const PROXY_SERVER = 'https://cors-anywhere.herokuapp.com/'; export const baseURL = PROXY_SERVER + BOL_SERVER; @@ -40,3 +42,110 @@ export const TableHeading = [ name: 'Action thing', }, ]; + +export const MenuItems: MenuOptions[] = [ + { + "id":1, + "name":"my store", + "options":[ + { + "id":1, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":2, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":3, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":4, + "icon":"some.svg", + "name":"Item Name" + } + ] + }, + { + "id":2, + "name":"Research Products", + "options":[ + { + "id":1, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":2, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":3, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":4, + "icon":"some.svg", + "name":"Item Name" + } + ] + }, + { + "id":3, + "name":"Learn", + "options":[ + { + "id":1, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":2, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":3, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":4, + "icon":"some.svg", + "name":"Item Name" + } + ] + }, + { + "id":4, + "name":"Settings", + "options":[ + { + "id":1, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":2, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":3, + "icon":"some.svg", + "name":"Item Name" + }, + { + "id":4, + "icon":"some.svg", + "name":"Item Name" + } + ] + } +];