├── .nvmrc ├── server ├── .nvmrc ├── public │ ├── company │ │ └── emarket │ │ │ └── logo.png │ ├── display-images │ │ ├── p120.jpeg │ │ ├── mac-mini.png │ │ ├── ipad-2020.jpeg │ │ ├── home_slider_0.jpg │ │ ├── home_slider_1.jpg │ │ ├── lenovo-yoga.jpeg │ │ ├── razer-opus.jpeg │ │ └── smart-watches.jpeg │ ├── user-image │ │ └── default-man.png │ ├── display-icons │ │ ├── card-payment-icon.png │ │ ├── fast-delivery-icon.png │ │ └── online-support-icon.png │ └── product-image │ │ └── Electronics │ │ └── Mobiles │ │ ├── Samsung │ │ ├── 1 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 2 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 3 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 4 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 5 │ │ │ └── 1.jpg │ │ ├── 6 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 7 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 8 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 9 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ └── 10 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── Xiaomi │ │ ├── 1 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 2 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 3 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 4 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 5 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 6 │ │ │ └── 1.jpg │ │ ├── 7 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 8 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 9 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ └── 10 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ └── Mobiles │ │ ├── Samsung │ │ ├── 1 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 2 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 3 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 4 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 5 │ │ │ └── 1.jpg │ │ ├── 6 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 7 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 8 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ ├── 9 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ └── 10 │ │ │ ├── 1.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ └── 4.jpg │ │ └── Xiaomi │ │ ├── 1 │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ │ ├── 2 │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ │ ├── 3 │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ │ ├── 4 │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ │ ├── 5 │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ │ ├── 6 │ │ └── 1.jpg │ │ ├── 7 │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ │ ├── 8 │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ │ ├── 9 │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ │ └── 10 │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg ├── Dockerfile ├── src │ ├── .eslintrc.js │ ├── models │ │ ├── Category.js │ │ ├── Wishlist.js │ │ ├── SubCategory.js │ │ ├── SubSubCategory.js │ │ ├── OrderItem.js │ │ ├── Review.js │ │ ├── Showcase.js │ │ ├── Company.js │ │ ├── Order.js │ │ ├── User.js │ │ ├── Product.js │ │ └── index.js │ ├── controllers │ │ ├── CompanyController.js │ │ ├── ImageController.js │ │ ├── OrderItemController.js │ │ ├── CheckoutController.js │ │ ├── CategoryController.js │ │ ├── SubCategoryController.js │ │ ├── SubSubCategoryController.js │ │ ├── ShowcaseController.js │ │ ├── ReviewController.js │ │ ├── WishlistController.js │ │ └── OrderController.js │ ├── config │ │ └── config.js │ ├── policies │ │ ├── isAuthenticated.js │ │ └── AuthenticationControllerPolicy.js │ ├── passport.js │ └── app.js ├── example.env ├── jest.config.js ├── seed │ ├── subCategories.json │ ├── wishlists.json │ ├── categories.json │ ├── companies.json │ ├── reviews.json │ ├── index.js │ ├── showcases.json │ ├── users.json │ └── subSubCategories.json ├── tests │ ├── setup.js │ └── factories │ │ └── testDataFactory.js └── package.json ├── shop ├── .nvmrc ├── .browserslistrc ├── public │ ├── emarket.png │ └── index.html ├── babel.config.js ├── src │ ├── services │ │ ├── CompanyService.js │ │ ├── Api.js │ │ ├── CheckoutService.js │ │ ├── OrderItemService.js │ │ ├── ShowcaseService.js │ │ ├── ReviewService.js │ │ ├── CategoryService.js │ │ ├── WishlistService.js │ │ ├── UserService.js │ │ ├── SubCategoryService.js │ │ ├── OrderService.js │ │ ├── SubSubCategoryService.js │ │ ├── AuthenticationService.js │ │ └── ProductsService.js │ ├── components │ │ ├── templateCode.vue │ │ ├── NotFound │ │ │ └── InvalidParameter.vue │ │ ├── Common │ │ │ └── MyFooter.vue │ │ ├── Order │ │ │ ├── OrderDetails.vue │ │ │ └── OrderItems.vue │ │ ├── Admins │ │ │ ├── Order │ │ │ │ └── OrderDetails.vue │ │ │ └── ATopHeader.vue │ │ ├── Products │ │ │ └── FilterComponent.vue │ │ ├── User │ │ │ ├── ReqPassToken.vue │ │ │ └── Profile │ │ │ │ └── UReviews.vue │ │ ├── MaintainProduct │ │ │ ├── AddToCart.vue │ │ │ └── AddToWishlist.vue │ │ ├── Home │ │ │ ├── Showcase.vue │ │ │ ├── Support.vue │ │ │ ├── TopSellProduct.vue │ │ │ └── NewAddProduct.vue │ │ └── ProductDetails │ │ │ ├── Recommendation.vue │ │ │ └── ProductHeader.vue │ ├── App.vue │ ├── main.js │ ├── views │ │ ├── AboutUs.vue │ │ ├── ErrorPage │ │ │ ├── Unauthorized.vue │ │ │ └── NotFound.vue │ │ ├── Admin │ │ │ ├── ADashboard.vue │ │ │ ├── AProfile.vue │ │ │ └── AOrder.vue │ │ ├── BuyProduct │ │ │ ├── Checkout.vue │ │ │ └── ViewOrder.vue │ │ ├── Home.vue │ │ ├── PayMoney │ │ │ └── CancelPayment.vue │ │ ├── Product │ │ │ ├── AllProducts.vue │ │ │ ├── SubSubCategoryProducts.vue │ │ │ ├── CategoryProducts.vue │ │ │ └── SubCategoryProducts.vue │ │ └── User │ │ │ └── Profile.vue │ └── store │ │ ├── index.js │ │ ├── Company.js │ │ ├── Cart.js │ │ ├── CurrentUser.js │ │ ├── Wishlist.js │ │ ├── Category.js │ │ └── Review.js ├── Dockerfile ├── server.js ├── .eslintrc.js └── package.json ├── jsconfig.json ├── .gitignore ├── sonar-project.properties ├── .vscode └── settings.json ├── vetur.config.js ├── docker-compose.yaml └── LICENSE /.nvmrc: -------------------------------------------------------------------------------- 1 | v18.20.2 2 | -------------------------------------------------------------------------------- /server/.nvmrc: -------------------------------------------------------------------------------- 1 | v18.20.2 2 | -------------------------------------------------------------------------------- /shop/.nvmrc: -------------------------------------------------------------------------------- 1 | v18.20.2 2 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["./shop/**/*"] 3 | } 4 | -------------------------------------------------------------------------------- /shop/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /shop/public/emarket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/shop/public/emarket.png -------------------------------------------------------------------------------- /server/public/company/emarket/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/company/emarket/logo.png -------------------------------------------------------------------------------- /server/public/display-images/p120.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-images/p120.jpeg -------------------------------------------------------------------------------- /server/public/display-images/mac-mini.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-images/mac-mini.png -------------------------------------------------------------------------------- /server/public/user-image/default-man.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/user-image/default-man.png -------------------------------------------------------------------------------- /server/public/display-images/ipad-2020.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-images/ipad-2020.jpeg -------------------------------------------------------------------------------- /server/public/display-images/home_slider_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-images/home_slider_0.jpg -------------------------------------------------------------------------------- /server/public/display-images/home_slider_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-images/home_slider_1.jpg -------------------------------------------------------------------------------- /server/public/display-images/lenovo-yoga.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-images/lenovo-yoga.jpeg -------------------------------------------------------------------------------- /server/public/display-images/razer-opus.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-images/razer-opus.jpeg -------------------------------------------------------------------------------- /server/public/display-images/smart-watches.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-images/smart-watches.jpeg -------------------------------------------------------------------------------- /shop/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | "@vue/cli-plugin-babel/preset", 4 | "@babel/preset-typescript", 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18-alpine 2 | WORKDIR /app 3 | COPY package*.json ./ 4 | RUN npm install 5 | COPY . . 6 | CMD ["npm", "start"] 7 | EXPOSE 8080 8 | -------------------------------------------------------------------------------- /server/public/display-icons/card-payment-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-icons/card-payment-icon.png -------------------------------------------------------------------------------- /server/public/display-icons/fast-delivery-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-icons/fast-delivery-icon.png -------------------------------------------------------------------------------- /server/public/display-icons/online-support-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/display-icons/online-support-icon.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | node_modules/ 3 | dist 4 | .env* 5 | 6 | # testing 7 | server/coverage 8 | shop/coverage 9 | 10 | # vim swap files 11 | *.swp 12 | -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/1/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/1/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/1/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/1/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/1/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/1/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/1/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/1/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/2/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/2/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/2/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/2/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/2/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/2/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/2/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/2/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/3/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/3/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/3/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/3/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/3/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/3/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/3/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/3/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/4/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/4/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/4/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/4/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/4/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/4/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/4/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/4/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/5/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/5/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/6/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/6/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/6/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/6/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/6/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/6/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/6/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/6/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/7/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/7/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/7/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/7/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/7/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/7/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/7/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/7/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/8/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/8/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/8/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/8/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/8/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/8/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/8/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/8/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/9/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/9/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/9/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/9/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/9/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/9/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/9/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/9/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/1/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/1/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/1/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/1/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/1/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/1/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/1/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/1/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/10/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/10/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/10/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/10/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/10/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/10/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/10/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/10/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/2/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/2/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/2/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/2/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/2/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/2/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/2/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/2/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/3/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/3/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/3/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/3/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/3/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/3/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/3/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/3/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/4/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/4/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/4/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/4/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/4/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/4/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/4/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/4/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/5/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/5/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/5/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/5/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/5/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/5/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/5/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/5/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/6/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/6/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/7/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/7/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/7/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/7/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/7/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/7/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/7/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/7/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/8/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/8/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/8/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/8/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/8/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/8/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/8/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/8/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/9/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/9/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/9/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/9/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/9/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/9/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Xiaomi/9/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Xiaomi/9/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/10/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/10/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/10/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/10/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/10/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/10/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Samsung/10/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Samsung/10/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/1/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/1/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/1/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/1/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/1/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/1/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/1/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/1/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/2/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/2/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/2/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/2/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/2/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/2/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/2/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/2/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/3/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/3/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/3/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/3/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/3/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/3/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/3/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/3/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/4/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/4/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/4/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/4/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/4/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/4/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/4/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/4/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/5/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/5/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/6/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/6/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/6/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/6/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/6/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/6/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/6/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/6/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/7/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/7/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/7/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/7/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/7/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/7/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/7/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/7/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/8/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/8/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/8/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/8/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/8/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/8/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/8/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/8/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/9/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/9/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/9/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/9/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/9/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/9/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/9/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/9/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/1/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/1/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/1/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/1/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/1/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/1/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/1/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/1/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/10/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/10/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/10/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/10/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/10/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/10/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/10/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/10/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/2/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/2/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/2/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/2/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/2/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/2/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/2/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/2/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/3/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/3/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/3/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/3/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/3/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/3/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/3/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/3/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/4/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/4/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/4/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/4/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/4/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/4/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/4/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/4/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/5/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/5/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/5/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/5/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/5/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/5/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/5/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/5/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/6/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/6/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/7/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/7/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/7/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/7/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/7/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/7/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/7/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/7/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/8/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/8/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/8/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/8/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/8/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/8/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/8/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/8/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/9/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/9/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/9/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/9/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/9/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/9/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/9/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Xiaomi/9/4.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/10/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/10/1.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/10/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/10/2.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/10/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/10/3.jpg -------------------------------------------------------------------------------- /server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/10/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohammadrony/emarket/HEAD/server/public/product-image/Electronics/Mobiles/Mobiles/Samsung/10/4.jpg -------------------------------------------------------------------------------- /shop/src/services/CompanyService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getCompany(companyId) { 5 | return Api().get(`/api/company/getCompany/${companyId}`); 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.projectKey=emarket 2 | sonar.sources=./backend/src,./frontend/src 3 | sonar.tests=./backend/tests,./frontend/tests 4 | sonar.javascript.lcov.reportPaths=coverage/lcov.info 5 | -------------------------------------------------------------------------------- /server/src/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es2021": true 6 | }, 7 | "parserOptions": { 8 | "ecmaVersion": 12 9 | }, 10 | "rules": { 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "sqltools.connections": [], 3 | "files.exclude": { 4 | "**/.git": true, 5 | "**/.svn": true, 6 | "**/.hg": true, 7 | "**/node_modules": true, 8 | "**/dist": true, 9 | "**/.env*": true, 10 | "**/.vscode": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vetur.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | settings: { 3 | "vetur.useWorkspaceDependencies": true, 4 | "vetur.experimental.templateInterpolationService": true 5 | }, 6 | projects: [ 7 | { 8 | root: './shop/', 9 | package: './package.json', 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /shop/src/services/Api.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import store from "../store"; 3 | 4 | export default () => { 5 | return axios.create({ 6 | baseURL: `http://localhost:8081`, 7 | headers: { 8 | Authorization: `Bearer ${store.state.CurrentUser?.token || ""}`, 9 | }, 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /server/example.env: -------------------------------------------------------------------------------- 1 | STRIPE_SECRET_KEY= 2 | EMARKET_EMAIL= 3 | EMARKET_PASSWORD= 4 | 5 | PORT=8081 6 | DB_HOST=localhost 7 | DB_PORT=3306 8 | DB_NAME=emarket 9 | DB_USER=root 10 | DB_PASS=12345678 11 | DIALECT=mysql 12 | 13 | JWT_SECRET=secret 14 | 15 | # For production 16 | # NODE_ENV=production -------------------------------------------------------------------------------- /shop/src/components/templateCode.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /shop/src/services/CheckoutService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | createCheckoutSession(checkoutProducts) { 5 | return Api().post("/api/checkout/createCheckoutSession", checkoutProducts); 6 | }, 7 | retrieveCheckoutSession(sessionId) { 8 | return Api().get(`/api/checkout/retrieveCheckoutSession/${sessionId}`); 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /shop/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build stage 2 | FROM node:18-alpine AS build 3 | WORKDIR /app 4 | COPY package*.json ./ 5 | RUN npm install 6 | COPY . . 7 | RUN npm run build 8 | 9 | # Production stage 10 | FROM node:18-alpine AS production 11 | WORKDIR /app 12 | COPY --from=build /app/dist ./dist 13 | COPY package*.json ./ 14 | RUN npm install --only=production 15 | CMD ["npm", "run", "serve"] 16 | -------------------------------------------------------------------------------- /server/src/models/Category.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Category = sequelize.define('Category', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | }, 9 | name: { 10 | type: DataTypes.STRING 11 | } 12 | }) 13 | return Category 14 | } 15 | -------------------------------------------------------------------------------- /server/src/controllers/CompanyController.js: -------------------------------------------------------------------------------- 1 | const { Company } = require('../models') 2 | 3 | module.exports = { 4 | async getCompany(req, res) { 5 | try { 6 | const company = await Company.findByPk(req.params.companyId); 7 | 8 | res.send(company) 9 | } catch (err) { 10 | res.status(500).send({ 11 | error: 'An error occured when trying to fetch company.' 12 | }) 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /shop/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | 11 | 19 | -------------------------------------------------------------------------------- /shop/server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const serveStatic = require("serve-static"); 3 | const history = require("connect-history-api-fallback"); 4 | const enforce = require("express-sslify"); 5 | 6 | const app = express(); 7 | 8 | app.use(serveStatic(__dirname + "/dist")); 9 | app.use(history()); 10 | app.use(enforce.HTTPS({ trustProtoHeader: true })); 11 | 12 | app.listen(process.env.PORT || 5000); 13 | -------------------------------------------------------------------------------- /shop/src/services/OrderItemService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getOrderItemList(orderId) { 5 | return Api().get(`/api/orderItem/getOrderItemList/${orderId}`); 6 | }, 7 | createOrderItem(credentials) { 8 | return Api().post("/api/orderItem/createOrderItem", credentials); 9 | }, 10 | deleteOrderItem(orderItemId) { 11 | return Api().delete(`/api/orderItem/deleteOrderItem/${orderItemId}`); 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /server/src/models/Wishlist.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Wishlist = sequelize.define('Wishlist', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | } 9 | }) 10 | Wishlist.associate = function (models) { 11 | Wishlist.belongsTo(models.User) 12 | Wishlist.belongsTo(models.Product) 13 | } 14 | return Wishlist 15 | } 16 | -------------------------------------------------------------------------------- /server/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | testMatch: ['**/tests/**/*.test.js'], 4 | collectCoverage: true, 5 | coverageDirectory: 'coverage', 6 | coverageReporters: ['text', 'lcov', 'html'], 7 | coverageThreshold: { 8 | global: { 9 | branches: 40, 10 | functions: 40, 11 | lines: 40, 12 | statements: 40 13 | } 14 | }, 15 | setupFilesAfterEnv: ['/tests/setup.js'], 16 | testTimeout: 100000 17 | }; 18 | -------------------------------------------------------------------------------- /server/src/models/SubCategory.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const SubCategory = sequelize.define('SubCategory', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | }, 9 | name: DataTypes.STRING 10 | }) 11 | SubCategory.associate = function (models) { 12 | SubCategory.belongsTo(models.Category) 13 | } 14 | return SubCategory 15 | } 16 | -------------------------------------------------------------------------------- /server/seed/subCategories.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Mobiles", 5 | "CategoryId": 1 6 | }, 7 | { 8 | "id": 2, 9 | "name": "Mobile Accessories", 10 | "CategoryId": 1 11 | }, 12 | { 13 | "id": 3, 14 | "name": "Computer Accessories", 15 | "CategoryId": 1 16 | }, 17 | { 18 | "id": 4, 19 | "name": "Tvs Brand", 20 | "CategoryId": 2 21 | }, 22 | { 23 | "id": 5, 24 | "name": "Washing Machine", 25 | "CategoryId": 3 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /server/src/models/SubSubCategory.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const SubSubCategory = sequelize.define('SubSubCategory', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | }, 9 | name: DataTypes.STRING 10 | }) 11 | SubSubCategory.associate = function (models) { 12 | SubSubCategory.belongsTo(models.SubCategory) 13 | } 14 | return SubSubCategory 15 | } 16 | -------------------------------------------------------------------------------- /server/src/models/OrderItem.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const OrderItem = sequelize.define('OrderItem', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true, 8 | }, 9 | quantity: DataTypes.INTEGER 10 | }) 11 | OrderItem.associate = function (models) { 12 | OrderItem.belongsTo(models.Product) 13 | OrderItem.belongsTo(models.Order) 14 | } 15 | return OrderItem 16 | } -------------------------------------------------------------------------------- /server/src/config/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | port: process.env.PORT || 8081, 3 | db: { 4 | host: process.env.DB_HOST || "localhost", 5 | port: process.env.DB_PORT || "3306", 6 | database: process.env.DB_NAME || "emarket", 7 | user: process.env.DB_USER || "root", 8 | password: process.env.DB_PASS || "12345678", 9 | dialect: process.env.DIALECT || "mysql", 10 | }, 11 | authentication: { 12 | jwtSecret : process.env.JWT_SECRET || 'secret' 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /server/src/models/Review.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Review = sequelize.define('Review', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | }, 9 | rating: DataTypes.INTEGER, 10 | comment: DataTypes.STRING, 11 | }) 12 | Review.associate = function (models) { 13 | Review.belongsTo(models.User) 14 | Review.belongsTo(models.Product) 15 | } 16 | return Review 17 | } -------------------------------------------------------------------------------- /shop/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | }, 6 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"], 7 | parserOptions: { 8 | parser: "@babel/eslint-parser", 9 | }, 10 | rules: { 11 | "vue/multi-word-component-names": "off", 12 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", 13 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", 14 | "prettier/prettier": ["error", { "endOfLine": "auto" }], 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /shop/src/services/ShowcaseService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getShowcaseItems() { 5 | return Api().get("/api/showcase/getShowcaseItems"); 6 | }, 7 | createShowcaseItem(credentials) { 8 | return Api().post("/api/showcase/createShowcaseItem", credentials); 9 | }, 10 | updateShowcaseItem(credentials) { 11 | return Api().put("/api/showcase/updateShowcaseItem", credentials); 12 | }, 13 | deleteShowcaseItem(showcaseItemId) { 14 | return Api().delete(`/api/showcase/deleteShowcaseItem/${showcaseItemId}`); 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /shop/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App.vue"; 3 | import router from "./router"; 4 | import store from "./store"; 5 | import { BootstrapVue, IconsPlugin } from "bootstrap-vue"; 6 | import { sync } from "vuex-router-sync"; 7 | const unsync = sync(store, router); 8 | Vue.use(IconsPlugin); 9 | Vue.use(BootstrapVue); 10 | Vue.config.productionTip = false; 11 | unsync(); 12 | import "bootstrap/dist/css/bootstrap.css"; 13 | import "bootstrap-vue/dist/bootstrap-vue.css"; 14 | new Vue({ 15 | router, 16 | store, 17 | render: (h) => h(App), 18 | }).$mount("#app"); 19 | -------------------------------------------------------------------------------- /server/src/policies/isAuthenticated.js: -------------------------------------------------------------------------------- 1 | const passport = require('passport') 2 | 3 | module.exports = function(req, res, next) { 4 | passport.authenticate('jwt', function(err, user){ 5 | if(err) { 6 | res.status(403).send({ 7 | error: 'you do not have access to this resource' 8 | }) 9 | } else if(!user){ 10 | res.status(403).send({ 11 | error: 'you do not have access to this resource' 12 | }) 13 | } else { 14 | req.user = user 15 | next() 16 | } 17 | })(req, res, next) 18 | } -------------------------------------------------------------------------------- /server/src/models/Showcase.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Showcase = sequelize.define('Showcase', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | }, 9 | type: DataTypes.STRING, 10 | caption: DataTypes.STRING, 11 | image: DataTypes.STRING, 12 | routerLink: DataTypes.STRING, 13 | priority: DataTypes.INTEGER, 14 | }) 15 | Showcase.associate = function (models) { 16 | Showcase.belongsTo(models.Company) 17 | } 18 | return Showcase 19 | } -------------------------------------------------------------------------------- /shop/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /shop/src/services/ReviewService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getReviewList(productId) { 5 | return Api().get(`/api/review/getReviewList/${productId}`); 6 | }, 7 | getUsersReviewList(userId) { 8 | return Api().get(`/api/review/getUsersReviewList/${userId}`); 9 | }, 10 | createReview(credentials) { 11 | return Api().post("/api/review/createReview", credentials); 12 | }, 13 | updateReview(credentials) { 14 | return Api().put("/api/review/updateReview", credentials); 15 | }, 16 | deleteReview(reviewId) { 17 | return Api().delete(`/api/review/deleteReview/${reviewId}`); 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /shop/src/services/CategoryService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getCategoryList() { 5 | return Api().get("/api/category/getCategoryList"); 6 | }, 7 | getCategoryByName(name) { 8 | return Api().get(`/api/category/getCategoryByName/${name}`); 9 | }, 10 | createCategory(credentials) { 11 | return Api().post("/api/category/createCategory", credentials); 12 | }, 13 | updateCategory(credentials) { 14 | return Api().put("/api/category/updateCategory", credentials); 15 | }, 16 | deleteCategory(categoryId) { 17 | return Api().delete(`/api/category/deleteCategory/${categoryId}`); 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /server/seed/wishlists.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "UserId": 1, 5 | "ProductId": 1 6 | }, 7 | { 8 | "id": 2, 9 | "UserId": 1, 10 | "ProductId": 2 11 | }, 12 | { 13 | "id": 3, 14 | "UserId": 1, 15 | "ProductId": 3 16 | }, 17 | { 18 | "id": 4, 19 | "UserId": 1, 20 | "ProductId": 4 21 | }, 22 | { 23 | "id": 5, 24 | "UserId": 1, 25 | "ProductId": 5 26 | }, 27 | { 28 | "id": 6, 29 | "UserId": 1, 30 | "ProductId": 6 31 | }, 32 | { 33 | "id": 7, 34 | "UserId": 2, 35 | "ProductId": 3 36 | }, 37 | { 38 | "id": 8, 39 | "UserId": 2, 40 | "ProductId": 4 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /shop/src/services/WishlistService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getWishlist() { 5 | return Api().get("/api/wishlist/getWishlist"); 6 | }, 7 | getWishlistItem(productId) { 8 | return Api().get(`/api/wishlist/getWishlistItem/${productId}`); 9 | }, 10 | createWishlistItem(credentials) { 11 | return Api().post("/api/wishlist/createWishlistItem", credentials); 12 | }, 13 | removeWishlistItem(productId) { 14 | return Api().delete(`/api/wishlist/removeWishlistItem/${productId}`); 15 | }, 16 | deleteWishItemByProduct(productId) { 17 | return Api().delete(`/api/wishlist/deleteWishItemByProduct/${productId}`); 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /shop/src/services/UserService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | checkUserName(userName) { 5 | return Api().get(`/api/user/checkUserName/${userName}`); 6 | }, 7 | deleteAccount(userId) { 8 | return Api().delete(`/api/user/deleteAccount/${userId}`); 9 | }, 10 | getUserList() { 11 | return Api().get("/api/user/getUserList"); 12 | }, 13 | updateUser(credentials) { 14 | return Api().post("/api/user/updateUser", credentials); 15 | }, 16 | getUserById(userId) { 17 | return Api().get(`/api/user/getUserById/${userId}`); 18 | }, 19 | getUserByEmail(email) { 20 | return Api().get(`/api/user/getUserByEmail/${email}`); 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /shop/src/views/AboutUs.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /shop/src/services/SubCategoryService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getSubCategoryList() { 5 | return Api().get("/api/subCategory/getSubCategoryList"); 6 | }, 7 | getSubCategoryByName(name) { 8 | return Api().get(`/api/subCategory/getSubCategoryByName/${name}`); 9 | }, 10 | createSubCategory(credentials) { 11 | return Api().post("/api/subCategory/createSubCategory", credentials); 12 | }, 13 | updateSubCategory(credentials) { 14 | return Api().put("/api/subCategory/updateSubCategory", credentials); 15 | }, 16 | deleteSubCategory(subCategoryId) { 17 | return Api().delete(`/api/subCategory/deleteSubCategory/${subCategoryId}`); 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /shop/src/services/OrderService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getOrderList() { 5 | return Api().get("/api/order/getOrderList"); 6 | }, 7 | getOrder(orderId) { 8 | return Api().get(`/api/order/getOrder/${orderId}`); 9 | }, 10 | getOrderBySessionId(sessionId) { 11 | return Api().get(`/api/order/getOrderBySessionId/${sessionId}`); 12 | }, 13 | createOrder(credentials) { 14 | return Api().post("/api/order/createOrder", credentials); 15 | }, 16 | updateOrder(credentials) { 17 | return Api().put("/api/order/updateOrder", credentials); 18 | }, 19 | deleteOrder(orderId) { 20 | return Api().delete(`/api/order/deleteOrder/${orderId}`); 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /server/src/models/Company.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Company = sequelize.define('Company', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | }, 9 | name: DataTypes.STRING, 10 | email: DataTypes.STRING, 11 | phoneNo: DataTypes.STRING, 12 | icon: DataTypes.STRING, 13 | logo: DataTypes.STRING, 14 | code: DataTypes.STRING, 15 | header: DataTypes.STRING, 16 | motive: DataTypes.STRING, 17 | details: DataTypes.TEXT, 18 | location: DataTypes.STRING, 19 | }) 20 | return Company 21 | } -------------------------------------------------------------------------------- /shop/src/services/SubSubCategoryService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getSubSubCategoryList() { 5 | return Api().get("/api/subSubCategory/getSubSubCategoryList"); 6 | }, 7 | getSubSubCategoryByName(name) { 8 | return Api().get(`/api/subSubCategory/getSubSubCategoryByName/${name}`); 9 | }, 10 | createSubSubCategory(credentials) { 11 | return Api().post("/api/subSubCategory/createSubSubCategory", credentials); 12 | }, 13 | updateSubSubCategory(credentials) { 14 | return Api().put("/api/subSubCategory/updateSubSubCategory", credentials); 15 | }, 16 | deleteSubSubCategory(subSubCategoryId) { 17 | return Api().delete( 18 | `/api/subSubCategory/deleteSubSubCategory/${subSubCategoryId}` 19 | ); 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /server/src/models/Order.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Order = sequelize.define('Order', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | }, 9 | name: DataTypes.STRING, 10 | phoneNo: DataTypes.STRING, 11 | email: DataTypes.STRING, 12 | address: DataTypes.STRING, 13 | status: DataTypes.STRING, 14 | variant: DataTypes.STRING, 15 | checkoutSessionId:{ 16 | type: DataTypes.STRING, 17 | }, 18 | productCost: DataTypes.INTEGER, 19 | currency: DataTypes.STRING, 20 | shippingCost: DataTypes.INTEGER, 21 | }) 22 | return Order 23 | } -------------------------------------------------------------------------------- /server/src/passport.js: -------------------------------------------------------------------------------- 1 | const passport = require('passport') 2 | const config = require('./config/config') 3 | const {User} = require('./models') 4 | 5 | const JwtStrategy = require('passport-jwt').Strategy 6 | const ExtractJwt = require('passport-jwt').ExtractJwt 7 | 8 | passport.use( 9 | new JwtStrategy({ 10 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), 11 | secretOrKey: config.authentication.jwtSecret 12 | }, async function (jwtPayload, done) { 13 | try { 14 | const user = await User.findOne({ 15 | where: { 16 | id: jwtPayload.id 17 | } 18 | }) 19 | if(!user){ 20 | return done(new Error(), false) 21 | } 22 | return done(null, user) 23 | } catch(err){ 24 | return done(new Error(), false) 25 | } 26 | }) 27 | ) 28 | 29 | module.exports = null -------------------------------------------------------------------------------- /shop/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Vuex from "vuex"; 3 | import { CartModule } from "./Cart.js"; 4 | import { ReviewModule } from "./Review.js"; 5 | import { CompanyModule } from "./Company.js"; 6 | import { CategoryModule } from "./Category.js"; 7 | import { ProductsModule } from "./Products.js"; 8 | import { CheckoutModule } from "./Checkout.js"; 9 | import { WishlistModule } from "./Wishlist.js"; 10 | import { CurrentUserModule } from "./CurrentUser.js"; 11 | import createPersistedState from "vuex-persistedstate"; 12 | Vue.use(Vuex); 13 | 14 | export default new Vuex.Store({ 15 | strict: true, 16 | plugins: [createPersistedState()], 17 | modules: { 18 | Cart: CartModule, 19 | Review: ReviewModule, 20 | Company: CompanyModule, 21 | Category: CategoryModule, 22 | Products: ProductsModule, 23 | Checkout: CheckoutModule, 24 | Wishlist: WishlistModule, 25 | CurrentUser: CurrentUserModule, 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /shop/src/views/ErrorPage/Unauthorized.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /shop/src/views/Admin/ADashboard.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /shop/src/views/ErrorPage/NotFound.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /server/seed/categories.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Electronics" 5 | }, 6 | { 7 | "id": 2, 8 | "name": "TV & Multimedia" 9 | }, 10 | { 11 | "id": 3, 12 | "name": "Home & Furniture" 13 | }, 14 | { 15 | "id": 4, 16 | "name": "Sports & Books" 17 | }, 18 | { 19 | "id": 5, 20 | "name": "Tools & Hardware" 21 | }, 22 | { 23 | "id": 6, 24 | "name": "Clothes" 25 | }, 26 | { 27 | "id": 7, 28 | "name": "Flowers" 29 | }, 30 | { 31 | "id": 8, 32 | "name": "Accessories" 33 | }, 34 | { 35 | "id": 9, 36 | "name": "Baby & Kids" 37 | }, 38 | { 39 | "id": 10, 40 | "name": "Sports & Beauty" 41 | }, 42 | { 43 | "id": 11, 44 | "name": "Car Appliances" 45 | }, 46 | { 47 | "id": 12, 48 | "name": "Outdoors" 49 | }, 50 | { 51 | "id": 13, 52 | "name": "Home Appliances" 53 | }, 54 | { 55 | "id": 14, 56 | "name": "Health Products" 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /server/seed/companies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "E Market BD", 5 | "icon": "", 6 | "logo": "http://localhost:8081/public/company/emarket/logo.png", 7 | "code": "emarket", 8 | "email": "support@emarket.com", 9 | "phoneNo": "+8801710000000", 10 | "location": "45/A, New town
Anywhere, Somewhere.
", 11 | "header": "Find what you need here", 12 | "motive": "emarket is just a software project. It is developed to learn how to build a web application. I've included all these data randomly from the internet from different source.", 13 | "details": "Large text here. about the emarket" 14 | }, 15 | { 16 | "id": 2, 17 | "name": "SUPER MARKET", 18 | "icon": "", 19 | "logo": "", 20 | "code": "supermarket", 21 | "email": "support@supermarket.com", 22 | "phoneNo": "+8801700000000", 23 | "location": "29/D, Sahid Sarak
Farmgate, Dhaka.
", 24 | "header": "Find what you need here", 25 | "motive": "SUPER MARKET sub title here", 26 | "details": "Large text here. about SUPER MARKET" 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | db: 3 | image: mysql:8.0 4 | restart: unless-stopped 5 | env_file: 6 | - .env 7 | networks: 8 | - emarket 9 | ports: 10 | - "3306:3306" 11 | volumes: 12 | - db_data:/var/lib/mysql 13 | healthcheck: 14 | test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] 15 | interval: 10s 16 | timeout: 5s 17 | retries: 10 18 | 19 | server: 20 | build: 21 | context: ./server 22 | dockerfile: Dockerfile 23 | restart: unless-stopped 24 | networks: 25 | - emarket 26 | ports: 27 | - "8081:8081" 28 | env_file: 29 | - .env 30 | depends_on: 31 | db: 32 | condition: service_healthy 33 | 34 | shop: 35 | build: 36 | context: ./shop 37 | dockerfile: Dockerfile 38 | restart: unless-stopped 39 | networks: 40 | - emarket 41 | ports: 42 | - "8080:8080" 43 | depends_on: 44 | - server 45 | 46 | volumes: 47 | db_data: 48 | 49 | networks: 50 | emarket: 51 | name: emarket 52 | driver: bridge 53 | -------------------------------------------------------------------------------- /server/src/models/User.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const User = sequelize.define('User', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | }, 9 | username: { 10 | type: DataTypes.STRING, 11 | allowNull: false, 12 | unique: true 13 | }, 14 | firstName: DataTypes.STRING, 15 | lastName: DataTypes.STRING, 16 | profileImage: DataTypes.STRING, 17 | registerToken: DataTypes.STRING, 18 | email: { 19 | type: DataTypes.STRING, 20 | unique: true 21 | }, 22 | phoneNo: DataTypes.STRING, 23 | password: DataTypes.STRING, 24 | resetPasswordToken: DataTypes.STRING, 25 | userType: DataTypes.STRING, 26 | variant: DataTypes.STRING, 27 | priority: DataTypes.INTEGER, 28 | }) 29 | User.associate = function (models) { 30 | User.belongsTo(models.Company) 31 | } 32 | return User 33 | } -------------------------------------------------------------------------------- /shop/src/views/BuyProduct/Checkout.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Md. Asaduzzaman Rony 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /shop/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /server/tests/setup.js: -------------------------------------------------------------------------------- 1 | const { sequelize, User, Product, Category, SubCategory, SubSubCategory } = require('../src/models'); 2 | 3 | beforeAll(async () => { 4 | console.time('setup'); 5 | await sequelize.sync({ force: true }); 6 | console.timeEnd('setup'); 7 | 8 | // Mock console to reduce test noise 9 | jest.spyOn(console, 'log').mockImplementation(() => {}); 10 | jest.spyOn(console, 'info').mockImplementation(() => {}); 11 | jest.spyOn(console, 'debug').mockImplementation(() => {}); 12 | jest.spyOn(console, 'warn').mockImplementation(() => {}); 13 | jest.spyOn(console, 'error').mockImplementation(() => {}); 14 | }); 15 | 16 | beforeEach(async () => { 17 | await Product.destroy({ where: {} }); 18 | await User.destroy({ where: {} }); 19 | await SubSubCategory.destroy({ where: {} }); 20 | await SubCategory.destroy({ where: {} }); 21 | await Category.destroy({ where: {} }); 22 | }); 23 | 24 | afterAll(async () => { 25 | await sequelize.close(); 26 | console.log.mockRestore?.(); 27 | console.info.mockRestore?.(); 28 | console.debug.mockRestore?.(); 29 | console.warn.mockRestore?.(); 30 | console.error.mockRestore?.(); 31 | }); 32 | -------------------------------------------------------------------------------- /server/src/app.js: -------------------------------------------------------------------------------- 1 | console.log("server started") 2 | if(process.env.NODE_ENV !== 'production'){ 3 | require('dotenv').config({path: "./.env"}) 4 | } 5 | const express = require("express") 6 | const cors = require("cors") 7 | const morgan = require("morgan") 8 | const config = require("./config/config") 9 | const { sequelize } = require("./models") 10 | const app = express(); 11 | app.use(morgan("combined")); 12 | app.use(express.json()) 13 | app.use(express.urlencoded({ extended: true })) 14 | app.use(cors()); 15 | app.use('/public', express.static('public')); 16 | 17 | require('./passport') 18 | require("./routes")(app) 19 | 20 | // Catch all for 404 21 | app.use((req, res, next) => { 22 | res.status(404).send({ error: 'Not found' }); 23 | }); 24 | 25 | // In test environment, export the app without starting the server 26 | if (process.env.NODE_ENV !== 'test') { 27 | sequelize.authenticate() 28 | .then(() => { 29 | app.listen(config.port, () => console.log(`Express server running on port ${config.port}`)); 30 | }) 31 | .catch(err => { 32 | console.error('Unable to connect to the database:', err); 33 | }); 34 | } 35 | 36 | module.exports = app 37 | -------------------------------------------------------------------------------- /shop/src/services/AuthenticationService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | register(credentials) { 5 | return Api().post("/api/auth/register", credentials); 6 | }, 7 | login(credentials) { 8 | return Api().post("/api/auth/login", credentials); 9 | }, 10 | verifyPassword(currentPassword) { 11 | return Api().get(`/api/auth/verifyPassword/${currentPassword}`); 12 | }, 13 | updatePassword(credentials) { 14 | return Api().post("/api/auth/updatePassword", credentials); 15 | }, 16 | requestPasswordToken(credentials) { 17 | return Api().post("/api/auth/requestPasswordToken", credentials); 18 | }, 19 | verifyPasswordToken(token) { 20 | return Api().get(`/api/auth/verifyPasswordToken/${token}`); 21 | }, 22 | checkRegsToken(credentials) { 23 | return Api().post("/api/auth/checkRegsToken", credentials); 24 | }, 25 | verifyRegsToken(credentials) { 26 | return Api().post("/api/auth/verifyRegsToken", credentials); 27 | }, 28 | resetPassword(credentials) { 29 | return Api().post("/api/auth/resetPassword", credentials); 30 | }, 31 | resetRegsToken(credentials) { 32 | return Api().post("/api/auth/resetRegsToken", credentials); 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /shop/src/store/Company.js: -------------------------------------------------------------------------------- 1 | import CompanyService from "@/services/CompanyService.js"; 2 | export const CompanyModule = { 3 | namespaced: true, 4 | strict: true, 5 | state: { 6 | companyId: 1, 7 | company: {}, 8 | }, 9 | mutations: { 10 | SET_COMPANY(state, company) { 11 | state.company = company; 12 | }, 13 | }, 14 | actions: { 15 | async setCompany({ state, commit }) { 16 | try { 17 | const company = (await CompanyService.getCompany(state.companyId)).data; 18 | commit("SET_COMPANY", company); 19 | } catch (error) { 20 | console.log(error.response.data.error); 21 | } 22 | }, 23 | async getCompany({ state, dispatch }) { 24 | if (Object.keys(state.company).length == 0) { 25 | await dispatch("setCompany"); 26 | } 27 | return state.company; 28 | }, 29 | async getCompanyLogo({ state, dispatch }) { 30 | if (!state.company.logo) { 31 | await dispatch("setCompany"); 32 | } 33 | return state.company.logo; 34 | }, 35 | async getCompanyName({ state, dispatch }) { 36 | if (!state.company.name) { 37 | await dispatch("setCompany"); 38 | } 39 | return state.company.name; 40 | }, 41 | }, 42 | }; 43 | -------------------------------------------------------------------------------- /shop/src/views/Admin/AProfile.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "emarket-server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon src/app.js --exec \"npm run lint && node\"", 8 | "lint": "eslint src/**/*.js", 9 | 10 | "test": "DB_NAME=emarket_test NODE_ENV=test jest --runInBand", 11 | "test:watch": "DB_NAME=emarket_test NODE_ENV=test jest --runInBand --watch", 12 | "test:coverage": "DB_NAME=emarket_test NODE_ENV=test jest --runInBand --coverage", 13 | "seed": "node ./seed" 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "dependencies": { 18 | "bluebird": "^3.7.2", 19 | "cors": "^2.8.5", 20 | "express": "^4.18.2", 21 | "express-session": "^1.17.3", 22 | "fs": "^0.0.1-security", 23 | "joi": "^17.9.2", 24 | "jsonwebtoken": "^9.0.0", 25 | "morgan": "^1.10.0", 26 | "multer": "^1.4.5-lts.1", 27 | "mysql": "^2.18.1", 28 | "mysql2": "^3.2.4", 29 | "nodemailer": "^6.9.1", 30 | "passport": "^0.6.0", 31 | "passport-jwt": "^4.0.1", 32 | "sequelize": "^6.6.2", 33 | "stripe": "^12.3.0" 34 | }, 35 | "devDependencies": { 36 | "dotenv": "^16.0.3", 37 | "eslint": "^8.39.0", 38 | "nodemon": "^2.0.22", 39 | "jest": "^29.5.0", 40 | "supertest": "^6.3.3", 41 | "@types/jest": "^29.5.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /server/src/models/Product.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, DataTypes) => { 2 | const Product = sequelize.define('Product', { 3 | id: { 4 | type: DataTypes.INTEGER, 5 | allowNull: false, 6 | primaryKey: true, 7 | autoIncrement: true 8 | }, 9 | code: DataTypes.STRING, 10 | title: DataTypes.STRING, 11 | subtitle: DataTypes.STRING, 12 | description: DataTypes.TEXT, 13 | amount: DataTypes.INTEGER, 14 | rating: DataTypes.FLOAT, 15 | peopleRated: DataTypes.INTEGER, 16 | currency: DataTypes.STRING, 17 | sales: DataTypes.INTEGER, 18 | image1: DataTypes.STRING, 19 | image2: DataTypes.STRING, 20 | image3: DataTypes.STRING, 21 | image4: DataTypes.STRING, 22 | image5: DataTypes.STRING, 23 | image6: DataTypes.STRING, 24 | image7: DataTypes.STRING, 25 | image8: DataTypes.STRING, 26 | image9: DataTypes.STRING, 27 | image10: DataTypes.STRING, 28 | }) 29 | Product.associate = function (models) { 30 | Product.belongsTo(models.Category) 31 | Product.belongsTo(models.SubCategory) 32 | Product.belongsTo(models.SubSubCategory) 33 | } 34 | return Product 35 | } -------------------------------------------------------------------------------- /shop/src/services/ProductsService.js: -------------------------------------------------------------------------------- 1 | import Api from "./Api"; 2 | 3 | export default { 4 | getAllProducts() { 5 | return Api().get("/api/products/getAllProducts"); 6 | }, 7 | topSellProduct(limit) { 8 | return Api().get(`/api/products/topSellProduct/${limit}`); 9 | }, 10 | newAddProduct(limit) { 11 | return Api().get(`/api/products/newAddProduct/${limit}`); 12 | }, 13 | getRecommendation({ subSubCategoryId, limit }) { 14 | return Api().get( 15 | `/api/products/getRecommendation/${subSubCategoryId}/${limit}` 16 | ); 17 | }, 18 | getProductSales(productId) { 19 | return Api().get(`/api/products/getProductSales/${productId}`); 20 | }, 21 | getProduct(productId) { 22 | return Api().get(`/api/products/getProduct/${productId}`); 23 | }, 24 | getProductId(productTitle) { 25 | return Api().get(`/api/products/getProductId/${productTitle}`); 26 | }, 27 | getProductRating(productId) { 28 | return Api().get(`/api/products/getProductRating/${productId}`); 29 | }, 30 | createProduct(credentials) { 31 | return Api().post("/api/products/createProduct", credentials); 32 | }, 33 | updateProduct(credentials) { 34 | return Api().put("/api/products/updateProduct", credentials); 35 | }, 36 | deleteProduct(productId) { 37 | return Api().delete(`/api/products/deleteProduct/${productId}`); 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /shop/src/views/PayMoney/CancelPayment.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /server/src/models/index.js: -------------------------------------------------------------------------------- 1 | const config = require("../config/config"); 2 | const Sequelize = require("sequelize"); 3 | 4 | const sequelize = new Sequelize(config.db.database, config.db.user, config.db.password, { 5 | dialect: config.db.dialect, 6 | host: config.db.host, 7 | port: config.db.port 8 | }) 9 | 10 | const db = {} 11 | db.User = require("./User")(sequelize, Sequelize.DataTypes); 12 | db.Company = require("./Company")(sequelize, Sequelize.DataTypes); 13 | db.Showcase = require("./Showcase")(sequelize, Sequelize.DataTypes); 14 | db.Category = require("./Category")(sequelize, Sequelize.DataTypes); 15 | db.SubCategory = require("./SubCategory")(sequelize, Sequelize.DataTypes); 16 | db.SubSubCategory = require("./SubSubCategory")(sequelize, Sequelize.DataTypes); 17 | db.OrderItem = require("./OrderItem")(sequelize, Sequelize.DataTypes); 18 | db.Wishlist = require("./Wishlist")(sequelize, Sequelize.DataTypes); 19 | db.Product = require("./Product")(sequelize, Sequelize.DataTypes); 20 | db.Review = require("./Review")(sequelize, Sequelize.DataTypes); 21 | db.Order = require("./Order")(sequelize, Sequelize.DataTypes); 22 | 23 | Object.keys(db).forEach((modelName) => { 24 | if ('associate' in db[modelName]) { 25 | db[modelName].associate(db) 26 | } 27 | }) 28 | db.Sequelize = Sequelize; 29 | db.sequelize = sequelize; 30 | 31 | module.exports = db -------------------------------------------------------------------------------- /shop/src/views/Product/AllProducts.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /server/src/controllers/ImageController.js: -------------------------------------------------------------------------------- 1 | const multer = require("multer"); 2 | const fs = require("fs"); 3 | 4 | const storage = multer.diskStorage({ 5 | destination: (req, file, cb) => { 6 | const storagePath = "./public/uploads/"; 7 | fs.mkdirSync(storagePath, { recursive: true }); 8 | 9 | cb(null, storagePath); 10 | }, 11 | filename: (req, file, cb) => { 12 | cb(null, Date.now() + file.originalname); 13 | }, 14 | }); 15 | 16 | const fileFilter = (req, file, cb) => { 17 | if ( 18 | file.mimetype === "image/jpg" || 19 | file.mimetype === "image/png" || 20 | file.mimetype === "image/jpeg" 21 | ) { 22 | cb(null, true); 23 | } else { 24 | cb(new Error("Image Upload Problem"), false); 25 | } 26 | }; 27 | 28 | const upload = multer({ 29 | storage: storage, 30 | limits: { 31 | fileSize: 1024 * 1024 * 10, 32 | }, 33 | fileFilter: fileFilter, 34 | }).array("imageField", 10); 35 | 36 | module.exports = { 37 | async uploadProductImage(req, res, next) { 38 | try { 39 | // what is actual code 40 | await upload(req, res, function (err) { 41 | if (err) { 42 | return res.send("An error occured on uploading images"); 43 | } else { 44 | next(); 45 | } 46 | }); 47 | } catch (error) { 48 | res.status(500).send({ 49 | error: "An error2 occured when uploading product image.", 50 | }); 51 | } 52 | }, 53 | }; 54 | -------------------------------------------------------------------------------- /server/src/controllers/OrderItemController.js: -------------------------------------------------------------------------------- 1 | const { OrderItem, Product } = require('../models') 2 | 3 | module.exports = { 4 | async getOrderItemList(req, res) { 5 | try { 6 | const orderId = req.params.orderId 7 | const orderItems = await OrderItem.findAll({ 8 | where: { 9 | OrderId: orderId 10 | }, 11 | include: { 12 | model: Product, 13 | attributes: [ 14 | 'id', 15 | 'title', 16 | 'amount', 17 | 'currency', 18 | 'image1' 19 | ] 20 | } 21 | }) 22 | res.send(orderItems) 23 | } catch (err) { 24 | res.status(500).send({ 25 | error: 'An error occured when trying to fetch the order items.' 26 | }) 27 | } 28 | }, 29 | async createOrderItem(req, res) { 30 | try { 31 | const orderItemCreated = await OrderItem.create(req.body) 32 | res.send(orderItemCreated) 33 | } catch (err) { 34 | res.status(500).send({ 35 | error: 'An error occured when trying to create an order item.' 36 | }) 37 | } 38 | }, 39 | async deleteOrderItem(req, res) { 40 | try { 41 | const orderItem = await OrderItem.findByPk(req.params.orderItemId) 42 | if (!orderItem) { 43 | return res.status(403).send({ 44 | error: 'No order item to delete.' 45 | }) 46 | } 47 | await orderItem.destroy() 48 | res.send(orderItem) 49 | 50 | } catch (err) { 51 | res.status(500).send({ 52 | error: 'An error occured when trying to delete an order item.' 53 | }) 54 | } 55 | }, 56 | } 57 | -------------------------------------------------------------------------------- /shop/src/components/NotFound/InvalidParameter.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /shop/src/components/Common/MyFooter.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 47 | 48 | 53 | -------------------------------------------------------------------------------- /shop/src/views/User/Profile.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /server/src/controllers/CheckoutController.js: -------------------------------------------------------------------------------- 1 | const stripeSecretKey = process.env.STRIPE_SECRET_KEY; 2 | const stripe = require("stripe")(stripeSecretKey); 3 | module.exports = { 4 | async createCheckoutSession(req, res) { 5 | try { 6 | const checkoutProduct = req.body.checkoutProduct; 7 | var i; 8 | var item1 = []; 9 | for (i = 0; i < checkoutProduct.length; i++) { 10 | item1.push(checkoutProduct[i]); 11 | } 12 | const session = await stripe.checkout.sessions.create({ 13 | success_url: 14 | "http://localhost:8080/success-payment?id={CHECKOUT_SESSION_ID}", 15 | cancel_url: "http://localhost:8080/cancel-payment", 16 | payment_method_types: ["card"], 17 | mode: "payment", 18 | line_items: item1, 19 | metadata: { 20 | customerName: req.body.customerName, 21 | customerPhoneNo: req.body.customerPhoneNo, 22 | shippingAddress: req.body.shippingAddress, 23 | }, 24 | customer_email: req.body.customerEmail, 25 | }); 26 | res.json({ 27 | id: session.id, 28 | }); 29 | } catch (err) { 30 | res.status(500).send({ 31 | error: "An error occured when trying to checkout into stripe.", 32 | }); 33 | } 34 | }, 35 | async retrieveCheckoutSession(req, res) { 36 | try { 37 | const sessionId = req.params.sessionId; 38 | const session = await stripe.checkout.sessions.retrieve(sessionId, { 39 | expand: ["line_items"], 40 | }); 41 | res.send(session); 42 | } catch (err) { 43 | res.status(500).send({ 44 | error: "An error occured when trying to retrieve checkout session.", 45 | }); 46 | } 47 | }, 48 | }; 49 | -------------------------------------------------------------------------------- /shop/src/store/Cart.js: -------------------------------------------------------------------------------- 1 | export const CartModule = { 2 | namespaced: true, 3 | strict: true, 4 | state: { 5 | cartProducts: [], 6 | }, 7 | mutations: { 8 | SET_CART_PRODUCTS(state, cartProducts) { 9 | state.cartProducts = cartProducts; 10 | }, 11 | ADD_CART_ITEM(state, newItem) { 12 | state.cartProducts.unshift(newItem); 13 | }, 14 | UPDATE_CART_ITEM_QUANTITY(state, { index, quantity }) { 15 | state.cartProducts[index].quantity = quantity; 16 | }, 17 | REMOVE_CART_ITEM(state, index) { 18 | state.cartProducts.splice(index, 1); 19 | }, 20 | }, 21 | actions: { 22 | clearCart({ commit }) { 23 | commit("SET_CART_PRODUCTS", []); 24 | }, 25 | getCartItem({ state }, productId) { 26 | const index = state.cartProducts.findIndex( 27 | (obj) => obj.productId == productId 28 | ); 29 | return index; 30 | }, 31 | async addToCart({ commit, dispatch }, cartItem) { 32 | const index = await dispatch("getCartItem", cartItem.productId); 33 | if (index == -1) { 34 | commit("ADD_CART_ITEM", cartItem); 35 | return 0; 36 | } 37 | }, 38 | 39 | async updateCartItemQuantity( 40 | { commit, dispatch }, 41 | { productId, quantity } 42 | ) { 43 | const index = await dispatch("getCartItem", productId); 44 | if (index != -1) { 45 | commit("UPDATE_CART_ITEM_QUANTITY", { index, quantity }); 46 | } 47 | }, 48 | 49 | async removeCartItem({ commit, dispatch }, productId) { 50 | const index = await dispatch("getCartItem", productId); 51 | if (index != -1) { 52 | commit("REMOVE_CART_ITEM", index); 53 | return -1; 54 | } 55 | }, 56 | }, 57 | }; 58 | -------------------------------------------------------------------------------- /shop/src/components/Order/OrderDetails.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /shop/src/components/Admins/Order/OrderDetails.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /shop/src/views/Product/SubSubCategoryProducts.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /shop/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "emarket", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@babel/eslint-parser": "^7.21.3", 12 | "@babel/preset-typescript": "^7.27.1", 13 | "@stripe/stripe-js": "^1.52.1", 14 | "autoprefixer": "^10.4.5", 15 | "axios": "^1.4.0", 16 | "bootstrap": "^4.6.1", 17 | "bootstrap-vue": "^2.23.1", 18 | "connect-history-api-fallback": "^2.0.0", 19 | "core-js": "^3.46.0", 20 | "express": "^4.18.2", 21 | "express-sslify": "^1.2.0", 22 | "serve": "^14.2.5", 23 | "serve-static": "^1.15.0", 24 | "strip": "^3.0.0", 25 | "vue": "^2.6.12", 26 | "vue-router": "^3.6.5", 27 | "vue2-editor": "^2.10.3", 28 | "vuex": "^3.6.2", 29 | "vuex-persistedstate": "^4.1.0", 30 | "vuex-router-sync": "^5.0.0" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "^7.22.0", 34 | "@babel/preset-env": "^7.22.0", 35 | "@playwright/test": "^1.56.1", 36 | "@types/node": "^24.8.1", 37 | "@vue/cli-plugin-babel": "^5.0.8", 38 | "@vue/cli-plugin-eslint": "^5.0.8", 39 | "@vue/cli-plugin-router": "^5.0.8", 40 | "@vue/cli-plugin-vuex": "^5.0.8", 41 | "@vue/cli-service": "^5.0.8", 42 | "@vue/eslint-config-prettier": "^7.1.0", 43 | "@vue/runtime-dom": "^3.2.47", 44 | "eslint": "^8.39.0", 45 | "eslint-plugin-prettier": "^4.2.1", 46 | "eslint-plugin-vue": "^9.11.0", 47 | "node-sass": "^8.0.0", 48 | "playwright": "^1.56.1", 49 | "prettier": "^2.8.8", 50 | "sass-loader": "^13.2.2", 51 | "selenium": "^2.20.0", 52 | "selenium-webdriver": "^4.37.0", 53 | "vue-template-compiler": "^2.6.12" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /server/src/controllers/CategoryController.js: -------------------------------------------------------------------------------- 1 | const { Category } = require('../models') 2 | 3 | module.exports = { 4 | async getCategoryByName(req, res) { 5 | try { 6 | const categoryName = req.params.name; 7 | const category = await Category.findOne({ 8 | where: { 9 | name: categoryName 10 | } 11 | }) 12 | res.send(category) 13 | } catch (err) { 14 | res.status(500).send({ 15 | error: 'An error occured when trying to fetch a category.' 16 | }) 17 | } 18 | }, 19 | async getCategoryList(req, res) { 20 | try { 21 | const categories = await Category.findAll() 22 | res.send(categories) 23 | } catch (err) { 24 | res.status(500).send({ 25 | error: 'An error occured when trying to fetch the categories.' 26 | }) 27 | } 28 | }, 29 | async createCategory(req, res) { 30 | try { 31 | const category = await Category.create(req.body) 32 | res.send(category) 33 | } catch (err) { 34 | res.status(500).send({ 35 | error: 'An error occured when trying to create a category.' 36 | }) 37 | } 38 | }, 39 | async updateCategory(req, res) { 40 | try { 41 | await Category.update(req.body, { 42 | where: { 43 | id: req.body.id 44 | } 45 | }) 46 | res.send(req.body) 47 | } catch (err) { 48 | res.status(500).send({ 49 | error: 'An error occured when trying to update a category.' 50 | }) 51 | } 52 | }, 53 | async deleteCategory(req, res) { 54 | try { 55 | const category = await Category.findByPk(req.params.categoryId) 56 | if (!category) { 57 | return res.status(403).send({ 58 | error: 'No category to delete.' 59 | }) 60 | } 61 | await category.destroy() 62 | res.send(category) 63 | 64 | } catch (err) { 65 | res.status(500).send({ 66 | error: 'An error occured when trying to delete a category.' 67 | }) 68 | } 69 | }, 70 | } 71 | -------------------------------------------------------------------------------- /server/seed/reviews.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "rating": 0, 5 | "comment": "this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy.", 6 | "UserId": 1, 7 | "ProductId": 1 8 | }, 9 | { 10 | "id": 2, 11 | "rating": 5, 12 | "comment": "this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy.", 13 | "UserId": 1, 14 | "ProductId": 2 15 | }, 16 | { 17 | "id": 3, 18 | "rating": 4, 19 | "comment": "this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy.", 20 | "UserId": 1, 21 | "ProductId": 3 22 | }, 23 | { 24 | "id": 4, 25 | "rating": 5, 26 | "comment": "this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy.", 27 | "UserId": 4, 28 | "ProductId": 1 29 | }, 30 | { 31 | "id": 5, 32 | "rating": 4, 33 | "comment": "this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy.", 34 | "UserId": 5, 35 | "ProductId": 1 36 | }, 37 | { 38 | "id": 6, 39 | "rating": 0, 40 | "comment": "this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy.", 41 | "UserId": 2, 42 | "ProductId": 1 43 | }, 44 | { 45 | "id": 7, 46 | "rating": 0, 47 | "comment": "this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy.", 48 | "UserId": 3, 49 | "ProductId": 1 50 | }, 51 | { 52 | "id": 8, 53 | "rating": 5, 54 | "comment": "this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy. this was nice in buy.", 55 | "UserId": 3, 56 | "ProductId": 2 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /server/src/controllers/SubCategoryController.js: -------------------------------------------------------------------------------- 1 | const { SubCategory } = require('../models') 2 | 3 | module.exports = { 4 | async getSubCategoryByName(req, res) { 5 | try { 6 | const subCategory = await SubCategory.findOne({ 7 | where: { 8 | name: req.params.name 9 | } 10 | }) 11 | res.send(subCategory) 12 | } catch (err) { 13 | res.status(500).send({ 14 | error: 'An error occured when trying to fetch a sub category.' 15 | }) 16 | } 17 | }, 18 | async getSubCategoryList(req, res) { 19 | try { 20 | const subCategories = await SubCategory.findAll() 21 | res.send(subCategories) 22 | } catch (err) { 23 | res.status(500).send({ 24 | error: 'An error occured when trying to fetch sub categories.' 25 | }) 26 | } 27 | }, 28 | async createSubCategory(req, res) { 29 | try { 30 | const subCategory = await SubCategory.create(req.body) 31 | res.send(subCategory) 32 | } catch (err) { 33 | res.status(500).send({ 34 | error: 'An error occured when trying to create a sub category.' 35 | }) 36 | } 37 | }, 38 | async updateSubCategory(req, res) { 39 | try { 40 | await SubCategory.update(req.body, { 41 | where: { 42 | id: req.body.id 43 | } 44 | }) 45 | res.send(req.body) 46 | } catch (err) { 47 | res.status(500).send({ 48 | error: 'An error occured when trying to update a sub category.' 49 | }) 50 | } 51 | }, 52 | async deleteSubCategory(req, res) { 53 | try { 54 | const subCategory = await SubCategory.findByPk(req.params.subCategoryId) 55 | if (!subCategory) { 56 | return res.status(403).send({ 57 | error: 'No sub category to delete.' 58 | }) 59 | } 60 | await subCategory.destroy() 61 | res.send(subCategory) 62 | 63 | } catch (err) { 64 | res.status(500).send({ 65 | error: 'An error occured when trying to delete a sub category.' 66 | }) 67 | } 68 | }, 69 | } 70 | -------------------------------------------------------------------------------- /shop/src/views/Product/CategoryProducts.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /shop/src/views/Product/SubCategoryProducts.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /shop/src/store/CurrentUser.js: -------------------------------------------------------------------------------- 1 | export const CurrentUserModule = { 2 | namespaced: true, 3 | strict: true, 4 | state: { 5 | token: "", 6 | user: {}, 7 | admin: false, 8 | userId: 0, 9 | newUserEmail: "", 10 | newUserId: 0, 11 | userLoggedIn: false, 12 | }, 13 | mutations: { 14 | SET_TOKEN(state, token) { 15 | state.token = token; 16 | if (token != "") { 17 | state.userLoggedIn = true; 18 | } else { 19 | state.userLoggedIn = false; 20 | } 21 | }, 22 | 23 | SET_USER(state, user) { 24 | state.user = user; 25 | if (Object.keys(user).length != 0) { 26 | state.userId = user.id; 27 | if (user.priority == 1) { 28 | state.admin = true; 29 | } else { 30 | state.admin = false; 31 | } 32 | } else { 33 | state.admin = false; 34 | state.userId = 0; 35 | } 36 | }, 37 | SET_NAME(state, { firstName, lastName }) { 38 | state.user.firstName = firstName; 39 | state.user.lastName = lastName; 40 | }, 41 | SET_USERNAME(state, userName) { 42 | state.user.username = userName; 43 | }, 44 | SET_NEW_USER_ID(state, id) { 45 | state.newUserId = id; 46 | }, 47 | SET_NEW_USER_EMAIL(state, email) { 48 | state.newUserEmail = email; 49 | }, 50 | }, 51 | actions: { 52 | setToken({ commit }, token) { 53 | commit("SET_TOKEN", token); 54 | }, 55 | setUser({ commit }, user) { 56 | commit("SET_USER", user); 57 | }, 58 | setName({ commit }, { firstName, lastName }) { 59 | commit("SET_NAME", { firstName, lastName }); 60 | }, 61 | setUserName({ commit }, userName) { 62 | commit("SET_USERNAME", userName); 63 | }, 64 | setNewUserId({ commit }, id) { 65 | commit("SET_NEW_USER_ID", id); 66 | }, 67 | setNewUserEmail({ commit }, email) { 68 | commit("SET_NEW_USER_EMAIL", email); 69 | }, 70 | }, 71 | }; 72 | -------------------------------------------------------------------------------- /server/src/controllers/SubSubCategoryController.js: -------------------------------------------------------------------------------- 1 | const { SubSubCategory } = require('../models') 2 | 3 | module.exports = { 4 | async getSubSubCategoryByName(req, res) { 5 | try { 6 | const subSubCategory = await SubSubCategory.findOne({ 7 | where: { 8 | name: req.params.name 9 | } 10 | }) 11 | res.send(subSubCategory) 12 | } catch (err) { 13 | res.status(500).send({ 14 | error: 'An error occured when trying to fetch a category.' 15 | }) 16 | } 17 | }, 18 | async getSubSubCategoryList(req, res) { 19 | try { 20 | const subSubCategories = await SubSubCategory.findAll() 21 | res.send(subSubCategories) 22 | } catch (err) { 23 | res.status(500).send({ 24 | error: 'An error occured when trying to fetch sub categories.' 25 | }) 26 | } 27 | }, 28 | async createSubSubCategory(req, res) { 29 | try { 30 | const subSubCategory = await SubSubCategory.create(req.body) 31 | res.send(subSubCategory) 32 | } catch (err) { 33 | res.status(500).send({ 34 | error: 'An error occured when trying to create a sub sub category.' 35 | }) 36 | } 37 | }, 38 | async updateSubSubCategory(req, res) { 39 | try { 40 | await SubSubCategory.update(req.body, { 41 | where: { 42 | id: req.body.id 43 | } 44 | }) 45 | res.send(req.body) 46 | } catch (err) { 47 | res.status(500).send({ 48 | error: 'An error occured when trying to update a sub sub category.' 49 | }) 50 | } 51 | }, 52 | async deleteSubSubCategory(req, res) { 53 | try { 54 | const subSubCategory = await SubSubCategory.findByPk(req.params.subSubCategoryId) 55 | if (!subSubCategory) { 56 | return res.status(403).send({ 57 | error: 'No sub sub category to delete.' 58 | }) 59 | } 60 | await subSubCategory.destroy() 61 | res.send(subSubCategory) 62 | 63 | } catch (err) { 64 | res.status(500).send({ 65 | error: 'An error occured when trying to delete a sub sub category.' 66 | }) 67 | } 68 | }, 69 | } 70 | -------------------------------------------------------------------------------- /shop/src/components/Products/FilterComponent.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /server/src/controllers/ShowcaseController.js: -------------------------------------------------------------------------------- 1 | const { Showcase } = require('../models') 2 | 3 | module.exports = { 4 | async getShowcaseItems(req, res) { 5 | try { 6 | const showcaseItems = await Showcase.findAll({ 7 | order: [ 8 | ['createdAt', 'DESC'] 9 | ] 10 | }) 11 | res.send(showcaseItems) 12 | } catch (err) { 13 | res.status(500).send({ 14 | error: 'An error occured when trying to fetch a showcase items.' 15 | }) 16 | } 17 | }, 18 | async createShowcaseItem(req, res) { 19 | try { 20 | if (req.user.priority == 1) { 21 | const showcase = await Showcase.create(req.body) 22 | res.send(showcase) 23 | } 24 | else { 25 | return res.status(403).send({ 26 | error: "You don't have permission to create a showcase item." 27 | }) 28 | } 29 | } catch (err) { 30 | res.status(500).send({ 31 | error: "An error occured when trying to create a showcase item." 32 | }) 33 | } 34 | }, 35 | async updateShowcaseItem(req, res) { 36 | try { 37 | if (req.user.priority == 1) { 38 | 39 | await Showcase.update(req.body, { 40 | where: { 41 | id: req.body.id 42 | } 43 | }) 44 | } else { 45 | return res.status(403).send({ 46 | error: "You don't have permission to update a showcase item." 47 | }) 48 | } 49 | res.send(req.body) 50 | } catch (err) { 51 | res.status(500).send({ 52 | error: 'An error occured when trying to update a showcase item.' 53 | }) 54 | } 55 | }, 56 | async deleteShowcaseItem(req, res) { 57 | try { 58 | if (req.user.priority == 1) { 59 | await Showcase.destroy({ 60 | where: { 61 | id: req.params.showcaseItemId 62 | } 63 | }) 64 | res.send({ id: req.params.showcaseItemId }) 65 | } else { 66 | return res.status(403).send({ 67 | error: "You don't have permission to do delete a showcase item." 68 | }) 69 | } 70 | } catch (err) { 71 | res.status(500).send({ 72 | error: 'An error occured when trying to delete a category.' 73 | }) 74 | } 75 | }, 76 | } 77 | -------------------------------------------------------------------------------- /server/seed/index.js: -------------------------------------------------------------------------------- 1 | const { sequelize, Company, User, Showcase, Category, SubCategory, SubSubCategory, Order, OrderItem, Product, Review, Wishlist } = require('../src/models') 2 | 3 | const Promise = require('bluebird') 4 | const companies = require('./companies.json') 5 | const users = require('./users.json') 6 | const showcases = require('./showcases.json') 7 | const categories = require('./categories.json') 8 | const orders = require('./orders.json') 9 | const orderItems = require('./orderItems.json') 10 | const subCategories = require('./subCategories.json') 11 | const subSubCategories = require('./subSubCategories.json') 12 | const products = require('./products.json') 13 | const reviews = require('./reviews.json') 14 | const wishlists = require('./wishlists.json') 15 | 16 | sequelize.sync({ force: true }) 17 | .then(async () => { 18 | await Promise.all( 19 | companies.map(company => { 20 | Company.create(company) 21 | }) 22 | ) 23 | await Promise.all( 24 | users.map(user => { 25 | User.create(user) 26 | }) 27 | ) 28 | await Promise.all( 29 | showcases.map(showcase => { 30 | Showcase.create(showcase) 31 | }) 32 | ) 33 | await Promise.all( 34 | categories.map(category => { 35 | Category.create(category) 36 | }) 37 | ) 38 | await Promise.all( 39 | subCategories.map(subCategory => { 40 | SubCategory.create(subCategory) 41 | }) 42 | ) 43 | await Promise.all( 44 | subSubCategories.map(subSubCategory => { 45 | SubSubCategory.create(subSubCategory) 46 | }) 47 | ) 48 | await Promise.all( 49 | products.map(product => { 50 | Product.create(product) 51 | }) 52 | ) 53 | await Promise.all( 54 | reviews.map(review => { 55 | Review.create(review) 56 | }) 57 | ) 58 | await Promise.all( 59 | orders.map(order => { 60 | Order.create(order) 61 | }) 62 | ) 63 | await Promise.all( 64 | orderItems.map(orderItem => { 65 | OrderItem.create(orderItem) 66 | }) 67 | ) 68 | await Promise.all( 69 | wishlists.map(wishlistItem => { 70 | Wishlist.create(wishlistItem) 71 | }) 72 | ) 73 | }) 74 | 75 | -------------------------------------------------------------------------------- /server/seed/showcases.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "type": "carousel", 5 | "caption": "A New Online Shop Experience.", 6 | "image": "http://localhost:8081/public/display-images/home_slider_1.jpg", 7 | "routerLink": "/products/Electronics", 8 | "priority": 1, 9 | "CompanyId": 1 10 | }, 11 | { 12 | "id": 2, 13 | "type": "carousel", 14 | "caption": "", 15 | "image": "http://localhost:8081/public/display-images/home_slider_0.jpg", 16 | "routerLink": "/products/Electronics", 17 | "priority": 1, 18 | "CompanyId": 1 19 | }, 20 | { 21 | "id": 3, 22 | "type": "card", 23 | "caption": "", 24 | "image": "http://localhost:8081/public/display-images/mac-mini.png", 25 | "routerLink": "/products/Electronics", 26 | "priority": 1, 27 | "CompanyId": 1 28 | }, 29 | { 30 | "id": 4, 31 | "type": "card", 32 | "caption": "", 33 | "image": "http://localhost:8081/public/display-images/ipad-2020.jpeg", 34 | "routerLink": "/products/Electronics", 35 | "priority": 1, 36 | "CompanyId": 1 37 | }, 38 | { 39 | "id": 5, 40 | "type": "card", 41 | "caption": "", 42 | "image": "http://localhost:8081/public/display-images/razer-opus.jpeg", 43 | "routerLink": "/products/Electronics", 44 | "priority": 1, 45 | "CompanyId": 1 46 | }, 47 | { 48 | "id": 6, 49 | "type": "card", 50 | "caption": "", 51 | "image": "http://localhost:8081/public/display-images/p120.jpeg", 52 | "routerLink": "/products/Electronics", 53 | "priority": 1, 54 | "CompanyId": 1 55 | }, 56 | { 57 | "id": 7, 58 | "type": "big card", 59 | "caption": "", 60 | "image": "http://localhost:8081/public/display-images/smart-watches.jpeg", 61 | "routerLink": "/products/Electronics", 62 | "priority": 1, 63 | "CompanyId": 1 64 | }, 65 | { 66 | "id": 8, 67 | "type": "big card", 68 | "caption": "", 69 | "image": "http://localhost:8081/public/display-images/lenovo-yoga.jpeg", 70 | "routerLink": "/products/Electronics", 71 | "priority": 1, 72 | "CompanyId": 1 73 | } 74 | ] 75 | -------------------------------------------------------------------------------- /shop/src/components/Order/OrderItems.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /server/seed/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "email": "admin@gmail.com", 5 | "username": "admin", 6 | "firstName": "Md.", 7 | "lastName": "Rony", 8 | "phoneNo": "+8801700100000", 9 | "password": "12345678", 10 | "registerToken": "", 11 | "resetPasswordToken": "", 12 | "profileImage": "http://localhost:8081/public/user-image/default-man.png", 13 | "userType": "Admin", 14 | "variant": "dark", 15 | "CompanyId": 1, 16 | "priority": 1 17 | }, 18 | { 19 | "id": 2, 20 | "email": "rony@gmail.com", 21 | "username": "ronyku", 22 | "firstName": "Md.", 23 | "lastName": "Rony", 24 | "phoneNo": "+8801700100001", 25 | "password": "12345678", 26 | "registerToken": "", 27 | "resetPasswordToken": "", 28 | "profileImage": "http://localhost:8081/public/user-image/default-man.png", 29 | "userType": "Customer", 30 | "variant": "warning", 31 | "CompanyId": 1, 32 | "priority": 2 33 | }, 34 | { 35 | "id": 3, 36 | "email": "hossain@gmail.com", 37 | "username": "hossain", 38 | "firstName": "Md.", 39 | "lastName": "Hossain", 40 | "phoneNo": "+8801700100002", 41 | "password": "12345678", 42 | "registerToken": "", 43 | "resetPasswordToken": "", 44 | "profileImage": "http://localhost:8081/public/user-image/default-man.png", 45 | "userType": "Customer", 46 | "variant": "warning", 47 | "CompanyId": 1, 48 | "priority": 2 49 | }, 50 | { 51 | "id": 4, 52 | "email": "sahin@gmail.com", 53 | "username": "sahin255", 54 | "firstName": "Sheikh", 55 | "lastName": "Sahin", 56 | "phoneNo": "+8801700100003", 57 | "password": "12345678", 58 | "registerToken": "", 59 | "resetPasswordToken": "", 60 | "profileImage": "http://localhost:8081/public/user-image/default-man.png", 61 | "userType": "Customer", 62 | "variant": "warning", 63 | "CompanyId": 1, 64 | "priority": 2 65 | }, 66 | { 67 | "id": 5, 68 | "email": "asad@gmail.com", 69 | "username": "asad", 70 | "firstName": "Md.", 71 | "lastName": "Asad", 72 | "phoneNo": "+8801700100004", 73 | "password": "12345678", 74 | "registerToken": "", 75 | "resetPasswordToken": "", 76 | "profileImage": "http://localhost:8081/public/user-image/default-man.png", 77 | "userType": "Customer", 78 | "variant": "warning", 79 | "CompanyId": 1, 80 | "priority": 2 81 | } 82 | ] 83 | -------------------------------------------------------------------------------- /shop/src/views/BuyProduct/ViewOrder.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /shop/src/views/Admin/AOrder.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /shop/src/components/Admins/ATopHeader.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /shop/src/components/User/ReqPassToken.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /server/src/controllers/ReviewController.js: -------------------------------------------------------------------------------- 1 | const { Product, Review, User } = require('../models') 2 | 3 | 4 | module.exports = { 5 | async getReviewList(req, res) { 6 | try { 7 | const productId = req.params.productId 8 | const reviews = await Review.findAll({ 9 | where: { 10 | ProductId: productId 11 | }, 12 | include: [{ 13 | model: User, 14 | attributes: [ 15 | 'profileImage', 16 | 'firstName', 17 | 'lastName' 18 | ] 19 | }, { 20 | model: Product, 21 | attributes: [ 22 | 'rating', 23 | 'peopleRated' 24 | ] 25 | }], 26 | order: [ 27 | ['createdAt', 'DESC'] 28 | ] 29 | }) 30 | res.send(reviews) 31 | } catch (err) { 32 | res.status(500).send({ 33 | error: 'An error occured when trying to fetch the reviews.' 34 | }) 35 | } 36 | }, 37 | async getUsersReviewList(req, res) { 38 | try { 39 | const reviewList = await Review.findAll({ 40 | where: { 41 | UserId: req.params.userId 42 | }, 43 | include: { 44 | model: Product, 45 | attributes: [ 46 | "title", 47 | "rating", 48 | "peopleRated", 49 | "image1" 50 | ] 51 | } 52 | }) 53 | res.send(reviewList); 54 | } catch (error) { 55 | res.status(500).send({ 56 | error: "An error occured when trying to fetch users review list." 57 | }) 58 | } 59 | }, 60 | async createReview(req, res) { 61 | try { 62 | const review = { rating: parseInt(req.body.rating), comment: req.body.comment, UserId: req.user.id, ProductId: req.body.productId } 63 | const updatedReview = await Review.create(review) 64 | res.send(updatedReview) 65 | } catch (err) { 66 | res.status(500).send({ 67 | error: 'An error occured when trying to create a review.' 68 | }) 69 | } 70 | }, 71 | async updateReview(req, res) { 72 | try { 73 | const review = { rating: parseInt(req.body.rating), comment: req.body.comment, UserId: req.user.id, ProductId: req.body.productId } 74 | await Review.update(review, { 75 | where: { 76 | id: req.body.id 77 | } 78 | }) 79 | res.send(review) 80 | } catch (err) { 81 | res.status(500).send({ 82 | error: 'An error occured when trying to update a review.' 83 | }) 84 | } 85 | }, 86 | async deleteReview(req, res) { 87 | try { 88 | const review = await Review.findByPk(req.params.reviewId) 89 | 90 | if (!review) { 91 | return res.status(403).send({ 92 | error: 'No review to delete.' 93 | }) 94 | } 95 | await review.destroy() 96 | res.send(review) 97 | 98 | } catch (err) { 99 | res.status(500).send({ 100 | error: 'An error occured when trying to delete a review.' 101 | }) 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /shop/src/store/Wishlist.js: -------------------------------------------------------------------------------- 1 | import WishlistService from "@/services/WishlistService.js"; 2 | export const WishlistModule = { 3 | namespaced: true, 4 | strict: true, 5 | state: { 6 | dataLoaded: false, 7 | wishlist: [], 8 | }, 9 | mutations: { 10 | SET_WISHLIST(state, wishlist) { 11 | state.wishlist = wishlist; 12 | }, 13 | ADD_WISHLIST_ITEM(state, wishlistItem) { 14 | state.wishlist.unshift(wishlistItem); 15 | }, 16 | REMOVE_WISHLIST_ITEM(state, index) { 17 | state.wishlist.splice(index, 1); 18 | }, 19 | SET_DATA_LOADED(state, dataLoaded) { 20 | state.dataLoaded = dataLoaded; 21 | }, 22 | }, 23 | actions: { 24 | async clearWishlist({ commit }) { 25 | commit("SET_WISHLIST", []); 26 | commit("SET_DATA_LOADED", false); 27 | }, 28 | async setWishlist({ state, commit }) { 29 | if (!state.dataLoaded) { 30 | try { 31 | const wishlist = (await WishlistService.getWishlist()).data; 32 | commit("SET_WISHLIST", wishlist); 33 | commit("SET_DATA_LOADED", true); 34 | } catch (error) { 35 | console.log(error.response.data.error); 36 | } 37 | } 38 | }, 39 | async getWishlist({ state, dispatch }) { 40 | if (!state.dataLoaded && state.wishlist.length == 0) { 41 | await dispatch("setWishlist"); 42 | } 43 | return state.wishlist; 44 | }, 45 | async getWishlistItem({ dispatch }, productId) { 46 | const wishlist = await dispatch("getWishlist"); 47 | const index = wishlist.findIndex((obj) => obj.ProductId == productId); 48 | return index; 49 | }, 50 | async addToWishlist({ commit, dispatch }, productId) { 51 | const index = await dispatch("getWishlistItem", productId); 52 | if (index == -1) { 53 | try { 54 | await WishlistService.createWishlistItem({ 55 | productId: productId, 56 | }); 57 | } catch (error) { 58 | console.log(error.response.data.error); 59 | } 60 | try { 61 | const wishlistItem = ( 62 | await WishlistService.getWishlistItem(productId) 63 | ).data; 64 | commit("ADD_WISHLIST_ITEM", wishlistItem); 65 | return 0; 66 | } catch (error) { 67 | console.log(error.response.data.error); 68 | } 69 | } 70 | }, 71 | async removeWishlistItem({ commit, dispatch }, productId) { 72 | const index = await dispatch("getWishlistItem", productId); 73 | if (index != -1) { 74 | try { 75 | await WishlistService.removeWishlistItem(productId); 76 | commit("REMOVE_WISHLIST_ITEM", index); 77 | return -1; 78 | } catch (error) { 79 | console.log(error.response.data.error); 80 | } 81 | } 82 | }, 83 | }, 84 | }; 85 | -------------------------------------------------------------------------------- /shop/src/components/MaintainProduct/AddToCart.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 105 | 106 | -------------------------------------------------------------------------------- /shop/src/components/Home/Showcase.vue: -------------------------------------------------------------------------------- 1 | 53 | 54 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /server/src/controllers/WishlistController.js: -------------------------------------------------------------------------------- 1 | const { Wishlist, Product } = require("../models"); 2 | 3 | module.exports = { 4 | async getWishlist(req, res) { 5 | try { 6 | const wishlist = await Wishlist.findAll({ 7 | where: { 8 | UserId: req.user.id, 9 | }, 10 | include: { 11 | model: Product, 12 | attributes: ["id", "title", "image1", "rating", "amount", "currency"], 13 | }, 14 | }); 15 | res.send(wishlist); 16 | } catch (err) { 17 | res.status(500).send({ 18 | error: "An error occured when trying to fetch all wishlist item.", 19 | }); 20 | } 21 | }, 22 | async getWishlistItem(req, res) { 23 | try { 24 | const wishlistItem = await Wishlist.findOne({ 25 | where: { 26 | UserId: req.user.id, 27 | ProductId: req.params.productId, 28 | }, 29 | include: { 30 | model: Product, 31 | attributes: ["id", "title", "image1", "rating", "amount", "currency"], 32 | }, 33 | }); 34 | res.send(wishlistItem); 35 | } catch (err) { 36 | res.status(500).send({ 37 | error: "An error occured when trying to fetch wishlist item.", 38 | }); 39 | } 40 | }, 41 | async createWishlistItem(req, res) { 42 | try { 43 | const wishlistItem = await Wishlist.create({ 44 | UserId: req.user.id, 45 | ProductId: req.body.productId, 46 | }); 47 | res.send(wishlistItem); 48 | } catch (err) { 49 | res.status(500).send({ 50 | error: "An error occured when trying to add wishlist item.", 51 | }); 52 | } 53 | }, 54 | async removeWishlistItem(req, res) { 55 | try { 56 | const wishlistItem = await Wishlist.findOne({ 57 | where: { 58 | UserId: req.user.id, 59 | ProductId: req.params.productId, 60 | }, 61 | }); 62 | if (!wishlistItem) { 63 | return res.status(403).send({ 64 | error: "No item to remove.", 65 | }); 66 | } 67 | await wishlistItem.destroy(); 68 | res.send(wishlistItem); 69 | } catch (err) { 70 | res.status(500).send({ 71 | error: "An error occured when trying to remove a wishlist item.", 72 | }); 73 | } 74 | }, 75 | async deleteWishItemByProduct(req, res) { 76 | try { 77 | if (req.user && req.user.priority == 1) { 78 | await Wishlist.destroy({ 79 | where: { 80 | ProductId: req.params.productId, 81 | }, 82 | }); 83 | res.send({ productId: req.body.productId }); 84 | } else { 85 | return res.status(403).send({ 86 | error: "You don't have permits to do that.", 87 | }); 88 | } 89 | } catch (err) { 90 | res.status(500).send({ 91 | error: 92 | "An error occured when trying to delete wishlist item by product.", 93 | }); 94 | } 95 | }, 96 | }; 97 | -------------------------------------------------------------------------------- /server/seed/subSubCategories.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Samsung", 5 | "SubCategoryId": 1 6 | }, 7 | { 8 | "id": 2, 9 | "name": "Xiaomi", 10 | "SubCategoryId": 1 11 | }, 12 | { 13 | "id": 3, 14 | "name": "Realme", 15 | "SubCategoryId": 1 16 | }, 17 | { 18 | "id": 4, 19 | "name": "Nokia", 20 | "SubCategoryId": 1 21 | }, 22 | { 23 | "id": 5, 24 | "name": "Huawei", 25 | "SubCategoryId": 1 26 | }, 27 | { 28 | "id": 6, 29 | "name": "oppo", 30 | "SubCategoryId": 1 31 | }, 32 | { 33 | "id": 7, 34 | "name": "Apple", 35 | "SubCategoryId": 1 36 | }, 37 | { 38 | "id": 8, 39 | "name": "Vivo", 40 | "SubCategoryId": 1 41 | }, 42 | { 43 | "id": 9, 44 | "name": "Pixel", 45 | "SubCategoryId": 1 46 | }, 47 | { 48 | "id": 10, 49 | "name": "Walton", 50 | "SubCategoryId": 1 51 | }, 52 | { 53 | "id": 11, 54 | "name": "LG", 55 | "SubCategoryId": 1 56 | }, 57 | { 58 | "id": 12, 59 | "name": "Mobile Charger", 60 | "SubCategoryId": 2 61 | }, 62 | { 63 | "id": 13, 64 | "name": "Mobile Cover", 65 | "SubCategoryId": 2 66 | }, 67 | { 68 | "id": 14, 69 | "name": "Power Bank", 70 | "SubCategoryId": 2 71 | }, 72 | { 73 | "id": 15, 74 | "name": "Memory Card", 75 | "SubCategoryId": 2 76 | }, 77 | { 78 | "id": 16, 79 | "name": "Data Cable", 80 | "SubCategoryId": 2 81 | }, 82 | { 83 | "id": 17, 84 | "name": "Screenguard", 85 | "SubCategoryId": 2 86 | }, 87 | { 88 | "id": 18, 89 | "name": "Headphones", 90 | "SubCategoryId": 2 91 | }, 92 | { 93 | "id": 19, 94 | "name": "External Hard Disk", 95 | "SubCategoryId": 3 96 | }, 97 | { 98 | "id": 20, 99 | "name": "Pendrive", 100 | "SubCategoryId": 3 101 | }, 102 | { 103 | "id": 21, 104 | "name": "Laptop Skins", 105 | "SubCategoryId": 3 106 | }, 107 | { 108 | "id": 22, 109 | "name": "Laptop Bags", 110 | "SubCategoryId": 3 111 | }, 112 | { 113 | "id": 23, 114 | "name": "Mouse", 115 | "SubCategoryId": 3 116 | }, 117 | { 118 | "id": 24, 119 | "name": "Keyboard", 120 | "SubCategoryId": 3 121 | }, 122 | { 123 | "id": 25, 124 | "name": "Samsung", 125 | "SubCategoryId": 4 126 | }, 127 | { 128 | "id": 26, 129 | "name": "LG", 130 | "SubCategoryId": 4 131 | }, 132 | { 133 | "id": 27, 134 | "name": "Sony", 135 | "SubCategoryId": 4 136 | }, 137 | { 138 | "id": 28, 139 | "name": "Micromax", 140 | "SubCategoryId": 4 141 | }, 142 | { 143 | "id": 29, 144 | "name": "Mi", 145 | "SubCategoryId": 4 146 | }, 147 | { 148 | "id": 30, 149 | "name": "Thomson", 150 | "SubCategoryId": 4 151 | }, 152 | { 153 | "id": 31, 154 | "name": "Fully Automatic Front", 155 | "SubCategoryId": 5 156 | }, 157 | { 158 | "id": 32, 159 | "name": "Semi Automatic Top", 160 | "SubCategoryId": 5 161 | }, 162 | { 163 | "id": 33, 164 | "name": "Fully Automatic Top", 165 | "SubCategoryId": 5 166 | } 167 | ] 168 | -------------------------------------------------------------------------------- /server/src/controllers/OrderController.js: -------------------------------------------------------------------------------- 1 | const { Order } = require('../models') 2 | const nodemailer = require('nodemailer') 3 | 4 | let emailFrom = `Emarket <${process.env.EMARKET_EMAIL}>` 5 | 6 | module.exports = { 7 | async getOrderList(req, res) { 8 | try { 9 | const orderList = await Order.findAll({ 10 | order: [['createdAt', 'DESC']] 11 | }); 12 | res.send(orderList) 13 | } catch (err) { 14 | res.status(500).send({ 15 | error: 'An error occured when trying to fetch order list.' 16 | }) 17 | } 18 | }, 19 | async getOrder(req, res) { 20 | try { 21 | const order = await Order.findByPk(req.params.orderId) 22 | res.send(order) 23 | } catch (err) { 24 | res.status(500).send({ 25 | error: 'An error occured when trying to fetch an order.' 26 | }) 27 | } 28 | }, 29 | async getOrderBySessionId(req, res) { 30 | try { 31 | const order = await Order.findOne({ 32 | where: { 33 | checkoutSessionId: req.params.sessionId 34 | } 35 | }) 36 | res.send(order) 37 | } catch (err) { 38 | res.status(500).send({ 39 | error: 'An error occured when trying to fetch an order.' 40 | }) 41 | } 42 | }, 43 | async createOrder(req, res) { 44 | try { 45 | const order = await Order.create(req.body) 46 | var transporter = await nodemailer.createTransport({ 47 | service: 'gmail', 48 | auth: { 49 | user: process.env.EMARKET_EMAIL, 50 | pass: process.env.EMARKET_PASSWORD, 51 | }, 52 | tls: { 53 | rejectUnauthorized: false 54 | } 55 | }) 56 | var mailOptions = { 57 | from: emailFrom, 58 | to: order.email, 59 | subject: "Check Order Status", 60 | text: 'Hi ' + order.name + ',\n\n' + 61 | 'Thanks for your purchase!\n\n' + 62 | 'Please follow the link to keep track on your order.\n\n' + 63 | 'http://' + 'localhost:8080' + '/order/' + order.checkoutSessionId + '\n\n' + 64 | 'Your session Id: ' + order.checkoutSessionId + '\n\n' + 65 | 'Thanks for using emarket\n' 66 | } 67 | await transporter.sendMail(mailOptions, function (err) { 68 | if (err) { 69 | return res.status(403).send({ 70 | error: "An error occured when trying to send an email to register." 71 | }); 72 | } 73 | }); 74 | res.send(order) 75 | } catch (err) { 76 | res.status(500).send({ 77 | error: 'An error occured when trying to create an order.' 78 | }) 79 | } 80 | }, 81 | async updateOrder(req, res) { 82 | try { 83 | await Order.update(req.body, { 84 | where: { 85 | id: req.body.id 86 | } 87 | }) 88 | res.send(req.body) 89 | } catch (err) { 90 | res.status(500).send({ 91 | error: 'An error occured when trying to update an order.' 92 | }) 93 | } 94 | }, 95 | async deleteOrder(req, res) { 96 | try { 97 | const order = await Order.findByPk(req.params.orderId) 98 | if (!order) { 99 | return res.status(403).send({ 100 | error: 'No order to delete.' 101 | }) 102 | } 103 | await order.destroy() 104 | res.send(order) 105 | } catch (err) { 106 | res.status(500).send({ 107 | error: 'An error occured when trying to delete an order.' 108 | }) 109 | } 110 | }, 111 | } 112 | -------------------------------------------------------------------------------- /shop/src/components/User/Profile/UReviews.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /server/src/policies/AuthenticationControllerPolicy.js: -------------------------------------------------------------------------------- 1 | const Joi = require('joi') 2 | 3 | module.exports = { 4 | register(req, res, next) { 5 | const schema = Joi.object({ 6 | username: Joi.string().regex(new RegExp('^[a-zA-Z0-9]{4,16}$')), 7 | firstName: Joi.string().regex(new RegExp('^.{2,32}$')), 8 | lastName: Joi.string().regex(new RegExp('^.{2,32}$')), 9 | email: Joi.string().email(), 10 | password: Joi.string().regex(new RegExp('^[a-zA-Z0-9]{8,32}$')), 11 | CompanyId: Joi.number().integer().min(1).max(1) 12 | }) 13 | 14 | const validate = schema.validate(req.body) 15 | if (validate.error) { 16 | switch (validate.error.details[0].context.key) { 17 | case 'username': 18 | res.status(400).send({ 19 | error: 'Username can have 4-16 characters. Only lower case, upper case and numerics is allowed.' 20 | }) 21 | break 22 | case 'firstName': 23 | res.status(400).send({ 24 | error: 'First name can have 2-32 characters' 25 | }) 26 | break 27 | case 'lastName': 28 | res.status(400).send({ 29 | error: 'Last name can have 2-32 characters' 30 | }) 31 | break 32 | case 'email': 33 | res.status(400).send({ 34 | error: 'please provide a valid email address' 35 | }) 36 | break 37 | case 'password': 38 | res.status(400).send({ 39 | error: 'password can have 8-32 characters. Only lower case, upper case and numerics is allowed.' 40 | }) 41 | break 42 | case 'CompanyId': 43 | res.status(400).send({ 44 | error: 'Please provide a valid company' 45 | }) 46 | break 47 | default: 48 | res.status(400).send({ 49 | error: 'Invalid error in authentication controller.' 50 | }) 51 | } 52 | } else { 53 | next() 54 | } 55 | }, 56 | updatePassword(req, res, next) { 57 | const schema = Joi.object({ 58 | password: Joi.string().regex( 59 | new RegExp('^[a-zA-z0-9]{8,32}$') 60 | ), 61 | }) 62 | const validate = schema.validate(req.body) 63 | if (validate.error) { 64 | switch (validate.error.details[0].context.key) { 65 | case "password": 66 | res.status(400).send({ 67 | error: 'Invalid password format. Only lower case, upper case and numerics is allowed.' 68 | }) 69 | break; 70 | default: 71 | res.status(400).send({ 72 | error: 'Invalid error in authentication controller.' 73 | }) 74 | } 75 | } else { 76 | next() 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /shop/src/components/MaintainProduct/AddToWishlist.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /shop/src/components/Home/Support.vue: -------------------------------------------------------------------------------- 1 | 87 | 88 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /shop/src/store/Category.js: -------------------------------------------------------------------------------- 1 | import CategoryService from "@/services/CategoryService.js"; 2 | import SubCategoryService from "@/services/SubCategoryService.js"; 3 | import SubSubCategoryService from "@/services/SubSubCategoryService.js"; 4 | export const CategoryModule = { 5 | namespaced: true, 6 | strict: true, 7 | state: { 8 | categoryList: [], 9 | subCategoryList: [], 10 | subSubCategoryList: [], 11 | }, 12 | mutations: { 13 | SET_CATEGORY_LIST(state, categoryList) { 14 | state.categoryList = categoryList; 15 | }, 16 | SET_SUB_CATEGORY_LIST(state, subCategoryList) { 17 | state.subCategoryList = subCategoryList; 18 | }, 19 | SET_SUB_SUB_CATEGORY_LIST(state, subSubCategoryList) { 20 | state.subSubCategoryList = subSubCategoryList; 21 | }, 22 | }, 23 | actions: { 24 | async setCategoryList({ commit }) { 25 | try { 26 | const categoryList = (await CategoryService.getCategoryList()).data; 27 | commit("SET_CATEGORY_LIST", categoryList); 28 | } catch (error) { 29 | console.log(error.response.data.error); 30 | } 31 | }, 32 | 33 | async setSubCategoryList({ commit }) { 34 | try { 35 | const subCategoryList = (await SubCategoryService.getSubCategoryList()) 36 | .data; 37 | commit("SET_SUB_CATEGORY_LIST", subCategoryList); 38 | } catch (error) { 39 | console.log(error.response.data.error); 40 | } 41 | }, 42 | 43 | async setSubSubCategoryList({ commit }) { 44 | try { 45 | const subSubCategoryList = ( 46 | await SubSubCategoryService.getSubSubCategoryList() 47 | ).data; 48 | commit("SET_SUB_SUB_CATEGORY_LIST", subSubCategoryList); 49 | } catch (error) { 50 | console.log(error.response.data.error); 51 | } 52 | }, 53 | async getCategoryList({ state, dispatch }) { 54 | if (state.categoryList && state.categoryList.length == 0) { 55 | await dispatch("setCategoryList"); 56 | } 57 | return state.categoryList; 58 | }, 59 | async getSubCategoryList({ state, dispatch }) { 60 | if (state.subCategoryList && state.subCategoryList.length == 0) { 61 | await dispatch("setSubCategoryList"); 62 | } 63 | return state.subCategoryList; 64 | }, 65 | async getSubSubCategoryList({ state, dispatch }) { 66 | if (state.subSubCategoryList && state.subSubCategoryList.length == 0) { 67 | await dispatch("setSubSubCategoryList"); 68 | } 69 | return state.subSubCategoryList; 70 | }, 71 | async getCategoryName({ state, dispatch }, categoryId) { 72 | const categoryList = await dispatch("getCategoryList"); 73 | const index = categoryList.findIndex((obj) => obj.id == categoryId); 74 | return state.categoryList[index].name; 75 | }, 76 | async getSubCategoryName({ state, dispatch }, subCategoryId) { 77 | const subCategoryList = await dispatch("getSubCategoryList"); 78 | const index = subCategoryList.findIndex((obj) => obj.id == subCategoryId); 79 | return state.subCategoryList[index].name; 80 | }, 81 | async getSubSubCategoryName({ state, dispatch }, subSubCategoryId) { 82 | const subSubCategoryList = await dispatch("getSubSubCategoryList"); 83 | const index = subSubCategoryList.findIndex( 84 | (obj) => obj.id == subSubCategoryId 85 | ); 86 | return state.subSubCategoryList[index].name; 87 | }, 88 | }, 89 | }; 90 | -------------------------------------------------------------------------------- /shop/src/components/ProductDetails/Recommendation.vue: -------------------------------------------------------------------------------- 1 | 64 | 65 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /shop/src/components/Home/TopSellProduct.vue: -------------------------------------------------------------------------------- 1 | 64 | 65 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /shop/src/components/Home/NewAddProduct.vue: -------------------------------------------------------------------------------- 1 | 66 | 67 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /shop/src/store/Review.js: -------------------------------------------------------------------------------- 1 | import ProductsService from "@/services/ProductsService.js"; 2 | import ReviewService from "@/services/ReviewService.js"; 3 | export const ReviewModule = { 4 | namespaced: true, 5 | strict: true, 6 | mutations: { 7 | DO_SOMETHING() { 8 | return; 9 | }, 10 | }, 11 | actions: { 12 | async createReview( 13 | { commit }, 14 | { rating, comment, productId, productRating } 15 | ) { 16 | commit("DO_SOMETHING"); 17 | try { 18 | await ReviewService.createReview({ 19 | rating: rating, 20 | comment: comment, 21 | productId: productId, 22 | }); 23 | } catch (error) { 24 | console.log(error.response.data.error); 25 | } 26 | if (rating != 0) { 27 | const newRating = 28 | (productRating.peopleRated * productRating.rating + rating) / 29 | (productRating.peopleRated + 1); 30 | try { 31 | await ProductsService.updateProduct({ 32 | id: productId, 33 | rating: newRating, 34 | peopleRated: productRating.peopleRated + 1, 35 | }); 36 | } catch (error) { 37 | console.log(error.response.data.error); 38 | } 39 | } 40 | }, 41 | async updateReview({ commit }, { review, newRating, newComment }) { 42 | commit("DO_SOMETHING"); 43 | try { 44 | await ReviewService.updateReview({ 45 | id: review.id, 46 | rating: newRating, 47 | comment: newComment, 48 | productId: review.ProductId, 49 | }); 50 | } catch (error) { 51 | console.log(error.response.data.error); 52 | } 53 | if (newRating != 0 && newRating != review.rating) { 54 | var newRatingProduct, peopleRated; 55 | if (review.rating == 0) { 56 | peopleRated = review.Product.peopleRated + 1; 57 | newRatingProduct = 58 | (review.Product.peopleRated * review.Product.rating + newRating) / 59 | peopleRated; 60 | } else { 61 | peopleRated = review.Product.peopleRated; 62 | newRatingProduct = 63 | (review.Product.peopleRated * review.Product.rating + 64 | newRating - 65 | review.rating) / 66 | peopleRated; 67 | } 68 | try { 69 | await ProductsService.updateProduct({ 70 | id: review.ProductId, 71 | rating: newRatingProduct, 72 | peopleRated: peopleRated, 73 | }); 74 | } catch (error) { 75 | console.log(error.response.data.error); 76 | } 77 | } 78 | }, 79 | async deleteReview({ commit }, review) { 80 | commit("DO_SOMETHING"); 81 | try { 82 | await ReviewService.deleteReview(review.id); 83 | } catch (error) { 84 | console.log(error.response.data.error); 85 | } 86 | if (review.rating != 0) { 87 | var newRatingProduct; 88 | if (review.Product.peopleRated == 1) { 89 | newRatingProduct = 0; 90 | } else { 91 | newRatingProduct = 92 | (review.Product.peopleRated * review.Product.rating - 93 | review.rating) / 94 | (review.Product.peopleRated - 1); 95 | } 96 | try { 97 | await ProductsService.updateProduct({ 98 | id: review.ProductId, 99 | rating: newRatingProduct, 100 | peopleRated: review.Product.peopleRated - 1, 101 | }); 102 | } catch (error) { 103 | console.log(error.response.data.error); 104 | } 105 | } 106 | }, 107 | }, 108 | }; 109 | -------------------------------------------------------------------------------- /shop/src/components/ProductDetails/ProductHeader.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /server/tests/factories/testDataFactory.js: -------------------------------------------------------------------------------- 1 | // Test data factory for creating consistent test data 2 | 3 | const createUser = (overrides = {}) => ({ 4 | username: 'testuser', 5 | firstName: 'Test', 6 | lastName: 'User', 7 | email: 'test@example.com', 8 | password: 'password123', 9 | userType: 'Customer', 10 | variant: 'warning', 11 | priority: 2, 12 | CompanyId: 1, 13 | profileImage: 'http://localhost:8081/public/user-image/default-man.png', 14 | ...overrides 15 | }); 16 | 17 | const createAdminUser = (overrides = {}) => createUser({ 18 | username: 'adminuser', 19 | firstName: 'Admin', 20 | lastName: 'User', 21 | email: 'admin@example.com', 22 | userType: 'Admin', 23 | variant: 'dark', 24 | priority: 1, 25 | ...overrides 26 | }); 27 | 28 | const createCategory = (overrides = {}) => ({ 29 | name: 'Electronics', 30 | description: 'Electronic products', 31 | ...overrides 32 | }); 33 | 34 | const createSubCategory = (categoryId, overrides = {}) => ({ 35 | name: 'Mobiles', 36 | description: 'Mobile phones', 37 | CategoryId: categoryId, 38 | ...overrides 39 | }); 40 | 41 | const createSubSubCategory = (subCategoryId, overrides = {}) => ({ 42 | name: 'Smartphones', 43 | description: 'Smart mobile phones', 44 | SubCategoryId: subCategoryId, 45 | ...overrides 46 | }); 47 | 48 | const createProduct = (categoryId, subCategoryId, subSubCategoryId, overrides = {}) => ({ 49 | title: 'Test Product', 50 | description: 'A test product for testing', 51 | amount: 99.99, 52 | currency: 'USD', 53 | rating: 4.5, 54 | sales: 0, 55 | image1: 'test-image.jpg', 56 | CategoryId: categoryId, 57 | SubCategoryId: subCategoryId, 58 | SubSubCategoryId: subSubCategoryId, 59 | ...overrides 60 | }); 61 | 62 | const createOrder = (userId, overrides = {}) => ({ 63 | UserId: userId, 64 | totalAmount: 199.98, 65 | status: 'pending', 66 | shippingAddress: '123 Test St, Test City, TC 12345', 67 | ...overrides 68 | }); 69 | 70 | const createOrderItem = (orderId, productId, overrides = {}) => ({ 71 | OrderId: orderId, 72 | ProductId: productId, 73 | quantity: 1, 74 | price: 99.99, 75 | ...overrides 76 | }); 77 | 78 | const createReview = (userId, productId, overrides = {}) => ({ 79 | UserId: userId, 80 | ProductId: productId, 81 | rating: 5, 82 | comment: 'Great product!', 83 | ...overrides 84 | }); 85 | 86 | const createWishlist = (userId, productId, overrides = {}) => ({ 87 | UserId: userId, 88 | ProductId: productId, 89 | ...overrides 90 | }); 91 | 92 | // API request data factories 93 | const createLoginRequest = (overrides = {}) => ({ 94 | email: 'test@example.com', 95 | password: 'password123', 96 | ...overrides 97 | }); 98 | 99 | const createRegisterRequest = (overrides = {}) => ({ 100 | username: 'newuser', 101 | firstName: 'New', 102 | lastName: 'User', 103 | email: 'newuser@example.com', 104 | password: 'password123', 105 | userType: 'Customer', 106 | ...overrides 107 | }); 108 | 109 | const createProductRequest = (overrides = {}) => ({ 110 | title: 'New Product', 111 | description: 'A new product', 112 | amount: 149.99, 113 | currency: 'USD', 114 | rating: 4.0, 115 | sales: 0, 116 | CategoryId: 1, 117 | SubCategoryId: 1, 118 | SubSubCategoryId: 1, 119 | ...overrides 120 | }); 121 | 122 | // Mock response data 123 | const createApiResponse = (data, status = 200) => ({ 124 | status, 125 | data, 126 | statusText: status === 200 ? 'OK' : 'Error' 127 | }); 128 | 129 | const createErrorResponse = (message, status = 500) => ({ 130 | status, 131 | data: { error: message }, 132 | statusText: 'Error' 133 | }); 134 | 135 | module.exports = { 136 | createUser, 137 | createAdminUser, 138 | createCategory, 139 | createSubCategory, 140 | createSubSubCategory, 141 | createProduct, 142 | createOrder, 143 | createOrderItem, 144 | createReview, 145 | createWishlist, 146 | createLoginRequest, 147 | createRegisterRequest, 148 | createProductRequest, 149 | createApiResponse, 150 | createErrorResponse 151 | }; 152 | --------------------------------------------------------------------------------