├── public
├── robots.txt
├── favicon.ico
├── img
│ ├── Vue-Icons.png
│ └── icons
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── mstile-150x150.png
│ │ ├── apple-touch-icon.png
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-512x512.png
│ │ ├── apple-touch-icon-60x60.png
│ │ ├── apple-touch-icon-76x76.png
│ │ ├── apple-touch-icon-120x120.png
│ │ ├── apple-touch-icon-152x152.png
│ │ ├── apple-touch-icon-180x180.png
│ │ ├── msapplication-icon-144x144.png
│ │ └── safari-pinned-tab.svg
├── manifest.json
└── index.html
├── .env.development
├── .env.production
├── src
├── assets
│ ├── logo.png
│ ├── login-img.png
│ └── create-account.svg
├── components
│ ├── products
│ │ ├── cart
│ │ │ ├── ShippingDetails.vue
│ │ │ ├── CartCalculator.vue
│ │ │ ├── Checkout.vue
│ │ │ └── CartProducts.vue
│ │ ├── actions
│ │ │ ├── CreateProduct.vue
│ │ │ ├── EditProduct.vue
│ │ │ └── ProductForm.vue
│ │ ├── ProductsList.vue
│ │ ├── BestProducts.vue
│ │ ├── TopProducts.vue
│ │ ├── filters
│ │ │ └── ProductFilter.vue
│ │ └── ProductDetail.vue
│ ├── shared
│ │ ├── service
│ │ │ ├── ErrorHandler.js
│ │ │ └── authService.js
│ │ ├── CardLoader.vue
│ │ ├── Modal.vue
│ │ └── CardTemplate.vue
│ ├── checkout
│ │ └── CheckoutModal.vue
│ ├── HelloWorld.vue
│ └── CreateAccount.vue
├── main.js
├── store.js
├── registerServiceWorker.js
├── views
│ ├── Home.vue
│ ├── About.vue
│ ├── Products.vue
│ └── login.vue
├── router.js
└── App.vue
├── babel.config.js
├── .gitignore
├── server
├── mongo
│ ├── model
│ │ ├── user.js
│ │ ├── shipping-detail.js
│ │ └── product.js
│ └── config.js
└── routes
│ ├── authApi.js
│ ├── shippingDetailApi.js
│ ├── api.js
│ └── productApi.js
├── .github
└── FUNDING.yml
├── LICENSE.md
├── server.js
├── package.json
└── README.md
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/.env.development:
--------------------------------------------------------------------------------
1 | VUE_APP_BASE_URL=http://localhost:8080/api
--------------------------------------------------------------------------------
/.env.production:
--------------------------------------------------------------------------------
1 | VUE_APP_BASE_URL=https://vue-shop-cart.herokuapp.com/api
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/public/img/Vue-Icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/Vue-Icons.png
--------------------------------------------------------------------------------
/src/assets/login-img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/src/assets/login-img.png
--------------------------------------------------------------------------------
/public/img/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/public/img/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/public/img/icons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/mstile-150x150.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/img/icons/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/android-chrome-192x192.png
--------------------------------------------------------------------------------
/public/img/icons/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/android-chrome-512x512.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/public/img/icons/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/public/img/icons/msapplication-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ikismail/Vue-ShoppingCart/HEAD/public/img/icons/msapplication-icon-144x144.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
23 | # Config
24 | /server/mongo/configDummy.js
--------------------------------------------------------------------------------
/server/mongo/model/user.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | var Schema = mongoose.Schema;
3 |
4 | var UserSchema = new Schema({
5 | firstName: String,
6 | lastName: String,
7 | fullName: String,
8 | email: String,
9 | isAdmin: Boolean,
10 | password: String,
11 | createdOn: String,
12 | });
13 |
14 | module.exports = mongoose.model("User", UserSchema);
15 |
--------------------------------------------------------------------------------
/src/components/products/cart/ShippingDetails.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/server/mongo/model/shipping-detail.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | var Schema = mongoose.Schema;
3 |
4 | var ShippingDetailSchema = new Schema({
5 | address1: String,
6 | address2: String,
7 | country: String,
8 | zipCode: String,
9 | shippingDate: String,
10 | products: Array,
11 | userId: String,
12 | totalPrice: String,
13 | });
14 |
15 | module.exports = mongoose.model("ShippingDetail", ShippingDetailSchema);
16 |
--------------------------------------------------------------------------------
/server/mongo/model/product.js:
--------------------------------------------------------------------------------
1 | var mongoose = require("mongoose");
2 | var Schema = mongoose.Schema;
3 |
4 | var ProductSchema = new Schema({
5 | productName: String,
6 | productDescription: String,
7 | productCategory: String,
8 | productPrice: String,
9 | productImage: String,
10 | productSeller: String,
11 | isBestProduct: Boolean,
12 | isTopProduct: Boolean,
13 | productRating: Number,
14 | });
15 |
16 | module.exports = mongoose.model("Product", ProductSchema);
17 |
--------------------------------------------------------------------------------
/src/components/shared/service/ErrorHandler.js:
--------------------------------------------------------------------------------
1 | /* Handling Errors through Toastr */
2 |
3 |
4 | import toastr from "toastr";
5 |
6 | export const successToaster = (title, desc) => {
7 | return (toastr.success(desc, title))
8 | }
9 | export const errorToaster = (title, desc) => {
10 | return (toastr.error(desc, title))
11 | }
12 |
13 | export const warnToaster = (title, desc) => {
14 | return (toastr.warning(desc, title))
15 | }
16 |
17 | export const infoToaster = (title, desc) => {
18 | return (toastr.info(desc, title))
19 | }
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-shopping-cart",
3 | "short_name": "vue-shopping-cart",
4 | "icons": [
5 | {
6 | "src": "/img/icons/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/img/icons/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "start_url": "/index.html",
17 | "display": "standalone",
18 | "background_color": "#000000",
19 | "theme_color": "#4DBA87"
20 | }
21 |
--------------------------------------------------------------------------------
/src/components/checkout/CheckoutModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/server/mongo/config.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | mongoose.connect(
4 | "mongodb+srv://read-only:mlabreadonly@hifdth-track.x6ijp.mongodb.net/vue-shop",
5 | {
6 | useNewUrlParser: true,
7 | useUnifiedTopology: true,
8 | }
9 | ); // connect to our database
10 |
11 | // db.on('error', console.error.bind(console, 'connection error:'));
12 | const db = mongoose.connection;
13 | db.once("open", () => console.info("Connected to MongoDB Sample"));
14 | db.on("error", console.error.bind(console, "connection error:"));
15 |
16 | module.exports = mongoose;
17 |
--------------------------------------------------------------------------------
/src/components/shared/CardLoader.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
23 |
24 |
--------------------------------------------------------------------------------
/server/routes/authApi.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const router = express.Router();
3 |
4 | const UserModel = require("../mongo/model/user");
5 |
6 | router.route("/login").post((req, res) => {
7 | UserModel.find(
8 | {
9 | email: req.body.email,
10 | password: req.body.password,
11 | },
12 | function(err, user) {
13 | if (err) {
14 | res.send(err);
15 | }
16 |
17 | if (user.length === 0) {
18 | res.status(401).json({
19 | status: 401,
20 | message: "Unauthorized credentials mismatch",
21 | });
22 | } else {
23 | res.json(user);
24 | }
25 | }
26 | );
27 | });
28 | module.exports = router;
29 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 | custom: ['paypal.me/ikismail7']
14 |
--------------------------------------------------------------------------------
/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 "./registerServiceWorker";
6 | import VueAwesomeSwiper from "vue-awesome-swiper";
7 | import NProgress from "nprogress";
8 |
9 | // require styles
10 | import "swiper/swiper.min.css";
11 | import "../node_modules/nprogress/nprogress.css";
12 |
13 | Vue.use(VueAwesomeSwiper);
14 |
15 | Vue.config.productionTip = false;
16 |
17 | router.beforeResolve((to, from, next) => {
18 | if (to.name) {
19 | NProgress.start();
20 | }
21 | next();
22 | });
23 |
24 | router.afterEach(() => {
25 | NProgress.done();
26 | });
27 | // eslint-disable-next-line no-unused-vars
28 | let vm = new Vue({
29 | router,
30 | store,
31 | render: (h) => h(App),
32 | }).$mount("#app");
33 |
--------------------------------------------------------------------------------
/src/components/products/actions/CreateProduct.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
37 |
38 |
--------------------------------------------------------------------------------
/src/components/products/actions/EditProduct.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
35 |
36 |
--------------------------------------------------------------------------------
/src/assets/create-account.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import {
4 | encryptUser
5 | } from './components/shared/service/authService'
6 |
7 | Vue.use(Vuex)
8 |
9 | export default new Vuex.Store({
10 | state: {
11 | cartProducts: [],
12 | loggedUser: {}
13 | },
14 | getters: {
15 | cartProducts: state => {
16 | return state.cartProducts
17 | },
18 | getLoggedUser: state => {
19 | return state.loggedUser
20 | }
21 | },
22 | mutations: {
23 | ADD_CART_LOCAL: (state, product) => {
24 | state.cartProducts.push(product)
25 | localStorage.setItem('iki-cart', JSON.stringify(state.cartProducts))
26 | },
27 |
28 | ADD_LOGGED_USER: (state, user) => {
29 | state.loggedUser = user
30 | localStorage.setItem('_auth', encryptUser(user))
31 | },
32 |
33 | SET_CART_PRODUCTS: (state, products) => {
34 | state.cartProducts = []
35 | state.cartProducts = products
36 | },
37 | },
38 | actions: {}
39 | })
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 | MIT License
3 |
4 | Copyright (c) 2022 Mohammed Ismail
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
--------------------------------------------------------------------------------
/src/components/products/ProductsList.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
35 |
36 |
49 |
--------------------------------------------------------------------------------
/src/components/shared/service/authService.js:
--------------------------------------------------------------------------------
1 | /* Encryption User based on base64 */
2 | export const encryptUser = (user) => {
3 | const objStr = JSON.stringify(user);
4 | const encryptedValue = new Buffer(objStr).toString("base64");
5 | return encryptedValue;
6 | }
7 |
8 | /* Decrypting User based on base64*/
9 | export const decryptUser = () => {
10 | const data = localStorage.getItem("_auth");
11 | if (!data) {
12 | return null;
13 | }
14 | const strObj = new Buffer(data || "", "base64").toString("utf8");
15 | const value = JSON.parse(strObj);
16 | return value;
17 | }
18 |
19 | /* Verify that person is loggedIn */
20 | export const isLoggedIn = () => {
21 | const data = decryptUser();
22 | if (data) {
23 | return true;
24 | }
25 | return false;
26 | }
27 |
28 | /* Verifying that the user is Admin or not */
29 | export const isAdmin = () => {
30 | const data = decryptUser();
31 | let hasAdmin = false;
32 | if (data["isAdmin"]) {
33 | hasAdmin = true;
34 | }
35 | return hasAdmin;
36 | }
37 |
38 | /* Returning the logged User */
39 | export const getLoggedInUser = () => {
40 | const data = decryptUser();
41 | return data;
42 | }
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 |
3 | import {
4 | register
5 | } from 'register-service-worker'
6 | import {
7 | infoToaster,
8 | errorToaster
9 | } from './components/shared/service/ErrorHandler'
10 |
11 | if (process.env.NODE_ENV === 'production') {
12 | register(`${process.env.BASE_URL}service-worker.js`, {
13 | ready() {
14 | console.log(
15 | 'App is being served from cache by a service worker.\n' +
16 | 'For more details, visit https://goo.gl/AFskqB'
17 | )
18 | },
19 | cached() {
20 | console.log('Content has been cached for offline use.')
21 | },
22 | updated() {
23 | console.log('New content is available; please refresh.')
24 | infoToaster('Please refresh', 'New content is available')
25 | },
26 | offline() {
27 | console.log('No internet connection found. App is running in offline mode.')
28 | },
29 | error(error) {
30 | console.error('Error during service worker registration:', error)
31 | errorToaster('Error during service worker registration', error)
32 | }
33 | })
34 | }
--------------------------------------------------------------------------------
/src/components/shared/Modal.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
23 |
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
43 |
49 |
--------------------------------------------------------------------------------
/server/routes/shippingDetailApi.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const router = express.Router();
3 |
4 | // const mongodb = require('../mongo/config')
5 |
6 | const ShippingModel = require("../mongo/model/shipping-detail");
7 |
8 | /*
9 | API for ShippingSchema Schema
10 | Product Create and Read all Policies API 's
11 |
12 | */
13 | router
14 | .route("/shipping")
15 |
16 | // Create a new ShippingDetail
17 | .post((req, res) => {
18 | const shippingDetail = new ShippingModel(); // create a new instance of the Product model
19 |
20 | shippingDetail.address1 = req.body.address1;
21 | shippingDetail.address2 = req.body.address2;
22 | shippingDetail.country = req.body.country;
23 | shippingDetail.zipCode = req.body.zipCode;
24 | shippingDetail.shippingDate = req.body.shippingDate;
25 | shippingDetail.products = req.body.products;
26 | shippingDetail.userId = req.body.userId;
27 | shippingDetail.totalPrice = req.body.totalPrice;
28 |
29 | // save the bear and check for errors
30 | shippingDetail.save(shippingDetail, (err, shippingDetail) => {
31 | if (err) {
32 | res.send(err);
33 | }
34 |
35 | console.log("**********NEWLY CREATED SITEURL***********");
36 | console.log(shippingDetail);
37 | res.send(shippingDetail);
38 | });
39 | });
40 |
41 | module.exports = router;
42 |
--------------------------------------------------------------------------------
/src/components/products/cart/CartCalculator.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Your cart
5 | {{
6 | cartProducts.length
7 | }}
8 |
9 |
28 |
29 |
30 |
53 |
55 |
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ikismail - VueShop
8 |
9 |
A ShoppingCart (Ecommerce) Application using Vue.js.
10 |
11 |
12 |
13 |
14 |
15 | Our Best Products
16 |
17 |
18 | Show All
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Our Top Products
27 |
28 |
29 | Show All
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
50 |
55 |
--------------------------------------------------------------------------------
/src/components/products/BestProducts.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
56 |
57 |
62 |
--------------------------------------------------------------------------------
/src/components/products/TopProducts.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
55 |
56 |
65 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | // Get dependencies
2 | const express = require("express");
3 | const bodyParser = require("body-parser");
4 | const history = require("connect-history-api-fallback");
5 | // Get our API routes
6 | // eslint-disable-next-line no-unused-vars
7 | const mongodb = require("./server/mongo/config");
8 |
9 | const api = require("./server/routes/api");
10 | const productApi = require("./server/routes/productApi");
11 | const ShippingDetailApi = require("./server/routes/shippingDetailApi");
12 | const authApi = require("./server/routes/authApi");
13 |
14 | const app = express();
15 |
16 | // Parsers for POST data
17 | app.use(bodyParser.json());
18 | app.use(
19 | bodyParser.urlencoded({
20 | extended: false,
21 | })
22 | );
23 |
24 | // Create link to Angular build directory
25 | var distDir = __dirname + "/dist";
26 | app.use(express.static(distDir));
27 |
28 | /* Access Control Allow Origin */
29 | app.use((req, res, next) => {
30 | // Website you wish to allow to connect
31 | res.setHeader("Access-Control-Allow-Origin", "*");
32 |
33 | // Request methods you wish to allow
34 | res.setHeader(
35 | "Access-Control-Allow-Methods",
36 | "GET, POST, OPTIONS, PUT, PATCH, DELETE"
37 | );
38 |
39 | // Request headers you wish to allow
40 | res.setHeader(
41 | "Access-Control-Allow-Headers",
42 | "X-Requested-With,content-type"
43 | );
44 |
45 | // Set to true if you need the website to include cookies in the requests sent
46 | // to the API (e.g. in case you use sessions)
47 | res.setHeader("Access-Control-Allow-Credentials", true);
48 |
49 | next();
50 | });
51 |
52 | app.use(history({ index: "/index.html" }));
53 |
54 | app.use("/api", [api, productApi, authApi, ShippingDetailApi]);
55 |
56 | // Initialize the app.
57 | var server = app.listen(process.env.PORT || 8080, function() {
58 | var port = server.address().port;
59 | console.log("App now running on port", port);
60 | });
61 |
--------------------------------------------------------------------------------
/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
20 |
21 |
22 | ikismail7@gmail.com
23 |
24 |
28 |
29 |
Angular
30 |
Vuejs
31 |
React
32 |
Github
33 |
RestService
34 |
35 |
40 |
41 |
44 |
45 |
46 |
47 |
48 |
53 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-shopping-cart",
3 | "version": "0.2.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "start": "nodemon server.js",
8 | "dev": "concurrently \"npm:start\" \"npm:serve --fix\"",
9 | "dev:build": "vue-cli-service build --mode development",
10 | "build": "vue-cli-service build",
11 | "lint": "vue-cli-service lint",
12 | "postinstall": "vue-cli-service build"
13 | },
14 | "dependencies": {
15 | "axios": "^0.21.1",
16 | "body-parser": "^1.19.0",
17 | "bootstrap": "^4.6.0",
18 | "concurrently": "^6.0.0",
19 | "connect-history-api-fallback": "^1.6.0",
20 | "core-js": "^3.6.5",
21 | "express": "^4.17.1",
22 | "lodash": "^4.17.21",
23 | "mongoose": "^5.11.18",
24 | "nodemon": "^2.0.7",
25 | "nprogress": "^0.2.0",
26 | "register-service-worker": "^1.7.2",
27 | "swiper": "^6.4.15",
28 | "toastr": "^2.1.4",
29 | "vue": "^2.6.11",
30 | "vue-awesome-swiper": "^4.1.1",
31 | "vue-content-loading": "^1.6.0",
32 | "vue-router": "^3.5.1",
33 | "vuex": "^3.6.2"
34 | },
35 | "devDependencies": {
36 | "@types/lodash": "^4.14.168",
37 | "@vue/cli-plugin-babel": "~4.5.0",
38 | "@vue/cli-plugin-eslint": "~4.5.0",
39 | "@vue/cli-service": "~4.5.0",
40 | "babel-eslint": "^10.1.0",
41 | "eslint": "^6.7.2",
42 | "eslint-plugin-vue": "^6.2.2",
43 | "node-sass": "^5.0.0",
44 | "sass-loader": "^11.0.1",
45 | "vue-template-compiler": "^2.6.11"
46 | },
47 | "engines" : {
48 | "node" : "12"
49 | },
50 | "eslintConfig": {
51 | "root": true,
52 | "env": {
53 | "node": true
54 | },
55 | "extends": [
56 | "plugin:vue/essential",
57 | "eslint:recommended"
58 | ],
59 | "parserOptions": {
60 | "parser": "babel-eslint"
61 | },
62 | "rules": {}
63 | },
64 | "browserslist": [
65 | "> 1%",
66 | "last 2 versions",
67 | "not dead"
68 | ]
69 | }
70 |
--------------------------------------------------------------------------------
/src/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Home from './views/Home.vue'
4 | import {
5 | isLoggedIn
6 | } from './components/shared/service/authService'
7 |
8 | Vue.use(Router)
9 |
10 | export default new Router({
11 | mode: 'hash',
12 | base: process.env.BASE_URL,
13 | routes: [{
14 | path: '/',
15 | name: 'home',
16 | component: Home
17 | },
18 | {
19 | path: '/about',
20 | name: 'about',
21 | // route level code-splitting
22 | // this generates a separate chunk (about.[hash].js) for this route
23 | // which is lazy-loaded when the route is visited.
24 | component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
25 | },
26 | {
27 | path: '/products',
28 | name: 'products',
29 | component: () => import('./views/Products.vue')
30 | },
31 | {
32 | path: '/products/:id',
33 | name: 'productDetails',
34 | component: () => import('./components/products/ProductDetail.vue')
35 | },
36 | {
37 | path: '/cart',
38 | name: 'cart',
39 | component: () => import('./components/products/cart/CartProducts.vue'),
40 | beforeEnter: (to, from, next) => {
41 | if (isLoggedIn()) {
42 | next()
43 | } else {
44 | next({
45 | name: 'login',
46 | query: {
47 | from: to.name
48 | }
49 | })
50 | }
51 | }
52 | },
53 | {
54 | path: '/checkout',
55 | name: 'checkout',
56 | component: () => import('./components/products/cart/Checkout.vue'),
57 | beforeEnter: (to, from, next) => {
58 | if (isLoggedIn()) {
59 | next()
60 | } else {
61 | next({
62 | name: 'login',
63 | query: {
64 | from: to.name
65 | }
66 | })
67 | }
68 | }
69 | },
70 | {
71 | path: '/login',
72 | name: 'login',
73 | component: () => import('./views/login.vue')
74 | }
75 | ]
76 | })
77 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
32 | vue-shopping-cart
33 |
34 |
35 |
36 |
37 | We're sorry but vue-shopping-cart doesn't work properly without
39 | JavaScript enabled. Please enable it to continue.
41 |
42 |
43 |
44 |
45 |
50 |
55 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation .
8 |
9 |
Installed CLI Plugins
10 |
15 |
Essential Links
16 |
23 |
Ecosystem
24 |
31 |
32 |
33 |
34 |
42 |
43 |
44 |
60 |
--------------------------------------------------------------------------------
/server/routes/api.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const router = express.Router();
3 |
4 | const UserModel = require("../mongo/model/user");
5 |
6 | /* GET api listing. */
7 | router.get("/", (req, res) => {
8 | res.send("api works");
9 | });
10 |
11 | /*
12 | API for User Schema
13 | User Create and Read all Policies API's
14 |
15 | */
16 | router
17 | .route("/users")
18 |
19 | // Create a new User
20 | .post((req, res) => {
21 | const user = new UserModel(); // create a new instance of the User model
22 |
23 | user.firstName = req.body.firstName;
24 | user.lastName = req.body.lastName;
25 | user.fullName = req.body.firstName + " " + req.body.lastName;
26 | user.password = req.body.password;
27 | user.email = req.body.email;
28 | user.isAdmin = false;
29 | user.createdOn = new Date().toLocaleString();
30 |
31 | // save the bear and check for errors
32 | user.save(user, (err, user) => {
33 | if (err) {
34 | res.send(err);
35 | }
36 | console.log("**********NEWLY CREATED SITEURL***********");
37 | res.send(user);
38 | });
39 | })
40 | // Get All Users
41 | .get((req, res) => {
42 | UserModel.find((err, data) => {
43 | if (err) {
44 | res.send(err);
45 | }
46 | res.json(data);
47 | });
48 | });
49 |
50 | /* USER Update and Read by Id and delete users API's */
51 | // on routes that end in /users/:user_id
52 | // ----------------------------------------------------
53 | router
54 | .route("/users/:user_id")
55 |
56 | // get the user with that id (accessed at GET http://localhost:8080/api/users/:user_id)
57 | .get(function(req, res) {
58 | UserModel.findById(req.params.user_id, function(err, data) {
59 | if (err) {
60 | res.send(err);
61 | }
62 | res.json(data);
63 | });
64 | })
65 |
66 | // update the user with this id (accessed at PUT http://localhost:8080/api/users/:user_id)
67 | .put(function(req, res) {
68 | // use our user model to find the user we want
69 | UserModel.findById(req.params.user_id, function(err, user) {
70 | if (err) {
71 | res.send(err);
72 | }
73 |
74 | user.name = req.body.name;
75 | user.password = req.body.password;
76 | user.email = req.body.email;
77 | user.isAdmin = false;
78 | user.user_avatar = req.body.user_avatar;
79 | user.phoneNumber = req.body.phoneNumber;
80 | user.createdOn = req.body.createdOn;
81 |
82 | // save the bear
83 | user.save(function(err, data) {
84 | if (err) {
85 | res.send(err);
86 | }
87 | res.send(data);
88 | });
89 | });
90 | });
91 |
92 | module.exports = router;
93 |
--------------------------------------------------------------------------------
/src/components/shared/CardTemplate.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
{{ item.productName }}.
12 |
{{ item.productDescription }}.
13 |
14 |
15 |
20 | View
21 |
22 |
23 |
29 | Edit
30 |
31 |
32 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
90 |
--------------------------------------------------------------------------------
/src/views/Products.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
90 |
91 |
96 |
--------------------------------------------------------------------------------
/src/components/products/filters/ProductFilter.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Filters:
6 |
7 |
11 |
12 | Create New Product
13 |
14 |
15 |
16 | By Category:
17 | updateProductCategory(event, 'productCategory')"
22 | >
23 | {{ category.productCategory }}
29 |
30 |
31 |
32 | By Seller:
33 | updateProductCategory(event, 'productSeller')"
38 | >
39 | {{ seller.productSeller }}
45 |
46 |
47 |
48 | Cras justo odio
49 | Dapibus ac facilisis in
50 | Morbi leo risus
51 | Porta ac consectetur ac
52 | Vestibulum at eros
53 |
54 |
55 |
56 |
57 |
58 |
59 |
87 |
88 |
93 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ShoppingCart - Vue.js + Node.js + Express + MongoDB
2 |
3 | [](http://hits.dwyl.io/ikismail/Vue-ShoppingCart)
4 | [](https://github.com/ikismail/Vue-ShoppingCart/network)
5 | [](https://david-dm.org/ikismail/Vue-ShoppingCart.svg)
6 | [](https://github.com/ikismail/Vue-ShoppingCart/stargazers)
7 | [](https://github.com/ikismail/Vue-ShoppingCart/issues)
8 | [](https://github.com/ikismail/Vue-ShoppingCart/blob/master/LICENSE)
9 | [](https://vue-shop-cart.herokuapp.com/)
10 | [](https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Fikismail%2FVue-ShoppingCart)
11 |
12 | Developing a **ShoppingCart (Ecommerce) Application using Vue.js**
13 |
14 | **Live Demo** : [Vue-Shopping-Cart](#)
15 |
16 | This project was generated with [Vue CLI](https://github.com/vuejs/vue-cli) version **3.x**
17 |
18 | ## Functionalitites
19 | 1. User Registeration and Authentication using Passport.js (Email/password | Google Authentication)
20 | 2. CRUD Operations like
21 | * User can add product to his cart
22 | * Admin can add product to the product list.
23 | * Admin can edit/delete the product.
24 | 3. Security
25 | * Implementation of Authentication and Authorization.
26 |
27 | ## Tools and Technologies:
28 | * Technology : Vue.js + Express + Node.js + MongoDb (MEVN), HTML, Bootstrap, PWA.
29 |
30 | ## Installation
31 |
32 | 1. Vue CLI - [Installation of Vue CLI](https://cli.vuejs.org/guide/installation.html)
33 | 2. NodeJs - [Download Nodejs](https://nodejs.org/en/download/)
34 | 3. Package Manager - NPM / Yarn
35 | 4. Clone the repository and run `npm install` if you use **npm** as package manager or `yarn install` if you use **yarn** as package manager.
36 | 5. Configuring MongoDB `server/mongo/config.js`
37 | ```
38 | mongoose.connect('', {
39 | useNewUrlParser: true
40 | }); // connect to your database
41 |
42 | ```
43 | 6. Run the server `npm run serve`
44 |
45 | ## Screenshots:
46 |
47 | ### Main Page:
48 | 
49 |
50 | ### Product Page:
51 | 
52 |
53 | ## How can I support the developer ?
54 |
55 | * Star my Github repo ⭐
56 | * Create pull requests, submit bugs, suggest new features or documentation updates 🛠
57 |
58 | ## Project setup
59 | ```
60 | npm install
61 | ```
62 |
63 | ### Compiles and hot-reloads for development
64 | ```
65 | npm run serve
66 | ```
67 |
68 | ### Compiles and minifies for production
69 | ```
70 | npm run build
71 | ```
72 |
73 | ### Run your tests
74 | ```
75 | npm run test
76 | ```
77 |
78 | ### Lints and fixes files
79 | ```
80 | npm run lint
81 | ```
82 |
--------------------------------------------------------------------------------
/src/components/products/cart/Checkout.vue:
--------------------------------------------------------------------------------
1 |
2 |
78 |
79 |
80 |
104 |
105 |
118 |
--------------------------------------------------------------------------------
/src/views/login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
43 |
44 |
45 | Already a member?
46 | Sign in
47 |
48 |
49 | New to ikismail?
50 | Create an Account
51 |
52 |
53 |
54 |
55 |
56 |
57 |
107 |
145 |
--------------------------------------------------------------------------------
/src/components/products/cart/CartProducts.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
19 |
20 |
{{ item.productName }}.
21 |
24 |
25 |
29 | View
30 |
31 |
32 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
Oops!
49 |
No Products Found
50 |
Your cart is empty
51 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | Continue Shipping
69 | Checkout
72 |
73 |
74 |
75 |
76 |
77 |
78 |
107 |
108 |
123 |
--------------------------------------------------------------------------------
/src/components/CreateAccount.vue:
--------------------------------------------------------------------------------
1 |
2 |
79 |
80 |
141 |
142 |
150 |
--------------------------------------------------------------------------------
/server/routes/productApi.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const router = express.Router();
3 |
4 | // const mongodb = require('../mongo/config')
5 |
6 | const ProductModel = require("../mongo/model/product");
7 |
8 | /*
9 | API for Product Schema
10 | Product Create and Read all Policies API 's
11 |
12 | */
13 | router
14 | .route("/products")
15 |
16 | // Create a new Product
17 | .post((req, res) => {
18 | const product = new ProductModel(); // create a new instance of the Product model
19 |
20 | product.productName = req.body.productName;
21 | product.productDescription = req.body.productDescription;
22 | product.productCategory = req.body.productCategory;
23 | product.productPrice = req.body.productPrice;
24 | product.productImage = req.body.productImage;
25 | product.productSeller = req.body.productSeller;
26 | product.productRating = req.body.productRating;
27 |
28 | // save the bear and check for errors
29 | product.save(product, (err, product) => {
30 | if (err) {
31 | res.send(err);
32 | }
33 |
34 | console.log("**********NEWLY CREATED SITEURL***********");
35 | console.log(product);
36 | res.send(product);
37 | });
38 | })
39 | // Get All products
40 | .get((req, res) => {
41 | ProductModel.find((err, data) => {
42 | if (err) {
43 | res.send(err);
44 | }
45 | console.log("data", data);
46 | res.json(data);
47 | });
48 | });
49 |
50 | router.route("/best/products/").get(function(req, res) {
51 | ProductModel.find(
52 | {
53 | isBestProduct: true,
54 | },
55 | function(err, product) {
56 | if (err) {
57 | res.send(err);
58 | }
59 | console.log("data", product);
60 | res.json(product);
61 | }
62 | ).limit(4);
63 | });
64 |
65 | router.route("/top/products/").get(function(req, res) {
66 | ProductModel.find(
67 | {
68 | isTopProduct: true,
69 | },
70 | function(err, product) {
71 | if (err) {
72 | res.send(err);
73 | }
74 | console.log("data", product);
75 | res.json(product);
76 | }
77 | ).limit(4);
78 | });
79 |
80 | router.route("/products/similarProduct").get(function(req, res) {
81 | ProductModel.find(
82 | {
83 | productSeller: req.query["productSeller"],
84 | },
85 | function(err, product) {
86 | if (err) {
87 | res.send(err);
88 | }
89 | console.log("data", product);
90 | res.json(product);
91 | }
92 | ).limit(4);
93 | });
94 |
95 | /* Getting product Categories */
96 | router.route("/products/productCategories").get((req, res) => {
97 | ProductModel.aggregate(
98 | [
99 | {
100 | $group: {
101 | _id: "$productCategory",
102 | },
103 | },
104 | ],
105 | (err, products) => {
106 | if (err) {
107 | res.send(err);
108 | }
109 |
110 | console.log("data", products);
111 | res.json(products);
112 | }
113 | );
114 | });
115 |
116 | router.route("/products/productsByCategory").get((req, res) => {
117 | ProductModel.find(
118 | {
119 | productCategory: req.query["productCategory"],
120 | },
121 | (err, data) => {
122 | console.log("inside if");
123 | if (err) {
124 | res.send(err);
125 | }
126 | console.log("data", data);
127 | res.json(data);
128 | }
129 | );
130 | });
131 |
132 | /* ProductModel Update and Read by Id and delete products API's */
133 | // on routes that end in /products/:product_id
134 | // ----------------------------------------------------
135 | router
136 | .route("/products/:product_id")
137 |
138 | // get the product with that id (accessed at GET http://localhost:8080/api/products/:product_id)
139 | .get(function(req, res) {
140 | ProductModel.findById(req.params.product_id, function(err, data) {
141 | if (err) {
142 | res.send(err);
143 | }
144 | console.log("data", data);
145 | res.json(data);
146 | });
147 | })
148 |
149 | // update the product with this id (accessed at PUT http://localhost:8080/api/products/:product_id)
150 | .put(function(req, res) {
151 | // use our product model to find the product we want
152 | ProductModel.findById(req.params.product_id, function(err, product) {
153 | if (err) {
154 | res.send(err);
155 | }
156 |
157 | product.productName = req.body.productName;
158 | product.productDescription = req.body.productDescription;
159 | product.productCategory = req.body.productCategory;
160 | product.productPrice = req.body.productPrice;
161 | product.productImage = req.body.productImage;
162 | product.productSeller = req.body.productSeller;
163 | product.productRating = req.body.productRating;
164 |
165 | // save the bear
166 | product.save(function(err, data) {
167 | if (err) {
168 | res.send(err);
169 | }
170 | console.log("Updating product", data);
171 | res.send(data);
172 | });
173 | });
174 | })
175 |
176 | // delete the product with this id (accessed at DELETE http://localhost:8080/api/products/:product_id)
177 | .delete(function(req, res) {
178 | ProductModel.remove(
179 | {
180 | _id: req.params.product_id,
181 | },
182 | function(err, product) {
183 | if (err) {
184 | res.send(err);
185 | }
186 | res.send(product);
187 | }
188 | );
189 | });
190 |
191 | module.exports = router;
192 |
--------------------------------------------------------------------------------
/src/components/products/ProductDetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 |
20 |
21 |
Product Price
22 |
23 | ₹ {{ product.productPrice }}
26 |
27 |
30 |
31 |
Product Seller
32 |
33 | {{
34 | product.productSeller
35 | }}
36 |
37 |
38 |
39 | Add to Cart
40 |
41 |
42 |
43 |
44 |
45 |
46 |
Product Details
47 |
48 |
49 |
50 | Product Name
51 | {{ product.productName }}
52 |
53 |
54 | Product Description
55 | {{ product.productDescription }}
56 |
57 |
58 | Product Category
59 | {{ product.productCategory }}
60 |
61 |
62 | Product Rating
63 |
64 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | Similar Products
78 |
79 |
80 |
81 |
90 |
91 |
92 |
93 |
94 |
154 |
155 |
197 |
--------------------------------------------------------------------------------
/src/components/products/actions/ProductForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
68 |
69 |
127 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
15 |
16 |
17 |
18 |
19 |
20 | Home
21 |
22 |
23 | All Products
26 |
27 |
28 | Pricing
29 |
30 |
31 | About
32 |
33 |
34 |
35 |
36 |
37 |
38 | {{ this.cartProducts.length }}
39 |
40 |
41 |
42 |
43 |
53 |
67 |
68 |
69 | Login
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
114 |
115 |
116 |
117 |
165 |
166 |
167 |
250 |
--------------------------------------------------------------------------------
/public/img/icons/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.11, written by Peter Selinger 2001-2013
9 |
10 |
12 |
101 |
102 |
103 |
--------------------------------------------------------------------------------