├── .dockerignore ├── public ├── _redirects ├── logo.png ├── offer_ad.webp ├── imgs │ ├── emptyOrders.png │ ├── sideoffers │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ └── sideOffer.webp │ ├── title_logo.png │ ├── catogorytoggle.png │ ├── homeBanners │ │ ├── 1.webp │ │ └── 2.webp │ ├── offers │ │ ├── offer1.webp │ │ ├── offer2.webp │ │ ├── offer3.webp │ │ └── offer4.webp │ ├── shopeaseLogo.webp │ ├── ShopEase_offers │ │ ├── 1.png │ │ ├── 2.png │ │ └── 3.png │ ├── demo_row_products │ │ ├── 1.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ ├── 9.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 13.png │ │ ├── 14.png │ │ ├── 15.png │ │ ├── 16.png │ │ ├── 17.png │ │ ├── Best_seller │ │ │ ├── image │ │ │ │ ├── 1.png │ │ │ │ ├── 2.png │ │ │ │ ├── 3.png │ │ │ │ ├── 4.png │ │ │ │ └── 5.png │ │ │ └── thumbImg │ │ │ │ ├── 1.png │ │ │ │ ├── 2.png │ │ │ │ ├── 3.png │ │ │ │ ├── 4.png │ │ │ │ └── 5.png │ │ ├── Featured │ │ │ ├── image │ │ │ │ ├── 20.png │ │ │ │ ├── 21.png │ │ │ │ ├── 22.png │ │ │ │ ├── 23.png │ │ │ │ └── 24.png │ │ │ └── thumbnail │ │ │ │ ├── 20.png │ │ │ │ ├── 21.png │ │ │ │ ├── 22.png │ │ │ │ ├── 23.png │ │ │ │ └── 24.png │ │ └── Limited_offers │ │ │ ├── 51upsgtoSJL.jpg │ │ │ ├── 91++0qiC+1S.jpg │ │ │ ├── vitamix-blender-2-speed-500x500.webp │ │ │ ├── asics-gel-cumulus-24-0340-tested-1657127192.jpg │ │ │ └── ONIKUMA-X27-RGB-Gaming-Headset-Stereo-Surround-l-Noise-Canceling-Mic-RGB.webp │ ├── headerCatogeryImgs │ │ ├── Beauty.webp │ │ ├── Flights.webp │ │ ├── Grocery.webp │ │ ├── Fashions.webp │ │ ├── Electronics.webp │ │ ├── Furnniture.webp │ │ ├── TopOfferce.webp │ │ ├── HomeAndKitchen.webp │ │ ├── MubileAndTablets.webp │ │ └── TvAndAppliances.webp │ ├── icons │ │ ├── down-arrow.svg │ │ ├── left-arrow.svg │ │ ├── right-arrow.svg │ │ ├── search.svg │ │ ├── user.svg │ │ ├── menu.svg │ │ ├── shopping-cart.svg │ │ └── refresh.svg │ └── logo.svg └── vite.svg ├── src ├── vite-env.d.ts ├── components │ ├── HomeBanner.tsx │ ├── SearchBar.tsx │ ├── Ad.tsx │ ├── ProductGroupsTab.tsx │ ├── chatbot │ │ ├── ChatBox.tsx │ │ └── ChatBot.tsx │ ├── AccountSidebar.tsx │ ├── PaymentSuccesfull.tsx │ ├── HomeSlider.tsx │ ├── ProductCard.tsx │ ├── Rewards.tsx │ ├── Offer.tsx │ ├── Footer.tsx │ ├── Orders.tsx │ ├── WishList.tsx │ ├── PopupCard.tsx │ ├── Profile.tsx │ ├── AccountDetails.tsx │ ├── CustomProductsRows.tsx │ ├── HeaderCategory.tsx │ ├── ProductFilterSiderbar.tsx │ ├── NestedHoverNavlink.tsx │ ├── Checkout.tsx │ ├── Header.tsx │ └── ProductDetails.tsx ├── redux │ ├── actions │ │ ├── DarkModeAction.tsx │ │ ├── searchActions.tsx │ │ ├── cartActions.tsx │ │ ├── dataAction.tsx │ │ └── authActions.tsx │ ├── reducers │ │ ├── searchReducer.tsx │ │ ├── DarkReducer.tsx │ │ ├── dataReducer.tsx │ │ ├── authReducer.tsx │ │ ├── cartReducer.tsx │ │ └── axiosFetchData.tsx │ └── store.ts ├── pages │ ├── Error.tsx │ ├── ProductsGroup.tsx │ ├── Account.tsx │ ├── Cart.tsx │ ├── Home.tsx │ ├── ProductGallery.tsx │ └── Login.tsx ├── apollo │ ├── client.ts │ └── fetchData.ts ├── test │ ├── ProductGallery.tsx │ └── fetchData.test.ts ├── types │ ├── productTypes.ts │ └── layoutTypes.ts ├── main.tsx ├── optimazation │ └── AppOptimazation.ts ├── index.css ├── paths.ts ├── assets │ ├── footerUtility.ts │ ├── globalUtlities.ts │ └── headerCategoryData.ts └── App.tsx ├── netlify.toml ├── WLN9OvxLaw.png ├── msedge_TumEkFZ95I.png ├── msedge_a5NnVoDCHa.png ├── postcss.config.js ├── vite.config.ts ├── tsconfig.node.json ├── .hintrc ├── .env ├── .gitignore ├── docker-compose.yml ├── .eslintrc.cjs ├── .github └── workflows │ ├── cd.yml │ └── ci.yml ├── tsconfig.json ├── Dockerfile ├── index.html ├── package.json ├── tailwind.config.js ├── README.md └── into main /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 2 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "npm run build" 3 | publish = "dist" 4 | -------------------------------------------------------------------------------- /WLN9OvxLaw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/WLN9OvxLaw.png -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/logo.png -------------------------------------------------------------------------------- /public/offer_ad.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/offer_ad.webp -------------------------------------------------------------------------------- /msedge_TumEkFZ95I.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/msedge_TumEkFZ95I.png -------------------------------------------------------------------------------- /msedge_a5NnVoDCHa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/msedge_a5NnVoDCHa.png -------------------------------------------------------------------------------- /public/imgs/emptyOrders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/emptyOrders.png -------------------------------------------------------------------------------- /public/imgs/sideoffers/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/sideoffers/1.png -------------------------------------------------------------------------------- /public/imgs/sideoffers/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/sideoffers/2.png -------------------------------------------------------------------------------- /public/imgs/sideoffers/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/sideoffers/3.png -------------------------------------------------------------------------------- /public/imgs/sideoffers/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/sideoffers/4.png -------------------------------------------------------------------------------- /public/imgs/sideoffers/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/sideoffers/5.png -------------------------------------------------------------------------------- /public/imgs/title_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/title_logo.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/imgs/catogorytoggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/catogorytoggle.png -------------------------------------------------------------------------------- /public/imgs/homeBanners/1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/homeBanners/1.webp -------------------------------------------------------------------------------- /public/imgs/homeBanners/2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/homeBanners/2.webp -------------------------------------------------------------------------------- /public/imgs/offers/offer1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/offers/offer1.webp -------------------------------------------------------------------------------- /public/imgs/offers/offer2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/offers/offer2.webp -------------------------------------------------------------------------------- /public/imgs/offers/offer3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/offers/offer3.webp -------------------------------------------------------------------------------- /public/imgs/offers/offer4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/offers/offer4.webp -------------------------------------------------------------------------------- /public/imgs/shopeaseLogo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/shopeaseLogo.webp -------------------------------------------------------------------------------- /public/imgs/ShopEase_offers/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/ShopEase_offers/1.png -------------------------------------------------------------------------------- /public/imgs/ShopEase_offers/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/ShopEase_offers/2.png -------------------------------------------------------------------------------- /public/imgs/ShopEase_offers/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/ShopEase_offers/3.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/1.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/2.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/3.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/4.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/5.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/6.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/7.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/8.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/9.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/10.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/11.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/12.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/13.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/14.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/15.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/16.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/17.png -------------------------------------------------------------------------------- /public/imgs/sideoffers/sideOffer.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/sideoffers/sideOffer.webp -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/Beauty.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/Beauty.webp -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/Flights.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/Flights.webp -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/Grocery.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/Grocery.webp -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/Fashions.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/Fashions.webp -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/Electronics.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/Electronics.webp -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/Furnniture.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/Furnniture.webp -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/TopOfferce.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/TopOfferce.webp -------------------------------------------------------------------------------- /src/components/HomeBanner.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | const HomeBanner = () => { 4 | return ( 5 |
HomeBanner
6 | ); 7 | }; 8 | 9 | export { HomeBanner} -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/HomeAndKitchen.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/HomeAndKitchen.webp -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/image/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/image/1.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/image/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/image/2.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/image/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/image/3.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/image/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/image/4.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/image/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/image/5.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/image/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/image/20.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/image/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/image/21.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/image/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/image/22.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/image/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/image/23.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/image/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/image/24.png -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/MubileAndTablets.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/MubileAndTablets.webp -------------------------------------------------------------------------------- /public/imgs/headerCatogeryImgs/TvAndAppliances.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/headerCatogeryImgs/TvAndAppliances.webp -------------------------------------------------------------------------------- /src/components/SearchBar.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | const SearchBar = () => { 5 | return ( 6 |
SearchBar
7 | ); 8 | }; 9 | 10 | export { SearchBar} -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/thumbnail/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/thumbnail/20.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/thumbnail/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/thumbnail/21.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/thumbnail/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/thumbnail/22.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/thumbnail/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/thumbnail/23.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Featured/thumbnail/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Featured/thumbnail/24.png -------------------------------------------------------------------------------- /src/redux/actions/DarkModeAction.tsx: -------------------------------------------------------------------------------- 1 | 2 | export const DARK__MODE_TOGGLE = "DARK_MODE_TOGGLE" 3 | 4 | 5 | export const toggleDarkMode = () => ({ type: DARK__MODE_TOGGLE }) -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/thumbImg/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/thumbImg/1.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/thumbImg/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/thumbImg/2.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/thumbImg/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/thumbImg/3.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/thumbImg/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/thumbImg/4.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Best_seller/thumbImg/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Best_seller/thumbImg/5.png -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Limited_offers/51upsgtoSJL.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Limited_offers/51upsgtoSJL.jpg -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Limited_offers/91++0qiC+1S.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Limited_offers/91++0qiC+1S.jpg -------------------------------------------------------------------------------- /src/redux/actions/searchActions.tsx: -------------------------------------------------------------------------------- 1 | export const SEARCH_PRODUCTS = "SEARCH_PRODUCTS" 2 | 3 | export const searchProducts = (query:string)=>({ 4 | type :SEARCH_PRODUCTS, 5 | payload :{query} 6 | }); 7 | -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Limited_offers/vitamix-blender-2-speed-500x500.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Limited_offers/vitamix-blender-2-speed-500x500.webp -------------------------------------------------------------------------------- /src/components/Ad.tsx: -------------------------------------------------------------------------------- 1 | 2 | export const Ad = () => { 3 | return ( 4 |
5 | Ad_Poster 6 |
7 | ) 8 | } 9 | -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Limited_offers/asics-gel-cumulus-24-0340-tested-1657127192.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Limited_offers/asics-gel-cumulus-24-0340-tested-1657127192.jpg -------------------------------------------------------------------------------- /src/pages/Error.tsx: -------------------------------------------------------------------------------- 1 | 2 | const Error = () => { 3 | return ( 4 |
5 | Error 6 |
7 | ); 8 | }; 9 | 10 | export default Error; 11 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | build: { 8 | outDir:'dist', 9 | } 10 | }) 11 | 12 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /.hintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "development" 4 | ], 5 | "hints": { 6 | "axe/name-role-value": [ 7 | "default", 8 | { 9 | "button-name": "off" 10 | } 11 | ], 12 | "button-type": "off", 13 | "no-inline-styles": "off" 14 | } 15 | } -------------------------------------------------------------------------------- /public/imgs/icons/down-arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/imgs/icons/left-arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/imgs/icons/right-arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/imgs/demo_row_products/Limited_offers/ONIKUMA-X27-RGB-Gaming-Headset-Stereo-Surround-l-Noise-Canceling-Mic-RGB.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/muhammadshakkeerp/Shopease/HEAD/public/imgs/demo_row_products/Limited_offers/ONIKUMA-X27-RGB-Gaming-Headset-Stereo-Surround-l-Noise-Canceling-Mic-RGB.webp -------------------------------------------------------------------------------- /src/apollo/client.ts: -------------------------------------------------------------------------------- 1 | import { ApolloClient, InMemoryCache } from "@apollo/client"; 2 | 3 | export const client = new ApolloClient({ 4 | // uri: "https://ShopEase-clone-server-dzyl-git-host-vercel-iamintelligent.vercel.app/graphql", 5 | uri: "http://localhost:3000/graphql", 6 | cache: new InMemoryCache(), 7 | }); 8 | -------------------------------------------------------------------------------- /public/imgs/icons/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/imgs/icons/user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/imgs/icons/menu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | VITE_FIREBASE_API_KEY=AIzaSyCIMR8fUv1NMFf3G1_veC3_-OdjAPMnF9E 2 | VITE_FIREBASE_AUTH_DOMAIN=flipkartclone-bd94a.firebaseapp.com 3 | VITE_FIREBASE_PROJECT_ID=flipkartclone-bd94a 4 | VITE_FIREBASE_STORAGE_BUCKET=flipkartclone-bd94a.appspot.com 5 | VITE_FIREBASE_MESSAGING_SENDER_ID=49350568372 6 | VITE_FIREBASE_APP_ID=1:49350568372:web:52a52424fb37b173676ae1 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | .env 15 | 16 | # Editor directories and files 17 | .vscode/* 18 | !.vscode/extensions.json 19 | .idea 20 | .DS_Store 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | -------------------------------------------------------------------------------- /src/components/ProductGroupsTab.tsx: -------------------------------------------------------------------------------- 1 | import { headerCategories } from "../assets/headerCategoryData" 2 | 3 | export const ProductGroupsTab = () => { 4 | return ( 5 | 7 | ) 8 | } 9 | -------------------------------------------------------------------------------- /public/imgs/icons/shopping-cart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/imgs/icons/refresh.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/ProductGallery.tsx: -------------------------------------------------------------------------------- 1 | import { ProductGallery } from '../paths'; 2 | import { render } from '@testing-library/react' 3 | import '@testing-library/jest-dom/extend-expect'; 4 | 5 | 6 | test('renders loading message', () => { 7 | const { getByText } = render(); 8 | const loadingElement = getByText(/Loading.../i); 9 | expect(loadingElement).toBeDefined(); 10 | }); 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/test/fetchData.test.ts: -------------------------------------------------------------------------------- 1 | import { fetchData } from '../apollo/fetchData'; // Adjust the path as per your project structure 2 | 3 | test('fetchData function fetches data successfully', async () => { 4 | const dispatchMock = jest.fn(); 5 | await fetchData()(dispatchMock); 6 | expect(dispatchMock).toHaveBeenCalledTimes(2); // Assuming fetchDataRequest and fetchDataSuccess dispatch actions are called 7 | }); 8 | 9 | // Add more test cases as needed 10 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | 3 | services: 4 | ShopEase: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | ports: 9 | - "5180:5173" # Map the container's port 3000 to the host machine's port 3000 10 | volumes: 11 | - .:/usr/src/app # Enable live code reloading by mounting the current directory to the container 12 | environment: 13 | - NODE_ENV=development # Set Node environment to development 14 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /src/redux/reducers/searchReducer.tsx: -------------------------------------------------------------------------------- 1 | import { SEARCH_PRODUCTS } from "../actions/searchActions"; 2 | 3 | interface SearchState { 4 | query: string; 5 | } 6 | 7 | const initialState: SearchState = { 8 | query: "", 9 | }; 10 | 11 | const searchReducer = (state = initialState, action: any) => { 12 | switch (action.type) { 13 | case SEARCH_PRODUCTS: 14 | return { 15 | ...state, 16 | query: action.payload.query, 17 | }; 18 | default: 19 | return state; 20 | } 21 | }; 22 | 23 | export default searchReducer -------------------------------------------------------------------------------- /src/components/chatbot/ChatBox.tsx: -------------------------------------------------------------------------------- 1 | 2 | const ChatBox = () => { 3 | // Sample messages for demonstration purposes 4 | const messages = [ 5 | { id: 1, text: 'Hello there!', sender: 'user' }, 6 | { id: 2, text: 'Hi! How can I help you today?', sender: 'admin' }, 7 | ]; 8 | 9 | return ( 10 |
11 | {messages.map((message) => ( 12 |
13 | {message.text} 14 |
15 | ))} 16 |
17 | ); 18 | }; 19 | 20 | export default ChatBox; 21 | -------------------------------------------------------------------------------- /.github/workflows/cd.yml: -------------------------------------------------------------------------------- 1 | name: CD 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - feature/Account 8 | - fix/netlify 9 | 10 | jobs: 11 | deploy: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v2 17 | 18 | - name: Install dependencies 19 | run: npm install 20 | 21 | - name: Build 22 | run: npm run build 23 | 24 | - name: Deploy to Netlify 25 | uses: nwtgck/actions-netlify@v2.0 26 | with: 27 | publish-dir: ./dist 28 | # env: 29 | # NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} 30 | -------------------------------------------------------------------------------- /src/redux/actions/cartActions.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | export enum CartAction { 4 | ADD_TO_CART = "ADD_TO_CART", 5 | REMOVE_FROM_CART = "REMOVE_FROM_CART", 6 | } 7 | 8 | interface AddToCartAction { 9 | type:CartAction.ADD_TO_CART, 10 | payload:number 11 | } 12 | interface RemoveToCartAction { 13 | type:CartAction.REMOVE_FROM_CART, 14 | payload:number 15 | } 16 | 17 | export type CartFunctionType = AddToCartAction | RemoveToCartAction 18 | 19 | export const addToCart = (itemId: number) => ({ 20 | type: CartAction.ADD_TO_CART, 21 | payload: itemId , 22 | }); 23 | 24 | export const removeToCart = (itemId: number) => ({ 25 | type: CartAction.REMOVE_FROM_CART, 26 | payload: itemId , 27 | }); 28 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - feature/Account 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [16.x] 16 | 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v2 20 | 21 | - name: Use Node.js ${{ matrix.node-version }} 22 | uses: actions/setup-node@v2 23 | with: 24 | node-version: ${{ matrix.node-version }} 25 | 26 | - name: Install dependencies 27 | run: npm install 28 | 29 | - name: Build 30 | run: npm run build 31 | 32 | # - name: Test 33 | # run: npm test 34 | -------------------------------------------------------------------------------- /src/components/AccountSidebar.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom" 2 | import { accountLinks } from "../assets/globalUtlities" 3 | import { useState } from "react" 4 | 5 | export const AccountSidebar = () => { 6 | const [showActiveRoute, setShowActiveRoute] = useState("") 7 | console.log(showActiveRoute) 8 | return ( 9 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | "esModuleInterop": true, 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /src/redux/reducers/DarkReducer.tsx: -------------------------------------------------------------------------------- 1 | import { DARK__MODE_TOGGLE } from "../actions/DarkModeAction" 2 | 3 | interface DarkModeProps { 4 | isEnabled: boolean 5 | } 6 | const initialState: DarkModeProps = { 7 | isEnabled: localStorage.getItem('darkModeEnabled') === 'true' 8 | } 9 | 10 | const DarkReducer = (state = initialState, action: { type: string }): DarkModeProps => { 11 | let newEnabledState = false; 12 | switch (action.type) { 13 | case DARK__MODE_TOGGLE: 14 | newEnabledState = !state.isEnabled; 15 | localStorage.setItem("darkModeEnabled", newEnabledState.toString()) 16 | return { 17 | ...state, isEnabled: newEnabledState 18 | } 19 | default: 20 | return state 21 | } 22 | } 23 | 24 | export default DarkReducer -------------------------------------------------------------------------------- /src/types/productTypes.ts: -------------------------------------------------------------------------------- 1 | interface FetchProducts { 2 | id: string; 3 | title: string; 4 | price: number; 5 | description: string; 6 | category: string; 7 | image: string; 8 | rating: RatingProps; 9 | } 10 | 11 | interface RatingProps { 12 | rate: number; 13 | count: number; 14 | } 15 | 16 | interface ProductProps { 17 | id: number; 18 | title: string | undefined; 19 | thumbImg: string; 20 | img: string | undefined; 21 | quantity?: number; 22 | price: number; 23 | offerAvailable: boolean; 24 | cart?: ProductProps[]; 25 | } 26 | 27 | interface GraphProducts { 28 | data: unknown; 29 | id: number; 30 | title: string; 31 | image: string; 32 | price: number; 33 | rating: { 34 | count: number; 35 | rate: number; 36 | }; 37 | } 38 | 39 | export type { FetchProducts, ProductProps, GraphProducts }; 40 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App.tsx"; 4 | import "./index.css"; 5 | import { BrowserRouter } from "react-router-dom"; 6 | import { Provider } from "react-redux"; 7 | import store from "./redux/store"; 8 | import { ApolloProvider } from "@apollo/client"; 9 | import { client } from "./apollo/client"; 10 | 11 | ReactDOM.createRoot(document.getElementById("root")!).render( 12 | 13 | 14 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | ); 28 | -------------------------------------------------------------------------------- /src/components/PaymentSuccesfull.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | const PaymentSuccessful: React.FC = () => { 5 | useEffect(() => { 6 | window.scrollTo(0, 0) 7 | }, []) 8 | return ( 9 |
10 |

Payment Successful

11 |

Your payment has been successfully processed.

12 |

Thank you for shopping with us!

13 | {/* Add any additional information or action buttons here */} 14 | 15 |
16 | 17 | ); 18 | }; 19 | 20 | export default PaymentSuccessful -------------------------------------------------------------------------------- /src/pages/ProductsGroup.tsx: -------------------------------------------------------------------------------- 1 | import { useSelector } from "react-redux" 2 | import { rowProductsData } from "../assets/globalUtlities" 3 | import { ProductCard, ProductFilterSiderbar, ProductGroupsTab } from "../paths" 4 | import { RootState } from "../redux/store" 5 | 6 | const ProductsGroup = () => { 7 | const darkMode = useSelector((state: RootState) => state?.dark) 8 | return ( 9 |
10 | 11 |
12 | 13 |
14 | {rowProductsData?.map((item, index) => )} 15 |
16 |
17 |
18 | ) 19 | } 20 | 21 | export default ProductsGroup 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/redux/reducers/dataReducer.tsx: -------------------------------------------------------------------------------- 1 | import { DataFunctionsTypes, FETCH_DATA_FAILURE, FETCH_DATA_REQUEST, FETCH_DATA_SUCCESS, } from "../actions/dataAction"; 2 | 3 | const initialState = { 4 | loading: false, 5 | result: [], 6 | error: '', 7 | }; 8 | 9 | const dataReducer = (state = initialState, action: DataFunctionsTypes) => { 10 | console.log(state) 11 | switch (action.type) { 12 | case FETCH_DATA_REQUEST: 13 | return { 14 | ...state, 15 | loading: true, 16 | }; 17 | case FETCH_DATA_SUCCESS: 18 | return { 19 | ...state, 20 | loading: false, 21 | result: action.payload, 22 | error: '', 23 | }; 24 | case FETCH_DATA_FAILURE: 25 | return { 26 | ...state, 27 | loading: false, 28 | error: action.payload, 29 | }; 30 | default: 31 | return state; 32 | } 33 | }; 34 | 35 | export default dataReducer; 36 | -------------------------------------------------------------------------------- /src/components/HomeSlider.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { 3 | bannerImg1, 4 | bannerImg2, 5 | } from "../assets/globalUtlities"; 6 | 7 | const HomeSlider = () => { 8 | const bannerImgArray = [ 9 | bannerImg1, 10 | bannerImg2, 11 | ]; 12 | const [currentImg, setCurrentImg] = useState(0); 13 | 14 | useEffect(() => { 15 | // Modulo Operation algorithms used here 16 | // Cycling Through Images Using Modulo 17 | const timer = setInterval(() => { 18 | // (1+1) % 5 = 19 | const nextImg = (currentImg + 1) % bannerImgArray.length; 20 | setCurrentImg(nextImg); 21 | }, 2000); 22 | return () => clearInterval(timer); 23 | }, [bannerImgArray.length, currentImg]); 24 | 25 | return ( 26 |
27 | banner_img 28 |
29 | ); 30 | }; 31 | 32 | export { HomeSlider }; 33 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the Node.js image as the base image 2 | FROM node:alpine AS builder 3 | 4 | # Set the working directory inside the container 5 | WORKDIR /usr/src/app 6 | 7 | # Copy package.json and package-lock.json to the working directory 8 | COPY package.json package-lock.json ./ 9 | 10 | # Install dependencies 11 | RUN npm install 12 | 13 | # Copy all project files to the working directory 14 | COPY . . 15 | 16 | # Install Vite globally or run commands directly using npx 17 | RUN npm install -g vite 18 | 19 | # Build your application (replace with your build command) 20 | RUN npm run build 21 | 22 | # Use a minimal production image 23 | FROM node:alpine 24 | 25 | WORKDIR /usr/src/app 26 | 27 | COPY --from=builder /usr/src/app/dist ./dist 28 | COPY package.json package-lock.json ./ 29 | RUN npm install --only=production 30 | 31 | # Expose the port your app is running on (if needed) 32 | EXPOSE 5173 33 | 34 | # Start the app in development mode 35 | CMD ["npm", "run", "dev"] 36 | -------------------------------------------------------------------------------- /src/redux/reducers/authReducer.tsx: -------------------------------------------------------------------------------- 1 | import { createReducer, PayloadAction } from "@reduxjs/toolkit"; 2 | import { ConfirmationResult } from "firebase/auth"; 3 | import { 4 | SET_CONFIRMATION_RESULT, 5 | LOGIN_SUCCESS, 6 | LOGIN_FAILURE, 7 | } from "../actions/authActions"; 8 | 9 | export interface AuthState { 10 | confirmationResult: ConfirmationResult | null; 11 | isLoggedIn: boolean; 12 | } 13 | 14 | const initialState: AuthState = { 15 | confirmationResult: null, 16 | isLoggedIn: false, 17 | }; 18 | 19 | const authReducer = createReducer(initialState, { 20 | [SET_CONFIRMATION_RESULT]: ( 21 | state: AuthState, 22 | action: PayloadAction 23 | ) => { 24 | state.confirmationResult = action.payload; 25 | }, 26 | [LOGIN_SUCCESS]: (state: AuthState) => { 27 | state.isLoggedIn = true; 28 | }, 29 | [LOGIN_FAILURE]: (state: AuthState) => { 30 | state.isLoggedIn = false; 31 | }, 32 | }); 33 | 34 | export default authReducer; 35 | -------------------------------------------------------------------------------- /src/components/ProductCard.tsx: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import { ProductProps } from "../types/productTypes"; 3 | 4 | const ProductCard = ({ 5 | product, 6 | index, 7 | }: { 8 | product: ProductProps | undefined; 9 | index: number; 10 | refreshSite: boolean 11 | }) => { 12 | return ( 13 |
14 | 15 | row-img 16 |
17 |
18 |

{product?.title}

19 |
20 |

{product?.title}

21 |
22 | 23 |
24 | ); 25 | }; 26 | 27 | export { ProductCard }; 28 | -------------------------------------------------------------------------------- /src/components/Rewards.tsx: -------------------------------------------------------------------------------- 1 | // Rewards.tsx 2 | import React from 'react'; 3 | 4 | const Rewards: React.FC = () => { 5 | return ( 6 |
7 |

Rewards & Offers

8 | 9 | {/* Reward Cards */} 10 |
11 | {/* Sample Reward Card */} 12 |
13 |

Reward Title

14 |

Description of the reward goes here.

15 |
16 | 50% Off 17 | 20 |
21 |
22 | 23 | {/* Add more Reward Cards here */} 24 | {/* ... */} 25 |
26 |
27 | ); 28 | }; 29 | 30 | export default Rewards -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ShopEase | The unltimate shopping website 8 | 9 | 13 | 17 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/apollo/fetchData.ts: -------------------------------------------------------------------------------- 1 | import { Dispatch } from "redux"; 2 | import { gql } from "@apollo/client"; 3 | import { AnyAction } from "@reduxjs/toolkit"; 4 | import { client } from "./client"; 5 | import { 6 | fetchDataFailure, 7 | fetchDataRequest, 8 | fetchDataSuccess, 9 | } from "../redux/actions/dataAction"; 10 | 11 | export const fetchData = () => async (dispatch: Dispatch) => { 12 | try { 13 | dispatch(fetchDataRequest()); 14 | const GET_PRODUCTS = gql` 15 | query { 16 | products { 17 | id 18 | title 19 | price 20 | description 21 | category 22 | image 23 | rating { 24 | rate 25 | count 26 | } 27 | } 28 | } 29 | `; 30 | const { data } = await client.query({ query: GET_PRODUCTS }); 31 | dispatch(fetchDataSuccess(data?.products)); 32 | } catch (error) { 33 | if (error instanceof Error) { 34 | dispatch(fetchDataFailure(error.message)); 35 | } else { 36 | dispatch(fetchDataFailure("An unknown error occurred")); 37 | } 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/redux/actions/dataAction.tsx: -------------------------------------------------------------------------------- 1 | import { FetchProducts } from "../../types/productTypes"; 2 | // Action Types 3 | export const FETCH_DATA_REQUEST = "FETCH_DATA_REQUEST"; 4 | export const FETCH_DATA_SUCCESS = "FETCH_DATA_SUCCESS"; 5 | export const FETCH_DATA_FAILURE = "FETCH_DATA_FAILURE"; 6 | 7 | interface fetchDataRequestAction { 8 | type: typeof FETCH_DATA_REQUEST; 9 | } 10 | interface fetchDataSuccessAction { 11 | type: typeof FETCH_DATA_SUCCESS; 12 | payload: FetchProducts[]; 13 | } 14 | interface fatchDataFailureAction { 15 | type: typeof FETCH_DATA_FAILURE; 16 | payload: string; 17 | } 18 | export type DataFunctionsTypes = 19 | | fetchDataRequestAction 20 | | fetchDataSuccessAction 21 | | fatchDataFailureAction; 22 | 23 | export const fetchDataRequest = (): fetchDataRequestAction => ({ 24 | type: FETCH_DATA_REQUEST, 25 | }); 26 | 27 | export const fetchDataSuccess = (data: FetchProducts[]): fetchDataSuccessAction => ({ 28 | type: FETCH_DATA_SUCCESS, 29 | payload: data, 30 | }); 31 | 32 | export const fetchDataFailure = (error: string): fatchDataFailureAction => ({ 33 | type: FETCH_DATA_FAILURE, 34 | payload: error, 35 | }); -------------------------------------------------------------------------------- /src/types/layoutTypes.ts: -------------------------------------------------------------------------------- 1 | import { ProductProps } from "./productTypes"; 2 | 3 | type SubItem = { 4 | name: string; 5 | id: string; 6 | }; 7 | 8 | export type SubCategory = { 9 | category: string; 10 | title: string; 11 | subItems: SubItem[]; 12 | }; 13 | 14 | type HeaderCategoryProps = { 15 | title: string; 16 | img: string; 17 | subCategories: SubCategory[]; 18 | }; 19 | 20 | type headerCategoriesProps = HeaderCategoryProps[]; 21 | 22 | type RowProductsProps = { 23 | id: number; 24 | title: string; 25 | img: string; 26 | price: number; 27 | quantity: number; 28 | offerAvailable: boolean; 29 | }[]; 30 | type ProductDetailsProps = { 31 | id: number; 32 | title: string; 33 | img: string; 34 | price: number; 35 | quantity: number; 36 | offerAvailable: boolean; 37 | cart?:ProductProps[] 38 | }; 39 | interface FooterDataItem { 40 | heading: string; 41 | content: string; 42 | } 43 | 44 | interface FooterDataProps { 45 | [section: string]: FooterDataItem; 46 | } 47 | 48 | export type { 49 | RowProductsProps, 50 | ProductDetailsProps, 51 | FooterDataProps, 52 | headerCategoriesProps, 53 | HeaderCategoryProps, 54 | }; 55 | -------------------------------------------------------------------------------- /src/redux/reducers/cartReducer.tsx: -------------------------------------------------------------------------------- 1 | import { rowProductsData } from "../../assets/globalUtlities"; 2 | import { ProductProps } from "../../types/productTypes"; 3 | import { CartFunctionType, CartAction } from "../actions/cartActions"; 4 | 5 | export interface CartState { 6 | cart: ProductProps[]; 7 | } 8 | 9 | const initialState: CartState = { 10 | cart: [], 11 | }; 12 | 13 | const cartReducer = (state = initialState, action: CartFunctionType) => { 14 | switch (action.type) { 15 | case CartAction.ADD_TO_CART: 16 | // eslint-disable-next-line no-case-declarations 17 | const isAlreadyAdded = state.cart.some( 18 | (product) => product.id === action.payload 19 | ); 20 | 21 | // eslint-disable-next-line no-case-declarations 22 | let addedItem: ProductProps[] = []; 23 | if (!isAlreadyAdded) { 24 | addedItem = rowProductsData?.filter( 25 | (item) => item.id === action.payload 26 | ); 27 | } 28 | if (addedItem) { 29 | return { ...state, cart: [...state.cart, ...addedItem] }; 30 | } 31 | return state; 32 | 33 | case CartAction.REMOVE_FROM_CART: 34 | return { 35 | ...state, 36 | cart: state?.cart?.filter((item) => item.id != action.payload), 37 | }; 38 | default: 39 | return state; 40 | } 41 | }; 42 | 43 | export default cartReducer; 44 | -------------------------------------------------------------------------------- /src/pages/Account.tsx: -------------------------------------------------------------------------------- 1 | import { Route, Routes } from "react-router-dom" 2 | import { AccountDetails, Login, Orders, Profile, Rewards, Wishlist } from "../optimazation/AppOptimazation" 3 | import { AccountSidebar } from "../paths" 4 | import { Suspense } from "react" 5 | 6 | const Account = () => { 7 | return ( 8 |
9 | {/* first section */} 10 |
11 | 12 |
13 | {/* second section */} 14 | Loading...
}> 15 |
16 | 17 | } /> 18 | } /> 19 | } /> 20 | } /> 21 | } /> 22 | } /> 23 | ; 24 |
25 | 26 | 27 | ) 28 | } 29 | 30 | export default Account 31 | 32 | -------------------------------------------------------------------------------- /src/components/Offer.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | import { offerImgs } from '../assets/globalUtlities'; 3 | 4 | export const Offer = () => { 5 | const [numImagesToShow, setNumImagesToShow] = useState(4); 6 | 7 | useEffect(() => { 8 | const handleResize = () => { 9 | if (window.innerWidth < 768) { 10 | setNumImagesToShow(2); // Show 2 images on mobile devices 11 | } else if (window.innerWidth < 1280) { 12 | setNumImagesToShow(3); // Show 4 images on medium devices 13 | } else { 14 | setNumImagesToShow(4); // Show all images on extra-large devices 15 | } 16 | }; 17 | 18 | // Listen for window resize events 19 | window.addEventListener('resize', handleResize); 20 | 21 | // Initial call to set the initial number of images 22 | handleResize(); 23 | 24 | // Cleanup the event listener on component unmount 25 | return () => { 26 | window.removeEventListener('resize', handleResize); 27 | }; 28 | }, []); 29 | 30 | return ( 31 |
32 | {offerImgs?.slice(0, numImagesToShow).map((img, index) => ( 33 |
34 | {img.img} 35 |
36 | ))} 37 |
38 | ); 39 | }; 40 | 41 | 42 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/redux/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore, Middleware } from "@reduxjs/toolkit"; 2 | import { combineReducers } from "redux"; 3 | import cartReducer from "./reducers/cartReducer"; 4 | import searchReducer from "./reducers/searchReducer"; 5 | import dataReducer from "./reducers/dataReducer"; 6 | import DarkReducer from "./reducers/DarkReducer"; 7 | import axiosFetchReducer from "./reducers/axiosFetchData"; 8 | // import authReducer, { AuthState } from "./reducers/authReducer"; 9 | 10 | export type CartState = ReturnType; 11 | export type DataState = ReturnType; 12 | export type DarkState = ReturnType; 13 | export type AxiosFetchState = ReturnType; 14 | 15 | export type RootState = { 16 | cart: CartState; 17 | fetchData: DataState; 18 | dark: DarkState; 19 | axiosFetchdata: AxiosFetchState; 20 | // auth: AuthState; 21 | }; 22 | 23 | const rootReducer = combineReducers({ 24 | cart: cartReducer, 25 | fetchData: dataReducer, 26 | axiosfetchData: axiosFetchReducer, 27 | search: searchReducer, 28 | dark: DarkReducer, 29 | // auth: authReducer, 30 | }); 31 | 32 | const additionalMiddleware: Middleware[] = []; 33 | 34 | const store = configureStore({ 35 | reducer: rootReducer, 36 | middleware: (getDefaultMiddleware) => 37 | getDefaultMiddleware().concat(additionalMiddleware), 38 | devTools: process.env.NODE_ENV !== "production", 39 | }); 40 | console.log("store",store) 41 | export default store; 42 | -------------------------------------------------------------------------------- /src/optimazation/AppOptimazation.ts: -------------------------------------------------------------------------------- 1 | import { lazy } from "react"; 2 | 3 | const Home = lazy(() => import("../pages/Home")); 4 | const Account = lazy(() => import("../pages/Account")); 5 | const Cart = lazy(() => import("../pages/Cart")); 6 | const ProductsGroup = lazy(() => import("../pages/ProductsGroup")); 7 | const NestedHoverNavlink = lazy( 8 | () => import("../components/NestedHoverNavlink") 9 | ); 10 | const ProductGallery = lazy(() => import("../pages/ProductGallery")); 11 | const ProductDetails = lazy(() => import("../components/ProductDetails")); 12 | const Checkout = lazy(() => import("../components/Checkout")); 13 | const PaymentSuccessful = lazy(() => import("../components/PaymentSuccesfull")); 14 | const ChatBot = lazy(() => import("../components/chatbot/ChatBot")); 15 | 16 | export { 17 | Home, 18 | Account, 19 | Cart, 20 | ProductsGroup, 21 | NestedHoverNavlink, 22 | ProductGallery, 23 | ProductDetails, 24 | Checkout, 25 | PaymentSuccessful, 26 | ChatBot, 27 | }; 28 | 29 | // Account section optimization 30 | const AccountDetails = lazy(() => import("../components/AccountDetails")); 31 | const Login = lazy(() => import("../pages/Login")); 32 | 33 | const Profile = lazy(() => import("../components/Profile")); 34 | const Wishlist = lazy(() => import("../components/WishList")); 35 | const Orders = lazy(() => import("../components/Orders")); 36 | const Rewards = lazy(() => import("../components/Rewards")); 37 | 38 | export { AccountDetails, Login, Profile, Wishlist, Orders, Rewards }; 39 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | 6 | body{ 7 | background-color: #f1f2f4; 8 | font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 9 | } 10 | /* bg */ 11 | .primary-bg { 12 | background:#2a55e5; 13 | } 14 | .primary-bg-h:hover { 15 | background:#6778b0; 16 | } 17 | .footer-bg{ 18 | background-color: #172337; 19 | } 20 | /* bg end */ 21 | /* fonts */ 22 | .primary-font { 23 | font-size: 14px; 24 | } 25 | .category-font { 26 | font-size: 20px; 27 | } 28 | .text-color{ 29 | color: #212121; 30 | } 31 | .mob-category-font { 32 | font-size: 16px; 33 | } 34 | .font-fam { 35 | font-family: Roboto, Helvetica, Arial, sans-serif; 36 | } 37 | 38 | .font-fam2{ 39 | font-family: inter_semi_bold,fallback-inter_semi_bold,Arial,sans-serif; 40 | } 41 | /* end fonts */ 42 | 43 | /* imgs */ 44 | 45 | .header-category-img { 46 | width: 92px; 47 | } 48 | 49 | /* padding */ 50 | .header-category-img-p{ 51 | padding:10px; 52 | } 53 | .mob-header-category-img-p{ 54 | padding:5px; 55 | } 56 | .category-name-p { 57 | padding: 16px 12px; 58 | } 59 | .mob-category-name-p { 60 | padding: 12px 16px ; 61 | } 62 | .mob-category-name-p { 63 | padding: 12px 16px ; 64 | } 65 | .sponsored-category-name-p { 66 | padding: 12px 16px ; 67 | } 68 | .mob-img-card-p { 69 | padding: 16px 16px 12px; 70 | } 71 | .img-card-p { 72 | padding: 6px; 73 | } 74 | /* end - padding */ 75 | 76 | 77 | /* header */ 78 | 79 | /* custom icon */ 80 | .custom_icon_size { 81 | font-size: 40px; 82 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flikart", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview", 11 | "test": "jest" 12 | }, 13 | "jest": { 14 | "preset": "ts-jest" 15 | }, 16 | "dependencies": { 17 | "@apollo/client": "^3.8.7", 18 | "@reduxjs/toolkit": "^1.9.7", 19 | "@tailwindcss/typography": "^0.5.10", 20 | "axios": "^1.6.2", 21 | "firebase": "^10.6.0", 22 | "font-awesome": "^4.7.0", 23 | "graphql": "^16.8.1", 24 | "jest": "^29.7.0", 25 | "react": "^18.2.0", 26 | "react-dom": "^18.2.0", 27 | "react-hook-form": "^7.48.2", 28 | "react-icons": "^4.11.0", 29 | "react-redux": "^8.1.3", 30 | "react-router-dom": "^6.16.0", 31 | "redux-thunk": "^2.4.2" 32 | }, 33 | "devDependencies": { 34 | "@testing-library/react": "^14.2.1", 35 | "@types/jest": "^29.5.12", 36 | "@types/react": "^18.2.15", 37 | "@types/react-dom": "^18.2.7", 38 | "@types/testing-library__react": "^10.2.0", 39 | "@typescript-eslint/eslint-plugin": "^6.0.0", 40 | "@typescript-eslint/parser": "^6.0.0", 41 | "@vitejs/plugin-react": "^4.0.3", 42 | "autoprefixer": "^10.4.17", 43 | "eslint": "^8.45.0", 44 | "eslint-plugin-react-hooks": "^4.6.0", 45 | "eslint-plugin-react-refresh": "^0.4.3", 46 | "postcss": "^8.4.31", 47 | "tailwindcss": "^3.3.5", 48 | "ts-jest": "^29.1.2", 49 | "typescript": "^5.3.3", 50 | "vite": "^4.4.5" 51 | } 52 | } -------------------------------------------------------------------------------- /src/redux/reducers/axiosFetchData.tsx: -------------------------------------------------------------------------------- 1 | import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; 2 | import axios from "axios"; 3 | 4 | 5 | interface Product { 6 | id: number, 7 | title: string, 8 | description: string, 9 | price: number 10 | } 11 | 12 | interface CategoryMap { 13 | [key: string]: Product[] 14 | } 15 | 16 | interface AppState { 17 | categoryMap: CategoryMap 18 | } 19 | 20 | const initialState: AppState = { 21 | categoryMap: {} 22 | } 23 | 24 | export const fetchProductData = createAsyncThunk("product/fetchData", async () => { 25 | const [productsResponse, categoriesResponse] = await Promise.all( 26 | [axios.get<{ products: Product[] }>('https://dummyjson.com/products'), 27 | axios.get('https://dummyjson.com/products') 28 | ]) 29 | const _products = productsResponse.data.products 30 | console.log(_products) 31 | 32 | const categories = categoriesResponse.data 33 | 34 | const newCategoryMap: CategoryMap = {}; 35 | 36 | for (const category of categories) { 37 | const categoryRespose = await axios.get<{ products: Product[] }>( 38 | `https://dummyjson.com/products/category/${category}` 39 | ) 40 | newCategoryMap[category] = categoryRespose.data.products 41 | } 42 | return newCategoryMap 43 | }) 44 | 45 | 46 | const dataSlice = createSlice({ 47 | name: 'data', 48 | initialState, 49 | reducers: {}, 50 | extraReducers: (builder) => { 51 | builder.addCase(fetchProductData.fulfilled, (state, action) => { 52 | state.categoryMap = action.payload; 53 | }); 54 | }, 55 | }); 56 | 57 | export default dataSlice.reducer; -------------------------------------------------------------------------------- /src/redux/actions/authActions.tsx: -------------------------------------------------------------------------------- 1 | import { Action, } from "@reduxjs/toolkit"; 2 | import { ThunkAction } from "redux-thunk"; 3 | import { RootState } from "../store"; // Update the path as per your file structure 4 | import { 5 | ConfirmationResult, 6 | getAuth, 7 | signInWithPhoneNumber, 8 | } from "firebase/auth"; 9 | 10 | // Action Types 11 | export const SET_CONFIRMATION_RESULT = "SET_CONFIRMATION_RESULT"; 12 | export const LOGIN_SUCCESS = "LOGIN_SUCCESS"; 13 | export const LOGIN_FAILURE = "LOGIN_FAILURE"; 14 | 15 | interface setConfirmationResultAction { 16 | type: typeof SET_CONFIRMATION_RESULT; 17 | payload: ConfirmationResult | null; 18 | } 19 | 20 | // Action Creators 21 | export const setConfirmationResult = ( 22 | confirmationResult: ConfirmationResult | null 23 | ): setConfirmationResultAction => ({ 24 | type: SET_CONFIRMATION_RESULT, 25 | payload: confirmationResult, 26 | }); 27 | 28 | export const loginSuccess = (): Action => ({ 29 | type: LOGIN_SUCCESS, 30 | }); 31 | 32 | export const loginFailure = (): Action => ({ 33 | type: LOGIN_FAILURE, 34 | }); 35 | 36 | // Async action to sign in with phone number 37 | export const signInWithPhoneNumberAction = ( 38 | phoneNumber: string, 39 | appVerifier: any 40 | ): ThunkAction> => { 41 | return async (dispatch) => { 42 | const auth = getAuth(); 43 | try { 44 | const confirmationResult = await signInWithPhoneNumber( 45 | auth, 46 | phoneNumber, 47 | appVerifier 48 | ); 49 | dispatch(setConfirmationResult(confirmationResult)); 50 | } catch (error) { 51 | dispatch(loginFailure()); 52 | // Handle error (SMS not sent) 53 | } 54 | }; 55 | }; 56 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | darkMode:"class", 4 | content: [ 5 | "./index.html", 6 | "./src/**/*.{js,ts,jsx,tsx}", 7 | ], 8 | theme: { 9 | extend: { 10 | fontFamily:{ 11 | robo:['Roboto','sans-serif'] 12 | }, 13 | backgroundColor:{ 14 | primaryColor: "#e2dfd2", 15 | secondaryColor:"#c7b6a3", 16 | lightGray:"#D1D5DB", 17 | darkModeBg:"#1f2937" 18 | }, 19 | colors:{ 20 | darkModeText:"#FFFFFF", 21 | dark:"#1A202C", 22 | lightText:"#FFFFFF", 23 | lightGray:"#D1D5DB", 24 | primary:"#2874f0" 25 | }, 26 | backgroundImage: { 27 | 'gradient-primary': 'linear-gradient(to right, var(--tw-gradient-stops))', 28 | 'gradient-secondary': 'linear-gradient(to bottom, var(--tw-gradient-stops))', 29 | }, 30 | gradientColorStops: theme => ({ 31 | 'primary-start': theme('colors.primaryColor'), 32 | 'primary-end': theme('colors.secondaryColor'), 33 | 'dark-start': theme('colors.darkModeBg'), 34 | 'dark-end': theme('colors.dark'), 35 | }), 36 | 37 | }, 38 | }, 39 | plugins: [ 40 | // eslint-disable-next-line no-undef 41 | require('tailwindcss'), 42 | // eslint-disable-next-line no-undef 43 | require('autoprefixer'), 44 | function ({ addUtilities }) { 45 | const newUtilities = { 46 | '.flexCenter': { 47 | display: 'flex', 48 | alignItems: 'center', 49 | justifyContent: 'center', 50 | }, 51 | 52 | }; 53 | addUtilities(newUtilities, ['responsive', 'hover']); 54 | }, 55 | 56 | ], 57 | } 58 | -------------------------------------------------------------------------------- /src/components/Footer.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { footerData, footerLinks } from "../assets/footerUtility"; 3 | import { FooterDataProps } from "../types/layoutTypes"; 4 | import { Link } from "react-router-dom"; 5 | 6 | export const Footer: React.FC = () => { 7 | return ( 8 |
9 |
10 | {Object.keys(footerData).map((key, index) => { 11 | const section: { 12 | heading: string; 13 | content: string; 14 | } = footerData[key]; 15 | return ( 16 |
17 |

{key}

18 |
{section.heading}
19 |
{section.content} 23 |
24 |
25 |
26 | 27 | ); 28 | })} 29 |
30 |
31 | {footerLinks?.map((item, index) => ( 32 |
    33 | {" "} 34 |
  • {item.title}
  • {" "} 35 |
    36 | {item?.links.map((subLink, index) => ( 37 | 38 | {" "} 39 |
  • 40 | {subLink.text} 41 |
  • {" "} 42 | 43 | ))} 44 |
    45 |
46 | ))} 47 |
48 |
49 | ); 50 | }; 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/components/Orders.tsx: -------------------------------------------------------------------------------- 1 | // Orders.tsx 2 | import React from 'react'; 3 | 4 | const Orders: React.FC = () => { 5 | // Sample orders data 6 | const orders = [ 7 | { 8 | id: '1', 9 | date: '2023-11-29', 10 | items: [ 11 | { name: 'Product 1', price: 0 }, 12 | { name: 'Product 2', price: 0 }, 13 | // Additional item details 14 | ], 15 | total: 0, 16 | status: 'Delivered', 17 | }, 18 | // More orders 19 | ]; 20 | 21 | return ( 22 |
23 | {/* */} 24 |
25 | empty image 26 |

You have no orders

27 | 28 |
29 | {/* */} 30 |

Your Orders

31 | {orders.map((order) => ( 32 |
33 |
34 |

Order ID: {order.id}

35 |

Date: {order.date}

36 |
37 |
38 | {order.items.map((item, index) => ( 39 |
40 |

{item.name}

41 |

${item.price}

42 |
43 | ))} 44 |
45 |
46 |

Total:

47 |

${order.total}

48 |
49 |

Status: {order.status}

50 |
51 | ))} 52 |
53 | ); 54 | }; 55 | 56 | 57 | export default Orders -------------------------------------------------------------------------------- /src/paths.ts: -------------------------------------------------------------------------------- 1 | import { CustomProductsRows } from "./components/CustomProductsRows"; 2 | import { Header } from "./components/Header"; 3 | import { HeaderCategory } from "./components/HeaderCategory"; 4 | import { HomeBanner } from "./components/HomeBanner"; 5 | import { HomeSlider } from "./components/HomeSlider"; 6 | import { Offer } from "./components/Offer"; 7 | import ProductDatails from "./components/ProductDetails"; 8 | import { SearchBar } from "./components/SearchBar"; 9 | import { ProductCard } from "./components/ProductCard"; 10 | import { Footer } from "./components/Footer"; 11 | import { PopupCard } from "./components/PopupCard"; 12 | import Rewards from "./components/Rewards"; 13 | import Profile from "./components/Profile"; 14 | import Wishlist from "./components/WishList"; 15 | import Orders from "./components/Orders"; 16 | import Login from "./pages/Login"; 17 | import { ProductGroupsTab } from "./components/ProductGroupsTab"; 18 | import { ProductFilterSiderbar } from "./components/ProductFilterSiderbar"; 19 | import { Ad } from "./components/Ad"; 20 | import { AccountSidebar } from "./components/AccountSidebar"; 21 | import AccountDetails from "./components/AccountDetails"; 22 | import Checkout from "./components/Checkout"; 23 | import PaymentSuccessful from "./components/PaymentSuccesfull"; 24 | import ChatBot from "./components/chatbot/ChatBot"; 25 | 26 | export { 27 | CustomProductsRows, 28 | Ad, 29 | Header, 30 | HeaderCategory, 31 | HomeBanner, 32 | HomeSlider, 33 | Rewards, 34 | Profile, 35 | Wishlist, 36 | Orders, 37 | Login, 38 | Offer, 39 | ProductDatails, 40 | SearchBar, 41 | PopupCard, 42 | ProductCard, 43 | ProductGroupsTab, 44 | ProductFilterSiderbar, 45 | Checkout, 46 | AccountSidebar, 47 | PaymentSuccessful, 48 | ChatBot, 49 | AccountDetails, 50 | Footer, 51 | }; 52 | 53 | // pages 54 | import Home from "./pages/Home"; 55 | import Cart from "./pages/Cart"; 56 | import ProductsGroup from "./pages/ProductsGroup"; 57 | import Error from "./pages/Error"; 58 | import ProductGallery from "./pages/ProductGallery"; 59 | import Account from "./pages/Account"; 60 | 61 | export { Home, Cart, Error, ProductGallery, ProductsGroup, Account }; 62 | -------------------------------------------------------------------------------- /src/pages/Cart.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useDispatch, useSelector } from "react-redux"; 3 | import { RootState } from "../redux/store"; 4 | import { RowProductsProps } from "../types/layoutTypes"; 5 | import { removeToCart } from "../redux/actions/cartActions"; 6 | 7 | type CartProps = { 8 | items: RowProductsProps; 9 | }; 10 | 11 | const Cart: React.FC = () => { 12 | const cart = useSelector((state: RootState) => state.cart); 13 | const dispatch = useDispatch(); 14 | const totalAmount = cart.cart.reduce( 15 | (accumulator, currentProduct) => accumulator + currentProduct.price, 16 | 0 17 | ); 18 | 19 | return ( 20 |
21 |

My Cart

22 |
23 | {cart?.cart?.length === 0 ? ( 24 |
25 | empty 26 |
27 | ) : ( 28 | cart?.cart?.map((product) => ( 29 |
30 | 36 | {product.title} 41 |
42 |

{product.title}

43 |

{product.price}

44 |
45 | {/* The closing div tag is missing */} 46 |
47 | )) 48 | )} 49 |
50 | {cart?.cart.length > 0 && ( 51 |
52 |
Total:- {totalAmount}
53 | 56 |
57 | )} 58 |
59 | ); 60 | }; 61 | 62 | export default Cart; 63 | -------------------------------------------------------------------------------- /src/components/WishList.tsx: -------------------------------------------------------------------------------- 1 | // WishList.tsx 2 | import React, { useState } from 'react'; 3 | 4 | interface WishlistItem { 5 | id: number; 6 | name: string; 7 | price: number; 8 | image: string; 9 | } 10 | 11 | const Wishlist: React.FC = () => { 12 | const [wishlistItems, setWishlistItems] = useState([ 13 | { 14 | id: 1, 15 | name: 'Product One', 16 | price: 20, 17 | image: 'https://th.bing.com/th/id/OIP.6sPhq9sCxNc4cCq-XW70mwHaE8?rs=1&pid=ImgDetMain', 18 | }, 19 | { 20 | id: 2, 21 | name: 'Product Two', 22 | price: 30, 23 | image: 'https://i1.wp.com/clippingpathsource.com/wp-content/uploads/2018/07/Product-photography-on-Wooden-Background.png?resize=960%2C581&ssl=1', 24 | }, 25 | // Add more items as needed 26 | ]); 27 | 28 | const removeFromWishlist = (itemId: number) => { 29 | const updatedWishlist = wishlistItems.filter(item => item.id !== itemId); 30 | setWishlistItems(updatedWishlist); 31 | }; 32 | 33 | return ( 34 |
35 |

My Wishlist ({wishlistItems.length})

36 | {wishlistItems.length === 0 ? ( 37 |

Your wishlist is empty.

38 | ) : ( 39 |
40 | {wishlistItems.map(item => ( 41 |
42 | {item.name} 43 |

{item.name}

44 |

${item.price}

45 | 51 |
52 | ))} 53 |
54 | )} 55 |
56 | ); 57 | }; 58 | export default Wishlist -------------------------------------------------------------------------------- /src/components/PopupCard.tsx: -------------------------------------------------------------------------------- 1 | // PopupCard.tsx 2 | import React, { useState, SetStateAction } from "react"; 3 | 4 | interface PopupCardProps { 5 | // onClose: () => void; 6 | setShowPopUp: React.Dispatch>; 7 | } 8 | 9 | export const PopupCard: React.FC = ({ setShowPopUp }) => { 10 | const [like, setLike] = useState(false); 11 | const [dislike, setDislike] = useState(false); 12 | const [isClose, setIsClose] = useState(false); 13 | 14 | const handleLike = () => { 15 | setLike(true); 16 | setDislike(false); 17 | setIsClose(true); 18 | }; 19 | 20 | const handleDislike = () => { 21 | setLike(false); 22 | setDislike(true); 23 | setIsClose(true); 24 | }; 25 | 26 | const onClose = () => { 27 | setIsClose(true); 28 | localStorage.setItem("isPopupClosed", "true"); 29 | setShowPopUp(false); 30 | }; 31 | 32 | return ( 33 |
38 | 44 |
45 |

46 | Like the new Design? 47 |

48 |
49 | 58 | 67 |
68 |
69 |
70 | ); 71 | }; 72 | -------------------------------------------------------------------------------- /src/components/Profile.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FaUser, FaEnvelope, FaPhone, FaGenderless } from 'react-icons/fa'; 3 | 4 | const Profile: React.FC = () => { 5 | return ( 6 |
7 | {/* Personal Information Section */} 8 |
9 |

Personal Information

10 |
11 |
12 | 13 | 14 |

John Doe

15 |
16 |
17 | 18 | 19 |

johndoe@example.com

20 |
21 |
22 | 23 | 24 |

+1234567890

25 |
26 |
27 | 28 | 29 |

Male

30 |
31 |
32 |
33 | 34 | {/* Account Settings Section */} 35 |
36 |

Account Settings

37 |
38 | {/* Add your content for account settings here */} 39 |

Manage your addresses, edit profile information, and more.

40 |
41 |
42 | 43 | {/* My Stuff Section */} 44 |
45 |

My Stuff

46 |
47 | {/* Add your content for my stuff here */} 48 |

Access your orders, reviews, wishlist, and saved UPI.

49 |
50 |
51 |
52 | ); 53 | }; 54 | export default Profile -------------------------------------------------------------------------------- /src/components/AccountDetails.tsx: -------------------------------------------------------------------------------- 1 | const AccountDetails: React.FC = () => { 2 | return ( 3 |
4 |

Personal Information

5 |
6 | 7 | 8 |
9 |
10 | 11 | 12 |
13 |
14 | 15 |
16 | 20 | 24 |
25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | 33 |
34 |
35 | 36 |
37 |
38 |

FAQs

39 | {/* Insert FAQ content here */} 40 |
41 |
42 | ); 43 | }; 44 | 45 | export default AccountDetails -------------------------------------------------------------------------------- /src/components/chatbot/ChatBot.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { BsChatQuoteFill } from 'react-icons/bs'; 3 | import { FaTimes } from 'react-icons/fa'; 4 | import ChatBox from './ChatBox'; 5 | 6 | const ChatBot = () => { 7 | const [toggleChat, setToggleChat] = useState(false); 8 | 9 | const toggleChatWindow = () => { 10 | setToggleChat(!toggleChat); 11 | }; 12 | 13 | return ( 14 |
15 | {/* Chat window */} 16 | {toggleChat && ( 17 |
18 | {/* Chat header */} 19 |
20 |

Chat with Us

21 | 24 |
25 | {/* Chat messages */} 26 |
27 | {/* ChatBox component to display messages */} 28 | 29 |
30 | {/* Chat input */} 31 |
32 | {/* Add input field and send button */} 33 | 38 | 39 |
40 |
41 | )} 42 | 43 | {/* Chat button */} 44 |
45 | 53 |
54 |
55 | ); 56 | }; 57 | 58 | export default ChatBot -------------------------------------------------------------------------------- /src/pages/Home.tsx: -------------------------------------------------------------------------------- 1 | import { FC, } from "react"; 2 | import { HeaderCategoryProps } from "../types/layoutTypes"; 3 | import { 4 | Ad, 5 | CustomProductsRows, 6 | HeaderCategory, 7 | HomeSlider, 8 | Offer, 9 | } from "../paths"; 10 | import { useSelector } from "react-redux"; 11 | import { AxiosFetchState } from "../redux/store"; 12 | import { featuredProducts } from "../assets/globalUtlities"; 13 | 14 | interface headerCategoriesProps { 15 | headerCategories: HeaderCategoryProps[], 16 | 17 | } 18 | 19 | const Home: FC = () => { 20 | const axiosData = useSelector((state: AxiosFetchState) => state) 21 | console.log(axiosData.categoryMap) 22 | return ( 23 |
24 | 25 | 26 | 27 |
28 | 29 | 30 |
31 |
32 | 33 | 34 |
35 |
36 | 37 |
38 |
39 | 40 | 41 |
42 |
43 | 44 | 45 |
46 |
47 | 48 |
49 |
50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 |
58 |
59 | 60 |
61 |
62 |
63 |
64 | ); 65 | } 66 | 67 | export default Home; 68 | -------------------------------------------------------------------------------- /src/pages/ProductGallery.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef, useState } from "react"; 2 | import { useDispatch, useSelector } from "react-redux"; 3 | import { useLocation, } from "react-router-dom"; 4 | import { DataState } from "../redux/store"; 5 | import { BiHeart, BiStar } from "react-icons/bi"; 6 | import { fetchData } from "../apollo/fetchData"; 7 | 8 | const ProductGallery = () => { 9 | const dispatch = useDispatch(); 10 | const data = useSelector((state: { fetchData: DataState }) => state.fetchData); 11 | // console.log(data); 12 | // console.log("Loading", data.loading); 13 | 14 | const [toggleFevourite, setToggleFevourite] = useState([]) 15 | 16 | const [inViewPort, setInViewport] = useState(false) 17 | const galleryRef = useRef(null) 18 | const { pathname } = useLocation(); 19 | console.log("view port", inViewPort); 20 | 21 | useEffect(() => { 22 | window.scrollTo(0, 0); 23 | fetchData()(dispatch); 24 | 25 | // refetching when network is restored 26 | const handleOnline = async () => { 27 | await fetchData()(dispatch) 28 | } 29 | window.addEventListener("online", handleOnline) 30 | return () => window.addEventListener("online", handleOnline) 31 | }, [pathname, dispatch]); 32 | 33 | useEffect(() => { 34 | fetchData()(dispatch) 35 | }, []) 36 | 37 | 38 | useEffect(() => { 39 | const options = { 40 | root: null, 41 | rootMargin: "-10px", 42 | threshold: .5, 43 | } 44 | 45 | const observer = new IntersectionObserver((entries) => { 46 | entries.forEach((entry => { 47 | if (entry.isIntersecting) { 48 | setInViewport(true) 49 | observer.unobserve(entry.target) 50 | } 51 | })) 52 | }, options) 53 | if (galleryRef.current) { 54 | observer.observe(galleryRef.current) 55 | } 56 | 57 | return () => { 58 | if (galleryRef.current) { 59 | observer.unobserve(galleryRef.current) 60 | } 61 | } 62 | }, [pathname]) 63 | return ( 64 | 65 |
66 | {data && data.loading &&

Loading...

} 67 |
68 | {data && data.result.map((item) => ( 69 |
70 | {item?.title} 71 |

{item?.title}

72 |

$ {item?.price}

73 |

{item?.rating?.count}

74 |

75 | 76 | {item?.rating?.rate} 77 |

78 | 81 |
82 | ))} 83 |
84 | {data && data.error &&
Error: {data.error}
} 85 |
86 | ); 87 | }; 88 | 89 | export default ProductGallery; 90 | -------------------------------------------------------------------------------- /src/assets/footerUtility.ts: -------------------------------------------------------------------------------- 1 | import { FooterDataProps } from "../types/layoutTypes"; 2 | 3 | export const footerData: FooterDataProps = { 4 | aboutShopEase: { 5 | heading: "ShopEase: The One-stop Shopping Destination", 6 | content: 7 | "E-commerce is revolutionizing the way we all shop in India. Why do you want to hop from one store to another in search of the latest phone when you can find it on the Internet in a single click? ... (content continues)", 8 | }, 9 | ShopEasePlus: { 10 | heading: "ShopEase Plus", 11 | content: 12 | "A world of limitless possibilities awaits you - ShopEase Plus was kickstarted as a loyalty reward programme for all its regular customers at zero subscription fee. All you need is 500 supercoins ... (content continues)", 13 | }, 14 | noCostEMI: { 15 | heading: "No Cost EMI", 16 | content: 17 | "In an attempt to make high-end products accessible to all, our No Cost EMI plan enables you to shop with us under EMI, without shelling out any processing fee. Applicable on select mobiles, laptops, large and small appliances, furniture ... (content continues)", 18 | }, 19 | emiDebitCards: { 20 | heading: "EMI on Debit Cards", 21 | content: 22 | "Did you know debit card holders account for 79.38 crore in the country, while there are only 3.14 crore credit card holders? After enabling EMI on Credit Cards, in another attempt to make online shopping accessible to everyone, ShopEase introduces EMI on Debit Cards ... (content continues)", 23 | }, 24 | mobileExchange: { 25 | heading: "Mobile Exchange Offers", 26 | content: 27 | "Get an instant discount on the phone that you have been eyeing on. Exchange your old mobile for a new one after the ShopEase experts calculate the value of your old phone, provided it is in a working condition without damage to the screen ... (content continues)", 28 | }, 29 | whatToBuy: { 30 | heading: "What Can You Buy From ShopEase?", 31 | content: 32 | "Mobile Phones, Electronic Devices and Accessories, Large Appliances, Small Home Appliances, Lifestyle, Home and Furniture, Baby and Kids, Books, Sports and Games, Grocery/Supermart ... (content continues)", 33 | }, 34 | }; 35 | 36 | export const footerLinks = [ 37 | { 38 | title: 'About Us', 39 | links: [ 40 | { text: 'Company Information', url: '/company-info' }, 41 | { text: 'Contact Us', url: '/contact' }, 42 | { text: 'Careers', url: '/careers' }, 43 | ], 44 | }, 45 | { 46 | title: 'Help', 47 | links: [ 48 | { text: 'Payments', url: '/payments' }, 49 | { text: 'Shipping', url: '/shipping' }, 50 | { text: 'Cancellation & Returns', url: '/returns' }, 51 | { text: 'FAQ', url: '/faq' }, 52 | ], 53 | }, 54 | { 55 | title: 'Policy', 56 | links: [ 57 | { text: 'Return Policy', url: '/return-policy' }, 58 | { text: 'Terms Of Use', url: '/terms' }, 59 | { text: 'Security', url: '/security' }, 60 | { text: 'Privacy', url: '/privacy' }, 61 | ], 62 | }, 63 | { 64 | title: 'Social', 65 | links: [ 66 | { text: 'Facebook', url: 'https://www.facebook.com/ShopEase' }, 67 | { text: 'Twitter', url: 'https://twitter.com/ShopEase' }, 68 | { text: 'Instagram', url: 'https://www.instagram.com/ShopEase/' }, 69 | ], 70 | }, 71 | ]; -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { FC, Suspense, useEffect, useState } from "react"; 2 | import { Footer, Header, PopupCard } from "./paths"; 3 | import { Route, Routes } from "react-router-dom"; 4 | import { useSelector } from "react-redux"; 5 | import { DarkState } from "./redux/store"; 6 | import { Account, Cart, ChatBot, Checkout, Home, NestedHoverNavlink, PaymentSuccessful, ProductGallery, ProductsGroup, ProductDetails } from "./optimazation/AppOptimazation"; 7 | import { ProductProps } from "./types/productTypes"; 8 | 9 | 10 | const App: FC = () => { 11 | const [showPopUp, setShowPopUp] = useState(false); 12 | const DarkMode = useSelector((state: { dark: DarkState }) => state?.dark) 13 | // after 4 sec of initial loading 14 | useEffect(() => { 15 | const timeOut = setTimeout(() => { 16 | // check local storage boolean data 17 | // not show popup again whether website is opened in same computer 18 | const isPopupClosed = localStorage.getItem("isPopupClosed"); 19 | if (!isPopupClosed) { 20 | setShowPopUp(true); 21 | } 22 | }, 4000); 23 | 24 | return () => clearTimeout(timeOut); 25 | }, []); 26 | 27 | 28 | const productDetails: ProductProps = { 29 | id: 0, 30 | title: "", 31 | img: "", 32 | offerAvailable: false, 33 | price: 0, 34 | quantity: 0, 35 | cart: [], 36 | thumbImg: "" 37 | } 38 | 39 | return ( 40 |
41 | {showPopUp && } 42 |
{ }} /> 43 | Loading...
} > 44 | 45 | } /> 46 | 51 | } 52 | /> 53 | }> 54 | }> 55 | {/* Nested Routing... */} 56 | } /> 57 | {/* END -- Nested Routing... */} 58 | 59 | 74 | } 75 | /> 76 | } /> 77 | } /> 78 | } /> 79 | 80 | 81 |
82 | 83 |
84 | 85 |