dispatch({ type: "editCategoryModalClose" })}
51 | className={`${
52 | data.editCategoryModal.modal ? "" : "hidden"
53 | } fixed top-0 left-0 z-30 w-full h-full bg-black opacity-50`}
54 | />
55 | {/* End Black Overlay */}
56 |
57 | {/* Modal Start */}
58 |
63 |
64 |
65 |
66 | Add Category
67 |
68 | {/* Close Modal */}
69 |
dispatch({ type: "editCategoryModalClose" })}
72 | className="cursor-pointer text-gray-100 py-2 px-2 rounded-full"
73 | >
74 |
88 |
89 |
90 |
91 |
92 |
102 |
103 |
104 |
118 |
119 |
120 |
127 |
128 |
129 |
130 |
131 | );
132 | };
133 |
134 | export default EditCategoryModal;
135 |
--------------------------------------------------------------------------------
/client/src/components/admin/partials/AdminSidebar.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment } from "react";
2 | import { useLocation, useHistory } from "react-router-dom";
3 |
4 | const AdminSidebar = (props) => {
5 | const location = useLocation();
6 | const history = useHistory();
7 |
8 | return (
9 |
10 |
124 |
125 | );
126 | };
127 |
128 | export default AdminSidebar;
129 |
--------------------------------------------------------------------------------
/client/src/components/admin/dashboardAdmin/TodaySell.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useContext, useEffect } from "react";
2 | import { useHistory } from "react-router-dom";
3 | import moment from "moment";
4 | import { DashboardContext } from "./";
5 | import { todayAllOrders } from "./Action";
6 |
7 | const apiURL = process.env.REACT_APP_API_URL;
8 |
9 | const SellTable = () => {
10 | const history = useHistory();
11 | const { data, dispatch } = useContext(DashboardContext);
12 |
13 | useEffect(() => {
14 | todayAllOrders(dispatch);
15 | // eslint-disable-next-line react-hooks/exhaustive-deps
16 | }, []);
17 |
18 | const ordersList = () => {
19 | let newList = [];
20 | if (data.totalOrders.Orders !== undefined) {
21 | data.totalOrders.Orders.forEach(function (elem) {
22 | if (moment(elem.createdAt).format("LL") === moment().format("LL")) {
23 | newList = [...newList, elem];
24 | }
25 | });
26 | }
27 | return newList;
28 | };
29 |
30 | return (
31 |
32 |
33 |
34 | Today's Orders{" "}
35 | {data.totalOrders.Orders !== undefined ? ordersList().length : 0}
36 |
37 |
38 |
39 |
40 | | Products |
41 | Image |
42 | Status |
43 | Order Address |
44 | Ordered at |
45 |
46 |
47 |
48 | {data.totalOrders.Orders !== undefined ? (
49 | ordersList().map((item, key) => {
50 | return ;
51 | })
52 | ) : (
53 |
54 | |
58 | No orders found today
59 | |
60 |
61 | )}
62 |
63 |
64 |
65 | Total{" "}
66 | {data.totalOrders.Orders !== undefined ? ordersList().length : 0}{" "}
67 | orders found
68 |
69 |
70 | history.push("/admin/dashboard/orders")}
72 | style={{ background: "#303031" }}
73 | className="cursor-pointer px-4 py-2 text-white rounded-full"
74 | >
75 | View All
76 |
77 |
78 |
79 |
80 | );
81 | };
82 |
83 | const TodayOrderTable = ({ order }) => {
84 | return (
85 |
86 |
87 | |
88 | {order.allProduct.map((item, index) => {
89 | return (
90 |
91 | {item.id.pName}
92 | {item.quantitiy}x
93 |
94 | );
95 | })}
96 | |
97 |
98 | {order.allProduct.map((item, index) => {
99 | return (
100 |
106 | );
107 | })}
108 | |
109 |
110 | {order.status === "Not processed" && (
111 |
112 | {order.status}
113 |
114 | )}
115 | {order.status === "Processing" && (
116 |
117 | {order.status}
118 |
119 | )}
120 | {order.status === "Shipped" && (
121 |
122 | {order.status}
123 |
124 | )}
125 | {order.status === "Delivered" && (
126 |
127 | {order.status}
128 |
129 | )}
130 | {order.status === "Cancelled" && (
131 |
132 | {order.status}
133 |
134 | )}
135 | |
136 | {order.address} |
137 |
138 | {moment(order.createdAt).format("lll")}
139 | |
140 |
141 |
142 | );
143 | };
144 |
145 | const TodaySell = (props) => {
146 | return (
147 |
148 |
149 |
150 | );
151 | };
152 |
153 | export default TodaySell;
154 |
--------------------------------------------------------------------------------
/client/src/components/shop/productDetails/ReviewForm.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useState, useContext } from "react";
2 | import { useParams } from "react-router-dom";
3 | import { Alert, reviewSubmitHanlder } from "./Action";
4 | import { LayoutContext } from "../layout";
5 | import { isAuthenticate } from "../auth/fetchApi";
6 | import { getSingleProduct } from "./FetchApi";
7 |
8 | const ReviewForm = (props) => {
9 | const { data, dispatch } = useContext(LayoutContext);
10 | let { id } = useParams(); // Product Id
11 |
12 | const [fData, setFdata] = useState({
13 | rating: "",
14 | review: "",
15 | error: false,
16 | success: false,
17 | pId: id,
18 | });
19 |
20 | if (fData.error || fData.success) {
21 | setTimeout(() => {
22 | setFdata({ ...fData, error: false, success: false });
23 | }, 3000);
24 | }
25 |
26 | const fetchData = async () => {
27 | try {
28 | let responseData = await getSingleProduct(id);
29 | if (responseData.Product) {
30 | dispatch({
31 | type: "singleProductDetail",
32 | payload: responseData.Product,
33 | });
34 | console.log(data);
35 | }
36 | if (responseData.error) {
37 | console.log(responseData.error);
38 | }
39 | } catch (error) {
40 | console.log(error);
41 | }
42 | };
43 |
44 | const ratingUserList = data.singleProductDetail.pRatingsReviews.map(
45 | (item) => {
46 | return item.user ? item.user._id : "";
47 | }
48 | );
49 |
50 | return (
51 |
52 |
53 | {fData.error ? Alert("red", fData.error) : ""}
54 | {fData.success ? Alert("green", fData.success) : ""}
55 |
56 | {ratingUserList.includes(isAuthenticate().user._id) ? (
57 |
58 | ) : (
59 |
157 | )}
158 |
159 | );
160 | };
161 |
162 | export default ReviewForm;
163 |
--------------------------------------------------------------------------------
/client/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.0/8 are considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl, {
104 | headers: { 'Service-Worker': 'script' },
105 | })
106 | .then(response => {
107 | // Ensure service worker exists, and that we really are getting a JS file.
108 | const contentType = response.headers.get('content-type');
109 | if (
110 | response.status === 404 ||
111 | (contentType != null && contentType.indexOf('javascript') === -1)
112 | ) {
113 | // No service worker found. Probably a different app. Reload the page.
114 | navigator.serviceWorker.ready.then(registration => {
115 | registration.unregister().then(() => {
116 | window.location.reload();
117 | });
118 | });
119 | } else {
120 | // Service worker found. Proceed as normal.
121 | registerValidSW(swUrl, config);
122 | }
123 | })
124 | .catch(() => {
125 | console.log(
126 | 'No internet connection found. App is running in offline mode.'
127 | );
128 | });
129 | }
130 |
131 | export function unregister() {
132 | if ('serviceWorker' in navigator) {
133 | navigator.serviceWorker.ready
134 | .then(registration => {
135 | registration.unregister();
136 | })
137 | .catch(error => {
138 | console.error(error.message);
139 | });
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/client/src/components/shop/auth/Signup.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useState } from "react";
2 | import { signupReq } from "./fetchApi";
3 |
4 | const Signup = (props) => {
5 | const [data, setData] = useState({
6 | name: "",
7 | email: "",
8 | password: "",
9 | cPassword: "",
10 | error: false,
11 | loading: false,
12 | success: false,
13 | });
14 |
15 | const alert = (msg, type) => (
16 |
{msg}
17 | );
18 |
19 | const formSubmit = async () => {
20 | setData({ ...data, loading: true });
21 | if (data.cPassword !== data.password) {
22 | return setData({
23 | ...data,
24 | error: {
25 | cPassword: "Password doesn't match",
26 | password: "Password doesn't match",
27 | },
28 | });
29 | }
30 | try {
31 | let responseData = await signupReq({
32 | name: data.name,
33 | email: data.email,
34 | password: data.password,
35 | cPassword: data.cPassword,
36 | });
37 | if (responseData.error) {
38 | setData({
39 | ...data,
40 | loading: false,
41 | error: responseData.error,
42 | password: "",
43 | cPassword: "",
44 | });
45 | } else if (responseData.success) {
46 | setData({
47 | success: responseData.success,
48 | name: "",
49 | email: "",
50 | password: "",
51 | cPassword: "",
52 | loading: false,
53 | error: false,
54 | });
55 | }
56 | } catch (error) {
57 | console.log(error);
58 | }
59 | };
60 |
61 | return (
62 |
63 | Register
64 |
178 |
179 | );
180 | };
181 |
182 | export default Signup;
183 |
--------------------------------------------------------------------------------
/client/src/components/shop/home/ProductByCategory.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useEffect, useState } from "react";
2 | import { useHistory, useParams } from "react-router-dom";
3 | import Layout from "../layout";
4 | import { productByCategory } from "../../admin/products/FetchApi";
5 |
6 | const apiURL = process.env.REACT_APP_API_URL;
7 |
8 | const Submenu = ({ category }) => {
9 | const history = useHistory();
10 | return (
11 |
12 | {/* Submenu Section */}
13 |
14 |
15 |
16 | history.push("/")}
19 | >
20 | Shop
21 |
22 | {category}
23 |
24 |
40 |
41 |
42 | {/* Submenu Section */}
43 |
44 | );
45 | };
46 |
47 | const AllProduct = ({ products }) => {
48 | const history = useHistory();
49 | const category =
50 | products && products.length > 0 ? products[0].pCategory.cName : "";
51 | return (
52 |
53 |
54 |
55 | {products && products.length > 0 ? (
56 | products.map((item, index) => {
57 | return (
58 |
59 |
60 |
![]()
history.push(`/products/${item._id}`)}
62 | className="w-full object-cover object-center cursor-pointer"
63 | src={`${apiURL}/uploads/products/${item.pImages[0]}`}
64 | alt=""
65 | />
66 |
67 |
68 | {item.pName}
69 |
70 |
71 |
72 |
86 |
87 |
88 | {item.pRatings ? item.pRatings.length : 0}
89 |
90 |
91 |
92 |
{item.pPrice}.00$
93 |
109 |
110 |
111 | );
112 | })
113 | ) : (
114 |
115 | No product found
116 |
117 | )}
118 |
119 |
120 | );
121 | };
122 |
123 | const PageComponent = () => {
124 | const [products, setProducts] = useState(null);
125 | const { catId } = useParams();
126 |
127 | useEffect(() => {
128 | fetchData();
129 | // eslint-disable-next-line react-hooks/exhaustive-deps
130 | }, []);
131 |
132 | const fetchData = async () => {
133 | try {
134 | let responseData = await productByCategory(catId);
135 | if (responseData && responseData.Products) {
136 | setProducts(responseData.Products);
137 | }
138 | } catch (error) {
139 | console.log(error);
140 | }
141 | };
142 |
143 | return (
144 |
145 |
146 |
147 | );
148 | };
149 |
150 | const ProductByCategory = (props) => {
151 | return (
152 |
153 | } />
154 |
155 | );
156 | };
157 |
158 | export default ProductByCategory;
159 |
--------------------------------------------------------------------------------
/client/src/components/shop/dashboardUser/UserOrders.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useEffect, useContext } from "react";
2 | import moment from "moment";
3 | import { fetchOrderByUser } from "./Action";
4 | import Layout, { DashboardUserContext } from "./Layout";
5 |
6 | const apiURL = process.env.REACT_APP_API_URL;
7 |
8 | const TableHeader = () => {
9 | return (
10 |
11 |
12 |
13 | | Products |
14 | Status |
15 | Total |
16 | Phone |
17 | Address |
18 | Transaction Id |
19 | Checkout |
20 | Processing |
21 |
22 |
23 |
24 | );
25 | };
26 |
27 | const TableBody = ({ order }) => {
28 | return (
29 |
30 |
31 |
32 | {order.allProduct.map((product, i) => {
33 | return (
34 |
35 |
40 | {product.id.pName}
41 | {product.quantitiy}x
42 |
43 | );
44 | })}
45 | |
46 |
47 | {order.status === "Not processed" && (
48 |
49 | {order.status}
50 |
51 | )}
52 | {order.status === "Processing" && (
53 |
54 | {order.status}
55 |
56 | )}
57 | {order.status === "Shipped" && (
58 |
59 | {order.status}
60 |
61 | )}
62 | {order.status === "Delivered" && (
63 |
64 | {order.status}
65 |
66 | )}
67 | {order.status === "Cancelled" && (
68 |
69 | {order.status}
70 |
71 | )}
72 | |
73 |
74 | ${order.amount}.00
75 | |
76 | {order.phone} |
77 | {order.address} |
78 |
79 | {order.transactionId}
80 | |
81 |
82 | {moment(order.createdAt).format("lll")}
83 | |
84 |
85 | {moment(order.updatedAt).format("lll")}
86 | |
87 |
88 |
89 | );
90 | };
91 |
92 | const OrdersComponent = () => {
93 | const { data, dispatch } = useContext(DashboardUserContext);
94 | const { OrderByUser: orders } = data;
95 |
96 | useEffect(() => {
97 | fetchOrderByUser(dispatch);
98 | // eslint-disable-next-line react-hooks/exhaustive-deps
99 | }, []);
100 |
101 | if (data.loading) {
102 | return (
103 |
119 | );
120 | }
121 | return (
122 |
123 |
124 |
125 |
126 | Orders
127 |
128 |
129 |
130 |
131 |
132 |
133 | {orders && orders.length > 0 ? (
134 | orders.map((item, i) => {
135 | return ;
136 | })
137 | ) : (
138 |
139 | |
143 | No order found
144 | |
145 |
146 | )}
147 |
148 |
149 |
150 | Total {orders && orders.length} order found
151 |
152 |
153 |
154 |
155 |
156 | );
157 | };
158 |
159 | const UserOrders = (props) => {
160 | return (
161 |
162 | } />
163 |
164 | );
165 | };
166 |
167 | export default UserOrders;
168 |
--------------------------------------------------------------------------------
/client/src/components/shop/home/SingleProduct.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useState, useEffect, useContext } from "react";
2 | import { useHistory } from "react-router-dom";
3 | import { getAllProduct } from "../../admin/products/FetchApi";
4 | import { HomeContext } from "./index";
5 | import { isWishReq, unWishReq, isWish } from "./Mixins";
6 |
7 | const apiURL = process.env.REACT_APP_API_URL;
8 |
9 | const SingleProduct = (props) => {
10 | const { data, dispatch } = useContext(HomeContext);
11 | const { products } = data;
12 | const history = useHistory();
13 |
14 | /* WhisList State */
15 | const [wList, setWlist] = useState(
16 | JSON.parse(localStorage.getItem("wishList"))
17 | );
18 |
19 | useEffect(() => {
20 | fetchData();
21 | // eslint-disable-next-line react-hooks/exhaustive-deps
22 | }, []);
23 |
24 | const fetchData = async () => {
25 | dispatch({ type: "loading", payload: true });
26 | try {
27 | let responseData = await getAllProduct();
28 | setTimeout(() => {
29 | if (responseData && responseData.Products) {
30 | dispatch({ type: "setProducts", payload: responseData.Products });
31 | dispatch({ type: "loading", payload: false });
32 | }
33 | }, 500);
34 | } catch (error) {
35 | console.log(error);
36 | }
37 | };
38 |
39 | if (data.loading) {
40 | return (
41 |
57 | );
58 | }
59 | return (
60 |
61 | {products && products.length > 0 ? (
62 | products.map((item, index) => {
63 | return (
64 |
65 |
66 |
![]()
history.push(`/products/${item._id}`)}
68 | className="w-full object-cover object-center cursor-pointer"
69 | src={`${apiURL}/uploads/products/${item.pImages[0]}`}
70 | alt=""
71 | />
72 |
73 |
74 | {item.pName}
75 |
76 |
77 |
78 |
92 |
93 |
94 | {item.pRatingsReviews.length}
95 |
96 |
97 |
98 |
${item.pPrice}.00
99 | {/* WhisList Logic */}
100 |
101 |
118 |
133 |
134 | {/* WhisList Logic End */}
135 |
136 |
137 | );
138 | })
139 | ) : (
140 |
141 | No product found
142 |
143 | )}
144 |
145 | );
146 | };
147 |
148 | export default SingleProduct;
149 |
--------------------------------------------------------------------------------
/client/src/components/admin/dashboardAdmin/DashboardCard.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useContext, useEffect } from "react";
2 | import { DashboardContext } from "./";
3 | import { GetAllData } from "./Action";
4 |
5 | const DashboardCard = (props) => {
6 | const { data, dispatch } = useContext(DashboardContext);
7 |
8 | useEffect(() => {
9 | GetAllData(dispatch);
10 | // eslint-disable-next-line react-hooks/exhaustive-deps
11 | }, []);
12 |
13 | return (
14 |
15 | {/* Card Start */}
16 |
17 |
18 |
34 |
35 | {data ? data.totalData.Users : 0}
36 |
37 |
Customers
38 |
39 |
7%
40 |
41 |
55 |
56 |
57 |
58 |
59 |
75 |
76 | {data ? data.totalData.Orders : 0}
77 |
78 |
Orders
79 |
80 |
10%
81 |
82 |
96 |
97 |
98 |
99 |
100 |
114 |
115 | {data ? data.totalData.Products : 0}
116 |
117 |
Product
118 |
119 |
120 |
136 |
137 | {data ? data.totalData.Categories : 0}
138 |
139 |
Categories
140 |
141 |
142 | {/* End Card */}
143 |
144 | );
145 | };
146 |
147 | export default DashboardCard;
148 |
--------------------------------------------------------------------------------