├── frontend ├── src │ ├── Components │ │ ├── Admin │ │ │ ├── Users │ │ │ │ ├── Users.css │ │ │ │ └── Users.jsx │ │ │ ├── Products │ │ │ │ ├── EditProduct.css │ │ │ │ ├── Products.css │ │ │ │ └── AddProduct.css │ │ │ ├── Panel │ │ │ │ ├── Progress.css │ │ │ │ ├── Progress.jsx │ │ │ │ └── panel.css │ │ │ ├── OrderDetails │ │ │ │ └── Orderdetails.css │ │ │ ├── Departments │ │ │ │ └── Departments.css │ │ │ ├── Login │ │ │ │ ├── login.jsx │ │ │ │ └── login.css │ │ │ └── Header │ │ │ │ ├── header.css │ │ │ │ └── header.jsx │ │ ├── Users │ │ │ ├── LoadingBox │ │ │ │ ├── loadingBox.css │ │ │ │ └── loadingBox.jsx │ │ │ ├── Banner │ │ │ │ ├── Banner.css │ │ │ │ └── Banner.jsx │ │ │ ├── MessageBox │ │ │ │ ├── messageBox.jsx │ │ │ │ └── messageBox.css │ │ │ ├── RowPosts │ │ │ │ ├── rowPost.css │ │ │ │ └── rowPost.jsx │ │ │ ├── Departments │ │ │ │ ├── department.jsx │ │ │ │ ├── departments.css │ │ │ │ └── departments.jsx │ │ │ ├── Footer │ │ │ │ ├── footer.jsx │ │ │ │ └── footer.css │ │ │ ├── Products │ │ │ │ ├── products.css │ │ │ │ ├── products.jsx │ │ │ │ └── product.jsx │ │ │ ├── Signup │ │ │ │ ├── signup.css │ │ │ │ └── signup.jsx │ │ │ ├── Login │ │ │ │ ├── login.css │ │ │ │ └── login.jsx │ │ │ ├── Profile │ │ │ │ ├── email.css │ │ │ │ ├── email.jsx │ │ │ │ ├── name.css │ │ │ │ ├── name.jsx │ │ │ │ ├── LogInSecurity │ │ │ │ │ ├── logInSecurity.jsx │ │ │ │ │ └── logInSecurity.css │ │ │ │ └── password.css │ │ │ ├── Order │ │ │ │ ├── order.css │ │ │ │ └── order.jsx │ │ │ ├── productScreen │ │ │ │ └── productScreen.css │ │ │ ├── Cart │ │ │ │ └── cart.css │ │ │ └── Address │ │ │ │ └── address.css │ │ └── PrivateRoute.jsx │ ├── Images │ │ ├── Box.png │ │ ├── cart.png │ │ ├── logo.png │ │ ├── user.png │ │ ├── users.png │ │ ├── amazon.png │ │ ├── checked.png │ │ ├── laptop.jpg │ │ ├── location.png │ │ ├── package.png │ │ ├── product.jpeg │ │ ├── products.png │ │ ├── profits.png │ │ ├── AmazonLogo.png │ │ ├── adminUsers.png │ │ ├── adminOrders.png │ │ ├── adminProducts.png │ │ ├── dollar-symbol.png │ │ ├── electronics.jpg │ │ ├── confirm-banner.png │ │ ├── shopping-basket.png │ │ ├── complete-payment-banner.png │ │ ├── checkout-spc-address-banner.png │ │ └── logo.svg │ ├── view │ │ ├── Admin │ │ │ └── Pages │ │ │ │ ├── login.jsx │ │ │ │ ├── Users.jsx │ │ │ │ ├── products.jsx │ │ │ │ ├── AddProducts.jsx │ │ │ │ ├── Departments.jsx │ │ │ │ ├── EditProducts.jsx │ │ │ │ ├── OrderDetails.jsx │ │ │ │ └── panel.jsx │ │ └── Users │ │ │ ├── Pages │ │ │ ├── login.jsx │ │ │ ├── signup.jsx │ │ │ ├── Login&Security │ │ │ │ ├── email.jsx │ │ │ │ ├── name.jsx │ │ │ │ ├── password.jsx │ │ │ │ └── logInSecurity.jsx │ │ │ ├── home.jsx │ │ │ ├── address.jsx │ │ │ ├── cart.jsx │ │ │ ├── payment.jsx │ │ │ ├── order.jsx │ │ │ ├── product.jsx │ │ │ ├── placeOrder.jsx │ │ │ ├── products.jsx │ │ │ ├── orderHistory.jsx │ │ │ └── productScreen.jsx │ │ │ └── public │ │ │ └── home.jsx │ ├── setupTests.js │ ├── App.css │ ├── constants │ │ ├── cartConstants.js │ │ ├── productConstants.js │ │ ├── adminConstants.js │ │ ├── orderConstants.js │ │ └── userconstants.js │ ├── index.css │ ├── reportWebVitals.js │ ├── store │ │ ├── FirebaseContext.js │ │ └── store.js │ ├── Firebase │ │ └── config.js │ ├── index.js │ ├── reducers │ │ ├── productReducers.js │ │ ├── cartReducers.js │ │ ├── adminReducers.js │ │ ├── orderReducers.js │ │ └── userReducers.js │ ├── actions │ │ ├── productActions.js │ │ ├── cartActions.js │ │ ├── adminActions.js │ │ ├── orderActions.js │ │ └── userActions.js │ └── App.js ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── manifest.json │ └── index.html ├── jsconfig.json ├── package.json └── README.md ├── backend ├── models │ ├── departmentModel.js │ ├── userModel.js │ ├── productModel.js │ └── orderModel.js ├── utils │ └── utils.js ├── server.js └── routers │ ├── departmentRouter.js │ ├── orderRouter.js │ ├── productRouter.js │ └── userRouter.js ├── .gitignore ├── package.json └── README.md /frontend/src/Components/Admin/Users/Users.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/src/Components/Users/LoadingBox/loadingBox.css: -------------------------------------------------------------------------------- 1 | .loadingBoxContainer{ 2 | margin-bottom: 540px; 3 | } -------------------------------------------------------------------------------- /frontend/src/Images/Box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/Box.png -------------------------------------------------------------------------------- /frontend/src/Images/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/cart.png -------------------------------------------------------------------------------- /frontend/src/Images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/logo.png -------------------------------------------------------------------------------- /frontend/src/Images/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/user.png -------------------------------------------------------------------------------- /frontend/src/Images/users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/users.png -------------------------------------------------------------------------------- /frontend/src/Images/amazon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/amazon.png -------------------------------------------------------------------------------- /frontend/src/Images/checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/checked.png -------------------------------------------------------------------------------- /frontend/src/Images/laptop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/laptop.jpg -------------------------------------------------------------------------------- /frontend/src/Images/location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/location.png -------------------------------------------------------------------------------- /frontend/src/Images/package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/package.png -------------------------------------------------------------------------------- /frontend/src/Images/product.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/product.jpeg -------------------------------------------------------------------------------- /frontend/src/Images/products.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/products.png -------------------------------------------------------------------------------- /frontend/src/Images/profits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/profits.png -------------------------------------------------------------------------------- /frontend/src/Images/AmazonLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/AmazonLogo.png -------------------------------------------------------------------------------- /frontend/src/Images/adminUsers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/adminUsers.png -------------------------------------------------------------------------------- /frontend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6" 4 | }, 5 | "exclude": ["node_modules"] 6 | } -------------------------------------------------------------------------------- /frontend/src/Images/adminOrders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/adminOrders.png -------------------------------------------------------------------------------- /frontend/src/Images/adminProducts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/adminProducts.png -------------------------------------------------------------------------------- /frontend/src/Images/dollar-symbol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/dollar-symbol.png -------------------------------------------------------------------------------- /frontend/src/Images/electronics.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/electronics.jpg -------------------------------------------------------------------------------- /frontend/src/Images/confirm-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/confirm-banner.png -------------------------------------------------------------------------------- /frontend/src/Images/shopping-basket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/shopping-basket.png -------------------------------------------------------------------------------- /frontend/src/Images/complete-payment-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/complete-payment-banner.png -------------------------------------------------------------------------------- /frontend/src/Images/checkout-spc-address-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alanchrissantony/Amazon/HEAD/frontend/src/Images/checkout-spc-address-banner.png -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Products/EditProduct.css: -------------------------------------------------------------------------------- 1 | .adminEditProductSection{ 2 | padding-top: 5rem; 3 | width: 100%; 4 | height: auto; 5 | overflow: auto; 6 | margin-bottom: 2rem; 7 | } -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Panel/Progress.css: -------------------------------------------------------------------------------- 1 | .CircularProgressbar{ 2 | height: 10rem; 3 | width: auto; 4 | margin-bottom: 2rem; 5 | } 6 | .circleProgressBarDiv{ 7 | background-color: #e9eef7; 8 | } -------------------------------------------------------------------------------- /frontend/src/Components/Users/Banner/Banner.css: -------------------------------------------------------------------------------- 1 | .BannerBackgroundImg{ 2 | width: 100%; 3 | height: auto; 4 | margin-bottom: -150px; 5 | mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0)); 6 | } -------------------------------------------------------------------------------- /frontend/src/ view/Admin/Pages/login.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import AdminLogin from '../../../Components/Admin/Login/login' 3 | 4 | function login() { 5 | return ( 6 |
7 | 8 |
9 | ) 10 | } 11 | 12 | export default login -------------------------------------------------------------------------------- /frontend/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/login.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Login from '../../../Components/Users/Login/login'; 3 | 4 | function login() { 5 | return ( 6 |
7 | 8 |
9 | ) 10 | } 11 | 12 | export default login; 13 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/signup.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Signup from '../../../Components/Users/Signup/signup'; 3 | 4 | function signup() { 5 | return ( 6 |
7 | 8 |
9 | ) 10 | } 11 | 12 | export default signup; 13 | -------------------------------------------------------------------------------- /frontend/src/Components/Admin/OrderDetails/Orderdetails.css: -------------------------------------------------------------------------------- 1 | .adminOrderDetailsSection{ 2 | padding-top: 5rem; 3 | width: 100%; 4 | height: auto; 5 | overflow: auto; 6 | margin-bottom: 2rem; 7 | } 8 | .orderDetailsProductContentOrderDiv{ 9 | width: 50%; 10 | 11 | } -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/Login&Security/email.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Email from '../../../../Components/Users/Profile/email' 3 | 4 | 5 | function name() { 6 | return ( 7 |
8 | 9 | 10 | 11 |
12 | ) 13 | } 14 | 15 | export default name -------------------------------------------------------------------------------- /frontend/src/App.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0%; 3 | padding: 0%; 4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 5 | } 6 | button:focus{ 7 | outline: 0px; 8 | } 9 | input{ 10 | padding-left: 1rem; 11 | } -------------------------------------------------------------------------------- /frontend/src/constants/cartConstants.js: -------------------------------------------------------------------------------- 1 | export const CART_ADD_ITEM = 'CART_ADD_ITEM'; 2 | export const CART_REMOVE_ITEM = 'CART_REMOVE_ITEM'; 3 | export const CART_SAVE_SHIPPING_ADDRESS = 'CART_SAVE_SHIPPING_ADDRESS'; 4 | export const CART_SAVE_PAYMENT_METHOD = 'CART_SAVE_PAYMENT_METHOD'; 5 | export const CART_EMPTY = 'CART_EMPTY'; -------------------------------------------------------------------------------- /frontend/src/Components/Users/LoadingBox/loadingBox.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './loadingBox.css' 3 | 4 | function loading() { 5 | return ( 6 |
7 | Loading..... 8 |
9 | ) 10 | } 11 | 12 | export default loading; 13 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/MessageBox/messageBox.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './messageBox.css' 3 | 4 | function message(props) { 5 | return ( 6 |
7 | 8 | {props.children} 9 | 10 |
11 | ) 12 | } 13 | 14 | export default message; 15 | -------------------------------------------------------------------------------- /backend/models/departmentModel.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | 3 | const departmentSchema = new mongoose.Schema( 4 | { 5 | name: { type: String, required: true, unique: true }, 6 | image: { type: String, required: true }, 7 | }, 8 | { 9 | timestamps: true, 10 | } 11 | ); 12 | const Department = mongoose.model('Department', departmentSchema); 13 | 14 | export default Department; -------------------------------------------------------------------------------- /frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | 11 | ], 12 | "start_url": ".", 13 | "display": "standalone", 14 | "theme_color": "#000000", 15 | "background_color": "#ffffff" 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/constants/productConstants.js: -------------------------------------------------------------------------------- 1 | export const PRODUCT_LIST_REQUEST = 'PRODUCT_LIST_REQUEST' 2 | export const PRODUCT_LIST_SUCCESS = 'PRODUCT_LIST_SUCCESS' 3 | export const PRODUCT_LIST_FAIL = 'PRODUCT_LIST_FAIL' 4 | 5 | export const PRODUCT_DETAILS_REQUEST = 'PRODUCT_DETAILS_REQUEST' 6 | export const PRODUCT_DETAILS_SUCCESS = 'PRODUCT_DETAILS_SUCCESS' 7 | export const PRODUCT_DETAILS_FAIL = 'PRODUCT_DETAILS_FAIL' -------------------------------------------------------------------------------- /frontend/src/ view/Users/public/home.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Departments from '../../../Components/Users/Departments/departments' 3 | import RowPost from '../../../Components/Users/RowPosts/rowPost'; 4 | 5 | 6 | 7 | 8 | function Home() { 9 | 10 | 11 | return ( 12 |
13 | 14 | 15 |
16 | ) 17 | } 18 | 19 | export default Home; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | .env 25 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/home.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Navbar from '../../../Components/Users/Navbar/navbar' 3 | import Home from '../public/home'; 4 | import Footer from '../../../Components/Users/Footer/footer'; 5 | 6 | 7 | function home() { 8 | return ( 9 |
10 | 11 | 12 |
14 | ) 15 | } 16 | 17 | export default home; 18 | -------------------------------------------------------------------------------- /frontend/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/address.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Address from '../../../Components/Users/Address/address'; 3 | import Navbar from '../../../Components/Users/Navbar/navbar' 4 | import Footer from '../../../Components/Users/Footer/footer' 5 | 6 | function address() { 7 | return ( 8 |
9 | 10 |
11 |
13 | ); 14 | } 15 | 16 | export default address; 17 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/cart.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Navbar from '../../../Components/Users/Navbar/navbar' 3 | import Cart from '../../../Components/Users/Cart/cart'; 4 | import Footer from '../../../Components/Users/Footer/footer'; 5 | 6 | function cart() { 7 | return ( 8 |
9 | 10 | 11 |
13 | ) 14 | } 15 | 16 | export default cart; 17 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Banner/Banner.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './Banner.css' 3 | 4 | function Banner() { 5 | return ( 6 |
7 | 8 |
9 | ) 10 | } 11 | 12 | export default Banner -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/Login&Security/name.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Name from '../../../../Components/Users/Profile/name' 3 | import Navbar from '../../../../Components/Users/Navbar/navbar' 4 | import Footer from '../../../../Components/Users/Footer/footer' 5 | 6 | function name() { 7 | return ( 8 |
9 | 10 | 11 |
13 | ) 14 | } 15 | 16 | export default name -------------------------------------------------------------------------------- /frontend/src/Components/PrivateRoute.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { useSelector } from 'react-redux'; 3 | import { Navigate } from '../../node_modules/react-router/index'; 4 | 5 | 6 | const PrivateRoute = ({ children }) => { 7 | const userSignin = useSelector((state) => state.userSignin); 8 | const { userInfo } = userSignin; 9 | return userInfo ? children: 10 | } 11 | 12 | export default PrivateRoute 13 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/payment.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Payment from '../../../Components/Users/Payment/payment'; 3 | import Navbar from '../../../Components/Users/Navbar/navbar' 4 | import Footer from '../../../Components/Users/Footer/footer' 5 | 6 | 7 | function payment() { 8 | return ( 9 |
10 | 11 | 12 |
13 |
14 | ); 15 | } 16 | 17 | export default payment; 18 | -------------------------------------------------------------------------------- /frontend/src/store/FirebaseContext.js: -------------------------------------------------------------------------------- 1 | import React ,{createContext,useState} from 'react' 2 | 3 | 4 | export const FirebaseContext=createContext(null) 5 | export const AuthContext=createContext(null) 6 | 7 | 8 | 9 | export default function Context({children}){ 10 | const [user,setUser]=useState(null) 11 | return( 12 | 13 | {children} 14 | 15 | ) 16 | } -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/order.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Order from '../../../Components/Users/Order/order' 3 | import Navbar from '../../../Components/Users/Navbar/navbar' 4 | import Footer from '../../../Components/Users/Footer/footer' 5 | 6 | function order() { 7 | return ( 8 |
9 | 10 | 11 |
12 |
13 | ) 14 | } 15 | 16 | export default order -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/product.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Navbar from '../../../Components/Users/Navbar/navbar' 3 | import Product from '../../../Components/Users/Products/product'; 4 | import Footer from '../../../Components/Users/Footer/footer'; 5 | 6 | function products() { 7 | return ( 8 |
9 | 10 | 11 |
12 |
13 | ) 14 | } 15 | 16 | export default products; 17 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/Login&Security/password.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Password from '../../../../Components/Users/Profile/password' 3 | import Navbar from '../../../../Components/Users/Navbar/navbar' 4 | import Footer from '../../../../Components/Users/Footer/footer' 5 | 6 | function password() { 7 | return ( 8 |
9 | 10 | 11 |
12 |
13 | ) 14 | } 15 | 16 | export default password -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/placeOrder.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PlaceOrder from '../../../Components/Users/PlaceOrder/placeOrder'; 3 | import Navbar from '../../../Components/Users/Navbar/navbar' 4 | import Footer from '../../../Components/Users/Footer/footer' 5 | 6 | 7 | function placeOrder() { 8 | return ( 9 |
10 | 11 | 12 |
13 |
14 | ); 15 | } 16 | 17 | export default placeOrder; 18 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/products.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Navbar from '../../../Components/Users/Navbar/navbar' 3 | import Products from '../../../Components/Users/Products/products'; 4 | import Footer from '../../../Components/Users/Footer/footer'; 5 | 6 | function products() { 7 | return ( 8 |
9 | 10 | 11 |
12 |
13 | ) 14 | } 15 | 16 | export default products; 17 | -------------------------------------------------------------------------------- /backend/models/userModel.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | 3 | 4 | const userSchema = new mongoose.Schema( 5 | { 6 | name: { type: String, required: true }, 7 | email: { type: String, required: true, unique: true }, 8 | password: { type: String, required: true }, 9 | isAdmin: { type: Boolean, default: false, required: true }, 10 | }, 11 | { 12 | timestamps: true, 13 | } 14 | ); 15 | const User = mongoose.model('User', userSchema); 16 | export default User; -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/orderHistory.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import OrderHistory from '../../../Components/Users/OrderHistory/orderHistory'; 3 | import Navbar from '../../../Components/Users/Navbar/navbar' 4 | import Footer from '../../../Components/Users/Footer/footer' 5 | 6 | 7 | function orderHistory() { 8 | return ( 9 |
10 | 11 | 12 |
13 |
14 | ); 15 | } 16 | 17 | export default orderHistory; 18 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/productScreen.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Navbar from '../../../Components/Users/Navbar/navbar' 3 | import Footer from '../../../Components/Users/Footer/footer'; 4 | import ProductScreen from '../../../Components/Users/productScreen/productScreen'; 5 | 6 | 7 | function productScreen() { 8 | return ( 9 |
10 | 11 | 12 |
13 |
14 | ) 15 | } 16 | 17 | export default productScreen; 18 | -------------------------------------------------------------------------------- /frontend/src/ view/Users/Pages/Login&Security/logInSecurity.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import LogInSecurity from '../../../../Components/Users/Profile/LogInSecurity/logInSecurity' 3 | import Navbar from '../../../../Components/Users/Navbar/navbar' 4 | import Footer from '../../../../Components/Users/Footer/footer' 5 | 6 | function logInSecurity() { 7 | return ( 8 |
9 | 10 | 11 |
12 |
13 | ) 14 | } 15 | 16 | export default logInSecurity -------------------------------------------------------------------------------- /frontend/src/Components/Users/MessageBox/messageBox.css: -------------------------------------------------------------------------------- 1 | .alert{ 2 | margin-top: auto; 3 | margin-left: auto; 4 | margin-right: auto; 5 | margin-bottom: auto; 6 | border-radius: 1rem; 7 | color: #721c24; 8 | background-color: #f8d7da; 9 | border-color: #f5c6cb; 10 | text-align: center; 11 | height: 3rem; 12 | width: 95%; 13 | padding-top: 1.3rem; 14 | border: 1px solid transparent; 15 | position: relative; 16 | font-size: 1rem; 17 | font-weight: 400; 18 | line-height: 1.5; 19 | } -------------------------------------------------------------------------------- /frontend/src/constants/adminConstants.js: -------------------------------------------------------------------------------- 1 | // Admin 2 | 3 | export const ORDER_TOTAL_ADMIN_LIST_REQUEST = 'ORDER_TOTAL_ADMIN_LIST_REQUEST'; 4 | export const ORDER_TOTAL_ADMIN_LIST_SUCCESS = 'ORDER_TOTAL_ADMIN_LIST_SUCCESS'; 5 | export const ORDER_TOTAL_ADMIN_LIST_FAIL = 'ORDER_TOTAL_ADMIN_LIST_FAIL'; 6 | 7 | export const ADMIN_TOTAL_USERS_LIST_REQUEST = 'ADMIN_TOTAL_USERS_LIST_REQUEST'; 8 | export const ADMIN_TOTAL_USERS_LIST_SUCCESS = 'ADMIN_TOTAL_USERS_LIST_SUCCESS'; 9 | export const ADMIN_TOTAL_USERS_LIST_FAIL = 'ADMIN_TOTAL_USERS_LIST_FAIL'; 10 | -------------------------------------------------------------------------------- /frontend/src/Firebase/config.js: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/compat/app'; 2 | import 'firebase/compat/auth'; 3 | 4 | dotenv.config(); 5 | 6 | // For Firebase JS SDK v7.20.0 and later, measurementId is optional 7 | const firebaseConfig = { 8 | apiKey: "AIzaSyAagmJCqShyEsv-esNz_DiJOKeGW5bvGCQ", 9 | authDomain: "fir-22b78.firebaseapp.com", 10 | projectId: "fir-22b78", 11 | storageBucket: "fir-22b78.appspot.com", 12 | messagingSenderId: "836233874985", 13 | appId: "1:836233874985:web:6be8cfa6d8e24f16c85638", 14 | measurementId: "G-8S0EXDQCEM" 15 | }; 16 | 17 | export default firebase.initializeApp(firebaseConfig) 18 | -------------------------------------------------------------------------------- /backend/models/productModel.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | 3 | const productSchema = new mongoose.Schema( 4 | { 5 | name: { type: String, required: true, unique: true }, 6 | image: { type: String, required: true }, 7 | brand: { type: String, required: true }, 8 | category: { type: String, required: true }, 9 | department: { type: String, required: true }, 10 | description: { type: String, required: true }, 11 | price: { type: Number, required: true }, 12 | countInStock: { type: Number, required: true }, 13 | rating: { type: Number, required: true }, 14 | numReviews: { type: Number, required: true }, 15 | }, 16 | { 17 | timestamps: true, 18 | } 19 | ); 20 | const Product = mongoose.model('Product', productSchema); 21 | 22 | export default Product; -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Products/Products.css: -------------------------------------------------------------------------------- 1 | .adminProductsSection{ 2 | padding-top: 5rem; 3 | width: 100%; 4 | height: auto; 5 | overflow: auto; 6 | margin-bottom: 2rem; 7 | } 8 | .productAddBtnDiv{ 9 | margin-bottom: 2rem; 10 | float: left; 11 | } 12 | .departmentAddBtnDiv{ 13 | margin-left: 1rem; 14 | } 15 | .btn-product-option{ 16 | float: left; 17 | } 18 | .btn-delete{ 19 | margin-left: 1rem; 20 | } 21 | .productIcon{ 22 | font-size: 1rem; 23 | } 24 | .adminInputSpace{ 25 | height: 2.5rem; 26 | border-radius: 3px; 27 | font-family: Arial,sans-serif; 28 | font-size: 13px; 29 | border: 1px solid #d0d0d0; 30 | border-top: 1px solid #bbb; 31 | outline-color: gray; 32 | outline-width: thin; 33 | margin-left: 50%; 34 | } -------------------------------------------------------------------------------- /frontend/src/Components/Users/RowPosts/rowPost.css: -------------------------------------------------------------------------------- 1 | .rowPosterSection{ 2 | background-color: #eaeded; 3 | width: 100%; 4 | height: 350px; 5 | min-height: 350px; 6 | } 7 | .rowPosterContainer{ 8 | width: 95.34%; 9 | margin: auto; 10 | height: auto; 11 | display: flex; 12 | justify-content: center; 13 | } 14 | .divRow{ 15 | width: 98%; 16 | background-color: #fff; 17 | margin: 1rem; 18 | height: 280px; 19 | float: left; 20 | } 21 | .posters{ 22 | display: flex; 23 | padding: 20px; 24 | overflow-x: scroll; 25 | overflow-y: hidden; 26 | } 27 | .posters::-webkit-scrollbar{ 28 | display: none; 29 | } 30 | .poster{ 31 | max-height: 250px; 32 | margin-right: 10px; 33 | cursor: pointer; 34 | } 35 | .poster:hover{ 36 | transform: scale(1.1); 37 | } 38 | -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Departments/Departments.css: -------------------------------------------------------------------------------- 1 | .addDepartmentSection{ 2 | width: 40%; 3 | height: auto; 4 | margin-left: auto; 5 | margin-right: auto; 6 | border: 1px solid; 7 | border-color: blanchedalmond; 8 | background-color: white; 9 | z-index: 999; 10 | position: fixed; 11 | display: flex; 12 | margin-left: 22%; 13 | } 14 | .addDepartmentContainer{ 15 | width: 90%; 16 | margin-left: auto; 17 | margin-right: auto; 18 | margin-top: 1rem; 19 | margin-bottom: 1rem; 20 | } 21 | .btn-addNewDepartment{ 22 | margin-left: auto; 23 | margin-right: 1.5rem; 24 | display: flex; 25 | } 26 | .addNewDepartmentTitle{ 27 | width: 100%; 28 | } 29 | .addNewDepartmentTitleIcon{ 30 | display: flex; 31 | margin-left: auto; 32 | cursor: pointer; 33 | } -------------------------------------------------------------------------------- /frontend/src/constants/orderConstants.js: -------------------------------------------------------------------------------- 1 | export const ORDER_CREATE_REQUEST = 'ORDER_CREATE_REQUEST'; 2 | export const ORDER_CREATE_SUCCESS = 'ORDER_CREATE_SUCCESS'; 3 | export const ORDER_CREATE_FAIL = 'ORDER_CREATE_FAIL'; 4 | export const ORDER_CREATE_RESET = 'ORDER_CREATE_RESET'; 5 | 6 | export const ORDER_DETAILS_REQUEST = 'ORDER_DETAILS_REQUEST'; 7 | export const ORDER_DETAILS_SUCCESS = 'ORDER_DETAILS_SUCCESS'; 8 | export const ORDER_DETAILS_FAIL = 'ORDER_DETAILS_FAIL'; 9 | 10 | export const ORDER_PAY_REQUEST = 'ORDER_PAY_REQUEST'; 11 | export const ORDER_PAY_SUCCESS = 'ORDER_PAY_SUCCESS'; 12 | export const ORDER_PAY_FAIL = 'ORDER_PAY_FAIL'; 13 | export const ORDER_PAY_RESET = 'ORDER_PAY_RESET'; 14 | 15 | export const ORDER_MINE_LIST_REQUEST = 'ORDER_MINE_LIST_REQUEST'; 16 | export const ORDER_MINE_LIST_SUCCESS = 'ORDER_MINE_LIST_SUCCESS'; 17 | export const ORDER_MINE_LIST_FAIL = 'ORDER_MINE_LIST_FAIL'; 18 | 19 | 20 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Departments/department.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './departments.css' 3 | import {useNavigate} from 'react-router-dom' 4 | 5 | function Department(props) { 6 | 7 | const {departments} = props; 8 | const navigate=useNavigate() 9 | 10 | 11 | return ( 12 |
{ 13 | e.preventDefault() 14 | navigate(`/product/${departments._id}`) 15 | }}> 16 |

{departments.name}

17 | 18 |
19 |

{ 20 | e.preventDefault() 21 | navigate(`/product/${departments._id}`) 22 | }}>Shop now

23 |
24 | ) 25 | } 26 | 27 | export default Department; 28 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Footer/footer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './footer.css' 3 | import logo from '../../../Images/logo.png' 4 | 5 | 6 | 7 | function footer() { 8 | 9 | var day = new Date(), 10 | date = day.getFullYear(); 11 | 12 | return ( 13 |
14 |
15 | 19 |
20 |
21 |
22 | 23 |
24 |
25 |

© 1996-{date}, Amazon.com, Inc. or its affiliates

26 |
27 |
28 |
29 | ) 30 | } 31 | 32 | export default footer; 33 | -------------------------------------------------------------------------------- /frontend/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | import store from './store/store'; 7 | import { Provider } from 'react-redux' 8 | import Context, { FirebaseContext } from './store/FirebaseContext'; 9 | import firebase from './Firebase/config' 10 | 11 | ReactDOM.render( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | , 21 | document.getElementById('root') 22 | ); 23 | 24 | // If you want to start measuring performance in your app, pass a function 25 | // to log results (for example: reportWebVitals(console.log)) 26 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 27 | reportWebVitals(); 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "amazon", 3 | "type": "module", 4 | "version": "1.0.0", 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": { 8 | "start": "nodemon --watch backend --exec node --experimental-modules backend/server.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/alanchrissantony/Amazon.git" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/alanchrissantony/Amazon/issues" 18 | }, 19 | "homepage": "https://github.com/alanchrissantony/Amazon#readme", 20 | "dependencies": { 21 | "bcryptjs": "^2.4.3", 22 | "body-parser": "^1.20.0", 23 | "dotenv": "^15.0.0", 24 | "express": "^4.17.2", 25 | "express-async-handler": "^1.2.0", 26 | "express-fileupload": "^1.4.0", 27 | "jsonwebtoken": "^8.5.1", 28 | "mongoose": "^6.1.8", 29 | "react-circular-progressbar": "^2.1.0" 30 | }, 31 | "devDependencies": { 32 | "nodemon": "^2.0.15" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /backend/utils/utils.js: -------------------------------------------------------------------------------- 1 | import jwt from 'jsonwebtoken'; 2 | 3 | export const generateToken = (user) => { 4 | return jwt.sign( 5 | { 6 | _id: user._id, 7 | name: user.name, 8 | email: user.email, 9 | isAdmin: user.isAdmin, 10 | }, 11 | process.env.JWT_SECRET || 'somethingsecret', 12 | { 13 | expiresIn: '30d', 14 | } 15 | ); 16 | }; 17 | 18 | 19 | 20 | export const isAuth = (req, res, next) => { 21 | const authorization = req.headers.authorization; 22 | if (authorization) { 23 | const token = authorization.slice(7, authorization.length); // Bearer XXXXXX 24 | jwt.verify( 25 | token, 26 | process.env.JWT_SECRET || 'somethingsecret', 27 | (err, decode) => { 28 | if (err) { 29 | res.status(401).send({ message: 'Invalid Token' }); 30 | } else { 31 | req.user = decode; 32 | next(); 33 | } 34 | } 35 | ); 36 | } else { 37 | res.status(401).send({ message: 'No Token' }); 38 | } 39 | }; -------------------------------------------------------------------------------- /frontend/src/Components/Users/Footer/footer.css: -------------------------------------------------------------------------------- 1 | .footerSection{ 2 | width: 100%; 3 | height: 100px; 4 | background-color: #131a22; 5 | clear: both; 6 | position: relative; 7 | bottom: 0rem; 8 | } 9 | .footerLogo{ 10 | display: block; 11 | margin-left: auto; 12 | margin-right: auto; 13 | padding-top: 10px; 14 | height: 40px; 15 | width: auto; 16 | } 17 | .footerContentText{ 18 | color: white; 19 | font-size: small; 20 | text-align: center; 21 | padding-top: 10px; 22 | margin-left: auto; 23 | margin-right: auto; 24 | } 25 | .footerBtn{ 26 | width: 100%; 27 | height: 49px; 28 | background-color: #232F3E; 29 | font-size: 13px; 30 | line-height: 19px; 31 | color: #FFF; 32 | position: relative; 33 | border-style: solid; 34 | border-width: 1px; 35 | border-color: #131a22; 36 | cursor: pointer; 37 | } 38 | .footerBtn:hover{ 39 | background-color: #37475a; 40 | } 41 | .footerBtn:focus{ 42 | outline-style: solid; 43 | outline-width: 1px; 44 | outline-color: #37475a; 45 | } -------------------------------------------------------------------------------- /frontend/src/constants/userconstants.js: -------------------------------------------------------------------------------- 1 | export const USER_REGISTER_REQUEST = 'USER_REGISTER_REQUEST'; 2 | export const USER_REGISTER_SUCCESS = 'USER_REGISTER_SUCCESS'; 3 | export const USER_REGISTER_FAIL = 'USER_REGISTER_FAIL'; 4 | 5 | export const USER_SIGNIN_REQUEST = 'USER_SIGNIN_REQUEST'; 6 | export const USER_SIGNIN_SUCCESS = 'USER_SIGNIN_SUCCESS'; 7 | export const USER_SIGNIN_FAIL = 'USER_SIGNIN_FAIL'; 8 | 9 | export const USER_VERIFY_SIGNIN_REQUEST = 'USER_VERIFY_SIGNIN_REQUEST'; 10 | export const USER_VERIFY_SIGNIN_SUCCESS = 'USER_VERIFY_SIGNIN_SUCCESS'; 11 | export const USER_VERIFY_SIGNIN_FAIL = 'USER_VERIFY_SIGNIN_FAIL'; 12 | 13 | export const USER_DETAILS_REQUEST = 'USER_DETAILS_REQUEST'; 14 | export const USER_DETAILS_SUCCESS = 'USER_DETAILS_SUCCESS'; 15 | export const USER_DETAILS_FAIL = 'USER_DETAILS_FAIL'; 16 | 17 | export const USER_UPDATE_PROFILE_REQUEST = 'USER_UPDATE_PROFILE_REQUEST'; 18 | export const USER_UPDATE_PROFILE_SUCCESS = 'USER_UPDATE_PROFILE_SUCCESS'; 19 | export const USER_UPDATE_PROFILE_FAIL = 'USER_UPDATE_PROFILE_FAIL'; 20 | export const USER_UPDATE_PROFILE_RESET = 'USER_UPDATE_PROFILE_RESET'; 21 | 22 | export const USER_SIGNOUT = 'USER_SIGNOUT'; -------------------------------------------------------------------------------- /frontend/src/reducers/productReducers.js: -------------------------------------------------------------------------------- 1 | import { PRODUCT_DETAILS_FAIL, PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_LIST_FAIL, PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS } from "../constants/productConstants"; 2 | 3 | export const productListReducer= (state = {loading:true, products:[]}, action)=>{ 4 | switch(action.type){ 5 | case PRODUCT_LIST_REQUEST: 6 | return{loading: true}; 7 | case PRODUCT_LIST_SUCCESS: 8 | return{loading: false, products: action.payload}; 9 | case PRODUCT_LIST_FAIL: 10 | return{loading:false, error: action.payload}; 11 | default: 12 | return state; 13 | } 14 | } 15 | 16 | export const productDetailsReducer = ( 17 | state = { product: {}, loading: true }, 18 | action 19 | ) => { 20 | switch (action.type) { 21 | case PRODUCT_DETAILS_REQUEST: 22 | return { loading: true }; 23 | case PRODUCT_DETAILS_SUCCESS: 24 | return { loading: false, product: action.payload }; 25 | case PRODUCT_DETAILS_FAIL: 26 | return { loading: false, error: action.payload }; 27 | default: 28 | return state; 29 | } 30 | }; -------------------------------------------------------------------------------- /frontend/src/Components/Users/Departments/departments.css: -------------------------------------------------------------------------------- 1 | .departmentRootSection{ 2 | background-color: #eaeded; 3 | width: 100%; 4 | } 5 | .departmentsSectionContainer{ 6 | height: auto; 7 | overflow: auto; 8 | } 9 | .departmentsDivContainer{ 10 | width: 95.34%; 11 | margin: auto; 12 | height: auto; 13 | z-index: 100; 14 | } 15 | .departmentBox{ 16 | height: 420px; 17 | width: 290px; 18 | background-color: #fff; 19 | float: left; 20 | margin: 1rem; 21 | cursor: pointer; 22 | } 23 | .departmentTitleLink{ 24 | text-decoration: none; 25 | color: black; 26 | } 27 | .departmentTitle{ 28 | margin: 1rem; 29 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif 30 | } 31 | .departmentImage{ 32 | margin-left: 1rem; 33 | max-width: 250px; 34 | height: auto; 35 | } 36 | .departmentShopLink{ 37 | margin: 2rem; 38 | position: static; 39 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 40 | color: #15788b; 41 | } 42 | .departmentShopLink:hover{ 43 | color: #5762cc; 44 | } -------------------------------------------------------------------------------- /frontend/src/actions/productActions.js: -------------------------------------------------------------------------------- 1 | import Axios from "axios" 2 | import { PRODUCT_DETAILS_FAIL, PRODUCT_DETAILS_REQUEST, PRODUCT_DETAILS_SUCCESS, PRODUCT_LIST_FAIL, PRODUCT_LIST_REQUEST, PRODUCT_LIST_SUCCESS } from "../constants/productConstants" 3 | 4 | export const listProducts=()=> async (dispatch)=>{ 5 | dispatch({ 6 | type: PRODUCT_LIST_REQUEST 7 | }) 8 | try{ 9 | const { data } = await Axios.get('/api/products') 10 | dispatch({type: PRODUCT_LIST_SUCCESS, payload: data}) 11 | }catch(error){ 12 | dispatch({type: PRODUCT_LIST_FAIL, payload: error.message}) 13 | } 14 | } 15 | 16 | 17 | 18 | export const detailsProduct = (productId) => async (dispatch) => { 19 | dispatch({ type: PRODUCT_DETAILS_REQUEST, payload: productId }); 20 | try { 21 | const { data } = await Axios.get(`/api/products/${productId}`); 22 | dispatch({ type: PRODUCT_DETAILS_SUCCESS, payload: data }); 23 | } catch (error) { 24 | dispatch({ 25 | type: PRODUCT_DETAILS_FAIL, 26 | payload: 27 | error.response && error.response.data.message 28 | ? error.response.data.message 29 | : error.message, 30 | }); 31 | } 32 | }; -------------------------------------------------------------------------------- /frontend/src/actions/cartActions.js: -------------------------------------------------------------------------------- 1 | import Axios from "axios"; 2 | import { CART_ADD_ITEM, CART_REMOVE_ITEM, CART_SAVE_PAYMENT_METHOD, CART_SAVE_SHIPPING_ADDRESS } from "../constants/cartConstants"; 3 | 4 | export const addToCart = (productId, qty) => async (dispatch, getState) => { 5 | const { data } = await Axios.get(`/api/products/${productId}`); 6 | dispatch({ 7 | type: CART_ADD_ITEM, 8 | payload: { 9 | name: data.name, 10 | image: data.image, 11 | price: data.price, 12 | decimal: data.decimal, 13 | countInStock: data.countInStock, 14 | product: data._id, 15 | qty, 16 | }, 17 | }); 18 | localStorage.setItem('cartItems', JSON.stringify(getState().cart.cartItems)); 19 | }; 20 | 21 | 22 | export const removeFromCart = (productId) => (dispatch, getState) => { 23 | dispatch({ type: CART_REMOVE_ITEM, payload: productId }); 24 | localStorage.setItem('cartItems', JSON.stringify(getState().cart.cartItems)); 25 | }; 26 | 27 | 28 | export const saveShippingAddress = (data) => (dispatch) => { 29 | dispatch({ type: CART_SAVE_SHIPPING_ADDRESS, payload: data }); 30 | localStorage.setItem('shippingAddress', JSON.stringify(data)); 31 | }; 32 | 33 | export const savePaymentMethod = (data) => (dispatch) => { 34 | dispatch({ type: CART_SAVE_PAYMENT_METHOD, payload: data }); 35 | }; -------------------------------------------------------------------------------- /frontend/src/ view/Admin/Pages/Users.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import { AuthContext } from "../../../store/FirebaseContext"; 3 | import { useNavigate } from "react-router-dom"; 4 | import LoadingBox from "../../../Components/Users/LoadingBox/loadingBox"; 5 | import Header from '../../../Components/Admin/Header/header' 6 | import User from '../../../Components/Admin/Users/Users' 7 | import Footer from '../../../Components/Users/Footer/footer' 8 | 9 | function Users() { 10 | 11 | const navigate = useNavigate(); 12 | const [userErr, setUserErr] = useState(true); 13 | 14 | const AdminSignIn = () => { 15 | const { user } = useContext(AuthContext); 16 | if (user) { 17 | localStorage.setItem("adminInfo", JSON.stringify(user)); 18 | } 19 | }; 20 | 21 | AdminSignIn(); 22 | 23 | useEffect(() => { 24 | const user = localStorage.getItem("adminInfo"); 25 | if (!user) { 26 | navigate("/admin/login"); 27 | } else if (user) { 28 | setUserErr(false); 29 | } 30 | }, [navigate]); 31 | 32 | return ( 33 |
34 | {userErr ? ( 35 | 36 | ) : ( 37 |
38 |
39 | 40 |
41 |
42 | )} 43 |
44 | ) 45 | } 46 | 47 | export default Users -------------------------------------------------------------------------------- /frontend/src/ view/Admin/Pages/products.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import Header from "../../../Components/Admin/Header/header"; 3 | import Products from "../../../Components/Admin/Products/Products"; 4 | import Footer from "../../../Components/Users/Footer/footer"; 5 | import { AuthContext } from "../../../store/FirebaseContext"; 6 | import { useNavigate } from "react-router-dom"; 7 | import LoadingBox from "../../../Components/Users/LoadingBox/loadingBox"; 8 | 9 | function Product() { 10 | const navigate = useNavigate(); 11 | const [userErr, setUserErr] = useState(true); 12 | 13 | const AdminSignIn = () => { 14 | const { user } = useContext(AuthContext); 15 | if (user) { 16 | localStorage.setItem("adminInfo", JSON.stringify(user)); 17 | } 18 | }; 19 | 20 | AdminSignIn(); 21 | 22 | useEffect(() => { 23 | const user = localStorage.getItem("adminInfo"); 24 | if (!user) { 25 | navigate("/admin/login"); 26 | } else if (user) { 27 | setUserErr(false); 28 | } 29 | }, [navigate]); 30 | 31 | return ( 32 |
33 | {userErr ? ( 34 | 35 | ) : ( 36 |
37 |
38 | 39 |
40 |
41 | )} 42 |
43 | ); 44 | } 45 | 46 | export default Product; 47 | -------------------------------------------------------------------------------- /frontend/src/ view/Admin/Pages/AddProducts.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import { AuthContext } from "../../../store/FirebaseContext"; 3 | import { useNavigate } from "react-router-dom"; 4 | import LoadingBox from "../../../Components/Users/LoadingBox/loadingBox"; 5 | import Header from '../../../Components/Admin/Header/header' 6 | import Footer from '../../../Components/Users/Footer/footer' 7 | import AddProduct from '../../../Components/Admin/Products/AddProduct' 8 | 9 | function AddProducts() { 10 | 11 | const navigate = useNavigate(); 12 | const [userErr, setUserErr] = useState(true); 13 | 14 | const AdminSignIn = () => { 15 | const { user } = useContext(AuthContext); 16 | if (user) { 17 | localStorage.setItem("adminInfo", JSON.stringify(user)); 18 | } 19 | }; 20 | 21 | AdminSignIn(); 22 | 23 | useEffect(() => { 24 | const user = localStorage.getItem("adminInfo"); 25 | if (!user) { 26 | navigate("/admin/login"); 27 | } else if (user) { 28 | setUserErr(false); 29 | } 30 | }, [navigate]); 31 | 32 | return ( 33 |
34 | {userErr ? ( 35 | 36 | ) : ( 37 |
38 |
39 | 40 |
41 |
42 | )} 43 |
44 | ) 45 | } 46 | 47 | export default AddProducts -------------------------------------------------------------------------------- /frontend/src/ view/Admin/Pages/Departments.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import { AuthContext } from "../../../store/FirebaseContext"; 3 | import { useNavigate } from "react-router-dom"; 4 | import LoadingBox from "../../../Components/Users/LoadingBox/loadingBox"; 5 | import Header from '../../../Components/Admin/Header/header' 6 | import Department from '../../../Components/Admin/Departments/Departments' 7 | import Footer from '../../../Components/Users/Footer/footer' 8 | 9 | function Departments() { 10 | 11 | const navigate = useNavigate(); 12 | const [userErr, setUserErr] = useState(true); 13 | 14 | const AdminSignIn = () => { 15 | const { user } = useContext(AuthContext); 16 | if (user) { 17 | localStorage.setItem("adminInfo", JSON.stringify(user)); 18 | } 19 | }; 20 | 21 | AdminSignIn(); 22 | 23 | useEffect(() => { 24 | const user = localStorage.getItem("adminInfo"); 25 | if (!user) { 26 | navigate("/admin/login"); 27 | } else if (user) { 28 | setUserErr(false); 29 | } 30 | }, [navigate]); 31 | 32 | return ( 33 |
34 | {userErr ? ( 35 | 36 | ) : ( 37 |
38 |
39 | 40 |
41 |
42 | )} 43 |
44 | ) 45 | } 46 | 47 | export default Departments -------------------------------------------------------------------------------- /frontend/src/ view/Admin/Pages/EditProducts.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import { AuthContext } from "../../../store/FirebaseContext"; 3 | import { useNavigate } from "react-router-dom"; 4 | import LoadingBox from "../../../Components/Users/LoadingBox/loadingBox"; 5 | import Header from '../../../Components/Admin/Header/header' 6 | import EditProduct from '../../../Components/Admin/Products/EditProduct' 7 | import Footer from '../../../Components/Users/Footer/footer' 8 | 9 | function EditProducts() { 10 | 11 | const navigate = useNavigate(); 12 | const [userErr, setUserErr] = useState(true); 13 | 14 | const AdminSignIn = () => { 15 | const { user } = useContext(AuthContext); 16 | if (user) { 17 | localStorage.setItem("adminInfo", JSON.stringify(user)); 18 | } 19 | }; 20 | 21 | AdminSignIn(); 22 | 23 | useEffect(() => { 24 | const user = localStorage.getItem("adminInfo"); 25 | if (!user) { 26 | navigate("/admin/login"); 27 | } else if (user) { 28 | setUserErr(false); 29 | } 30 | }, [navigate]); 31 | 32 | return ( 33 |
34 | {userErr ? ( 35 | 36 | ) : ( 37 |
38 |
39 | 40 |
41 |
42 | )} 43 |
44 | ) 45 | } 46 | 47 | export default EditProducts -------------------------------------------------------------------------------- /frontend/src/ view/Admin/Pages/OrderDetails.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import { AuthContext } from "../../../store/FirebaseContext"; 3 | import { useNavigate } from "react-router-dom"; 4 | import LoadingBox from "../../../Components/Users/LoadingBox/loadingBox"; 5 | import Header from '../../../Components/Admin/Header/header' 6 | import OrderDetail from '../../../Components/Admin/OrderDetails/OrderDetails' 7 | import Footer from '../../../Components/Users/Footer/footer' 8 | 9 | function OrderDetails() { 10 | 11 | const navigate = useNavigate(); 12 | const [userErr, setUserErr] = useState(true); 13 | 14 | const AdminSignIn = () => { 15 | const { user } = useContext(AuthContext); 16 | if (user) { 17 | localStorage.setItem("adminInfo", JSON.stringify(user)); 18 | } 19 | }; 20 | 21 | AdminSignIn(); 22 | 23 | useEffect(() => { 24 | const user = localStorage.getItem("adminInfo"); 25 | if (!user) { 26 | navigate("/admin/login"); 27 | } else if (user) { 28 | setUserErr(false); 29 | } 30 | }, [navigate]); 31 | 32 | return ( 33 |
34 | {userErr ? ( 35 | 36 | ) : ( 37 |
38 |
39 | 40 |
41 |
42 | )} 43 |
44 | ) 45 | } 46 | 47 | export default OrderDetails -------------------------------------------------------------------------------- /frontend/src/reducers/cartReducers.js: -------------------------------------------------------------------------------- 1 | import { CART_ADD_ITEM, CART_EMPTY, CART_REMOVE_ITEM, CART_SAVE_PAYMENT_METHOD, CART_SAVE_SHIPPING_ADDRESS } from "../constants/cartConstants"; 2 | 3 | export const cartReducer = (state = { cartItems: [] }, action) => { 4 | switch (action.type) { 5 | case CART_ADD_ITEM: 6 | const item = action.payload; 7 | const existItem = state.cartItems.find((x) => x.product === item.product); 8 | if (existItem) { 9 | return { 10 | ...state, 11 | cartItems: state.cartItems.map((x) => 12 | x.product === existItem.product ? item : x 13 | ), 14 | }; 15 | } else { 16 | return { ...state, cartItems: [...state.cartItems, item] }; 17 | } 18 | case CART_REMOVE_ITEM: 19 | return { 20 | ...state, 21 | cartItems: state.cartItems.filter((x) => x.product !== action.payload), 22 | }; 23 | case CART_SAVE_SHIPPING_ADDRESS: 24 | return { ...state, shippingAddress: action.payload }; 25 | case CART_SAVE_PAYMENT_METHOD: 26 | return { ...state, paymentMethod: action.payload }; 27 | case CART_EMPTY: 28 | return { ...state, cartItems: [] }; 29 | default: 30 | return state; 31 | } 32 | }; -------------------------------------------------------------------------------- /backend/server.js: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import mongoose from 'mongoose'; 3 | import dotenv from 'dotenv' 4 | import data from './Data/data.js' 5 | import productRouter from './routers/productRouter.js'; 6 | import userRouter from './routers/userRouter.js' 7 | import orderRouter from './routers/orderRouter.js'; 8 | import departmentRouter from './routers/departmentRouter.js'; 9 | 10 | 11 | 12 | 13 | 14 | dotenv.config(); 15 | 16 | const app = express() 17 | 18 | app.use(express.json()); 19 | app.use(express.urlencoded({ extended: true })); 20 | 21 | mongoose.connect(process.env.MONGODB_URL || 'mongodb://localhost/amazon', { 22 | useNewUrlParser: true, 23 | useUnifiedTopology: true, 24 | }); 25 | 26 | app.use('/api/users', userRouter) 27 | app.use('/api/products', productRouter) 28 | app.use('/api/orders', orderRouter) 29 | app.use('/api/departments', departmentRouter) 30 | app.use('/api/config/paypal', (req,res)=>{ 31 | res.send(process.env.PAYPAL_CLIENT_ID || 'sb') 32 | }) 33 | 34 | 35 | 36 | 37 | app.get('/api/phones', (req, res) => { 38 | res.send(data.phones) 39 | }) 40 | 41 | 42 | 43 | app.get('/', (req, res) => { 44 | res.send('Server Started') 45 | }) 46 | 47 | app.use((err, req, res, next) => { 48 | res.status(500).send({ message: err.message }); 49 | }); 50 | 51 | const port = process.env.PORT || 5000; 52 | 53 | app.listen(port, () => { 54 | console.log(`Server at http://localhost:${port}`) 55 | }) -------------------------------------------------------------------------------- /frontend/src/actions/adminActions.js: -------------------------------------------------------------------------------- 1 | import Axios from "axios"; 2 | import { ADMIN_TOTAL_USERS_LIST_FAIL, ADMIN_TOTAL_USERS_LIST_REQUEST, ADMIN_TOTAL_USERS_LIST_SUCCESS, ORDER_TOTAL_ADMIN_LIST_FAIL, ORDER_TOTAL_ADMIN_LIST_REQUEST, ORDER_TOTAL_ADMIN_LIST_SUCCESS } from "../constants/adminConstants"; 3 | 4 | export const adminTotalListOrder = () => async (dispatch, getState) => { 5 | dispatch({ type: ORDER_TOTAL_ADMIN_LIST_REQUEST }); 6 | try { 7 | const { data } = await Axios.get('/api/orders/admin/total&orders'); 8 | dispatch({ type: ORDER_TOTAL_ADMIN_LIST_SUCCESS, payload: data }); 9 | } catch (error) { 10 | const message = 11 | error.response && error.response.data.message 12 | ? error.response.data.message 13 | : error.message; 14 | dispatch({ type: ORDER_TOTAL_ADMIN_LIST_FAIL, payload: message }); 15 | } 16 | }; 17 | 18 | export const adminTotalListUsers = () => async (dispatch, getState) => { 19 | dispatch({ type: ADMIN_TOTAL_USERS_LIST_REQUEST }); 20 | try { 21 | const { data } = await Axios.get('/api/users/admin/total&users'); 22 | dispatch({ type: ADMIN_TOTAL_USERS_LIST_SUCCESS, payload: data }); 23 | localStorage.setItem("userList", JSON.stringify(data)); 24 | } catch (error) { 25 | const message = 26 | error.response && error.response.data.message 27 | ? error.response.data.message 28 | : error.message; 29 | dispatch({ type: ADMIN_TOTAL_USERS_LIST_FAIL, payload: message }); 30 | } 31 | }; -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Products/AddProduct.css: -------------------------------------------------------------------------------- 1 | .AddProductContainer{ 2 | width: 80%; 3 | margin-left: auto; 4 | margin-right: auto; 5 | } 6 | .addProductSubTitle{ 7 | margin-bottom: 0rem; 8 | } 9 | .addProductInputContainer{ 10 | margin-top: 0rem; 11 | } 12 | .addProductInputLabel{ 13 | font-size: 13px; 14 | line-height: 19px; 15 | font-weight: 700; 16 | } 17 | .addProductFormLeft{ 18 | width: 50%; 19 | float: left; 20 | } 21 | .addProductFormRight{ 22 | width: 50%; 23 | float: left; 24 | } 25 | .selectDepartment{ 26 | width: 94%; 27 | outline: 0; 28 | color: #111; 29 | font-size: 13px; 30 | line-height: 29px; 31 | display: block; 32 | font-family: Arial,sans-serif; 33 | white-space: nowrap; 34 | background-color: transparent; 35 | display: inline-block; 36 | height: 31px; 37 | border: 1px solid; 38 | border-color: #bcc1c8 #bababa #adb2bb; 39 | background-color: #f1f2f4; 40 | margin-top: 0.3rem; 41 | border-radius: 3px; 42 | } 43 | .inputSpaceDescription{ 44 | width: 94%; 45 | height: 100px; 46 | margin-top: 0.3rem; 47 | border-radius: 3px; 48 | font-family: Arial,sans-serif; 49 | font-size: 13px; 50 | border: 1px solid #d0d0d0; 51 | border-top: 1px solid #bbb; 52 | outline-color: #f69b3c; 53 | outline-width: thin; 54 | } 55 | .btn-addProduct{ 56 | float: right; 57 | } 58 | .adminAddProductSection{ 59 | padding-top: 5rem; 60 | width: 100%; 61 | height: auto; 62 | overflow: auto; 63 | margin-bottom: 2rem; 64 | } -------------------------------------------------------------------------------- /frontend/src/ view/Admin/Pages/panel.jsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useEffect, useState } from "react"; 2 | import AdminPanel from "../../../Components/Admin/Panel/panel"; 3 | import Footer from "../../../Components/Users/Footer/footer"; 4 | import Header from "../../../Components/Admin/Header/header"; 5 | import Dash from "../../../Components/Admin/Panel/Dash"; 6 | import OrderActivity from "../../../Components/Admin/Panel/OrderActivity"; 7 | import Progress from "../../../Components/Admin/Panel/Progress"; 8 | import { AuthContext } from "../../../store/FirebaseContext"; 9 | import { useNavigate } from "react-router-dom"; 10 | import LoadingBox from "../../../Components/Users/LoadingBox/loadingBox"; 11 | 12 | 13 | function Panel() { 14 | const navigate = useNavigate(); 15 | const [userErr, setUserErr] = useState(true); 16 | 17 | const AdminSignIn = () => { 18 | const { user } = useContext(AuthContext); 19 | if (user) { 20 | localStorage.setItem("adminInfo", JSON.stringify(user)); 21 | } 22 | }; 23 | 24 | AdminSignIn(); 25 | 26 | useEffect(() => { 27 | const user = localStorage.getItem("adminInfo"); 28 | if (!user) { 29 | navigate("/admin/login"); 30 | } else if (user) { 31 | setUserErr(false); 32 | } 33 | }, [navigate]); 34 | 35 | return ( 36 |
37 | {userErr ? ( 38 | 39 | ) : ( 40 |
41 |
42 | 43 | 44 |
45 |
46 | )} 47 |
48 | ); 49 | } 50 | 51 | export default Panel; 52 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Products/products.css: -------------------------------------------------------------------------------- 1 | .productsSectionContainer{ 2 | width: 100%; 3 | height: auto; 4 | min-height: 600px; 5 | } 6 | .productsContainer{ 7 | width: 95.34%; 8 | margin: auto; 9 | height: auto; 10 | } 11 | .productBox{ 12 | height: 500px; 13 | width: 290px; 14 | background-color: #fff; 15 | float: left; 16 | margin: 1rem; 17 | cursor: pointer; 18 | margin-bottom: 5rem; 19 | } 20 | .productsImageDiv{ 21 | margin: 1rem; 22 | } 23 | .productsImage{ 24 | max-width: 250px; 25 | height: auto; 26 | } 27 | .productsTitleDiv{ 28 | margin-left: 2rem; 29 | margin-top: 1rem; 30 | } 31 | .productsTitleLink{ 32 | color: black; 33 | } 34 | .productsTitle{ 35 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 36 | font-size: 18px; 37 | font-weight: 400; 38 | } 39 | .productsTitle:hover{ 40 | color: #ffa53f; 41 | } 42 | .productsRatingDiv{ 43 | margin-left: 2rem; 44 | margin-top: 1rem; 45 | } 46 | .productsPriceDiv{ 47 | margin-left: 2rem; 48 | } 49 | .productsPrice{ 50 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 51 | } 52 | .productsRatingDiv span{ 53 | color: #ffa53f; 54 | margin: 0.1rem; 55 | float: left; 56 | } 57 | .productsPriceDollar{ 58 | font-size: smaller; 59 | } 60 | .productsPriceText{ 61 | font-size: large; 62 | } 63 | .productsReviewDiv{ 64 | padding-top: 0.3rem; 65 | font-size: smaller; 66 | color: #007185; 67 | } -------------------------------------------------------------------------------- /frontend/src/Components/Users/Departments/departments.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import './departments.css' 3 | import axios from 'axios'; 4 | import Department from './department'; 5 | import LoadingBox from '../LoadingBox/loadingBox'; 6 | import MessageBox from '../MessageBox/messageBox'; 7 | import Banner from '../Banner/Banner'; 8 | 9 | 10 | function Departments() { 11 | 12 | const [departments, setDepartments] = useState([]); 13 | const [loading, setLoading] = useState(false); 14 | const [error, setError] = useState(false); 15 | 16 | 17 | useEffect(()=>{ 18 | const fetchData = async ()=>{ 19 | 20 | try{ 21 | setLoading(true) 22 | const {data} =await axios.post('/api/departments') 23 | setLoading(false) 24 | setDepartments(data) 25 | }catch(err){ 26 | setError(err.message) 27 | setLoading(false) 28 | } 29 | }; 30 | fetchData(); 31 | },[]) 32 | 33 | 34 | 35 | return ( 36 |
37 | {loading ? ( 38 | 39 | ) : error ? ( 40 | {error} 41 | ) : ( 42 |
43 | 44 |
45 | 46 |
47 | 48 | {departments.map(departments=>( 49 | 50 | ))} 51 |
52 |
53 |
54 | )} 55 |
56 | ) 57 | } 58 | 59 | export default Departments; 60 | -------------------------------------------------------------------------------- /backend/routers/departmentRouter.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import expressAsyncHandler from 'express-async-handler'; 3 | import Department from '../models/departmentModel.js'; 4 | 5 | 6 | 7 | 8 | const departmentRouter = express.Router(); 9 | 10 | departmentRouter.post('/', 11 | expressAsyncHandler(async (req, res) => { 12 | const departments = await Department.find({}); 13 | res.send(departments); 14 | }) 15 | ); 16 | 17 | 18 | departmentRouter.post('/add', 19 | expressAsyncHandler(async (req, res) =>{ 20 | const data = req.body 21 | const createdDepartment = await Department.insertMany(data.department); 22 | res.send({ createdDepartment }); 23 | }) 24 | 25 | ); 26 | 27 | 28 | departmentRouter.post('/delete', 29 | expressAsyncHandler(async (req, res) =>{ 30 | const data = req.body 31 | const deletedDepartment = await Department.deleteOne({ _id: data.id }); 32 | res.send({ deletedDepartment }); 33 | }) 34 | 35 | ); 36 | 37 | 38 | departmentRouter.post('/edit', 39 | expressAsyncHandler(async (req, res) =>{ 40 | const data = req.body 41 | const department = await Department.findById(data._id); 42 | if(department){ 43 | department.name = data.name || department.name; 44 | department.image = data.image || department.image; 45 | const updated = await department.save() 46 | res.send({ updated }); 47 | } 48 | 49 | 50 | }) 51 | 52 | ); 53 | 54 | 55 | departmentRouter.post( 56 | '/:id', 57 | expressAsyncHandler(async (req, res) => { 58 | const department = await Department.findById(req.params.id); 59 | if (department) { 60 | res.send(department); 61 | } else { 62 | res.status(404).send({ message: 'Department Not Found' }); 63 | } 64 | }) 65 | ); 66 | 67 | 68 | 69 | export default departmentRouter; -------------------------------------------------------------------------------- /frontend/src/reducers/adminReducers.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | // export const adminSigninReducer = (state = {}, action) => { 6 | // switch (action.type) { 7 | // case ADMIN_SIGNIN_REQUEST: 8 | // return { loading: true }; 9 | // case ADMIN_SIGNIN_SUCCESS: 10 | // return { loading: false, adminInfo: action.payload }; 11 | // case ADMIN_SIGNIN_FAIL: 12 | // return { loading: false, error: action.payload }; 13 | // case ADMIN_SIGNOUT: 14 | // return {}; 15 | // default: 16 | // return state; 17 | // } 18 | // }; 19 | 20 | import { ADMIN_TOTAL_USERS_LIST_FAIL, ADMIN_TOTAL_USERS_LIST_REQUEST, ADMIN_TOTAL_USERS_LIST_SUCCESS, ORDER_TOTAL_ADMIN_LIST_FAIL, ORDER_TOTAL_ADMIN_LIST_REQUEST, ORDER_TOTAL_ADMIN_LIST_SUCCESS } from "../constants/adminConstants"; 21 | 22 | 23 | export const adminTotalListOrderReducer = (state = {}, action) => { 24 | switch (action.type) { 25 | case ORDER_TOTAL_ADMIN_LIST_REQUEST: 26 | return { loading: true }; 27 | case ORDER_TOTAL_ADMIN_LIST_SUCCESS: 28 | return { loading: false, adminInfo: action.payload }; 29 | case ORDER_TOTAL_ADMIN_LIST_FAIL: 30 | return { loading: false, error: action.payload }; 31 | default: 32 | return state; 33 | } 34 | }; 35 | 36 | export const adminTotalListUserReducer = (state = {}, action) => { 37 | switch (action.type) { 38 | case ADMIN_TOTAL_USERS_LIST_REQUEST: 39 | return { loading: true }; 40 | case ADMIN_TOTAL_USERS_LIST_SUCCESS: 41 | return { loading: false, adminInfo: action.payload }; 42 | case ADMIN_TOTAL_USERS_LIST_FAIL: 43 | return { loading: false, error: action.payload }; 44 | default: 45 | return state; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /backend/models/orderModel.js: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | 3 | const orderSchema = new mongoose.Schema( 4 | { 5 | orderItems: [ 6 | { 7 | name: { type: String, required: true }, 8 | qty: { type: Number, required: true }, 9 | image: { type: String, required: true }, 10 | price: { type: Number, required: true }, 11 | product: { 12 | type: mongoose.Schema.Types.ObjectId, 13 | ref: 'Product', 14 | required: true, 15 | }, 16 | }, 17 | ], 18 | shippingAddress: { 19 | name: { type: String, required: true }, 20 | address: { type: String, required: true }, 21 | landmark: { type: String, required: true }, 22 | place: { type: String, required: true }, 23 | city: { type: String, required: true }, 24 | pinCode: { type: String, required: true }, 25 | state: { type: String, required: true }, 26 | country: { type: String, required: true }, 27 | mobile: { type: Number, required: true }, 28 | }, 29 | paymentMethod: { type: String, required: true }, 30 | paymentResult: { 31 | id: String, 32 | status: String, 33 | update_time: String, 34 | email_address: String, 35 | }, 36 | itemsPrice: { type: Number, required: true }, 37 | shippingPrice: { type: Number, required: true }, 38 | discountPrice: { type: Number, required: true }, 39 | totalPrice: { type: Number, required: true }, 40 | user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, 41 | isPaid: { type: Boolean, default: false }, 42 | paidAt: { type: Date }, 43 | isDelivered: { type: Boolean, default: false }, 44 | deliveredAt: { type: Date }, 45 | }, 46 | { 47 | timestamps: true, 48 | } 49 | ); 50 | const Order = mongoose.model('Order', orderSchema); 51 | export default Order; -------------------------------------------------------------------------------- /frontend/src/Components/Users/RowPosts/rowPost.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import './rowPost.css' 3 | import axios from 'axios'; 4 | import LoadingBox from '../LoadingBox/loadingBox'; 5 | import MessageBox from '../MessageBox/messageBox'; 6 | import { useNavigate } from "react-router-dom"; 7 | 8 | 9 | function RowPost() { 10 | 11 | const navigate = useNavigate(); 12 | 13 | const [products, setProducts] = useState([]); 14 | const [loading, setLoading] = useState(false); 15 | const [error, setError] = useState(false); 16 | 17 | 18 | useEffect(()=>{ 19 | const fetchData = async ()=>{ 20 | 21 | try{ 22 | setLoading(false) 23 | const{data}=await axios.post('/api/products/62e93ab19d39866975775821') 24 | setLoading(false) 25 | setProducts(data) 26 | }catch(err){ 27 | setError(err.message) 28 | setLoading(false) 29 | } 30 | }; 31 | fetchData(); 32 | },[]) 33 | 34 | return ( 35 |
36 | {loading ? ( 37 | 38 | ) : error ? ( 39 | {error} 40 | ) : ( 41 |
42 |
43 |
44 |
45 | {products.map(products=>( 46 | { 47 | e.preventDefault() 48 | navigate(`/products/${products._id}`) 49 | }}/> 50 | ))} 51 |
52 |
53 |
54 |
55 | )} 56 | 57 | 58 |
59 | ) 60 | } 61 | 62 | export default RowPost; 63 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "https://alanchrissantony.github.io/Amazon", 3 | "name": "frontend", 4 | "proxy": "http://127.0.0.1:8000", 5 | "version": "0.1.0", 6 | "private": true, 7 | "dependencies": { 8 | "@fortawesome/free-solid-svg-icons": "^6.1.2", 9 | "@material-ui/core": "^4.12.3", 10 | "@material-ui/icons": "^4.11.2", 11 | "@testing-library/jest-dom": "^5.16.1", 12 | "@testing-library/react": "^12.1.2", 13 | "@testing-library/user-event": "^13.5.0", 14 | "axios": "^1.7.2", 15 | "bootstrap": "^5.2.0", 16 | "dotenv": "^16.4.5", 17 | "firebase": "^9.6.6", 18 | "font-awesome": "^4.7.0", 19 | "font-awesome-icons": "^1.6.0", 20 | "http-proxy-middleware": "^2.0.6", 21 | "random": "^3.0.6", 22 | "react": "^17.0.2", 23 | "react-bootstrap": "^2.4.0", 24 | "react-bootstrap-icons": "^1.8.4", 25 | "react-circular-progressbar": "^2.1.0", 26 | "react-custom-scrollbars": "^4.2.1", 27 | "react-dom": "^17.0.2", 28 | "react-dotenv": "^0.1.3", 29 | "react-paypal-button-v2": "^2.6.3", 30 | "react-redux": "^7.2.6", 31 | "react-router-dom": "^6.2.1", 32 | "react-scripts": "^3.0.1", 33 | "redux": "^4.1.2", 34 | "redux-thunk": "^2.4.1", 35 | "web-vitals": "^2.1.4" 36 | }, 37 | "scripts": { 38 | "start": "react-scripts start", 39 | "predeploy": "npm run build", 40 | "deploy": "gh-pages -d build", 41 | "build": "react-scripts build", 42 | "test": "react-scripts test", 43 | "eject": "react-scripts eject" 44 | }, 45 | "eslintConfig": { 46 | "extends": [ 47 | "react-app", 48 | "react-app/jest" 49 | ] 50 | }, 51 | "browserslist": { 52 | "production": [ 53 | ">0.2%", 54 | "not dead", 55 | "not op_mini all" 56 | ], 57 | "development": [ 58 | "last 1 chrome version", 59 | "last 1 firefox version", 60 | "last 1 safari version" 61 | ] 62 | }, 63 | "devDependencies": { 64 | "@iconify/react": "^3.2.2", 65 | "gh-pages": "^5.0.0" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /frontend/src/store/store.js: -------------------------------------------------------------------------------- 1 | import { createStore, compose, applyMiddleware, combineReducers } from 'redux' 2 | import thunk from 'redux-thunk' 3 | import { adminTotalListOrderReducer, adminTotalListUserReducer } from '../reducers/adminReducers'; 4 | 5 | import { cartReducer } from '../reducers/cartReducers'; 6 | import { orderCreateReducer, orderDetailsReducer, orderMineListReducer, orderPayReducer } from '../reducers/orderReducers'; 7 | import { productDetailsReducer, productListReducer } from '../reducers/productReducers'; 8 | import { userDetailsReducer, userRegisterReducer, userSigninReducer, userUpdateProfileReducer, userVerifySignInReducer } from '../reducers/userReducers'; 9 | 10 | const initialState = { 11 | userSignin: { 12 | userInfo: localStorage.getItem('userInfo') 13 | ? JSON.parse(localStorage.getItem('userInfo')) 14 | : null, 15 | }, 16 | cart: { 17 | cartItems: localStorage.getItem('cartItems') 18 | ? JSON.parse(localStorage.getItem('cartItems')) 19 | : [], 20 | shippingAddress: localStorage.getItem('shippingAddress') 21 | ? JSON.parse(localStorage.getItem('shippingAddress')) 22 | : {}, 23 | paymentMethod: 'PayPal', 24 | }, 25 | 26 | }; 27 | const reducer = combineReducers({ 28 | productList: productListReducer, 29 | productDetails: productDetailsReducer, 30 | cart: cartReducer, 31 | userSignin: userSigninReducer, 32 | userRegister: userRegisterReducer, 33 | orderCreate: orderCreateReducer, 34 | orderDetails: orderDetailsReducer, 35 | orderPay: orderPayReducer, 36 | orderMineList: orderMineListReducer, 37 | userDetails: userDetailsReducer, 38 | userUpdateProfile: userUpdateProfileReducer, 39 | userVerifySignIn: userVerifySignInReducer, 40 | adminOrderList: adminTotalListOrderReducer, 41 | adminUserList: adminTotalListUserReducer, 42 | }) 43 | 44 | const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; 45 | 46 | const store = createStore(reducer, initialState, composeEnhancer(applyMiddleware(thunk))) 47 | 48 | 49 | export default store -------------------------------------------------------------------------------- /frontend/src/reducers/orderReducers.js: -------------------------------------------------------------------------------- 1 | import { ORDER_CREATE_FAIL, ORDER_CREATE_REQUEST, ORDER_CREATE_RESET, ORDER_CREATE_SUCCESS, ORDER_DETAILS_FAIL, ORDER_DETAILS_REQUEST, ORDER_DETAILS_SUCCESS, ORDER_PAY_FAIL, ORDER_PAY_REQUEST, ORDER_PAY_SUCCESS, ORDER_PAY_RESET, ORDER_MINE_LIST_REQUEST, ORDER_MINE_LIST_SUCCESS, ORDER_MINE_LIST_FAIL } from "../constants/orderConstants"; 2 | 3 | 4 | export const orderCreateReducer = (state = {}, action) => { 5 | switch (action.type) { 6 | case ORDER_CREATE_REQUEST: 7 | return { loading: true }; 8 | case ORDER_CREATE_SUCCESS: 9 | return { loading: false, success: true, order: action.payload }; 10 | case ORDER_CREATE_FAIL: 11 | return { loading: false, error: action.payload }; 12 | case ORDER_CREATE_RESET: 13 | return {}; 14 | default: 15 | return state; 16 | } 17 | }; 18 | 19 | export const orderDetailsReducer = ( 20 | state = { loading: true }, 21 | action 22 | ) => { 23 | switch (action.type) { 24 | case ORDER_DETAILS_REQUEST: 25 | return { loading: true }; 26 | case ORDER_DETAILS_SUCCESS: 27 | return { loading: false, order: action.payload }; 28 | case ORDER_DETAILS_FAIL: 29 | return { loading: false, error: action.payload }; 30 | default: 31 | return state; 32 | } 33 | }; 34 | 35 | 36 | export const orderPayReducer = (state = {}, action) => { 37 | switch (action.type) { 38 | case ORDER_PAY_REQUEST: 39 | return { loading: true } 40 | case ORDER_PAY_SUCCESS: 41 | return { loading: false, success: true } 42 | case ORDER_PAY_FAIL: 43 | return { loading: false, error: action.payload } 44 | case ORDER_PAY_RESET: 45 | return {}; 46 | default: 47 | return state; 48 | } 49 | } 50 | 51 | 52 | export const orderMineListReducer = (state = { orders: [] }, action) => { 53 | switch (action.type) { 54 | case ORDER_MINE_LIST_REQUEST: 55 | return { loading: true }; 56 | case ORDER_MINE_LIST_SUCCESS: 57 | return { loading: false, orders: action.payload }; 58 | case ORDER_MINE_LIST_FAIL: 59 | return { loading: false, error: action.payload }; 60 | default: 61 | return state; 62 | } 63 | }; -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Login/login.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useContext } from "react"; 2 | import "./login.css"; 3 | import logo from "../../../Images/AmazonLogo.png"; 4 | import { Link, useNavigate } from "react-router-dom"; 5 | import { FirebaseContext } from "../../../store/FirebaseContext"; 6 | 7 | function AdminLogin() { 8 | const navigate = useNavigate(); 9 | 10 | const [email, setEmail] = useState(""); 11 | const [password, setPassword] = useState(""); 12 | 13 | const { firebase } = useContext(FirebaseContext); 14 | 15 | const handleLogin = (e) => { 16 | e.preventDefault(); 17 | firebase 18 | .auth() 19 | .signInWithEmailAndPassword(email, password) 20 | .then(() => { 21 | navigate("/admin"); 22 | }) 23 | .catch((error) => { 24 | alert(error.message); 25 | }); 26 | }; 27 | 28 | return ( 29 |
30 |
31 | 32 |
33 |
34 |

Admin Panel

35 |

Sign In

36 |
37 |
38 |
39 | 40 | { 46 | setEmail(e.target.value); 47 | }} 48 | /> 49 |
50 |
51 |
52 | 53 | { 59 | setPassword(e.target.value); 60 | }} 61 | /> 62 |
63 |
64 |
65 | 66 | Return to home page 67 | 68 | 71 |
72 |
73 |
74 | ); 75 | } 76 | 77 | export default AdminLogin; 78 | -------------------------------------------------------------------------------- /backend/routers/orderRouter.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import expressAsyncHandler from "express-async-handler"; 3 | import Order from "../models/orderModel.js"; 4 | import { isAuth } from "../utils/utils.js"; 5 | 6 | 7 | const orderRouter = express.Router(); 8 | 9 | 10 | orderRouter.post( 11 | '/', 12 | isAuth, 13 | expressAsyncHandler(async (req, res) => { 14 | if (req.body.orderItems.length === 0) { 15 | res.status(400).send({ message: 'Cart is empty' }); 16 | } else { 17 | 18 | const order = new Order({ 19 | orderItems: req.body.orderItems, 20 | shippingAddress: req.body.shippingAddress, 21 | paymentMethod: req.body.paymentMethod, 22 | itemsPrice: req.body.itemsPrice, 23 | shippingPrice: req.body.shippingPrice, 24 | discountPrice: req.body.discountPrice, 25 | totalPrice: req.body.totalPrice, 26 | user: req.user._id, 27 | }); 28 | const createdOrder = await order.save(); 29 | res 30 | .status(201) 31 | .send({ message: 'New Order Created', order: createdOrder }); 32 | } 33 | }) 34 | ); 35 | 36 | 37 | orderRouter.get( 38 | '/:id', 39 | isAuth, 40 | expressAsyncHandler(async (req, res) => { 41 | const order = await Order.findById(req.params.id); 42 | if (order) { 43 | res.send(order); 44 | } else { 45 | res.status(404).send({ message: 'Order Not Found' }); 46 | } 47 | }) 48 | ); 49 | 50 | 51 | orderRouter.put( 52 | '/:id/pay', 53 | isAuth, 54 | expressAsyncHandler(async (req, res) => { 55 | const order = await Order.findById(req.params.id); 56 | if (order) { 57 | order.isPaid = true; 58 | order.paidAt = Date.now(); 59 | order.paymentResult = { 60 | id: req.body.id, 61 | status: req.body.status, 62 | update_time: req.body.update_time, 63 | email_address: req.body.email_address, 64 | }; 65 | const updatedOrder = await order.save(); 66 | res.send({ message: 'Order Paid', order: updatedOrder }); 67 | } else { 68 | res.status(404).send({ message: 'Order Not Found' }); 69 | } 70 | }) 71 | ); 72 | 73 | orderRouter.get( 74 | '/mine/history', 75 | isAuth, 76 | expressAsyncHandler(async (req, res) => { 77 | const orders = await Order.find({ user: req.user._id }).sort( { _id: -1 } ); 78 | res.send(orders); 79 | }) 80 | ); 81 | 82 | 83 | // Admin 84 | 85 | orderRouter.post('/admin/total&orders', 86 | expressAsyncHandler(async (req,res) => { 87 | const orders = await Order.find().sort({updatedAt: -1}); 88 | res.send(orders) 89 | }) 90 | ) 91 | 92 | 93 | export default orderRouter; -------------------------------------------------------------------------------- /backend/routers/productRouter.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import expressAsyncHandler from 'express-async-handler'; 3 | import data from '../Data/data.js'; 4 | import Product from '../models/productModel.js'; 5 | 6 | 7 | 8 | const productRouter = express.Router(); 9 | 10 | productRouter.get('/', 11 | expressAsyncHandler(async (req, res) => { 12 | const products = await Product.find({}); 13 | res.send(products); 14 | }) 15 | ); 16 | 17 | productRouter.get('/seed', 18 | expressAsyncHandler(async (req, res) => { 19 | // await Product.remove({}); 20 | const createdProducts = await Product.insertMany(data.products); 21 | res.send({ createdProducts }); 22 | }) 23 | ); 24 | 25 | productRouter.post('/add', 26 | expressAsyncHandler(async (req, res) =>{ 27 | const data = req.body 28 | const createdProduct = await Product.insertMany(data.product); 29 | res.send({ createdProduct }); 30 | }) 31 | 32 | ); 33 | 34 | productRouter.post('/edit', 35 | expressAsyncHandler(async (req, res) =>{ 36 | const data = req.body 37 | 38 | const product = await Product.findById(data._id); 39 | 40 | if(product){ 41 | 42 | product.name = data.name || product.name; 43 | product.image = data.image || product.image; 44 | product.brand = data.brand || product.brand; 45 | product.category = data.category || product.category; 46 | product.department = data.department || product.department; 47 | product.description = data.description || product.description; 48 | product.price = data.price || product.price; 49 | product.countInStock = data.countInStock || product.countInStock; 50 | 51 | } 52 | const updatedProduct = await product.save() 53 | 54 | res.send({ updatedProduct }); 55 | 56 | }) 57 | 58 | ); 59 | 60 | productRouter.post('/delete', 61 | expressAsyncHandler(async (req, res) =>{ 62 | const data = req.body 63 | const deletedProduct = await Product.deleteOne({ _id: data.id }); 64 | res.send({ deletedProduct }); 65 | }) 66 | 67 | ) 68 | 69 | productRouter.get('/:id', 70 | expressAsyncHandler(async (req, res) => { 71 | const product = await Product.findById(req.params.id); 72 | if (product) { 73 | res.send(product); 74 | } else { 75 | res.status(404).send({ message: 'Product Not Found' }); 76 | } 77 | }) 78 | ); 79 | 80 | 81 | productRouter.post('/:id', 82 | expressAsyncHandler(async (req, res) => { 83 | const product = await Product.find({department: req.params.id}); 84 | if (product) { 85 | res.send(product); 86 | } else { 87 | res.status(404).send({ message: 'Product Not Found' }); 88 | } 89 | }) 90 | ); 91 | 92 | 93 | export default productRouter; -------------------------------------------------------------------------------- /frontend/src/Components/Users/Signup/signup.css: -------------------------------------------------------------------------------- 1 | /* login page */ 2 | .container-signup{ 3 | color: #333; 4 | } 5 | .logo-container { 6 | width: 11%; 7 | margin: auto; 8 | } 9 | 10 | .logo-signup { 11 | width: 10rem; 12 | height: auto; 13 | cursor: pointer; 14 | } 15 | .signup-box { 16 | margin: auto; 17 | width: 30%; 18 | border: 1px solid rgb(232, 232, 232); 19 | padding: 10px; 20 | } 21 | #signup-btn { 22 | width: 20rem; 23 | height: 2rem; 24 | margin-left: 10%; 25 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, 26 | Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; 27 | background-color: #f0c14b; 28 | border-color: #a88734 #9c7e31 #846a29; 29 | border-radius: 5px; 30 | margin-top: 2rem; 31 | border: none; 32 | cursor: pointer; 33 | } 34 | #signup-btn:hover { 35 | background-color: #eebb3b; 36 | } 37 | .create-account-text{ 38 | font-size: xx-large; 39 | font-weight: 500; 40 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 41 | margin-left: 10%; 42 | margin-bottom: 1rem; 43 | } 44 | .name-label{ 45 | font-size: 13px; 46 | line-height: 19px; 47 | font-weight: 700; 48 | margin-left: 10%; 49 | } 50 | .input{ 51 | width: 20rem; 52 | margin-left: 10%; 53 | height: 31px; 54 | margin-top: 0.3rem; 55 | margin-bottom: 1rem; 56 | border-radius: 3px; 57 | font-family: Arial,sans-serif; 58 | font-size: 13px; 59 | border: 1px solid #d0d0d0; 60 | border-top: 1px solid #bbb; 61 | outline-color: #f69b3c; 62 | outline-width: thin; 63 | } 64 | .email-label{ 65 | font-size: 13px; 66 | line-height: 19px; 67 | font-weight: 700; 68 | margin-left: 10%; 69 | padding-top: 1rem; 70 | } 71 | .password-label{ 72 | font-size: 13px; 73 | line-height: 19px; 74 | font-weight: 700; 75 | padding-top: 1rem; 76 | margin-left: 10%; 77 | } 78 | .privacy-text{ 79 | font-size:small; 80 | margin-left: 10%; 81 | padding-top: 2rem; 82 | } 83 | .signin{ 84 | font-size:small; 85 | margin-left: 25%; 86 | cursor: pointer; 87 | } 88 | .signin:hover{ 89 | color: #15788b; 90 | } 91 | .signupErrorContent{ 92 | color: #a02020; 93 | text-align: center; 94 | margin-bottom: 1rem; 95 | padding-top: 0.5rem; 96 | padding-bottom: 0.5rem; 97 | } 98 | .signupErrorDiv{ 99 | background-color: #ffe0e0; 100 | width: 20rem; 101 | margin-left: 10%; 102 | height: auto; 103 | } -------------------------------------------------------------------------------- /frontend/src/reducers/userReducers.js: -------------------------------------------------------------------------------- 1 | import { USER_DETAILS_FAIL, USER_DETAILS_REQUEST, USER_DETAILS_SUCCESS, USER_REGISTER_FAIL, USER_REGISTER_REQUEST, USER_REGISTER_SUCCESS, USER_SIGNIN_FAIL, USER_SIGNIN_REQUEST, USER_SIGNIN_SUCCESS, USER_SIGNOUT, USER_UPDATE_PROFILE_FAIL, USER_UPDATE_PROFILE_REQUEST, USER_UPDATE_PROFILE_RESET, USER_UPDATE_PROFILE_SUCCESS, USER_VERIFY_SIGNIN_FAIL, USER_VERIFY_SIGNIN_REQUEST, USER_VERIFY_SIGNIN_SUCCESS } from "../constants/userconstants"; 2 | 3 | 4 | 5 | export const userRegisterReducer = (state = {}, action) => { 6 | switch (action.type) { 7 | case USER_REGISTER_REQUEST: 8 | return { loading: true }; 9 | case USER_REGISTER_SUCCESS: 10 | return { loading: false, userInfo: action.payload }; 11 | case USER_REGISTER_FAIL: 12 | return { loading: false, error: action.payload }; 13 | default: 14 | return state; 15 | } 16 | }; 17 | 18 | 19 | 20 | export const userSigninReducer = (state = {}, action) => { 21 | switch (action.type) { 22 | case USER_SIGNIN_REQUEST: 23 | return { loading: true }; 24 | case USER_SIGNIN_SUCCESS: 25 | return { loading: false, userInfo: action.payload }; 26 | case USER_SIGNIN_FAIL: 27 | return { loading: false, error: action.payload }; 28 | case USER_SIGNOUT: 29 | return {}; 30 | default: 31 | return state; 32 | } 33 | }; 34 | 35 | export const userDetailsReducer = (state = { loading: true }, action) => { 36 | switch (action.type) { 37 | case USER_DETAILS_REQUEST: 38 | return { loading: true }; 39 | case USER_DETAILS_SUCCESS: 40 | return { loading: false, user: action.payload }; 41 | case USER_DETAILS_FAIL: 42 | return { loading: false, error: action.payload }; 43 | default: 44 | return state; 45 | } 46 | }; 47 | 48 | 49 | export const userUpdateProfileReducer = (state = {}, action) => { 50 | switch (action.type) { 51 | case USER_UPDATE_PROFILE_REQUEST: 52 | return { loading: true }; 53 | case USER_UPDATE_PROFILE_SUCCESS: 54 | return { loading: false, success: true }; 55 | case USER_UPDATE_PROFILE_FAIL: 56 | return { loading: false, error: action.payload }; 57 | case USER_UPDATE_PROFILE_RESET: 58 | return {}; 59 | default: 60 | return state; 61 | } 62 | }; 63 | 64 | export const userVerifySignInReducer = (state = {}, action) => { 65 | switch (action.type) { 66 | case USER_VERIFY_SIGNIN_REQUEST: 67 | return { loading: true }; 68 | case USER_VERIFY_SIGNIN_SUCCESS: 69 | return { loading: false, success: true }; 70 | case USER_VERIFY_SIGNIN_FAIL: 71 | return { loading: false, error: action.payload }; 72 | default: 73 | return state; 74 | } 75 | }; -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Header/header.css: -------------------------------------------------------------------------------- 1 | .containerheader{ 2 | height: 60px; 3 | width: 100%; 4 | position: absolute; 5 | background-color: #131921; 6 | } 7 | .logo{ 8 | width: 96px; 9 | margin: 1.1rem; 10 | position: absolute; 11 | cursor: pointer; 12 | } 13 | .panelTextDiv{ 14 | margin-left: 70%; 15 | } 16 | .productsText{ 17 | margin-left: 2rem; 18 | margin-top: 1rem; 19 | float: left; 20 | cursor: pointer; 21 | } 22 | .usersText{ 23 | margin-left: 2rem; 24 | margin-top: 1rem; 25 | float: left; 26 | cursor: pointer; 27 | } 28 | .ordersText{ 29 | margin-left: 2rem; 30 | margin-top: 1rem; 31 | float: left; 32 | cursor: pointer; 33 | } 34 | .adminText{ 35 | margin-left: 2rem; 36 | margin-top: 1rem; 37 | float: left; 38 | cursor: pointer; 39 | } 40 | .panelText{ 41 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 42 | font-size: 1rem; 43 | font-weight: 400; 44 | line-height: 1.5; 45 | color: darkgray; 46 | cursor: pointer; 47 | 48 | } 49 | .panelText:hover{ 50 | color: whitesmoke; 51 | } 52 | .headerSignOutBtn{ 53 | display: block; 54 | height: 33px; 55 | cursor: pointer; 56 | outline: 0; 57 | border: 1px solid; 58 | border-color: #c89411 #b0820f #99710d; 59 | border-radius: 3px 3px 3px 3px; 60 | box-shadow: inset 0 1px 0 0 #fcf3dc; 61 | background: -webkit-linear-gradient(top,#f8e3ad,#EEBA37); 62 | text-align: center; 63 | line-height: 31px; 64 | color: #111; 65 | text-decoration: none; 66 | line-height: 30px; 67 | font-size: 13px; 68 | width: 5rem; 69 | margin-left: auto; 70 | margin-right: auto; 71 | } 72 | .headerSignOutDiv{ 73 | width: 8rem; 74 | height: 4rem; 75 | background-color: #fff; 76 | z-index: 10000; 77 | position: relative; 78 | box-shadow: 0 2px 4px 0 rgb(0 0 0 / 13%); 79 | overflow: visible; 80 | border: 1px solid #bbb; 81 | border-radius: 3px 3px 3px 3px; 82 | margin-left: -2.5rem; 83 | } 84 | .dropdown-content{ 85 | position: absolute; 86 | display: none; 87 | } 88 | .panelText:hover .dropdown-content{ 89 | display: block; 90 | } 91 | 92 | .adminSearchBarDiv{ 93 | margin-left: 2rem; 94 | margin-top: 0.65rem; 95 | float: left; 96 | width: 70%; 97 | justify-items: end; 98 | justify-content: end; 99 | display: flex; 100 | } 101 | .adminSearchBar{ 102 | height: 39px; 103 | width: 80%; 104 | outline: none; 105 | border-right: none; 106 | box-shadow: none; 107 | border-bottom: none; 108 | } 109 | .headerSearchList{ 110 | width: 755px; 111 | height: auto; 112 | background-color: white; 113 | position: absolute; 114 | z-index: 999; 115 | margin-top: 49px; 116 | margin-left: 183px; 117 | border: 1px solid #ccc; 118 | } 119 | .headerSearchList div{ 120 | margin: 1rem; 121 | } 122 | .headerSearchList p{ 123 | font-weight: 700; 124 | cursor: pointer; 125 | } -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Login/login.css: -------------------------------------------------------------------------------- 1 | .adminLoginContainer{ 2 | width: 100%; 3 | height: 39rem; 4 | 5 | } 6 | .imgLogo{ 7 | width: 30%; 8 | height: auto; 9 | margin-left: 35%; 10 | } 11 | .logincontainer{ 12 | width: 40%; 13 | height: 20rem; 14 | margin-left: auto; 15 | margin-right: auto; 16 | border-radius: 8px 8px 0 0; 17 | border: 1px #D5D9D9 solid; 18 | } 19 | .signinContainer{ 20 | width: 100%; 21 | height: 4rem; 22 | background-color: #F0F2F2; 23 | } 24 | .AdminText{ 25 | font-size: xx-large; 26 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 27 | font-weight: 300; 28 | padding-left: 1rem; 29 | padding-top: 1rem; 30 | float: left; 31 | color: #565959; 32 | } 33 | .signInText{ 34 | font-size: xx-large; 35 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 36 | font-weight: 300; 37 | text-align: right; 38 | margin-right: 1rem; 39 | padding-top: 1rem; 40 | color: #333; 41 | } 42 | .fa-user{ 43 | float: left; 44 | margin-left: -164px; 45 | padding-top: 56px; 46 | } 47 | .usernameInput{ 48 | margin-left: 50px; 49 | margin-top: 2rem; 50 | width: 80%; 51 | border-radius: 3px; 52 | font-family: Arial,sans-serif; 53 | font-size: 13px; 54 | border: 1px solid #d0d0d0; 55 | border-top: 1px solid #bbb; 56 | outline-color: #f69b3c; 57 | outline-width: thin; 58 | height: 2rem; 59 | } 60 | .fa-lock{ 61 | margin-top: 2.5rem; 62 | margin-left: 2rem; 63 | float: left; 64 | } 65 | .passwordInput{ 66 | margin-left: 5px; 67 | margin-top: 2rem; 68 | width: 80%; 69 | height: 2rem; 70 | border-radius: 3px; 71 | font-family: Arial,sans-serif; 72 | font-size: 13px; 73 | border: 1px solid #d0d0d0; 74 | border-top: 1px solid #bbb; 75 | outline-color: #f69b3c; 76 | outline-width: thin; 77 | } 78 | .btn-login{ 79 | margin-left: auto; 80 | margin-right: 3.5rem; 81 | margin-top: 3rem; 82 | width: 150px; 83 | height: 31px; 84 | color: #111; 85 | text-align: center; 86 | font-size: 13px; 87 | display: block; 88 | font-family: Arial,sans-serif; 89 | white-space: nowrap; 90 | background-color: transparent; 91 | background-color: #f0c24f; 92 | border-radius: 3px; 93 | border: 1px solid; 94 | border-color: #bf942b; 95 | outline: #f69b3c; 96 | cursor: pointer; 97 | margin-bottom: 2rem; 98 | } 99 | .adminLoginReturn{ 100 | margin-top: 4rem; 101 | margin-left: 3.5rem; 102 | color: #007185; 103 | font-size: 14px; 104 | line-height: 20px; 105 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 106 | cursor: pointer; 107 | float: left; 108 | } 109 | .adminLoginReturn:hover{ 110 | color: #c45500; 111 | text-decoration: underline; 112 | } -------------------------------------------------------------------------------- /backend/routers/userRouter.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import data from "../Data/data.js"; 3 | import User from "../models/userModel.js"; 4 | import expressAsyncHandler from "express-async-handler"; 5 | import bcrypt from "bcryptjs"; 6 | import { generateToken, isAuth } from "../utils/utils.js"; 7 | 8 | const userRouter = express.Router(); 9 | 10 | userRouter.get( 11 | '/seed', 12 | expressAsyncHandler(async (req, res) => { 13 | // await User.remove({}); 14 | const createdUsers = await User.insertMany(data.users); 15 | res.send({ createdUsers }); 16 | }) 17 | ); 18 | 19 | 20 | 21 | userRouter.post( 22 | '/signin', 23 | expressAsyncHandler(async (req, res) => { 24 | const user = await User.findOne({ email: req.body.email }); 25 | if (user) { 26 | if (bcrypt.compareSync(req.body.password, user.password)) { 27 | res.send({ 28 | _id: user._id, 29 | name: user.name, 30 | email: user.email, 31 | isAdmin: user.isAdmin, 32 | token: generateToken(user), 33 | }); 34 | return; 35 | } 36 | } 37 | res.status(401).send({ message: 'Invalid email or password' }); 38 | }) 39 | ); 40 | 41 | 42 | userRouter.post( 43 | '/register', 44 | expressAsyncHandler(async (req, res) => { 45 | const user = new User({ 46 | name: req.body.name, 47 | email: req.body.email, 48 | password: bcrypt.hashSync(req.body.password, 8), 49 | }); 50 | const createdUser = await user.save(); 51 | res.send({ 52 | _id: createdUser._id, 53 | name: createdUser.name, 54 | email: createdUser.email, 55 | isAdmin: createdUser.isAdmin, 56 | token: generateToken(createdUser), 57 | }); 58 | }) 59 | ); 60 | 61 | userRouter.get( 62 | '/:id', 63 | expressAsyncHandler(async (req, res) => { 64 | const user = await User.findById(req.params.id); 65 | if (user) { 66 | res.send(user); 67 | } else { 68 | res.status(404).send({ message: 'User Not Found' }); 69 | } 70 | }) 71 | ); 72 | 73 | userRouter.put( 74 | '/profile', 75 | isAuth, 76 | expressAsyncHandler(async (req, res) => { 77 | const user = await User.findById(req.user._id); 78 | if (user) { 79 | user.name = req.body.name || user.name; 80 | user.email = req.body.email || user.email; 81 | if (req.body.password) { 82 | user.password = bcrypt.hashSync(req.body.password, 8); 83 | } 84 | const updatedUser = await user.save(); 85 | res.send({ 86 | _id: updatedUser._id, 87 | name: updatedUser.name, 88 | email: updatedUser.email, 89 | isAdmin: updatedUser.isAdmin, 90 | token: generateToken(updatedUser), 91 | }); 92 | } 93 | }) 94 | ); 95 | 96 | 97 | userRouter.post('/admin/total&users', 98 | expressAsyncHandler(async (req,res) => { 99 | const users = await User.find(); 100 | res.send(users) 101 | }) 102 | ); 103 | 104 | 105 | userRouter.post('/delete', 106 | expressAsyncHandler(async (req, res) =>{ 107 | const data = req.body 108 | const deletedUser = await User.deleteOne({ _id: data.id }); 109 | res.send({ deletedUser }); 110 | }) 111 | 112 | ); 113 | 114 | 115 | export default userRouter; -------------------------------------------------------------------------------- /frontend/src/Components/Users/Products/products.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import './products.css' 3 | import {useNavigate} from 'react-router-dom' 4 | import LoadingBox from '../LoadingBox/loadingBox'; 5 | import MessageBox from '../MessageBox/messageBox'; 6 | import { useDispatch, useSelector } from 'react-redux'; 7 | import { listProducts } from '../../../actions/productActions'; 8 | 9 | function Products() { 10 | 11 | const navigate = useNavigate() 12 | 13 | const dispatch = useDispatch() 14 | const productList = useSelector((state)=> state.productList) 15 | const {loading, error, products} = productList 16 | 17 | useEffect(() => { 18 | dispatch(listProducts()) 19 | }, []) 20 | 21 | return ( 22 |
23 | {loading ? ( 24 | 25 | ) : error ? ( 26 | {error} 27 | ) : ( 28 |
29 | {products.map(product => ( 30 |
{ 31 | navigate(`/products/${product._id}`) 32 | }}> 33 |
34 | 35 |
36 |
37 |

{product.description}

38 |
39 | 40 |
41 | = 1 ? "fa fa-star" : product.rating >= 0.5 ? "fa fa-star-half" : "fa fa-star-o"}> 42 | = 2 ? "fa fa-star" : product.rating >= 1.5 ? "fa fa-star-half" : "fa fa-star-o"}> 43 | = 3 ? "fa fa-star" : product.rating >= 2.5 ? "fa fa-star-half" : "fa fa-star-o"}> 44 | = 4 ? "fa fa-star" : product.rating >= 3.5 ? "fa fa-star-half" : "fa fa-star-o"}> 45 | = 5 ? "fa fa-star" : product.rating >= 4.5 ? "fa fa-star-half" : "fa fa-star-o"}> 46 |
47 |
{product.review}
48 |
49 |
50 |

${product.price}

51 |
52 |
53 |
54 | ))} 55 | 56 |
57 | )} 58 | 59 |
60 | ) 61 | } 62 | 63 | export default Products; 64 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Products/product.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import './products.css' 3 | import {useNavigate} from 'react-router-dom' 4 | import LoadingBox from '../LoadingBox/loadingBox'; 5 | import axios from '../../../../node_modules/axios/index'; 6 | 7 | 8 | function Product() { 9 | 10 | const navigate = useNavigate() 11 | 12 | const [products, setProducts] = useState(false) 13 | 14 | 15 | 16 | const dispatch_products = async()=>{ 17 | let path = window.location.pathname 18 | path = path.split('/')[2] 19 | 20 | const data = await axios.post(`/api/products/${path}`) 21 | 22 | setProducts(data.data) 23 | } 24 | 25 | 26 | useEffect(() => { 27 | 28 | dispatch_products() 29 | }, [window.location.pathname.split('/')[2]]) 30 | 31 | return ( 32 |
33 | {!products ? ( 34 | 35 | ) : ( 36 |
37 | {products.map(product => ( 38 |
{ 39 | navigate(`/products/${product._id}`) 40 | }}> 41 |
42 | 43 |
44 |
45 |

{product.description}

46 |
47 | 48 |
49 | = 1 ? "fa fa-star" : product.rating >= 0.5 ? "fa fa-star-half" : "fa fa-star-o"}> 50 | = 2 ? "fa fa-star" : product.rating >= 1.5 ? "fa fa-star-half" : "fa fa-star-o"}> 51 | = 3 ? "fa fa-star" : product.rating >= 2.5 ? "fa fa-star-half" : "fa fa-star-o"}> 52 | = 4 ? "fa fa-star" : product.rating >= 3.5 ? "fa fa-star-half" : "fa fa-star-o"}> 53 | = 5 ? "fa fa-star" : product.rating >= 4.5 ? "fa fa-star-half" : "fa fa-star-o"}> 54 |
55 |
{product.review}
56 |
57 |
58 |

${product.price}

59 |
60 |
61 |
62 | ))} 63 | 64 |
65 | )} 66 | 67 |
68 | ) 69 | } 70 | 71 | export default Product; 72 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Login/login.css: -------------------------------------------------------------------------------- 1 | /* login page */ 2 | 3 | .logo-container { 4 | width: 11%; 5 | margin: auto; 6 | } 7 | 8 | .logo-login { 9 | width: 10rem; 10 | height: auto; 11 | cursor: pointer; 12 | } 13 | .login-box { 14 | margin: auto; 15 | width: 30%; 16 | border: 1px solid rgb(232, 232, 232); 17 | padding: 10px; 18 | color: #333; 19 | } 20 | #login-btn { 21 | width: 20rem; 22 | height: 2rem; 23 | margin-left: 10%; 24 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, 25 | Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; 26 | background-color: #f0c14b; 27 | border-color: #a88734 #9c7e31 #846a29; 28 | border-radius: 5px; 29 | margin-top: 3rem; 30 | border: none; 31 | cursor: pointer; 32 | } 33 | #create-btn { 34 | width: 20rem; 35 | height: 2rem; 36 | margin-left: 3rem; 37 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, 38 | Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; 39 | background-color: #e7e9ec; 40 | border-radius: 5px; 41 | margin-top: 2rem; 42 | border: none; 43 | cursor: pointer; 44 | } 45 | #login-btn:hover { 46 | background-color: #eebb3b; 47 | } 48 | #create-btn:hover { 49 | background-color: #f0c14b; 50 | } 51 | 52 | .signin-text { 53 | font-size: xx-large; 54 | font-weight: 500; 55 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, 56 | Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; 57 | margin-left: 10%; 58 | margin-bottom: 2rem; 59 | } 60 | .email-label { 61 | font-size: 13px; 62 | line-height: 19px; 63 | font-weight: 700; 64 | margin-left: 10%; 65 | } 66 | .email-input { 67 | width: 20rem; 68 | margin-left: 10%; 69 | height: 28px; 70 | margin-top: 0.3rem; 71 | margin-bottom: 1rem; 72 | border-radius: 3px; 73 | font-family: Arial,sans-serif; 74 | font-size: 13px; 75 | border: 1px solid #d0d0d0; 76 | border-top: 1px solid #bbb; 77 | outline-color: #f69b3c; 78 | outline-width: thin; 79 | } 80 | .password-label { 81 | font-size: 13px; 82 | line-height: 19px; 83 | font-weight: 700; 84 | padding-top: 1rem; 85 | margin-left: 10%; 86 | } 87 | .password-input { 88 | width: 20rem; 89 | margin-left: 10%; 90 | height: 28px; 91 | margin-top: 0.3rem; 92 | border-radius: 3px; 93 | font-family: Arial,sans-serif; 94 | font-size: 13px; 95 | border: 1px solid #d0d0d0; 96 | border-top: 1px solid #bbb; 97 | outline-color: #f69b3c; 98 | outline-width: thin; 99 | } 100 | .privacy-text { 101 | font-size: small; 102 | margin-left: 10%; 103 | padding-top: 3rem; 104 | } 105 | .new-to-amazon-text { 106 | font-size: small; 107 | margin-left: 1rem; 108 | padding-top: 1rem; 109 | text-align: center; 110 | } 111 | .loginErrorContent{ 112 | color: #a02020; 113 | text-align: center; 114 | margin-bottom: 1rem; 115 | padding-top: 0.5rem; 116 | padding-bottom: 0.5rem; 117 | } 118 | .loginErrorDiv{ 119 | background-color: #ffe0e0; 120 | width: 20rem; 121 | margin-left: 10%; 122 | height: auto; 123 | } -------------------------------------------------------------------------------- /frontend/src/actions/orderActions.js: -------------------------------------------------------------------------------- 1 | import Axios from "axios"; 2 | import { CART_EMPTY } from "../constants/cartConstants"; 3 | import { ORDER_CREATE_FAIL, ORDER_CREATE_REQUEST, ORDER_CREATE_SUCCESS, ORDER_DETAILS_FAIL, ORDER_DETAILS_REQUEST, ORDER_DETAILS_SUCCESS, ORDER_MINE_LIST_FAIL, ORDER_MINE_LIST_REQUEST, ORDER_MINE_LIST_SUCCESS, ORDER_PAY_FAIL, ORDER_PAY_REQUEST, ORDER_PAY_SUCCESS } from "../constants/orderConstants" 4 | 5 | export const createOrder = (order) => async (dispatch, getState) => { 6 | dispatch({ type: ORDER_CREATE_REQUEST, payload: order }); 7 | try { 8 | const { 9 | userSignin: { userInfo }, 10 | } = getState(); 11 | const { data } = await Axios.post('/api/orders', order, { 12 | headers: { 13 | Authorization: `Bearer ${userInfo.token}`, 14 | }, 15 | }); 16 | dispatch({ type: ORDER_CREATE_SUCCESS, payload: data.order }); 17 | dispatch({ type: CART_EMPTY }); 18 | localStorage.removeItem('cartItems'); 19 | } catch (error) { 20 | dispatch({ 21 | type: ORDER_CREATE_FAIL, 22 | payload: 23 | error.response && error.response.data.message 24 | ? error.response.data.message 25 | : error.message, 26 | }); 27 | } 28 | }; 29 | 30 | export const detailsOrder = (orderId) => async (dispatch, getState) => { 31 | dispatch({ type: ORDER_DETAILS_REQUEST, payload: orderId }); 32 | const { 33 | userSignin: { userInfo }, 34 | } = getState(); 35 | try { 36 | const { data } = await Axios.get(`/api/orders/${orderId}`, { 37 | headers: { Authorization: `Bearer ${userInfo.token}` }, 38 | }); 39 | 40 | dispatch({ type: ORDER_DETAILS_SUCCESS, payload: data }); 41 | localStorage.setItem('orderDetails', JSON.stringify(data)); 42 | } catch (error) { 43 | const message = 44 | error.response && error.response.data.message 45 | ? error.response.data.message 46 | : error.message; 47 | dispatch({ type: ORDER_DETAILS_FAIL, payload: message }); 48 | } 49 | }; 50 | 51 | 52 | export const payOrder = (order, paymentResult) => async ( 53 | dispatch, 54 | getState 55 | ) => { 56 | dispatch({ type: ORDER_PAY_REQUEST, payload: { order, paymentResult } }); 57 | const { 58 | userSignin: { userInfo }, 59 | } = getState(); 60 | try { 61 | const { data } = Axios.put(`/api/orders/${order._id}/pay`, paymentResult, { 62 | headers: { Authorization: `Bearer ${userInfo.token}` }, 63 | }); 64 | dispatch({ type: ORDER_PAY_SUCCESS, payload: data }); 65 | } catch (error) { 66 | const message = 67 | error.response && error.response.data.message 68 | ? error.response.data.message 69 | : error.message; 70 | dispatch({ type: ORDER_PAY_FAIL, payload: message }); 71 | } 72 | }; 73 | 74 | 75 | export const listOrderMine = () => async (dispatch, getState) => { 76 | dispatch({ type: ORDER_MINE_LIST_REQUEST }); 77 | const { 78 | userSignin: { userInfo }, 79 | } = getState(); 80 | try { 81 | const { data } = await Axios.get('/api/orders/mine/history', { 82 | headers: { 83 | Authorization: `Bearer ${userInfo.token}`, 84 | }, 85 | }); 86 | 87 | dispatch({ type: ORDER_MINE_LIST_SUCCESS, payload: data }); 88 | } catch (error) { 89 | const message = 90 | error.response && error.response.data.message 91 | ? error.response.data.message 92 | : error.message; 93 | 94 | dispatch({ type: ORDER_MINE_LIST_FAIL, payload: message }); 95 | } 96 | }; 97 | 98 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 13 | 14 | The page will reload when you make changes.\ 15 | You may also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 35 | 36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 39 | 40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /frontend/src/Images/logo.svg: -------------------------------------------------------------------------------- 1 | Amazon-logo-RGB-REV -------------------------------------------------------------------------------- /frontend/src/Components/Users/Login/login.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import logo from '../../../Images/AmazonLogo.png' 3 | import { useNavigate } from 'react-router-dom' 4 | import './login.css' 5 | import { useDispatch, useSelector } from 'react-redux' 6 | import { signin } from '../../../actions/userActions' 7 | import LoadingBox from '../LoadingBox/loadingBox' 8 | import { useEffect } from 'react' 9 | 10 | function Login() { 11 | 12 | const navigate = useNavigate() 13 | 14 | 15 | const [email, setEmail] = useState('') 16 | const [password, setPassword] = useState('') 17 | 18 | const dispatch = useDispatch() 19 | 20 | 21 | const userSignIn = useSelector((state) => state.userSignin) 22 | const { userInfo, loading, error } = userSignIn; 23 | 24 | 25 | const handleLogin = (e) => { 26 | e.preventDefault() 27 | dispatch(signin(email,password)) 28 | } 29 | 30 | const pathname = window.location.search 31 | const pathUrl = pathname.split('=') 32 | const path = pathUrl[1] 33 | 34 | useEffect(()=>{ 35 | if(userInfo){ 36 | if(path){ 37 | navigate(`/${path}`) 38 | }else{ 39 | navigate('/') 40 | } 41 | } 42 | }) 43 | 44 | 45 | 46 | return ( 47 |
48 |
49 |
50 |
51 | { 52 | e.preventDefault() 53 | navigate('/') 54 | }} alt="" /> 55 |
56 |
57 |
58 |

Sign-In

59 | {loading && } 60 | {error &&

{error} !

} 61 | 62 |
63 | setEmail(e.target.value)} /> 65 |
66 | 67 |
68 | setPassword(e.target.value)} /> 70 |
71 | 72 |
73 |

By continuing, you agree to Amazon's Conditions of Use
and Privacy Notice.

74 |
75 |
76 |

New to Amazon?

77 | 81 | 82 |
83 |
84 |
85 |
86 |
87 | ) 88 | } 89 | 90 | export default Login; 91 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Profile/email.css: -------------------------------------------------------------------------------- 1 | .emailChangeSection{ 2 | width: 100%; 3 | height: auto; 4 | } 5 | .emailChangeContainer{ 6 | width: 60%; 7 | height: auto; 8 | margin-left: auto; 9 | margin-right: auto; 10 | } 11 | .emailChangeLogoDiv{ 12 | width: 256px; 13 | height: auto; 14 | margin-left: auto; 15 | margin-right: auto; 16 | } 17 | .emailChangeLogo{ 18 | max-width: 256px; 19 | cursor: pointer; 20 | } 21 | .emailChangeBoxContainer{ 22 | margin-left: auto; 23 | margin-right: auto; 24 | border-radius: 8px; 25 | background-color: #fff; 26 | width: 378px; 27 | height: auto; 28 | overflow: auto; 29 | border: 1px #D5D9D9 solid; 30 | margin-top: 1rem; 31 | } 32 | .emailChangeBoxDiv{ 33 | width: 90%; 34 | margin-top: 2rem; 35 | height: auto; 36 | margin-left: auto; 37 | margin-right: auto; 38 | } 39 | .emailChangeBoxTitle{ 40 | font-weight: 400; 41 | font-size: 28px; 42 | line-height: 36px; 43 | color: #0F1111; 44 | } 45 | .emailChangeBoxEmailTextDiv{ 46 | margin-top: 1rem; 47 | } 48 | .emailChangeBoxEmailText{ 49 | color: #0F1111; 50 | font-size: 14px; 51 | line-height: 20px; 52 | } 53 | .emailChangeBoxParaTextDiv{ 54 | margin-top: 1rem; 55 | } 56 | .emailChangeBoxParaText{ 57 | color: #0F1111; 58 | font-size: 14px; 59 | line-height: 20px; 60 | } 61 | .emailChangeBoxInputDiv{ 62 | margin-top: 2rem; 63 | } 64 | .emailChangeBoxLabel{ 65 | font-weight: 700; 66 | color: #0F1111; 67 | font-size: 14px; 68 | line-height: 20px; 69 | } 70 | .emailChangeBoxInput{ 71 | margin-top: 0.25rem; 72 | width: 100%; 73 | height: 31px; 74 | border-radius: 3px; 75 | font-family: Arial,sans-serif; 76 | font-size: 13px; 77 | border: 1px solid #d0d0d0; 78 | border-top: 1px solid #bbb; 79 | outline-color: #f69b3c; 80 | outline-width: thin; 81 | } 82 | .emailChangeBoxBtnDiv{ 83 | margin-top: 2rem; 84 | margin-bottom: 2rem; 85 | } 86 | .emailChangeBoxBtn{ 87 | width: 100%; 88 | height: 31px; 89 | border-radius: 8px; 90 | box-shadow: 0 2px 5px 0 rgb(213 217 217 / 50%); 91 | background: #FFD814; 92 | border-color: #FCD200; 93 | border-style: solid; 94 | border-width: 1px; 95 | cursor: pointer; 96 | display: inline-block; 97 | padding: 0; 98 | text-align: center; 99 | text-decoration: none; 100 | vertical-align: middle; 101 | color: #0F1111; 102 | font-size: 14px; 103 | line-height: 20px; 104 | } 105 | .emailChangeBoxBtn:hover{ 106 | background-color: #FDD000; 107 | } 108 | .emailChangeErrorContent { 109 | color: #721c24; 110 | text-align: center; 111 | margin-bottom: 1rem; 112 | padding-top: 1rem; 113 | padding-bottom: 0.25rem; 114 | } 115 | .emailChangeErrorDiv { 116 | background-color: #f8d7da; 117 | border-color: #f5c6cb; 118 | border-radius: 3px; 119 | border-width: 1px; 120 | border-style: solid; 121 | width: 100%; 122 | margin-bottom: 0.5rem; 123 | margin-left: auto; 124 | margin-right: auto; 125 | height: auto; 126 | } 127 | .emailChangeSuccessContent { 128 | color: #155724; 129 | text-align: center; 130 | margin-bottom: 1rem; 131 | padding-top: 1rem; 132 | padding-bottom: 0.25rem; 133 | } 134 | .emailChangeSuccessDiv { 135 | background-color: #d4edda; 136 | border-color: #c3e6cb; 137 | border-radius: 3px; 138 | border-width: 1px; 139 | border-style: solid; 140 | width: 100%; 141 | margin-bottom: 0.5rem; 142 | margin-left: auto; 143 | margin-right: auto; 144 | height: auto; 145 | } 146 | -------------------------------------------------------------------------------- /frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 43 | Amazon 44 | 45 | 46 | 47 | 48 |
49 | 59 | 60 | 61 | 62 | 65 | 66 | 69 | 72 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Order/order.css: -------------------------------------------------------------------------------- 1 | .orderSection{ 2 | width: 100%; 3 | height: auto; 4 | min-height: 550px; 5 | } 6 | .orderSectionContainer{ 7 | width: 95%; 8 | height: auto; 9 | background-color: #f0f2f2; 10 | margin-left: auto; 11 | margin-right: auto; 12 | margin-top: 1rem; 13 | border-radius: 8px; 14 | overflow: auto; 15 | } 16 | .orderSectionContainerDiv{ 17 | width: 95%; 18 | height: auto; 19 | background-color: #fff; 20 | margin-left: auto; 21 | margin-right: auto; 22 | margin-top: 1rem; 23 | border-radius: 8px; 24 | margin-bottom: 2rem; 25 | overflow: auto; 26 | border-style: solid; 27 | border-width: 1px; 28 | border-color: #d5d9d9; 29 | } 30 | .orderContainerSection{ 31 | width: 95%; 32 | height: auto; 33 | margin-left: auto; 34 | margin-right: auto; 35 | border-radius: 8px; 36 | margin-bottom: 1rem; 37 | } 38 | .orderPlaceTitle{ 39 | font-weight: 700; 40 | font-size: 18px; 41 | line-height: 24px; 42 | color: #067D62; 43 | font-family: "Amazon Ember",Arial,sans-serif; 44 | margin-left: 2rem; 45 | } 46 | .orderPlaceIcon{ 47 | width: 24px; 48 | height: auto; 49 | float: left; 50 | } 51 | .orderPlaceConformationDiv{ 52 | margin-top: 1rem; 53 | } 54 | .orderPlaceConformationText{ 55 | font-family: "Amazon Ember",Arial,sans-serif; 56 | color: #0F1111; 57 | font-size: 14px; 58 | line-height: 20px; 59 | } 60 | .orderPlaceShippingDiv{ 61 | margin-top: 1rem; 62 | } 63 | .orderPlaceShipping{ 64 | font-size: 14px; 65 | line-height: 20px; 66 | color: #0F1111; 67 | font-weight: 700; 68 | } 69 | .orderPlaceHr{ 70 | color: #d5d9d9; 71 | } 72 | .orderProductContainer{ 73 | margin-top: 1rem; 74 | } 75 | .orderPlaceDeliveryDate{ 76 | color: #007600; 77 | font-weight: 700; 78 | font-family: "Amazon Ember",Arial,sans-serif; 79 | font-size: 14px; 80 | line-height: 20px; 81 | 82 | } 83 | .orderPlaceDeliveryText{ 84 | color: #0F1111; 85 | font-family: "Amazon Ember",Arial,sans-serif; 86 | font-size: 14px; 87 | line-height: 20px; 88 | } 89 | .orderPlaceReviewDiv{ 90 | margin-top: 2rem; 91 | } 92 | .orderPlaceReview{ 93 | font-size: 14px; 94 | line-height: 20px; 95 | color: #007185; 96 | cursor: pointer; 97 | } 98 | .orderPlaceReview:hover{ 99 | text-decoration: underline; 100 | color: #C7511F; 101 | } 102 | .orderPlacePaidAtDiv{ 103 | margin-bottom: 1rem; 104 | } 105 | .orderPlacePaidAt{ 106 | font-size: 14px; 107 | line-height: 20px; 108 | color: #007600; 109 | } 110 | .orderPlacePaidAtText{ 111 | font-size: 14px; 112 | line-height: 20px; 113 | color: #0F1111; 114 | } 115 | .orderPlaceProductImageDiv{ 116 | float: left; 117 | margin-left: 2rem; 118 | } 119 | .orderPlaceProductImage{ 120 | max-width: 100px; 121 | max-height: 150px; 122 | height: auto; 123 | margin-top: -1rem; 124 | } 125 | .orderPlaceProductSectionContainer{ 126 | float: left; 127 | width: 15%; 128 | } 129 | .orderProductContainer{ 130 | width: 100%; 131 | height: auto; 132 | } 133 | .orderProductContainerAllContentDiv{ 134 | width: 100%; 135 | height: 150px; 136 | } 137 | .orderPlaceProductSection{ 138 | width: 70%; 139 | } 140 | .orderPlaceProductContentDiv{ 141 | margin-left: 22rem; 142 | } 143 | .orderPlaceProductTitle{ 144 | font-weight: 700; 145 | font-size: 13px; 146 | line-height: 19px; 147 | color: #333; 148 | } 149 | .orderPlaceReturnDiv{ 150 | margin: 1rem; 151 | } 152 | .orderPlaceReturn{ 153 | font-size: 14px; 154 | line-height: 20px; 155 | color: #007185; 156 | cursor: pointer; 157 | } 158 | .orderPlaceReturn:hover{ 159 | text-decoration: underline; 160 | color: #C7511F; 161 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Amazon

2 | 3 | # MERN Ecommerce-Application 4 | 5 | 6 | ## Table of contents 7 | 8 | - [Introduction](#introduction) 9 | - [Demo](#demo) 10 | - [Run](#run) 11 | - [Technology](#technology) 12 | - [Features](#features) 13 | - [Database Models](#database) 14 | 15 | ## Introduction 16 | 17 | A virtual ecommerce web application using React, Node js, Express js, and Mongoose. 18 | 19 | NOTE: Please read the RUN section before opening an issue. 20 | 21 | ## Demo 22 | 23 |

24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |

45 | 46 | 47 | The website resembles a real store and you can add products to your cart and pay for them. If you want to try the checkout process, you can use the dummy card number with any expiration date, CVC, and zip codes. Please DO NOT provide real card number and data. 48 | 49 | In order to access the admin panel on "/admin" 50 | 51 | ## Run 52 | 53 | 54 | - MONGO_URI: this is the connection string of your MongoDB database. 55 | 56 | Now you can run "npm start" in the terminal and the application should work. 57 | 58 | ## Technology 59 | 60 | The application is built with: 61 | 62 | - React version 17.0.2 63 | - Node.js version 12.16.3 64 | - Mongoose version 6.1.8 65 | - Firebase version 9.6.6 66 | - Express version 4.17.2 67 | - Bootstrap version 5.2.0 68 | 69 | 70 | ## Features 71 | 72 | The application displays an online store that contains products. 73 | 74 | Users can do the following: 75 | 76 | - Create an account, login 77 | - Browse available products added by the admin 78 | - Add products to the shopping cart 79 | - Buy products, in order to proceed forward, a user must be logged in 80 | - Display the shopping cart 81 | - The profile contains all the orders a user has made 82 | 83 | Admins can do the following: 84 | 85 | - Can manage orders, users, products. 86 | 87 | ## Database 88 | 89 | All the models can be found in the models directory created using mongoose. 90 | 91 | ### User: 92 | 93 | - username (String) 94 | - password (String) 95 | 96 | 97 | ### Product: 98 | 99 | - title (String) 100 | - imagePath (String) 101 | - description (String) 102 | - price (Number) 103 | - category (ObjectId - a reference to the category) 104 | - createdAt (Date) 105 | 106 | ### Cart: 107 | 108 | - items: an array of objects, each object contains:
109 | ~ productId (ObjectId - a reference to the product)
110 | ~ qty (Number)
111 | ~ price (Number)
112 | ~ title (String)
113 | - totalQty (Number) 114 | - totalCost (Number) 115 | - user (ObjectId - a reference to the user) 116 | - createdAt 117 |

118 | 119 | 120 | ### Payment: 121 | 122 | - Cash On Delivery 123 | - Online Payment(Paypal Payment Gateway) 124 | 125 | 126 | ### Order: 127 | 128 | - user (ObjectId - a reference to the user) 129 | - cart (instead of a reference, we had to structure an object identical to the cart) 130 | - address (String) 131 | - paymentId (String) 132 | - createdAt (Date) 133 | - Delivered (Boolean) 134 | 135 | 136 | 137 | [Alan Chris Antony](https://github.com/alanchrissantony) 138 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Profile/email.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react' 2 | import './email.css' 3 | import Logo from '../../../Images/AmazonLogo.png' 4 | import { useNavigate } from 'react-router-dom' 5 | import { useDispatch, useSelector } from 'react-redux' 6 | import { useState } from 'react' 7 | import { detailsUser, updateUserProfile } from '../../../actions/userActions' 8 | import LoadingBox from '../LoadingBox/loadingBox' 9 | import MessageBox from '../MessageBox/messageBox' 10 | import { USER_UPDATE_PROFILE_RESET } from '../../../constants/userconstants' 11 | 12 | function Email() { 13 | 14 | const navigate = useNavigate() 15 | 16 | const [email, setEmail] = useState('') 17 | 18 | const userSignin = useSelector((state) => state.userSignin); 19 | const { userInfo } = userSignin; 20 | const userDetails = useSelector((state) => state.userDetails); 21 | const { loading, error, user } = userDetails; 22 | const dispatch = useDispatch(); 23 | 24 | const userUpdateProfile = useSelector((state) => state.userUpdateProfile); 25 | const { success: successUpdate, error: errorUpdate, loading: loadingUpdate } = userUpdateProfile; 26 | 27 | 28 | useEffect(() => { 29 | if (!userInfo) { 30 | navigate('/login') 31 | } else if (!user) { 32 | dispatch({ type: USER_UPDATE_PROFILE_RESET }); 33 | dispatch(detailsUser(userInfo._id)); 34 | } else { 35 | setEmail(user.email); 36 | } 37 | }, [dispatch, userInfo, navigate, userInfo._id, user, user.email]); 38 | 39 | const submitHandler = (e) => { 40 | e.preventDefault(); 41 | // dispatch update profile 42 | dispatch(updateUserProfile({ userId: user._id, email })); 43 | }; 44 | 45 | return ( 46 |
47 | {loading ? ( 48 | 49 | ) : loadingUpdate ? ( 50 | 51 | ) : error ? ( 52 | 53 | ) : ( 54 |
55 |
56 | { 57 | e.preventDefault() 58 | navigate('/') 59 | }} /> 60 |
61 |
62 |
63 | {errorUpdate && ( 64 |

{errorUpdate} !

65 | )} 66 | {successUpdate && ( 67 |

{'Profile Updated Successfully'}

68 | )} 69 |
70 |

Change your email address

71 |
72 |
73 |

Current email address: {user.email}

74 |
75 |
76 |

Enter the new email address you would like to associate with your account below.

77 |
78 |
79 | 80 |
81 | { setEmail(e.target.value) }} /> 82 |
83 |
84 | 85 |
86 |
87 |
88 |
89 | )} 90 |
91 | ) 92 | } 93 | 94 | export default Email -------------------------------------------------------------------------------- /frontend/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './App.css'; 3 | import { BrowserRouter as Router, Routes, Route } from 'react-router-dom' 4 | import Home from './ view/Users/Pages/home'; 5 | import Products from './ view/Users/Pages/products'; 6 | import Product from './ view/Users/Pages/product'; 7 | import ProductScreen from './ view/Users/Pages/productScreen'; 8 | import Cart from './ view/Users/Pages/cart'; 9 | import Login from './ view/Users/Pages/login'; 10 | import Signup from './ view/Users/Pages/signup'; 11 | import Address from './ view/Users/Pages/address' 12 | import Payment from './ view/Users/Pages/payment' 13 | import PlaceOrder from './ view/Users/Pages/placeOrder' 14 | import Order from './ view/Users/Pages/order' 15 | import OrderHistory from './ view/Users/Pages/orderHistory'; 16 | import AdminLogin from './ view/Admin/Pages/login'; 17 | import LogInSecurity from './ view/Users/Pages/Login&Security/logInSecurity'; 18 | import Name from './ view/Users/Pages/Login&Security/name'; 19 | import Email from './ view/Users/Pages/Login&Security/email'; 20 | import Password from './ view/Users/Pages/Login&Security/password'; 21 | import PrivateRoute from './Components/PrivateRoute'; 22 | import AdminPanel from './ view/Admin/Pages/panel'; 23 | import ProductsView from './ view/Admin/Pages/products'; 24 | import AddProducts from './ view/Admin/Pages/AddProducts'; 25 | import { useEffect } from 'react'; 26 | import { useContext } from 'react'; 27 | import { AuthContext, FirebaseContext } from './store/FirebaseContext'; 28 | 29 | import Container from "react-bootstrap/Container"; 30 | import EditProducts from './ view/Admin/Pages/EditProducts'; 31 | import OrderDetails from './ view/Admin/Pages/OrderDetails'; 32 | import Users from './ view/Admin/Pages/Users'; 33 | import Departments from './ view/Admin/Pages/Departments'; 34 | 35 | 36 | function App() { 37 | 38 | const { setUser } = useContext(AuthContext) 39 | const { firebase } = useContext(FirebaseContext) 40 | 41 | useEffect(() => { 42 | firebase.auth().onAuthStateChanged((user) => { 43 | setUser(user) 44 | }) 45 | }) 46 | 47 | return ( 48 |
49 | 50 | 51 | 52 | } /> 53 | } /> 54 | } /> 55 | } /> 56 | } /> 57 | } /> 58 | } /> 59 | } /> 60 | } /> 61 | } /> 62 | } /> 63 | } /> 64 | } /> 65 | } /> 66 | } /> 67 | } /> 68 | 69 | } /> 70 | } /> 71 | } /> 72 | } /> 73 | } /> 74 | } /> 75 | } /> 76 | } /> 77 | 78 | 79 | 80 |
81 | ); 82 | } 83 | 84 | export default App; 85 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/productScreen/productScreen.css: -------------------------------------------------------------------------------- 1 | .productScreenSection{ 2 | height: auto; 3 | min-height: 600px; 4 | } 5 | .productScreenImageDiv{ 6 | width: 40%; 7 | height: 600px; 8 | float: left; 9 | } 10 | .productScreenContentDiv{ 11 | width: 60%; 12 | height: 600px; 13 | float: left; 14 | } 15 | .productScreenImage{ 16 | max-width: 100%; 17 | height: auto; 18 | margin: 5rem; 19 | } 20 | .productScreenTitle{ 21 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 22 | font-size: 24px; 23 | font-weight: 400; 24 | margin-top: 5rem; 25 | margin-left: 5rem; 26 | } 27 | .productScreenRatingDiv{ 28 | margin-left: 5rem; 29 | margin-top: 1rem; 30 | } 31 | .productScreenRatingDiv span{ 32 | color: #ffa53f; 33 | margin: 0.1rem; 34 | float: left; 35 | } 36 | .productScreenReviewDiv{ 37 | padding-top: 0.3rem; 38 | font-size: smaller; 39 | color: #007185; 40 | padding-left: 11.5rem; 41 | } 42 | .productScreenPriceDiv{ 43 | margin-left: 5rem; 44 | margin-top: 1rem; 45 | } 46 | .productScreenPriceTitle{ 47 | color: #565959; 48 | font-style: 14px; 49 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 50 | } 51 | .productScreenPriceValue{ 52 | font-size: 18px; 53 | line-height: 24px; 54 | color: #B12704; 55 | } 56 | .productScreenInStockDiv{ 57 | margin-top: 1rem; 58 | margin-left: 5rem; 59 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 60 | color: #007600; 61 | font-size: 18px; 62 | line-height: 24px; 63 | } 64 | .productScreenUnavailableText{ 65 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 66 | color: #B12704; 67 | font-size: 18px; 68 | line-height: 24px; 69 | } 70 | .btnQty{ 71 | width: 5rem; 72 | height: 2rem; 73 | border-radius: 0.5rem; 74 | border: none; 75 | background-color: #e6e6e6; 76 | margin-left: 5rem; 77 | margin-top: 1rem; 78 | } 79 | .btnText{ 80 | font-size: 15px; 81 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 82 | } 83 | .selectBtnQty{ 84 | border: none; 85 | outline: none; 86 | background-color: #e6e6e6; 87 | } 88 | .CartBuyButtonsDiv{ 89 | margin-left: 5rem; 90 | margin-top: 2rem; 91 | } 92 | .ProductCartBtn{ 93 | background-color: #ffd93c; 94 | border-color: #FCD200; 95 | border-width: 0.5px; 96 | border-radius: 20px; 97 | width: 232px; 98 | height: 45px; 99 | cursor: pointer; 100 | } 101 | .ProductCartBtn:hover{ 102 | background-color: #FCD200; 103 | } 104 | .ProductCartBtnText{ 105 | font-size: 14px; 106 | font-weight: 600; 107 | } 108 | .ProductBuyBtn{ 109 | background-color: #FFA41C; 110 | border-color: #FF8F00; 111 | border-width: 0.5px; 112 | border-radius: 20px; 113 | width: 232px; 114 | height: 45px; 115 | cursor: pointer; 116 | margin-left: 2rem; 117 | } 118 | .ProductBuyBtn:hover{ 119 | background-color: #FF8F00; 120 | } 121 | .ProductBuyBtnText{ 122 | font-size: 14px; 123 | font-weight: 600; 124 | } 125 | .productScreenBrandDiv{ 126 | margin-top: 0.5rem; 127 | margin-left: 5rem; 128 | } 129 | .productScreenBrand{ 130 | color: #565959; 131 | font-style: 18px; 132 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 133 | } 134 | .productScreenDescriptionDiv{ 135 | margin-left: 5rem; 136 | } 137 | .productScreenDescription{ 138 | font-size: small; 139 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 140 | } 141 | -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Panel/Progress.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./Progress.css"; 3 | import { CircularProgressbar } from "react-circular-progressbar"; 4 | import "react-circular-progressbar/dist/styles.css"; 5 | 6 | function Progress() { 7 | return ( 8 |
9 |
10 |
11 | 40 |
41 | 42 |
43 | 67 |
68 | 69 |
70 | 99 |
100 |
101 |
102 | ); 103 | } 104 | 105 | export default Progress; 106 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Profile/name.css: -------------------------------------------------------------------------------- 1 | .nameChangeSection { 2 | width: 100%; 3 | height: auto; 4 | min-height: 500px; 5 | } 6 | .nameChangeContainer { 7 | width: 54%; 8 | margin-top: 0.5rem; 9 | height: auto; 10 | margin-left: auto; 11 | margin-right: auto; 12 | } 13 | .nameChangeAccountText { 14 | color: #555; 15 | cursor: pointer; 16 | font-family: "Amazon Ember", Arial, sans-serif; 17 | font-size: 14px; 18 | line-height: 20px; 19 | } 20 | .nameChangeYourAccountText { 21 | color: #007185; 22 | cursor: pointer; 23 | font-family: "Amazon Ember", Arial, sans-serif; 24 | font-size: 14px; 25 | line-height: 20px; 26 | padding-right: 0.5rem; 27 | } 28 | .nameChangeLogInSecurityText { 29 | color: #007185; 30 | cursor: pointer; 31 | font-family: "Amazon Ember", Arial, sans-serif; 32 | font-size: 14px; 33 | line-height: 20px; 34 | padding-left: 0.5rem; 35 | padding-right: 0.5rem; 36 | } 37 | .nameChangeNameChangeText { 38 | color: #c45500; 39 | cursor: pointer; 40 | font-family: "Amazon Ember", Arial, sans-serif; 41 | font-size: 14px; 42 | line-height: 20px; 43 | padding-left: 0.5rem; 44 | } 45 | .nameChangeYourAccountText:hover { 46 | color: #c45500; 47 | text-decoration: underline; 48 | } 49 | .nameChangeLogInSecurityText:hover { 50 | color: #c45500; 51 | text-decoration: underline; 52 | } 53 | .nameChangeTitleDiv { 54 | margin-top: 1rem; 55 | } 56 | .nameChangeTitle { 57 | font-family: "Amazon Ember", Arial, sans-serif; 58 | color: #0f1111; 59 | font-weight: 400; 60 | font-size: 28px; 61 | line-height: 36px; 62 | } 63 | .nameChangeContainerDiv { 64 | margin-top: 1rem; 65 | width: 600px; 66 | height: auto; 67 | overflow: auto; 68 | border-radius: 4px; 69 | border: 1px #ddd solid; 70 | background-color: #fff; 71 | margin-bottom: 2rem; 72 | } 73 | .nameChangeDiv { 74 | width: 90%; 75 | height: auto; 76 | margin-top: 1rem; 77 | margin-left: auto; 78 | margin-right: auto; 79 | } 80 | .nameChangeBoxText { 81 | font-size: 13px; 82 | line-height: 19px; 83 | color: #111; 84 | } 85 | .nameChangeBoxInputDiv { 86 | margin-top: 2rem; 87 | } 88 | .nameChangeBoxLabel { 89 | font-weight: 700; 90 | font-size: 13px; 91 | line-height: 19px; 92 | color: #111; 93 | } 94 | .nameChangeBoxInput { 95 | height: 31px; 96 | width: 174px; 97 | margin-top: 0.25rem; 98 | border-radius: 3px; 99 | font-family: Arial,sans-serif; 100 | font-size: 13px; 101 | border: 1px solid #d0d0d0; 102 | border-top: 1px solid #bbb; 103 | outline-color: #f69b3c; 104 | outline-width: thin; 105 | } 106 | .nameChangeSaveBtnDiv { 107 | margin-top: 1.5rem; 108 | margin-bottom: 2rem; 109 | } 110 | .nameChangeSaveBtn { 111 | width: 120px; 112 | height: 31px; 113 | background: linear-gradient(to bottom, #f7dfa5, #f0c14b); 114 | border-color: #a88734 #9c7e31 #846a29; 115 | color: #333; 116 | border-radius: 3px; 117 | border-style: solid; 118 | border-width: 1px; 119 | cursor: pointer; 120 | } 121 | .nameChangeSaveBtn:hover { 122 | background-color: #fdbf1f; 123 | } 124 | .nameChangeSaveBtn:focus:hover { 125 | border-style: solid; 126 | border-width: 1px; 127 | border-color: #e47911; 128 | } 129 | .nameChangeErrorContent { 130 | color: #721c24; 131 | text-align: center; 132 | margin-bottom: 1rem; 133 | padding-top: 1rem; 134 | padding-bottom: 0.25rem; 135 | } 136 | .nameChangeErrorDiv { 137 | background-color: #f8d7da; 138 | border-color: #f5c6cb; 139 | border-radius: 3px; 140 | border-width: 1px; 141 | border-style: solid; 142 | width: 100%; 143 | margin-bottom: 0.5rem; 144 | margin-left: auto; 145 | margin-right: auto; 146 | height: auto; 147 | } 148 | .nameChangeSuccessContent { 149 | color: #155724; 150 | text-align: center; 151 | margin-bottom: 1rem; 152 | padding-top: 1rem; 153 | padding-bottom: 0.25rem; 154 | } 155 | .nameChangeSuccessDiv { 156 | background-color: #d4edda; 157 | border-color: #c3e6cb; 158 | border-radius: 3px; 159 | border-width: 1px; 160 | border-style: solid; 161 | width: 100%; 162 | margin-bottom: 0.5rem; 163 | margin-left: auto; 164 | margin-right: auto; 165 | height: auto; 166 | } 167 | -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Header/header.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./header.css"; 3 | import Logo from "../../../Images/logo.svg"; 4 | import { useNavigate, Link } from "react-router-dom"; 5 | import { FirebaseContext } from "../../../store/FirebaseContext"; 6 | import { useContext, useEffect, useState } from "react"; 7 | import axios from "axios"; 8 | import { Search } from "../../../../node_modules/@material-ui/icons/index"; 9 | 10 | function Header() { 11 | const navigate = useNavigate(); 12 | 13 | const { firebase } = useContext(FirebaseContext); 14 | 15 | const [products, setProducts] = useState(false); 16 | const [search, setSearch] = useState(false); 17 | 18 | const get_products = async () => { 19 | let url = "/api/products"; 20 | const { data } = await axios.get(url); 21 | setProducts(data); 22 | }; 23 | 24 | useEffect(() => { 25 | get_products(); 26 | }, []); 27 | 28 | return ( 29 |
30 |
31 | { 36 | e.preventDefault(); 37 | navigate("/admin"); 38 | }} 39 | /> 40 | 41 |
42 | {setSearch(e.target.value)}} /> 43 |
44 |
45 | 46 |
47 |
48 |
49 | {products && ( 50 |
51 | {products 52 | .filter((product) => { 53 | if (search == "") { 54 | return false; 55 | }else if(product.name.toLowerCase().includes(search.toLowerCase())){ 56 | return product 57 | } 58 | }) 59 | .map((product, key) => { 60 | return ( 61 |
62 |

{ 63 | e.preventDefault() 64 | navigate(`/product/${product.department}`) 65 | }}>{product.name}

66 |
67 | ); 68 | })} 69 |
70 | )} 71 |
72 | 77 | Products 78 | 79 | 84 | Users 85 | 86 | 91 | Orders 92 | 93 | 94 | 95 | Admin 96 |
    97 |
    98 |
    99 | 110 |
    111 |
112 |
113 |
114 |
115 |
116 |
117 | ); 118 | } 119 | 120 | export default Header; 121 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Profile/name.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react' 2 | import { useState } from 'react'; 3 | import { useDispatch, useSelector } from 'react-redux'; 4 | import { useNavigate } from 'react-router-dom'; 5 | import { detailsUser, updateUserProfile } from '../../../actions/userActions'; 6 | import { USER_UPDATE_PROFILE_RESET } from '../../../constants/userconstants'; 7 | import LoadingBox from '../LoadingBox/loadingBox'; 8 | import MessageBox from '../MessageBox/messageBox'; 9 | import './name.css' 10 | 11 | function Name() { 12 | 13 | const navigate = useNavigate() 14 | 15 | const userSignin = useSelector((state) => state.userSignin); 16 | const { userInfo } = userSignin; 17 | const userDetails = useSelector((state) => state.userDetails); 18 | const { loading, error, user } = userDetails; 19 | const dispatch = useDispatch(); 20 | 21 | const [name, setName] = useState('') 22 | 23 | const userUpdateProfile = useSelector((state) => state.userUpdateProfile); 24 | const { success: successUpdate, error: errorUpdate, loading: loadingUpdate } = userUpdateProfile; 25 | 26 | 27 | 28 | useEffect(() => { 29 | if (!userInfo) { 30 | navigate('/login') 31 | } else if (!user) { 32 | dispatch({ type: USER_UPDATE_PROFILE_RESET }); 33 | dispatch(detailsUser(userInfo._id)); 34 | } else { 35 | setName(user.name); 36 | } 37 | }, [dispatch, userInfo, navigate, userInfo._id, user]); 38 | 39 | const submitHandler = (e) => { 40 | e.preventDefault(); 41 | // dispatch update profile 42 | dispatch(updateUserProfile({ userId: user._id, name })); 43 | }; 44 | 45 | 46 | return ( 47 |
48 | {loading ? ( 49 | 50 | ) : loadingUpdate ? ( 51 | 52 | ) : error ? ( 53 | 54 | ) : ( 55 |
56 |
57 |

{ 58 | e.preventDefault() 59 | navigate('/') 60 | }} >Your Account {' '} {' ›'} { 61 | e.preventDefault() 62 | navigate('/login&security') 63 | }} > Login & Security{' '} {' ›'} Change Your Name

64 |
65 |
66 |

Change Your Name

67 |
68 |
69 |
70 | {errorUpdate && ( 71 |

{errorUpdate} !

72 | )} 73 | {successUpdate && ( 74 |

{'Profile Updated Successfully'}

75 | )} 76 |
77 |

If you want to change the name associated with your Amazon customer account, you may do so below. Be sure to click the Save Changes button when you are done.

78 |
79 |
80 | 81 |
82 | { setName(e.target.value) }} /> 83 |
84 |
85 | 86 |
87 |
88 |
89 |
90 | )} 91 |
92 | ) 93 | } 94 | 95 | export default Name -------------------------------------------------------------------------------- /frontend/src/Components/Users/Profile/LogInSecurity/logInSecurity.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useEffect } from 'react'; 3 | import { useDispatch, useSelector } from 'react-redux'; 4 | import { useNavigate } from 'react-router-dom'; 5 | import { detailsUser } from '../../../../actions/userActions'; 6 | import LoadingBox from '../../LoadingBox/loadingBox'; 7 | import MessageBox from '../../MessageBox/messageBox'; 8 | import './logInSecurity.css' 9 | 10 | function LogInSecurity() { 11 | 12 | const navigate = useNavigate() 13 | 14 | const userSignin = useSelector((state) => state.userSignin); 15 | const { userInfo } = userSignin; 16 | const userDetails = useSelector((state) => state.userDetails); 17 | const { loading, error, user } = userDetails; 18 | const dispatch = useDispatch(); 19 | 20 | 21 | useEffect(() => { 22 | if (!userInfo) { 23 | navigate('/login') 24 | } 25 | dispatch(detailsUser(userInfo._id)); 26 | }, [dispatch, userInfo, navigate]); 27 | 28 | return ( 29 |
30 | {loading ? ( 31 | 32 | ) : error ? ( 33 | {error} 34 | ) : ( 35 |
36 |
37 |

{ 38 | e.preventDefault() 39 | navigate('/') 40 | }} >Your Account {' '} {' ›'} Login & Security

41 |
42 |
43 |

Login & Security

44 |
45 |
46 |
47 |
48 |

Name:

49 |

{user.name}

50 |
51 |
52 | 56 |
57 |
58 | 59 |
60 |
61 |

E-mail:

62 |

{user.email}

63 |
64 |
65 | 69 |
70 |
71 | 72 |
73 |
74 |

Password:

75 |

{'***********'}

76 |
77 |
78 | 82 |
83 |
84 |
85 |
86 | 90 |
91 |
92 | )} 93 |
94 | ) 95 | } 96 | 97 | export default LogInSecurity -------------------------------------------------------------------------------- /frontend/src/actions/userActions.js: -------------------------------------------------------------------------------- 1 | import Axios from 'axios'; 2 | import { 3 | USER_DETAILS_FAIL, 4 | USER_DETAILS_REQUEST, 5 | USER_DETAILS_SUCCESS, 6 | USER_REGISTER_FAIL, 7 | USER_REGISTER_REQUEST, 8 | USER_REGISTER_SUCCESS, 9 | USER_SIGNIN_FAIL, 10 | USER_SIGNIN_REQUEST, 11 | USER_SIGNIN_SUCCESS, 12 | USER_SIGNOUT, 13 | USER_UPDATE_PROFILE_FAIL, 14 | USER_UPDATE_PROFILE_REQUEST, 15 | USER_UPDATE_PROFILE_SUCCESS, 16 | USER_VERIFY_SIGNIN_FAIL, 17 | USER_VERIFY_SIGNIN_REQUEST, 18 | USER_VERIFY_SIGNIN_SUCCESS 19 | } from '../constants/userconstants'; 20 | 21 | 22 | 23 | export const register = (name, email, password) => async (dispatch) => { 24 | dispatch({ type: USER_REGISTER_REQUEST, payload: { name, email, password } }); 25 | try { 26 | const { data } = await Axios.post('/api/users/register', { 27 | name, 28 | email, 29 | password, 30 | }); 31 | dispatch({ type: USER_REGISTER_SUCCESS, payload: data }); 32 | dispatch({ type: USER_SIGNIN_SUCCESS, payload: data }); 33 | localStorage.setItem('userInfo', JSON.stringify(data)); 34 | } catch (error) { 35 | dispatch({ 36 | type: USER_REGISTER_FAIL, 37 | payload: 38 | error.response && error.response.data.message 39 | ? error.response.data.message 40 | : error.message, 41 | }); 42 | } 43 | }; 44 | 45 | 46 | 47 | export const signin = (email, password) => async (dispatch) => { 48 | dispatch({ type: USER_SIGNIN_REQUEST, payload: { email, password } }); 49 | try { 50 | const { data } = await Axios.post('/api/users/signin', { email, password }); 51 | dispatch({ type: USER_SIGNIN_SUCCESS, payload: data }); 52 | localStorage.setItem('userInfo', JSON.stringify(data)); 53 | } catch (error) { 54 | dispatch({ 55 | type: USER_SIGNIN_FAIL, 56 | payload: 57 | error.response && error.response.data.message 58 | ? error.response.data.message 59 | : error.message, 60 | }); 61 | } 62 | }; 63 | export const signout = () => (dispatch) => { 64 | localStorage.removeItem('userInfo'); 65 | localStorage.removeItem('cartItems'); 66 | localStorage.removeItem('shippingAddress'); 67 | dispatch({ type: USER_SIGNOUT }); 68 | }; 69 | 70 | 71 | export const detailsUser = (userId) => async (dispatch, getState) => { 72 | dispatch({ type: USER_DETAILS_REQUEST, payload: userId }); 73 | const { 74 | userSignin: { userInfo }, 75 | } = getState(); 76 | try { 77 | const { data } = await Axios.get(`/api/users/${userId}`, { 78 | headers: { Authorization: `Bearer ${userInfo.token}` }, 79 | }); 80 | dispatch({ type: USER_DETAILS_SUCCESS, payload: data }); 81 | } catch (error) { 82 | const message = 83 | error.response && error.response.data.message 84 | ? error.response.data.message 85 | : error.message; 86 | dispatch({ type: USER_DETAILS_FAIL, payload: message }); 87 | } 88 | }; 89 | 90 | export const updateUserProfile = (user) => async (dispatch, getState) => { 91 | dispatch({ type: USER_UPDATE_PROFILE_REQUEST, payload: user }); 92 | const { 93 | userSignin: { userInfo }, 94 | } = getState(); 95 | try { 96 | const { data } = await Axios.put('/api/users/profile', user, { 97 | headers: { Authorization: `Bearer ${userInfo.token}` }, 98 | }); 99 | dispatch({ type: USER_UPDATE_PROFILE_SUCCESS, payload: data }); 100 | dispatch({ type: USER_SIGNIN_SUCCESS, payload: data }); 101 | localStorage.setItem('userInfo', JSON.stringify(data)); 102 | } catch (error) { 103 | const message = 104 | error.response && error.response.data.message 105 | ? error.response.data.message 106 | : error.message; 107 | dispatch({ type: USER_UPDATE_PROFILE_FAIL, payload: message }); 108 | } 109 | }; 110 | 111 | export const verifySignIn = (email, password) => async (dispatch) => { 112 | dispatch({ type: USER_VERIFY_SIGNIN_REQUEST, payload: { email, password } }); 113 | try { 114 | const { data } = await Axios.post('/api/users/signin', { email, password }); 115 | dispatch({ type: USER_VERIFY_SIGNIN_SUCCESS, payload: data }); 116 | localStorage.setItem('userInfo', JSON.stringify(data)); 117 | } catch (error) { 118 | dispatch({ 119 | type: USER_VERIFY_SIGNIN_FAIL, 120 | payload: 121 | error.response && error.response.data.message 122 | ? error.response.data.message 123 | : error.message, 124 | }); 125 | } 126 | }; -------------------------------------------------------------------------------- /frontend/src/Components/Users/Signup/signup.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import './signup.css' 3 | import logo from '../../../Images/AmazonLogo.png' 4 | import { useNavigate, Link } from 'react-router-dom' 5 | import { useDispatch, useSelector } from 'react-redux' 6 | import { register } from '../../../actions/userActions' 7 | import { useEffect } from 'react' 8 | import LoadingBox from '../LoadingBox/loadingBox' 9 | 10 | 11 | 12 | function Signup() { 13 | 14 | const navigate = useNavigate() 15 | 16 | 17 | const [name, setName] = useState('') 18 | const [email, setEmail] = useState('') 19 | const [password, setPassword] = useState('') 20 | const [rePassword, setRePassword] = useState('') 21 | const [matchPassword, setMatchPassword] = useState(null) 22 | 23 | 24 | 25 | const userRegister = useSelector((state) => state.userRegister); 26 | const { userInfo, loading, error } = userRegister; 27 | 28 | 29 | const dispatch = useDispatch(); 30 | 31 | const handleSubmit = (e) => { 32 | e.preventDefault(); 33 | if (password !== rePassword) { 34 | setMatchPassword('Password and confirm password are not match'); 35 | }else if (password.length < 8) { 36 | setMatchPassword('Passwords must have at least 8 characters'); 37 | } else { 38 | setMatchPassword(null) 39 | dispatch(register(name, email, password)); 40 | } 41 | }; 42 | 43 | const pathname = window.location.search 44 | const pathUrl = pathname.split('=') 45 | const path = pathUrl[1] 46 | 47 | useEffect(()=>{ 48 | if(userInfo){ 49 | if(path){ 50 | navigate(`/`) 51 | }else{ 52 | navigate('/') 53 | } 54 | } 55 | }) 56 | 57 | return ( 58 |
59 |
60 |
61 |
62 | { 63 | e.preventDefault() 64 | navigate('/') 65 | }} alt="" /> 66 |
67 |
68 |
69 |

Create account

70 | {loading && } 71 | {error &&

{error} !

} 72 | {matchPassword &&

{matchPassword} !

} 73 | 74 |
75 | setName(e.target.value)} /> 76 | 77 |
78 | setEmail(e.target.value)} /> 79 |
80 | 81 |
82 | setPassword(e.target.value)} /> 83 |
84 | 85 |
86 | setRePassword(e.target.value)} /> 87 |
88 | 89 |
90 |

By continuing, you agree to Amazon's Conditions of Use
and Privacy Notice.

91 | 92 |
93 |
94 | 95 | { 96 | e.preventDefault() 97 | navigate('/login') 98 | }}>Already have an account? Sign In 99 |
100 |
101 |
102 |
103 |
104 | ) 105 | } 106 | 107 | export default Signup; -------------------------------------------------------------------------------- /frontend/src/Components/Users/Cart/cart.css: -------------------------------------------------------------------------------- 1 | .cartSection{ 2 | width: 100%; 3 | height: auto; 4 | min-height: 550px; 5 | background-color: #eaeded; 6 | padding-top: 1rem; 7 | overflow:auto; 8 | } 9 | .cartContainer{ 10 | margin: auto; 11 | } 12 | .cartBoxContainer{ 13 | width: 1000px; 14 | height: auto; 15 | background-color: #ffffff; 16 | margin-left: 1rem; 17 | float: left; 18 | margin-bottom: 2rem; 19 | } 20 | .cartBox{ 21 | width:1000px; 22 | height: auto; 23 | } 24 | .checkoutBox{ 25 | width: 300px; 26 | height: 175px; 27 | background-color: #ffffff; 28 | margin-top: 1rem; 29 | margin-left: 65rem; 30 | text-align: center; 31 | } 32 | .shoppingCartText{ 33 | font-weight: 400; 34 | font-size: 28px; 35 | line-height: 36px; 36 | margin-top: 1rem; 37 | margin-left: 1rem; 38 | } 39 | .CartBoxPriceTitleText{ 40 | font-size: 14px; 41 | line-height: 20px; 42 | color: #565959; 43 | margin-left: 950px; 44 | } 45 | .cartTitleHr{ 46 | margin-left: 1rem; 47 | margin-right: 1rem; 48 | background-color: #dddddd; 49 | } 50 | .cartImageDiv{ 51 | margin: 0; 52 | width: 200px; 53 | height: 200px; 54 | float: left; 55 | } 56 | .cartImage{ 57 | max-width: 200px; 58 | max-height: 200px; 59 | } 60 | .cartContentBox{ 61 | margin-left: 220px; 62 | width: 600px; 63 | } 64 | .cartProductTitleDiv{ 65 | width: 600px; 66 | margin-top: 1rem; 67 | } 68 | .cartProductTitle{ 69 | font-size: 20px; 70 | font-weight: 400; 71 | } 72 | .cartStockDiv{ 73 | font-size: 12px; 74 | line-height: 16px; 75 | margin-top: 1rem; 76 | color: #007600; 77 | } 78 | .cartQtyBtnDiv{ 79 | width: 6rem; 80 | float: left; 81 | } 82 | .cartBtnQty{ 83 | width: 5rem; 84 | height: 2rem; 85 | border-radius: 0.5rem; 86 | border: none; 87 | background-color: #e6e6e6; 88 | margin-top: 2rem; 89 | cursor: pointer; 90 | } 91 | .cartSelectBtnQty{ 92 | border: none; 93 | outline: none; 94 | background-color: #e6e6e6; 95 | } 96 | .cartBtnText{ 97 | font-size: 15px; 98 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 99 | } 100 | .cartDeleteDiv{ 101 | margin-top: 40px; 102 | } 103 | .cartDeleteTextMark{ 104 | font-size: 12px; 105 | line-height: 16px; 106 | color: darkgray; 107 | } 108 | .cartDeleteText{ 109 | font-size: 12px; 110 | line-height: 16px; 111 | color: #047188; 112 | padding-left: 1rem; 113 | cursor: pointer; 114 | } 115 | .cartDeleteText:hover{ 116 | text-decoration: underline; 117 | } 118 | .cartProductPriceDiv{ 119 | text-align: right; 120 | width: 140px; 121 | height: 50px; 122 | margin-left: 850px; 123 | margin-top: -9rem; 124 | } 125 | .cartProductPrice{ 126 | font-size: 18px; 127 | line-height: 24px; 128 | font-weight: 700; 129 | font-family: sans-serif; 130 | } 131 | .subTotalCartDiv{ 132 | width: 100%; 133 | height: 60px; 134 | text-align: right; 135 | } 136 | .cartBottomHr{ 137 | margin-left: 1rem; 138 | margin-right: 1rem; 139 | margin-top: 10rem; 140 | background-color: #dddddd; 141 | } 142 | .subTotalCartText{ 143 | margin-right: 1rem; 144 | margin-top: 1rem; 145 | } 146 | .cartSubTotalText{ 147 | font-size: 18px; 148 | line-height: 24px; 149 | } 150 | .cartSubTotalPrice{ 151 | font-size: 18px; 152 | line-height: 24px; 153 | font-weight: 700; 154 | font-family: sans-serif; 155 | } 156 | .subTotalText{ 157 | padding-top: 2rem; 158 | } 159 | .checkOutSubTotalText{ 160 | font-size: 18px; 161 | line-height: 24px; 162 | } 163 | .checkOutSubTotalPrice{ 164 | font-size: 18px; 165 | line-height: 24px; 166 | font-weight: 700; 167 | font-family: sans-serif; 168 | } 169 | .checkOutBtn{ 170 | width: 258px; 171 | height: 30px; 172 | margin-top: 2rem; 173 | background-color: #ffd93c; 174 | border-color: #FCD200; 175 | border-width: 0.5px; 176 | border-radius: 10px; 177 | cursor: pointer; 178 | } 179 | .checkOutBtn:hover{ 180 | background-color: #FCD200; 181 | } 182 | .emptyCartDiv{ 183 | background-color: #fff; 184 | width: 60%; 185 | height: 150px; 186 | margin-left: auto; 187 | margin-right: auto; 188 | } 189 | .emptyCart{ 190 | width: 90%; 191 | height: 100%; 192 | margin-left: auto; 193 | margin-right: auto; 194 | } 195 | .emptyCartContentText{ 196 | padding-top: 1rem; 197 | font-weight: 400; 198 | font-size: 28px; 199 | line-height: 36px; 200 | color: #0F1111; 201 | } 202 | .emptyCartShoppingLink{ 203 | text-align: end; 204 | padding-top: 3rem; 205 | } 206 | .goShoppingLink{ 207 | color: #15788b; 208 | } 209 | .goShoppingLink:hover{ 210 | text-decoration: underline; 211 | color: #C7511F; 212 | } -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Panel/panel.css: -------------------------------------------------------------------------------- 1 | 2 | .adminPanelSectionContainer { 3 | width: 100%; 4 | height: auto; 5 | overflow: auto; 6 | background-color: #e9eef7; 7 | padding-bottom: 1rem; 8 | padding-top: 5rem; 9 | } 10 | .adminPanelOverviewSection { 11 | width: 90%; 12 | height: auto; 13 | margin-left: auto; 14 | margin-right: auto; 15 | } 16 | .adminPanelOverviewContainer { 17 | margin-top: 0rem; 18 | } 19 | 20 | .adminPanelOverviewTitle { 21 | font-weight: 400; 22 | font-size: 28px; 23 | line-height: 36px; 24 | color: #0f1111; 25 | } 26 | .adminPanelOverviewSubTitleDiv { 27 | margin-top: 0.5rem; 28 | } 29 | .adminPanelOverviewSubTitleText { 30 | color: #8798ad; 31 | font-size: 12px; 32 | text-shadow: none; 33 | } 34 | .adminPanelOverviewSubDashboardTitle { 35 | margin-right: 0.5rem; 36 | cursor: pointer; 37 | color: #8798ad; 38 | } 39 | .adminPanelOverviewSubAmazonDashboardTitle { 40 | margin-left: 0.5rem; 41 | margin-right: 0.5rem; 42 | cursor: pointer; 43 | color: #8798ad; 44 | } 45 | .adminPanelOverviewBoxContainer { 46 | margin-top: 1rem; 47 | width: 100%; 48 | height: auto; 49 | display: flex; 50 | justify-content: center; 51 | align-items: center; 52 | margin-left: auto; 53 | margin-right: auto; 54 | } 55 | .adminPanelOverviewOrdersBoxContainerDiv { 56 | width: 320px; 57 | min-height: 102px; 58 | height: auto; 59 | display: block; 60 | border-radius: 8px; 61 | background-color: #fff; 62 | border: 1px #d5d9d9 solid; 63 | float: left; 64 | cursor: pointer; 65 | } 66 | .adminPanelOverviewOrdersBoxContainerDiv:hover { 67 | background-color: #eeeeee; 68 | } 69 | .adminPanelOverviewOrdersBoxDiv { 70 | width: 90%; 71 | height: 90%; 72 | margin-left: auto; 73 | margin-right: auto; 74 | margin-top: 1rem; 75 | } 76 | .adminPanelOverviewOrdersImgDivContainer { 77 | float: left; 78 | } 79 | .adminPanelOverviewOrdersImg { 80 | padding-top: 1rem; 81 | width: 66px; 82 | height: auto; 83 | } 84 | .adminPanelOverviewOrdersTextDivContainer{ 85 | float: left; 86 | } 87 | .adminPanelOverviewOrdersText { 88 | color: #111; 89 | font-size: 17px; 90 | font-weight: 400; 91 | font-style: normal; 92 | text-transform: none; 93 | text-decoration: none; 94 | cursor: pointer; 95 | } 96 | .adminPanelOverviewOrdersSubText { 97 | color: #565959; 98 | cursor: pointer; 99 | font-size: 14px; 100 | } 101 | .adminPanelOverviewOrdersTextDivContainer { 102 | margin-left: .75rem; 103 | float: left; 104 | } 105 | 106 | .adminPanelOverviewUsersBoxContainerDiv { 107 | width: 320px; 108 | min-height: 102px; 109 | height: auto; 110 | display: block; 111 | border-radius: 8px; 112 | background-color: #fff; 113 | border: 1px #d5d9d9 solid; 114 | float: left; 115 | cursor: pointer; 116 | } 117 | .adminPanelOverviewUsersBoxContainerDiv:hover { 118 | background-color: #eeeeee; 119 | } 120 | .adminPanelOverviewUsersBoxDiv { 121 | width: 90%; 122 | height: 90%; 123 | margin-left: auto; 124 | margin-right: auto; 125 | margin-top: 1rem; 126 | } 127 | .adminPanelOverviewUsersImgDivContainer { 128 | float: left; 129 | } 130 | .adminPanelOverviewUsersImg { 131 | width: 66px; 132 | height: auto; 133 | } 134 | .adminPanelOverviewUsersText { 135 | color: #111; 136 | font-size: 17px; 137 | font-weight: 400; 138 | font-style: normal; 139 | text-transform: none; 140 | text-decoration: none; 141 | line-height: 32px; 142 | cursor: pointer; 143 | } 144 | .adminPanelOverviewUsersSubText { 145 | color: #565959; 146 | cursor: pointer; 147 | font-size: 14px; 148 | line-height: 20px; 149 | } 150 | .adminPanelOverviewUsersTextDivContainer { 151 | margin-left: 1rem; 152 | float: left; 153 | } 154 | 155 | .adminPanelOverviewProductsBoxContainerDiv { 156 | width: 320px; 157 | min-height: 102px; 158 | height: auto; 159 | display: block; 160 | border-radius: 8px; 161 | background-color: #fff; 162 | border: 1px #d5d9d9 solid; 163 | float: left; 164 | cursor: pointer; 165 | } 166 | .adminPanelOverviewProductsBoxContainerDiv:hover { 167 | background-color: #eeeeee; 168 | } 169 | .adminPanelOverviewProductsBoxDiv { 170 | width: 90%; 171 | height: 90%; 172 | margin-left: auto; 173 | margin-right: auto; 174 | margin-top: 1rem; 175 | } 176 | .adminPanelOverviewProductsImgDivContainer { 177 | float: left; 178 | } 179 | .adminPanelOverviewProductsImg { 180 | width: 66px; 181 | height: auto; 182 | } 183 | .adminPanelOverviewProductsText { 184 | color: #111; 185 | font-size: 17px; 186 | font-weight: 400; 187 | font-style: normal; 188 | text-transform: none; 189 | text-decoration: none; 190 | line-height: 32px; 191 | cursor: pointer; 192 | } 193 | .adminPanelOverviewProductsSubText { 194 | color: #565959; 195 | cursor: pointer; 196 | font-size: 14px; 197 | line-height: 20px; 198 | } 199 | .adminPanelOverviewProductsTextDivContainer { 200 | margin-left: 1rem; 201 | float: left; 202 | } 203 | .container-fluid { 204 | width: 100%; 205 | padding-right: 0px; 206 | padding-left: 0px; 207 | margin-right: auto; 208 | margin-left: auto; 209 | overflow: hidden; 210 | } 211 | -------------------------------------------------------------------------------- /frontend/src/Components/Users/Profile/LogInSecurity/logInSecurity.css: -------------------------------------------------------------------------------- 1 | .logInSecuritySection{ 2 | width: 100%; 3 | height: auto; 4 | min-height: 530px; 5 | } 6 | .logInSecurityContainer{ 7 | width: 54%; 8 | margin-top: 0.5rem; 9 | height: auto; 10 | margin-left: auto; 11 | margin-right: auto; 12 | } 13 | .logInSecurityAccountText{ 14 | color: #555; 15 | cursor: pointer; 16 | font-family: "Amazon Ember",Arial,sans-serif; 17 | font-size: 14px; 18 | line-height: 20px; 19 | } 20 | .logInSecurityYourAccountText{ 21 | color: #007185; 22 | cursor: pointer; 23 | font-family: "Amazon Ember",Arial,sans-serif; 24 | font-size: 14px; 25 | line-height: 20px; 26 | padding-right: 0.5rem; 27 | } 28 | .logInSecurityLogInSecurityText{ 29 | color: #c45500; 30 | cursor: pointer; 31 | font-family: "Amazon Ember",Arial,sans-serif; 32 | font-size: 14px; 33 | line-height: 20px; 34 | padding-left: 0.5rem; 35 | } 36 | .logInSecurityYourAccountText:hover{ 37 | color: #c45500; 38 | text-decoration: underline; 39 | } 40 | .logInSecurityTitleDiv{ 41 | margin-top: 1rem; 42 | } 43 | .logInSecurityTitle{ 44 | font-family: "Amazon Ember",Arial,sans-serif; 45 | color: #0F1111; 46 | font-weight: 400; 47 | font-size: 28px; 48 | line-height: 36px; 49 | } 50 | .logInSecurityContainerDiv{ 51 | margin-top: 1rem; 52 | width: 600px; 53 | height: 306px; 54 | border-radius: 4px; 55 | border: 1px #ddd solid; 56 | background-color: #fff; 57 | margin-bottom: 2rem; 58 | } 59 | .logInSecurityNameDiv{ 60 | width: 100%; 61 | height: 102px; 62 | border-bottom: 1px #ddd solid; 63 | } 64 | .logInSecurityNameTextDiv{ 65 | margin-top: 2rem; 66 | margin-left: 2rem; 67 | float: left; 68 | width: 75%; 69 | } 70 | .logInSecurityNameTitle{ 71 | font-weight: 700; 72 | color: #111; 73 | font-size: 13px; 74 | line-height: 19px; 75 | 76 | } 77 | .logInSecurityName{ 78 | margin-top: 0.25rem; 79 | color: #111; 80 | font-size: 13px; 81 | line-height: 19px; 82 | } 83 | .logInSecurityNameBtnDiv{ 84 | float: left; 85 | margin-top: 2.5rem; 86 | 87 | } 88 | .logInSecurityNameBtn{ 89 | width: 70px; 90 | height: 31px; 91 | background: #e7e9ec; 92 | border-radius: 3px; 93 | border-color: #adb1b8 #a2a6ac #8d9096; 94 | border-style: solid; 95 | border-width: 1px; 96 | cursor: pointer; 97 | display: inline-block; 98 | padding: 0; 99 | text-align: center; 100 | text-decoration: none; 101 | vertical-align: middle; 102 | } 103 | .logInSecurityEmailDiv{ 104 | width: 100%; 105 | height: 102px; 106 | border-bottom: 1px #ddd solid; 107 | } 108 | .logInSecurityEmailTextDiv{ 109 | margin-top: 2rem; 110 | margin-left: 2rem; 111 | float: left; 112 | width: 75%; 113 | } 114 | .logInSecurityEmailTitle{ 115 | font-weight: 700; 116 | color: #111; 117 | font-size: 13px; 118 | line-height: 19px; 119 | 120 | } 121 | .logInSecurityEmail{ 122 | margin-top: 0.25rem; 123 | color: #111; 124 | font-size: 13px; 125 | line-height: 19px; 126 | } 127 | .logInSecurityEmailBtnDiv{ 128 | float: left; 129 | margin-top: 2.5rem; 130 | 131 | } 132 | .logInSecurityEmailBtn{ 133 | width: 70px; 134 | height: 31px; 135 | background: #e7e9ec; 136 | border-radius: 3px; 137 | border-color: #adb1b8 #a2a6ac #8d9096; 138 | border-style: solid; 139 | border-width: 1px; 140 | cursor: pointer; 141 | display: inline-block; 142 | padding: 0; 143 | text-align: center; 144 | text-decoration: none; 145 | vertical-align: middle; 146 | } 147 | .logInSecurityPasswordDiv{ 148 | width: 100%; 149 | height: 102px; 150 | } 151 | .logInSecurityPasswordTextDiv{ 152 | margin-top: 2rem; 153 | margin-left: 2rem; 154 | float: left; 155 | width: 75%; 156 | } 157 | .logInSecurityPasswordTitle{ 158 | font-weight: 700; 159 | color: #111; 160 | font-size: 13px; 161 | line-height: 19px; 162 | 163 | } 164 | .logInSecurityPassword{ 165 | margin-top: 0.25rem; 166 | color: #111; 167 | font-size: 13px; 168 | line-height: 19px; 169 | } 170 | .logInSecurityPasswordBtnDiv{ 171 | float: left; 172 | margin-top: 2.5rem; 173 | 174 | } 175 | .logInSecurityPasswordBtn{ 176 | width: 70px; 177 | height: 31px; 178 | background: #e7e9ec; 179 | border-radius: 3px; 180 | border-color: #adb1b8 #a2a6ac #8d9096; 181 | border-style: solid; 182 | border-width: 1px; 183 | cursor: pointer; 184 | display: inline-block; 185 | padding: 0; 186 | text-align: center; 187 | text-decoration: none; 188 | vertical-align: middle; 189 | } 190 | .logInSecurityDoneBtnDiv{ 191 | margin-left: 1rem; 192 | } 193 | .logInSecurityDoneBtn{ 194 | width: 54px; 195 | height: 31px; 196 | background: linear-gradient(to bottom,#f7dfa5,#f0c14b); 197 | border-color: #a88734 #9c7e31 #846a29; 198 | color: #111; 199 | border-radius: 3px; 200 | border-style: solid; 201 | border-width: 1px; 202 | cursor: pointer; 203 | } 204 | .logInSecurityDoneBtn:focus:hover{ 205 | border-style: solid; 206 | border-width: 1px; 207 | border-color: #e47911; 208 | } -------------------------------------------------------------------------------- /frontend/src/Components/Users/Profile/password.css: -------------------------------------------------------------------------------- 1 | .passwordChangeSection{ 2 | width: 100%; 3 | height: auto; 4 | min-height: 500px; 5 | overflow: auto; 6 | } 7 | .passwordChangeContainer{ 8 | width: 54%; 9 | margin-top: 0.5rem; 10 | height: auto; 11 | margin-left: auto; 12 | margin-right: auto; 13 | } 14 | .passwordChangeAccountText{ 15 | color: #555; 16 | cursor: pointer; 17 | font-family: "Amazon Ember",Arial,sans-serif; 18 | font-size: 14px; 19 | line-height: 20px; 20 | } 21 | .passwordChangeYourAccountText{ 22 | color: #007185; 23 | cursor: pointer; 24 | font-family: "Amazon Ember",Arial,sans-serif; 25 | font-size: 14px; 26 | line-height: 20px; 27 | padding-right: 0.5rem; 28 | } 29 | .passwordChangeLogInSecurityText{ 30 | color: #007185; 31 | cursor: pointer; 32 | font-family: "Amazon Ember",Arial,sans-serif; 33 | font-size: 14px; 34 | line-height: 20px; 35 | padding-right: 0.5rem; 36 | padding-left: 0.5rem; 37 | } 38 | .passwordChangePasswordChangeText{ 39 | color: #c45500; 40 | cursor: pointer; 41 | font-family: "Amazon Ember",Arial,sans-serif; 42 | font-size: 14px; 43 | line-height: 20px; 44 | padding-left: 0.5rem; 45 | } 46 | .passwordChangeYourAccountText:hover{ 47 | color: #c45500; 48 | text-decoration: underline; 49 | } 50 | .passwordChangeLogInSecurityText:hover{ 51 | color: #c45500; 52 | text-decoration: underline; 53 | } 54 | .passwordChangeTitleDiv{ 55 | margin-top: 1rem; 56 | } 57 | .passwordChangeTitle{ 58 | font-family: "Amazon Ember",Arial,sans-serif; 59 | color: #0F1111; 60 | font-weight: 400; 61 | font-size: 28px; 62 | line-height: 36px; 63 | } 64 | .passwordChangeBoxSection{ 65 | width: 80%; 66 | height: auto; 67 | overflow: auto; 68 | border-radius: 4px; 69 | border: 1px #ddd solid; 70 | background-color: #fff; 71 | margin-bottom: 2rem; 72 | margin-top: 0.5rem; 73 | } 74 | .passwordChangeBoxContainer{ 75 | margin-top: 1rem; 76 | margin-left: 1rem; 77 | } 78 | .passwordChangeBoxParaText{ 79 | font-size: 13px; 80 | line-height: 19px; 81 | color: #111; 82 | } 83 | .passwordChangeBoxCurrentPasswordInputDiv{ 84 | margin-top: 1rem; 85 | } 86 | .passwordChangeBoxCurrentPasswordLabel{ 87 | font-weight: 700; 88 | font-size: 13px; 89 | line-height: 19px; 90 | color: #111; 91 | } 92 | .passwordChangeBoxCurrentPasswordInput{ 93 | width: 174px; 94 | height: 31px; 95 | border-radius: 3px; 96 | font-family: Arial,sans-serif; 97 | font-size: 13px; 98 | border: 1px solid #d0d0d0; 99 | border-top: 1px solid #bbb; 100 | outline-color: #f69b3c; 101 | outline-width: thin; 102 | margin-top: 0.25rem; 103 | } 104 | .passwordChangeBoxNewPasswordInputDiv{ 105 | margin-top: 1rem; 106 | } 107 | .passwordChangeBoxNewPasswordLabel{ 108 | font-weight: 700; 109 | font-size: 13px; 110 | line-height: 19px; 111 | color: #111; 112 | } 113 | .passwordChangeBoxNewPasswordInput{ 114 | width: 174px; 115 | height: 31px; 116 | border-radius: 3px; 117 | font-family: Arial,sans-serif; 118 | font-size: 13px; 119 | border: 1px solid #d0d0d0; 120 | border-top: 1px solid #bbb; 121 | outline-color: #f69b3c; 122 | outline-width: thin; 123 | margin-top: 0.25rem; 124 | } 125 | .passwordChangeBoxConformPasswordInputDiv{ 126 | margin-top: 1rem; 127 | } 128 | .passwordChangeBoxConformPasswordLabel{ 129 | font-weight: 700; 130 | font-size: 13px; 131 | line-height: 19px; 132 | color: #111; 133 | } 134 | .passwordChangeBoxConformPasswordInput{ 135 | width: 174px; 136 | height: 31px; 137 | border-radius: 3px; 138 | font-family: Arial,sans-serif; 139 | font-size: 13px; 140 | border: 1px solid #d0d0d0; 141 | border-top: 1px solid #bbb; 142 | outline-color: #f69b3c; 143 | outline-width: thin; 144 | margin-top: 0.25rem; 145 | } 146 | .passwordChangeSaveChangeBtnDiv{ 147 | margin-top: 2rem; 148 | margin-bottom: 2rem; 149 | } 150 | .passwordChangeSaveChangeBtn{ 151 | width: 120px; 152 | height: 31px; 153 | background: linear-gradient(to bottom,#f7dfa5,#f0c14b); 154 | border-color: #a88734 #9c7e31 #846a29; 155 | color: #222; 156 | border-radius: 3px; 157 | border-style: solid; 158 | border-width: 1px; 159 | cursor: pointer; 160 | } 161 | .passwordChangeSaveChangeBtn:hover{ 162 | 163 | background-color: #fdbf1f; 164 | } 165 | .passwordChangeSaveChangeBtn:focus:hover{ 166 | border-style: solid; 167 | border-width: 1px; 168 | border-color: #e47911; 169 | } 170 | .passwordChangeErrorContent { 171 | color: #721c24; 172 | text-align: center; 173 | margin-bottom: 1rem; 174 | padding-top: 1rem; 175 | padding-bottom: 0.25rem; 176 | } 177 | .passwordChangeErrorDiv { 178 | background-color: #f8d7da; 179 | border-color: #f5c6cb; 180 | border-radius: 3px; 181 | border-width: 1px; 182 | border-style: solid; 183 | width: 97%; 184 | margin-bottom: 0.5rem; 185 | height: auto; 186 | } 187 | .passwordChangeSuccessContent { 188 | color: #155724; 189 | text-align: center; 190 | margin-bottom: 1rem; 191 | padding-top: 1rem; 192 | padding-bottom: 0.25rem; 193 | } 194 | .passwordChangeSuccessDiv { 195 | background-color: #d4edda; 196 | border-color: #c3e6cb; 197 | border-radius: 3px; 198 | border-width: 1px; 199 | border-style: solid; 200 | width: 97%; 201 | margin-bottom: 0.5rem; 202 | height: auto; 203 | } -------------------------------------------------------------------------------- /frontend/src/Components/Users/Order/order.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react' 2 | import './order.css' 3 | import tick from '../../../Images/checked.png' 4 | import { useSelector } from 'react-redux'; 5 | import { Link, useNavigate } from 'react-router-dom'; 6 | import LoadingBox from '../LoadingBox/loadingBox'; 7 | import MessageBox from '../MessageBox/messageBox'; 8 | 9 | 10 | 11 | 12 | function Order() { 13 | 14 | const navigate = useNavigate() 15 | 16 | const userSignIn = useSelector((state) => state.userSignin) 17 | const { userInfo } = userSignIn; 18 | 19 | const orderDetails = useSelector((state) => state.orderDetails); 20 | const { order, loading, error } = orderDetails; 21 | 22 | 23 | const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", 24 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 25 | ]; 26 | 27 | const month = new Date(); 28 | 29 | var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; 30 | var week = new Date(); 31 | var dayName = days[week.getDay()]; 32 | 33 | 34 | var today = new Date(), 35 | date = dayName + ', ' + today.getDate() + ' ' + monthNames[month.getMonth()] + ' ' + today.getFullYear(); 36 | 37 | 38 | useEffect(() => { 39 | if (!userInfo) { 40 | navigate('/login?redirect=shipping') 41 | } else if (!order) { 42 | navigate('/') 43 | } 44 | }) 45 | 46 | const time = new Date 47 | var paidAt = time.getHours() + ':' + time.getMinutes() + ':' + time.getSeconds() 48 | 49 | 50 | 51 | return ( 52 |
53 |
54 |

{ 55 | e.preventDefault() 56 | navigate('/') 57 | }}>Return to home page {'>'}

58 |
59 | {loading ? ( 60 | 61 | ) : error ? ( 62 | {error} 63 | ) : ( 64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | 72 |

Order placed, thank you!

73 |
74 |
75 |

Confirmation will be sent to your email.

76 |
77 |
78 |

Shipping to

79 |
80 |
81 |

Payment paid on: {date},{' '}{paidAt}

82 |
83 |
84 |
85 |
86 | 87 | 88 | 89 | {order.orderItems.map(product => ( 90 | 91 |
92 |
93 |
94 |

{date}

95 |

Delivery date

96 |
97 |
98 | Review your order {'>'} 99 |
100 |
101 |
102 |
103 | 104 |
105 |
106 |
107 |

{product.name}

108 |
109 | 110 |
111 |
112 |
113 | ))} 114 | 115 |
116 |
117 |
118 |
119 | )} 120 |
121 | ) 122 | } 123 | 124 | export default Order -------------------------------------------------------------------------------- /frontend/src/Components/Users/Address/address.css: -------------------------------------------------------------------------------- 1 | .addressContainer{ 2 | width: 85%; 3 | margin-left: auto; 4 | margin-right: auto; 5 | margin-top: 1rem; 6 | height: auto; 7 | color: #333; 8 | margin-bottom: 5rem; 9 | } 10 | .newAddressDiv{ 11 | 12 | float: left; 13 | width: 50%; 14 | height: auto; 15 | } 16 | .addressTitleTextDiv{ 17 | margin-top: 2.5rem; 18 | margin-bottom: 1rem; 19 | } 20 | .SelectDeliveryAddressText{ 21 | font-size: 28px; 22 | line-height: 1.2; 23 | font-weight: 400; 24 | font-family: Arial,sans-serif; 25 | text-rendering: optimizeLegibility; 26 | color: #333; 27 | } 28 | .newAddressFormContainer{ 29 | width: 95%; 30 | } 31 | .addNewAddressText{ 32 | font-size: 21px; 33 | line-height: 1.3; 34 | font-weight: 700; 35 | } 36 | .formDivTop{ 37 | margin-top: 2rem; 38 | } 39 | .formDiv{ 40 | margin-top: 1rem; 41 | } 42 | .newAddressLabel{ 43 | font-size: 13px; 44 | line-height: 19px; 45 | font-weight: 700; 46 | } 47 | .selectCountry{ 48 | width: 94%; 49 | outline: 0; 50 | color: #111; 51 | font-size: 13px; 52 | line-height: 29px; 53 | display: block; 54 | font-family: Arial,sans-serif; 55 | white-space: nowrap; 56 | background-color: transparent; 57 | display: inline-block; 58 | height: 31px; 59 | border: 1px solid; 60 | border-color: #bcc1c8 #bababa #adb2bb; 61 | background-color: #f1f2f4; 62 | margin-top: 0.3rem; 63 | border-radius: 3px; 64 | } 65 | .inputSpace{ 66 | width: 94%; 67 | height: 31px; 68 | margin-top: 0.3rem; 69 | border-radius: 3px; 70 | font-family: Arial,sans-serif; 71 | font-size: 13px; 72 | border: 1px solid #d0d0d0; 73 | border-top: 1px solid #bbb; 74 | outline-color: #f69b3c; 75 | outline-width: thin; 76 | } 77 | .inputCity{ 78 | width: 260px; 79 | height: 31px; 80 | margin-top: 0.3rem; 81 | border-radius: 3px; 82 | font-family: Arial,sans-serif; 83 | font-size: 13px; 84 | border: 1px solid #d0d0d0; 85 | border-top: 1px solid #bbb; 86 | outline-color: #f69b3c; 87 | outline-width: thin; 88 | } 89 | .inputCityDiv{ 90 | float: left; 91 | } 92 | .selectStateDiv{ 93 | margin-top: 1rem; 94 | margin-left: 282px; 95 | } 96 | .selectState{ 97 | outline: 0; 98 | color: #111; 99 | font-size: 13px; 100 | line-height: 29px; 101 | display: block; 102 | font-family: Arial,sans-serif; 103 | white-space: nowrap; 104 | background-color: transparent; 105 | display: inline-block; 106 | height: 31px; 107 | border: 1px solid; 108 | border-color: #bcc1c8 #bababa #adb2bb; 109 | background-color: #f1f2f4; 110 | margin-top: 0.3rem; 111 | border-radius: 3px; 112 | width: 260px; 113 | } 114 | .labelDefaultAddress{ 115 | margin-left: 1rem; 116 | } 117 | .selectAddressType{ 118 | width: 94%; 119 | outline: 0; 120 | color: #111; 121 | font-size: 13px; 122 | line-height: 29px; 123 | display: block; 124 | font-family: Arial,sans-serif; 125 | white-space: nowrap; 126 | background-color: transparent; 127 | display: inline-block; 128 | height: 31px; 129 | border: 1px solid; 130 | border-color: #bcc1c8 #bababa #adb2bb; 131 | background-color: #f1f2f4; 132 | margin-top: 0.3rem; 133 | border-radius: 3px; 134 | } 135 | .deliveryInstructionDiv{ 136 | margin-top: 2rem; 137 | } 138 | .deliveryInstructionText{ 139 | font-size: 17px; 140 | line-height: 1.24; 141 | font-family: Arial,sans-serif; 142 | text-rendering: optimizeLegibility; 143 | font-weight: 700; 144 | } 145 | .deliveryInstructionContentDiv{ 146 | margin-top: 1rem; 147 | } 148 | .deliveryInstructionContentText{ 149 | font-size: 13px; 150 | line-height: 19px; 151 | } 152 | .useAddressBtnDiv{ 153 | margin-top: 2rem; 154 | } 155 | .useAddressBtn{ 156 | width: 120px; 157 | height: 31px; 158 | color: #111; 159 | text-align: center; 160 | font-size: 13px; 161 | line-height: 29px; 162 | display: block; 163 | font-family: Arial,sans-serif; 164 | white-space: nowrap; 165 | background-color: transparent; 166 | background-color: #f0c24f; 167 | border-radius: 3px; 168 | border: 1px solid; 169 | border-color: #bf942b; 170 | outline: #f69b3c; 171 | cursor: pointer; 172 | } 173 | .newAddressLocationDiv{ 174 | width: 50%; 175 | margin-left: 50%; 176 | } 177 | .newAddressFormContainerRight{ 178 | margin-top: 2rem; 179 | padding-top: 43px; 180 | } 181 | .existingShippingAddressSection{ 182 | margin-top: 1rem; 183 | } 184 | .existingShippingAddressName{ 185 | font-weight: 700; 186 | font-size: 16px; 187 | line-height: 22px; 188 | color: #333; 189 | } 190 | .existingShippingAddressAddress{ 191 | margin-top: 0.25rem; 192 | font-size: 13px; 193 | line-height: 19px; 194 | color: #333; 195 | 196 | } 197 | .existingShippingAddressPlace{ 198 | margin-top: 0.25rem; 199 | font-size: 13px; 200 | line-height: 19px; 201 | color: #333; 202 | } 203 | .existingShippingAddress{ 204 | margin-top: 0.25rem; 205 | font-size: 13px; 206 | line-height: 19px; 207 | color: #333; 208 | } 209 | .existingShippingAddressCountry{ 210 | margin-top: 0.25rem; 211 | font-size: 13px; 212 | line-height: 19px; 213 | color: #333; 214 | } 215 | .existingShippingAddInstructions{ 216 | margin-top: 0.25rem; 217 | font-size: 13px; 218 | line-height: 19px; 219 | color: #007eb9; 220 | cursor: pointer; 221 | } 222 | .existingShippingAddInstructions:hover{ 223 | color: #e47911; 224 | text-decoration: underline; 225 | } 226 | .existingShippingBtn{ 227 | margin-top: 1rem; 228 | width: 230px; 229 | height: 31px; 230 | color: #111; 231 | text-align: center; 232 | font-size: 13px; 233 | line-height: 29px; 234 | display: block; 235 | font-family: Arial,sans-serif; 236 | white-space: nowrap; 237 | background-color: transparent; 238 | background-color: #f0c24f; 239 | border-radius: 3px; 240 | border: 1px solid; 241 | border-color: #bf942b; 242 | outline: #f69b3c; 243 | cursor: pointer; 244 | margin-bottom: 2rem; 245 | } -------------------------------------------------------------------------------- /frontend/src/Components/Admin/Users/Users.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import axios from "axios"; 3 | import { Link } from "react-router-dom"; 4 | import LoadingBox from "../../Users/LoadingBox/loadingBox"; 5 | import MessageBox from "../../Users/MessageBox/messageBox"; 6 | import { JournalRichtext, Trash, XCircle } from "react-bootstrap-icons"; 7 | import { useDispatch } from "react-redux"; 8 | 9 | function Users() { 10 | const dispatch = useDispatch(); 11 | 12 | const [users, setUsers] = useState(false); 13 | const [viewUser, setViewUser] = useState(false); 14 | const [userPopup, setUserPopup] = useState(false); 15 | const [error, setError] = useState(false); 16 | 17 | const users_list = async () => { 18 | try { 19 | const url = "/api/users/admin/total&users"; 20 | const data = await axios.post(url); 21 | setUsers(data.data); 22 | } catch (error) { 23 | 24 | setError(error.message); 25 | } 26 | }; 27 | 28 | useEffect(() => { 29 | users_list(); 30 | }, []); 31 | 32 | const removeUser = (id) => { 33 | const userId = { 34 | id: id, 35 | }; 36 | let url = "/api/users/delete"; 37 | 38 | axios.post(url, userId).then(() => dispatch(users_list())); 39 | }; 40 | 41 | 42 | const view_toggle = async(id) =>{ 43 | const data = await axios.get(`/api/users/${id}`) 44 | setViewUser(data.data) 45 | setUserPopup(true) 46 | }; 47 | 48 | const close_toggle = ()=>{ 49 | setUserPopup(false) 50 | } 51 | 52 | 53 | return ( 54 |
55 | {!users ? ( 56 | 57 | ) : error ? ( 58 | {error.message} 59 | ) : ( 60 |
61 |
62 |
63 |

Users

64 |
65 |
66 |

67 | 68 | 69 | Dashboard 70 | 71 | 72 | {">"} 73 | 74 | 75 | Users 76 | 77 |

78 |
79 | {userPopup && ( 80 |
81 |
82 |
83 | 87 |

88 | User Detials 89 |

90 | 93 | 94 |
95 |
96 | 99 |
100 |
101 | 104 |
105 |
106 | 109 |
110 |
111 | 114 |
115 |
116 | 117 |
118 |
119 | )} 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | {users.map((user, index) => { 134 | return ( 135 | 136 | 137 | 138 | 139 | 140 | 141 | 160 | 161 | ); 162 | })} 163 | 164 |
NONameEmailIDCreated AtOptions
{index + 1}{user.name}{user.email}{user._id}{user.createdAt} 142 | 150 | 159 |
165 |
166 |
167 | )} 168 |
169 | ); 170 | } 171 | 172 | export default Users; 173 | --------------------------------------------------------------------------------