├── MERN Project
├── admin
│ ├── .gitignore
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ │ └── index.html
│ ├── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── components
│ │ │ ├── chart
│ │ │ │ ├── Chart.jsx
│ │ │ │ └── chart.css
│ │ │ ├── featuredInfo
│ │ │ │ ├── FeaturedInfo.jsx
│ │ │ │ └── featuredInfo.css
│ │ │ ├── sidebar
│ │ │ │ ├── Sidebar.jsx
│ │ │ │ └── sidebar.css
│ │ │ ├── topbar
│ │ │ │ ├── Topbar.jsx
│ │ │ │ └── topbar.css
│ │ │ ├── widgetLg
│ │ │ │ ├── WidgetLg.jsx
│ │ │ │ └── widgetLg.css
│ │ │ └── widgetSm
│ │ │ │ ├── WidgetSm.jsx
│ │ │ │ └── widgetSm.css
│ │ ├── dummyData.js
│ │ ├── firebase.js
│ │ ├── index.js
│ │ ├── pages
│ │ │ ├── home
│ │ │ │ ├── Home.jsx
│ │ │ │ └── home.css
│ │ │ ├── login
│ │ │ │ └── Login.jsx
│ │ │ ├── newProduct
│ │ │ │ ├── NewProduct.jsx
│ │ │ │ └── newProduct.css
│ │ │ ├── newUser
│ │ │ │ ├── NewUser.jsx
│ │ │ │ └── newUser.css
│ │ │ ├── product
│ │ │ │ ├── Product.jsx
│ │ │ │ └── product.css
│ │ │ ├── productList
│ │ │ │ ├── ProductList.jsx
│ │ │ │ └── productList.css
│ │ │ ├── user
│ │ │ │ ├── User.jsx
│ │ │ │ └── user.css
│ │ │ └── userList
│ │ │ │ ├── UserList.jsx
│ │ │ │ └── userList.css
│ │ ├── redux
│ │ │ ├── apiCalls.js
│ │ │ ├── productRedux.js
│ │ │ ├── store.js
│ │ │ └── userRedux.js
│ │ └── requestMethods.js
│ └── yarn.lock
├── api
│ ├── .gitignore
│ ├── index.js
│ ├── models
│ │ ├── Cart.js
│ │ ├── Order.js
│ │ ├── Product.js
│ │ └── User.js
│ ├── package-lock.json
│ ├── package.json
│ ├── routes
│ │ ├── auth.js
│ │ ├── cart.js
│ │ ├── order.js
│ │ ├── product.js
│ │ ├── stripe.js
│ │ ├── user.js
│ │ └── verifyToken.js
│ └── yarn.lock
└── client
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ └── index.html
│ ├── src
│ ├── App.jsx
│ ├── components
│ │ ├── Announcement.jsx
│ │ ├── Categories.jsx
│ │ ├── CategoryItem.jsx
│ │ ├── Footer.jsx
│ │ ├── Navbar.jsx
│ │ ├── Newsletter.jsx
│ │ ├── Product.jsx
│ │ ├── Products.jsx
│ │ └── Slider.jsx
│ ├── data.js
│ ├── index.js
│ ├── pages
│ │ ├── Cart.jsx
│ │ ├── Home.jsx
│ │ ├── Login.jsx
│ │ ├── Product.jsx
│ │ ├── ProductList.jsx
│ │ ├── Register.jsx
│ │ └── Success.jsx
│ ├── redux
│ │ ├── apiCalls.js
│ │ ├── cartRedux.js
│ │ ├── store.js
│ │ └── userRedux.js
│ ├── requestMethods.js
│ └── responsive.js
│ └── yarn.lock
├── README.md
├── React Quiz
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ └── index.html
├── src
│ ├── App.css
│ ├── App.jsx
│ ├── assets
│ │ └── bg.jpg
│ ├── components
│ │ ├── Start.jsx
│ │ ├── Timer.jsx
│ │ └── Trivia.jsx
│ ├── index.js
│ └── sounds
│ │ ├── correct.mp3
│ │ ├── play.mp3
│ │ ├── wait.mp3
│ │ └── wrong.mp3
└── yarn.lock
├── _config.yml
└── mern-blog-app
├── api
├── .gitignore
├── index.js
├── models
│ ├── Category.js
│ ├── Post.js
│ └── User.js
├── package.json
├── routes
│ ├── auth.js
│ ├── categories.js
│ ├── posts.js
│ └── users.js
└── yarn.lock
└── client
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
└── index.html
├── src
├── App.js
├── components
│ ├── header
│ │ ├── Header.jsx
│ │ └── header.css
│ ├── post
│ │ ├── Post.jsx
│ │ └── post.css
│ ├── posts
│ │ ├── Posts.jsx
│ │ └── posts.css
│ ├── sidebar
│ │ ├── Sidebar.jsx
│ │ └── sidebar.css
│ ├── singlePost
│ │ ├── SinglePost.jsx
│ │ └── singlePost.css
│ └── topbar
│ │ ├── TopBar.jsx
│ │ └── topbar.css
├── context
│ ├── Actions.js
│ ├── Context.js
│ └── Reducer.js
├── index.js
└── pages
│ ├── home
│ ├── Home.jsx
│ └── home.css
│ ├── login
│ ├── Login.jsx
│ └── login.css
│ ├── register
│ ├── Register.jsx
│ └── register.css
│ ├── settings
│ ├── Settings.jsx
│ └── settings.css
│ ├── single
│ ├── Single.jsx
│ └── single.css
│ └── write
│ ├── Write.jsx
│ └── write.css
└── yarn.lock
/MERN Project/admin/.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 |
--------------------------------------------------------------------------------
/MERN Project/admin/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 | ### `yarn start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `yarn 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 | ### `yarn 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 | ### `yarn 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 | ### `yarn 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 |
--------------------------------------------------------------------------------
/MERN Project/admin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lamaadmin",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@material-ui/core": "^4.11.4",
7 | "@material-ui/data-grid": "^4.0.0-alpha.29",
8 | "@material-ui/icons": "^4.11.2",
9 | "@reduxjs/toolkit": "^1.6.1",
10 | "@testing-library/jest-dom": "^5.11.4",
11 | "@testing-library/react": "^11.1.0",
12 | "@testing-library/user-event": "^12.1.10",
13 | "axios": "^0.21.4",
14 | "firebase": "^9.1.0",
15 | "react": "^17.0.2",
16 | "react-dom": "^17.0.2",
17 | "react-redux": "^7.2.5",
18 | "react-router-dom": "^5.2.0",
19 | "react-scripts": "4.0.3",
20 | "recharts": "^2.0.9",
21 | "redux-persist": "^6.0.0",
22 | "timeago.js": "^4.0.2",
23 | "web-vitals": "^1.0.1"
24 | },
25 | "scripts": {
26 | "start": "react-scripts start",
27 | "build": "react-scripts build",
28 | "test": "react-scripts test",
29 | "eject": "react-scripts eject"
30 | },
31 | "eslintConfig": {
32 | "extends": [
33 | "react-app",
34 | "react-app/jest"
35 | ]
36 | },
37 | "browserslist": {
38 | "production": [
39 | ">0.2%",
40 | "not dead",
41 | "not op_mini all"
42 | ],
43 | "development": [
44 | "last 1 chrome version",
45 | "last 1 firefox version",
46 | "last 1 safari version"
47 | ]
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/MERN Project/admin/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
18 | React Admin App
19 |
20 |
21 |
22 | You need to enable JavaScript to run this app.
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/App.css:
--------------------------------------------------------------------------------
1 | .container{
2 | display: flex;
3 | margin-top: 10px;
4 | }
5 |
6 |
7 | .link{
8 | text-decoration: none;
9 | color: inherit;
10 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/App.js:
--------------------------------------------------------------------------------
1 | import Sidebar from "./components/sidebar/Sidebar";
2 | import Topbar from "./components/topbar/Topbar";
3 | import "./App.css";
4 | import Home from "./pages/home/Home";
5 | import {
6 | BrowserRouter as Router,
7 | Switch,
8 | Route,
9 | Redirect,
10 | } from "react-router-dom";
11 | import UserList from "./pages/userList/UserList";
12 | import User from "./pages/user/User";
13 | import NewUser from "./pages/newUser/NewUser";
14 | import ProductList from "./pages/productList/ProductList";
15 | import Product from "./pages/product/Product";
16 | import NewProduct from "./pages/newProduct/NewProduct";
17 | import Login from "./pages/login/Login";
18 | import { useSelector } from "react-redux";
19 |
20 | function App() {
21 | const admin = useSelector((state) => state.user.currentUser.isAdmin);
22 | return (
23 |
24 |
25 |
26 |
27 |
28 | {admin && (
29 | <>
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | >
56 | )}
57 |
58 |
59 | );
60 | }
61 |
62 | export default App;
63 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/chart/Chart.jsx:
--------------------------------------------------------------------------------
1 | import "./chart.css";
2 | import {
3 | LineChart,
4 | Line,
5 | XAxis,
6 | CartesianGrid,
7 | Tooltip,
8 | ResponsiveContainer,
9 | } from "recharts";
10 |
11 | export default function Chart({ title, data, dataKey, grid }) {
12 |
13 | return (
14 |
15 |
{title}
16 |
17 |
18 |
19 |
20 |
21 | {grid && }
22 |
23 |
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/chart/chart.css:
--------------------------------------------------------------------------------
1 | .chart {
2 | margin: 20px;
3 | padding: 20px;
4 | -webkit-box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
5 | box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
6 | }
7 |
8 | .chartTitle {
9 | margin-bottom: 20px;
10 | }
11 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/featuredInfo/FeaturedInfo.jsx:
--------------------------------------------------------------------------------
1 | import "./featuredInfo.css";
2 | import { ArrowDownward, ArrowUpward } from "@material-ui/icons";
3 | import { useEffect, useState } from "react";
4 | import { userRequest } from "../../requestMethods";
5 |
6 | export default function FeaturedInfo() {
7 | const [income, setIncome] = useState([]);
8 | const [perc, setPerc] = useState(0);
9 |
10 | useEffect(() => {
11 | const getIncome = async () => {
12 | try {
13 | const res = await userRequest.get("orders/income");
14 | setIncome(res.data);
15 | setPerc((res.data[1].total * 100) / res.data[0].total - 100);
16 | } catch {}
17 | };
18 | getIncome();
19 | }, []);
20 |
21 | return (
22 |
23 |
24 |
Revanue
25 |
26 |
${income[1]?.total}
27 |
28 | %{Math.floor(perc)}{" "}
29 | {perc < 0 ? (
30 |
31 | ) : (
32 |
33 | )}
34 |
35 |
36 |
Compared to last month
37 |
38 |
39 |
Sales
40 |
41 |
$4,415
42 |
43 | -1.4
44 |
45 |
46 |
Compared to last month
47 |
48 |
49 |
Cost
50 |
51 |
$2,225
52 |
53 | +2.4
54 |
55 |
56 |
Compared to last month
57 |
58 |
59 | );
60 | }
61 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/featuredInfo/featuredInfo.css:
--------------------------------------------------------------------------------
1 | .featured {
2 | width: 100%;
3 | display: flex;
4 | justify-content: space-between;
5 | }
6 |
7 | .featuredItem {
8 | flex: 1;
9 | margin: 0px 20px;
10 | padding: 30px;
11 | border-radius: 10px;
12 | cursor: pointer;
13 | -webkit-box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
14 | box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
15 | }
16 |
17 | .featuredTitle{
18 | font-size: 20px;
19 | }
20 |
21 | .featuredMoneyContainer{
22 | margin: 10px 0px;
23 | display: flex;
24 | align-items: center;
25 | }
26 |
27 | .featuredMoney{
28 | font-size: 30px;
29 | font-weight: 600;
30 | }
31 |
32 | .featuredMoneyRate{
33 | display: flex;
34 | align-items: center;
35 | margin-left: 20px;
36 | }
37 |
38 | .featuredIcon{
39 | font-size: 14px;
40 | margin-left: 5px;
41 | color: green;
42 | }
43 |
44 | .featuredIcon.negative{
45 | color: red;
46 | }
47 |
48 | .featuredSub{
49 | font-size: 15px;
50 | color: gray;
51 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/sidebar/Sidebar.jsx:
--------------------------------------------------------------------------------
1 | import "./sidebar.css";
2 | import {
3 | LineStyle,
4 | Timeline,
5 | TrendingUp,
6 | PermIdentity,
7 | Storefront,
8 | AttachMoney,
9 | BarChart,
10 | MailOutline,
11 | DynamicFeed,
12 | ChatBubbleOutline,
13 | WorkOutline,
14 | Report,
15 | } from "@material-ui/icons";
16 | import { Link } from "react-router-dom";
17 |
18 | export default function Sidebar() {
19 | return (
20 |
21 |
22 |
23 |
Dashboard
24 |
25 |
26 |
27 |
28 | Home
29 |
30 |
31 |
32 |
33 | Analytics
34 |
35 |
36 |
37 | Sales
38 |
39 |
40 |
41 |
42 |
Quick Menu
43 |
44 |
45 |
46 |
47 | Users
48 |
49 |
50 |
51 |
52 |
53 | Products
54 |
55 |
56 |
57 |
58 | Transactions
59 |
60 |
61 |
62 | Reports
63 |
64 |
65 |
66 |
67 |
Notifications
68 |
69 |
70 |
71 | Mail
72 |
73 |
74 |
75 | Feedback
76 |
77 |
78 |
79 | Messages
80 |
81 |
82 |
83 |
84 |
Staff
85 |
86 |
87 |
88 | Manage
89 |
90 |
91 |
92 | Analytics
93 |
94 |
95 |
96 | Reports
97 |
98 |
99 |
100 |
101 |
102 | );
103 | }
104 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/sidebar/sidebar.css:
--------------------------------------------------------------------------------
1 | .sidebar {
2 | flex: 1;
3 | height: calc(100vh - 50px);
4 | background-color: rgb(251, 251, 255);
5 | position: sticky;
6 | top: 50px;
7 | }
8 |
9 | .sidebarWrapper {
10 | padding: 20px;
11 | color: #555;
12 | }
13 |
14 | .sidebarMenu {
15 | margin-bottom: 10px;
16 | }
17 |
18 | .sidebarTitle {
19 | font-size: 13px;
20 | color: rgb(187, 186, 186);
21 | }
22 |
23 | .sidebarList {
24 | list-style: none;
25 | padding: 5px;
26 | }
27 |
28 | .sidebarListItem {
29 | padding: 5px;
30 | cursor: pointer;
31 | display: flex;
32 | align-items: center;
33 | border-radius: 10px;
34 | }
35 |
36 | .sidebarListItem.active,
37 | .sidebarListItem:hover {
38 | background-color: rgb(240, 240, 255);
39 | }
40 |
41 | .sidebarIcon{
42 | margin-right: 5px;
43 | font-size: 20px !important;
44 | }
45 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/topbar/Topbar.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import "./topbar.css";
3 | import { NotificationsNone, Language, Settings } from "@material-ui/icons";
4 |
5 | export default function Topbar() {
6 | return (
7 |
8 |
9 |
10 | lamaadmin
11 |
12 |
13 |
14 |
15 | 2
16 |
17 |
18 |
19 | 2
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/topbar/topbar.css:
--------------------------------------------------------------------------------
1 | .topbar {
2 | width: 100%;
3 | height: 50px;
4 | background-color: white;
5 | position: sticky;
6 | top: 0;
7 | z-index: 999;
8 | }
9 |
10 | .topbarWrapper {
11 | height: 100%;
12 | padding: 0px 20px;
13 | display: flex;
14 | align-items: center;
15 | justify-content: space-between;
16 | }
17 |
18 | .logo {
19 | font-weight: bold;
20 | font-size: 30px;
21 | color: darkblue;
22 | cursor: pointer;
23 | }
24 |
25 | .topRight{
26 | display: flex;
27 | align-items: center;
28 | }
29 |
30 | .topbarIconContainer {
31 | position: relative;
32 | cursor: pointer;
33 | margin-right: 10px;
34 | color: #555;
35 | }
36 |
37 | .topIconBadge{
38 | width: 15px;
39 | height: 15px;
40 | position: absolute;
41 | top: -5px;
42 | right: 0px;
43 | background-color: red;
44 | color: white;
45 | border-radius: 50%;
46 | display: flex;
47 | align-items: center;
48 | justify-content: center;
49 | font-size: 10px;
50 | }
51 |
52 | .topAvatar{
53 | width: 40px;
54 | height: 40px;
55 | border-radius: 50%;
56 | cursor: pointer;
57 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/widgetLg/WidgetLg.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import { userRequest } from "../../requestMethods";
3 | import "./widgetLg.css";
4 | import {format} from "timeago.js"
5 |
6 | export default function WidgetLg() {
7 | const [orders, setOrders] = useState([]);
8 |
9 | useEffect(() => {
10 | const getOrders = async () => {
11 | try {
12 | const res = await userRequest.get("orders");
13 | setOrders(res.data);
14 | } catch {}
15 | };
16 | getOrders();
17 | }, []);
18 | const Button = ({ type }) => {
19 | return {type} ;
20 | };
21 | return (
22 |
23 |
Latest transactions
24 |
25 |
26 | Customer
27 | Date
28 | Amount
29 | Status
30 |
31 | {orders.map((order) => (
32 |
33 |
34 | {order.userId}
35 |
36 | {format(order.createdAt)}
37 | ${order.amount}
38 |
39 |
40 |
41 |
42 | ))}
43 |
44 |
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/widgetLg/widgetLg.css:
--------------------------------------------------------------------------------
1 | .widgetLg {
2 | flex: 2;
3 | -webkit-box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
4 | box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
5 | padding: 20px;
6 | }
7 |
8 | .widgetLgTitle {
9 | font-size: 22px;
10 | font-weight: 600;
11 | }
12 |
13 | .widgetLgTable{
14 | width: 100%;
15 | border-spacing: 20px;
16 | }
17 |
18 | .widgetLgTh{
19 | text-align: left;
20 | }
21 |
22 | .widgetLgUser{
23 | display: flex;
24 | align-items: center;
25 | font-weight: 600;
26 | }
27 |
28 | .widgetLgImg {
29 | width: 40px;
30 | height: 40px;
31 | border-radius: 50%;
32 | object-fit: cover;
33 | margin-right: 10px;
34 | }
35 |
36 | .widgetLgDate,.widgetLgAmount{
37 | font-weight: 300;
38 | }
39 |
40 | .widgetLgButton {
41 | padding: 5px 7px;
42 | border: none;
43 | border-radius: 10px;
44 | }
45 |
46 | .widgetLgButton.approved{
47 | background-color: #e5faf2;
48 | color: #3bb077;
49 | }
50 | .widgetLgButton.declined{
51 | background-color: #fff0f1;
52 | color: #d95087;
53 |
54 | }
55 | .widgetLgButton.pending{
56 | background-color: #ebf1fe;
57 | color: #2a7ade;
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/widgetSm/WidgetSm.jsx:
--------------------------------------------------------------------------------
1 | import "./widgetSm.css";
2 | import { Visibility } from "@material-ui/icons";
3 | import { useEffect, useState } from "react";
4 | import { userRequest } from "../../requestMethods";
5 |
6 | export default function WidgetSm() {
7 | const [users, setUsers] = useState([]);
8 |
9 | useEffect(() => {
10 | const getUsers = async () => {
11 | try {
12 | const res = await userRequest.get("users/?new=true");
13 | setUsers(res.data);
14 | } catch {}
15 | };
16 | getUsers();
17 | }, []);
18 |
19 | return (
20 |
21 |
New Join Members
22 |
43 |
44 | );
45 | }
46 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/components/widgetSm/widgetSm.css:
--------------------------------------------------------------------------------
1 | .widgetSm{
2 | flex: 1;
3 | -webkit-box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
4 | box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
5 | padding: 20px;
6 | margin-right: 20px;
7 | }
8 |
9 | .widgetSmTitle{
10 | font-size: 22px;
11 | font-weight: 600;
12 | }
13 |
14 | .widgetSmImg{
15 | width: 40px;
16 | height: 40px;
17 | border-radius: 50%;
18 | object-fit: cover;
19 | }
20 |
21 | .widgetSmList{
22 | margin: 0;
23 | padding: 0;
24 | list-style: none;
25 | }
26 |
27 | .widgetSmListItem{
28 | display: flex;
29 | align-items: center;
30 | justify-content: space-between;
31 | margin: 20px 0px;
32 | }
33 |
34 | .widgetSmUser{
35 | display: flex;
36 | flex-direction: column;
37 | }
38 |
39 | .widgetSmUsername{
40 | font-weight: 600;
41 | }
42 |
43 | .widgetSmUserTitle{
44 | font-weight: 300;
45 | }
46 |
47 | .widgetSmButton{
48 | display: flex;
49 | align-items: center;
50 | border: none;
51 | border-radius: 10px;
52 | padding: 7px 10px;
53 | background-color: #eeeef7;
54 | color: #555;
55 | cursor: pointer;
56 | }
57 |
58 | .widgetSmIcon{
59 | font-size: 16px !important;
60 | margin-right: 5px;
61 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/dummyData.js:
--------------------------------------------------------------------------------
1 | export const userData = [
2 | {
3 | name: "Jan",
4 | "Active User": 4000,
5 | },
6 | {
7 | name: "Feb",
8 | "Active User": 3000,
9 | },
10 | {
11 | name: "Mar",
12 | "Active User": 5000,
13 | },
14 | {
15 | name: "Apr",
16 | "Active User": 4000,
17 | },
18 | {
19 | name: "May",
20 | "Active User": 3000,
21 | },
22 | {
23 | name: "Jun",
24 | "Active User": 2000,
25 | },
26 | {
27 | name: "Jul",
28 | "Active User": 4000,
29 | },
30 | {
31 | name: "Agu",
32 | "Active User": 3000,
33 | },
34 | {
35 | name: "Sep",
36 | "Active User": 4000,
37 | },
38 | {
39 | name: "Oct",
40 | "Active User": 1000,
41 | },
42 | {
43 | name: "Nov",
44 | "Active User": 4000,
45 | },
46 | {
47 | name: "Dec",
48 | "Active User": 3000,
49 | },
50 | ];
51 |
52 | export const productData = [
53 | {
54 | name: "Jan",
55 | "Sales": 4000,
56 | },
57 | {
58 | name: "Feb",
59 | "Sales": 3000,
60 | },
61 | {
62 | name: "Mar",
63 | "Sales": 5000,
64 | },
65 | ];
66 |
67 | export const userRows = [
68 | {
69 | id: 1,
70 | username: "Jon Snow",
71 | avatar:
72 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
73 | email: "jon@gmail.com",
74 | status: "active",
75 | transaction: "$120.00",
76 | },
77 | {
78 | id: 2,
79 | username: "Jon Snow",
80 | avatar:
81 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
82 | email: "jon@gmail.com",
83 | status: "active",
84 | transaction: "$120.00",
85 | },
86 | {
87 | id: 3,
88 | username: "Jon Snow",
89 | avatar:
90 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
91 | email: "jon@gmail.com",
92 | status: "active",
93 | transaction: "$120.00",
94 | },
95 | {
96 | id: 4,
97 | username: "Jon Snow",
98 | avatar:
99 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
100 | email: "jon@gmail.com",
101 | status: "active",
102 | transaction: "$120.00",
103 | },
104 | {
105 | id: 5,
106 | username: "Jon Snow",
107 | avatar:
108 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
109 | email: "jon@gmail.com",
110 | status: "active",
111 | transaction: "$120.00",
112 | },
113 | {
114 | id: 6,
115 | username: "Jon Snow",
116 | avatar:
117 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
118 | email: "jon@gmail.com",
119 | status: "active",
120 | transaction: "$120.00",
121 | },
122 | {
123 | id: 7,
124 | username: "Jon Snow",
125 | avatar:
126 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
127 | email: "jon@gmail.com",
128 | status: "active",
129 | transaction: "$120.00",
130 | },
131 | {
132 | id: 8,
133 | username: "Jon Snow",
134 | avatar:
135 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
136 | email: "jon@gmail.com",
137 | status: "active",
138 | transaction: "$120.00",
139 | },
140 | {
141 | id: 9,
142 | username: "Jon Snow",
143 | avatar:
144 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
145 | email: "jon@gmail.com",
146 | status: "active",
147 | transaction: "$120.00",
148 | },
149 | {
150 | id: 10,
151 | username: "Jon Snow",
152 | avatar:
153 | "https://images.pexels.com/photos/1152994/pexels-photo-1152994.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
154 | email: "jon@gmail.com",
155 | status: "active",
156 | transaction: "$120.00",
157 | },
158 | ];
159 |
160 | export const productRows = [
161 | {
162 | id: 1,
163 | name: "Apple Airpods",
164 | img:
165 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
166 | stock: 123,
167 | status: "active",
168 | price: "$120.00",
169 | },
170 | {
171 | id: 2,
172 | name: "Apple Airpods",
173 | img:
174 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
175 | stock: 123,
176 | status: "active",
177 | price: "$120.00",
178 | },
179 | {
180 | id: 3,
181 | name: "Apple Airpods",
182 | img:
183 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
184 | stock: 123,
185 | status: "active",
186 | price: "$120.00",
187 | },
188 | {
189 | id: 4,
190 | name: "Apple Airpods",
191 | img:
192 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
193 | stock: 123,
194 | status: "active",
195 | price: "$120.00",
196 | },
197 | {
198 | id: 5,
199 | name: "Apple Airpods",
200 | img:
201 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
202 | stock: 123,
203 | status: "active",
204 | price: "$120.00",
205 | },
206 | {
207 | id: 6,
208 | name: "Apple Airpods",
209 | img:
210 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
211 | stock: 123,
212 | status: "active",
213 | price: "$120.00",
214 | },
215 | {
216 | id: 7,
217 | name: "Apple Airpods",
218 | img:
219 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
220 | stock: 123,
221 | status: "active",
222 | price: "$120.00",
223 | },
224 | {
225 | id: 8,
226 | name: "Apple Airpods",
227 | img:
228 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
229 | stock: 123,
230 | status: "active",
231 | price: "$120.00",
232 | },
233 | {
234 | id: 9,
235 | name: "Apple Airpods",
236 | img:
237 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
238 | stock: 123,
239 | status: "active",
240 | price: "$120.00",
241 | },
242 | {
243 | id: 10,
244 | name: "Apple Airpods",
245 | img:
246 | "https://images.pexels.com/photos/7156886/pexels-photo-7156886.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
247 | stock: 123,
248 | status: "active",
249 | price: "$120.00",
250 | },
251 | ];
--------------------------------------------------------------------------------
/MERN Project/admin/src/firebase.js:
--------------------------------------------------------------------------------
1 | // Import the functions you need from the SDKs you need
2 | import { initializeApp } from "firebase/app";
3 | // TODO: Add SDKs for Firebase products that you want to use
4 | // https://firebase.google.com/docs/web/setup#available-libraries
5 |
6 | // Your web app's Firebase configuration
7 | const firebaseConfig = {
8 | apiKey: "AIzaSyCB-h_T2ZL-a7xt5zMvZmSh8GBXtawzL0c",
9 | authDomain: "shop-889c6.firebaseapp.com",
10 | projectId: "shop-889c6",
11 | storageBucket: "shop-889c6.appspot.com",
12 | messagingSenderId: "105110075028",
13 | appId: "1:105110075028:web:7cee5adf1ed39f597e6681",
14 | };
15 |
16 | // Initialize Firebase
17 | const app = initializeApp(firebaseConfig);
18 |
19 | export default app;
20 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import App from "./App";
4 | import { Provider } from "react-redux";
5 | import { store, persistor } from "./redux/store";
6 | import { PersistGate } from "redux-persist/integration/react";
7 |
8 | ReactDOM.render(
9 |
10 |
11 |
12 |
13 | ,
14 | document.getElementById("root")
15 | );
16 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/home/Home.jsx:
--------------------------------------------------------------------------------
1 | import Chart from "../../components/chart/Chart";
2 | import FeaturedInfo from "../../components/featuredInfo/FeaturedInfo";
3 | import "./home.css";
4 | import { userData } from "../../dummyData";
5 | import WidgetSm from "../../components/widgetSm/WidgetSm";
6 | import WidgetLg from "../../components/widgetLg/WidgetLg";
7 | import { useEffect, useMemo, useState } from "react";
8 | import { userRequest } from "../../requestMethods";
9 |
10 | export default function Home() {
11 | const [userStats, setUserStats] = useState([]);
12 |
13 | const MONTHS = useMemo(
14 | () => [
15 | "Jan",
16 | "Feb",
17 | "Mar",
18 | "Apr",
19 | "May",
20 | "Jun",
21 | "Jul",
22 | "Agu",
23 | "Sep",
24 | "Oct",
25 | "Nov",
26 | "Dec",
27 | ],
28 | []
29 | );
30 |
31 | useEffect(() => {
32 | const getStats = async () => {
33 | try {
34 | const res = await userRequest.get("/users/stats");
35 | res.data.map((item) =>
36 | setUserStats((prev) => [
37 | ...prev,
38 | { name: MONTHS[item._id - 1], "Active User": item.total },
39 | ])
40 | );
41 | } catch {}
42 | };
43 | getStats();
44 | }, [MONTHS]);
45 |
46 | return (
47 |
48 |
49 |
55 |
56 |
57 |
58 |
59 |
60 | );
61 | }
62 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/home/home.css:
--------------------------------------------------------------------------------
1 | .home{
2 | flex: 4;
3 | }
4 |
5 | .homeWidgets{
6 | display: flex;
7 | margin: 20px;
8 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/login/Login.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { useDispatch } from "react-redux";
3 | import { login } from "../../redux/apiCalls";
4 |
5 | const Login = () => {
6 | const [username, setUsername] = useState("");
7 | const [password, setPassword] = useState("");
8 | const dispatch = useDispatch();
9 |
10 | const handleClick = (e) => {
11 | e.preventDefault();
12 | login(dispatch, { username, password });
13 | };
14 |
15 | return (
16 |
25 | setUsername(e.target.value)}
30 | />
31 | setPassword(e.target.value)}
36 | />
37 |
38 | Login
39 |
40 |
41 | );
42 | };
43 |
44 | export default Login;
45 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/newProduct/NewProduct.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import "./newProduct.css";
3 | import {
4 | getStorage,
5 | ref,
6 | uploadBytesResumable,
7 | getDownloadURL,
8 | } from "firebase/storage";
9 | import app from "../../firebase";
10 | import { addProduct } from "../../redux/apiCalls";
11 | import { useDispatch } from "react-redux";
12 |
13 | export default function NewProduct() {
14 | const [inputs, setInputs] = useState({});
15 | const [file, setFile] = useState(null);
16 | const [cat, setCat] = useState([]);
17 | const dispatch = useDispatch();
18 |
19 | const handleChange = (e) => {
20 | setInputs((prev) => {
21 | return { ...prev, [e.target.name]: e.target.value };
22 | });
23 | };
24 | const handleCat = (e) => {
25 | setCat(e.target.value.split(","));
26 | };
27 |
28 | const handleClick = (e) => {
29 | e.preventDefault();
30 | const fileName = new Date().getTime() + file.name;
31 | const storage = getStorage(app);
32 | const storageRef = ref(storage, fileName);
33 | const uploadTask = uploadBytesResumable(storageRef, file);
34 |
35 | // Register three observers:
36 | // 1. 'state_changed' observer, called any time the state changes
37 | // 2. Error observer, called on failure
38 | // 3. Completion observer, called on successful completion
39 | uploadTask.on(
40 | "state_changed",
41 | (snapshot) => {
42 | // Observe state change events such as progress, pause, and resume
43 | // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
44 | const progress =
45 | (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
46 | console.log("Upload is " + progress + "% done");
47 | switch (snapshot.state) {
48 | case "paused":
49 | console.log("Upload is paused");
50 | break;
51 | case "running":
52 | console.log("Upload is running");
53 | break;
54 | default:
55 | }
56 | },
57 | (error) => {
58 | // Handle unsuccessful uploads
59 | },
60 | () => {
61 | // Handle successful uploads on complete
62 | // For instance, get the download URL: https://firebasestorage.googleapis.com/...
63 | getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
64 | const product = { ...inputs, img: downloadURL, categories: cat };
65 | addProduct(product, dispatch);
66 | });
67 | }
68 | );
69 | };
70 |
71 | return (
72 |
73 |
New Product
74 |
125 |
126 | );
127 | }
128 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/newProduct/newProduct.css:
--------------------------------------------------------------------------------
1 | .newProduct {
2 | flex: 4;
3 | margin-left: 100px;
4 | }
5 |
6 | .addProductForm {
7 | margin-top: 10px;
8 | }
9 |
10 | .addProductItem {
11 | width: 250px;
12 | display: flex;
13 | flex-direction: column;
14 | margin-bottom: 10px;
15 | }
16 |
17 | .addProductItem > label {
18 | color: gray;
19 | font-weight: 600;
20 | margin-bottom: 10px;
21 | }
22 |
23 | .addProductItem > input {
24 | padding: 10px;
25 | }
26 |
27 | .addProductItem > select {
28 | padding: 10px;
29 | }
30 |
31 | .addProductButton {
32 | margin-top: 10px;
33 | padding: 7px 10px;
34 | border: none;
35 | border-radius: 10px;
36 | background-color: darkblue;
37 | color: white;
38 | font-weight: 600;
39 | cursor: pointer;
40 | }
41 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/newUser/NewUser.jsx:
--------------------------------------------------------------------------------
1 | import "./newUser.css";
2 |
3 | export default function NewUser() {
4 | return (
5 |
53 | );
54 | }
55 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/newUser/newUser.css:
--------------------------------------------------------------------------------
1 | .newUser {
2 | flex: 4;
3 | }
4 |
5 | .newUserForm {
6 | display: flex;
7 | flex-wrap: wrap;
8 | }
9 |
10 | .newUserItem {
11 | width: 400px;
12 | display: flex;
13 | flex-direction: column;
14 | margin-top: 10px;
15 | margin-right: 20px;
16 | }
17 |
18 | .newUserItem > label {
19 | margin-bottom: 10px;
20 | font-size: 14px;
21 | font-weight: 600;
22 | color: rgb(151, 150, 150);
23 | }
24 |
25 | .newUserItem > input {
26 | height: 20px;
27 | padding: 10px;
28 | border: 1px solid gray;
29 | border-radius: 5px;
30 | }
31 |
32 | .newUserGender > input {
33 | margin-top: 15px;
34 | }
35 |
36 | .newUserGender>label{
37 | margin: 10px;
38 | font-size: 18px;
39 | color: #555;
40 | }
41 |
42 | .newUserSelect{
43 | height: 40px;
44 | border-radius: 5px;
45 | }
46 |
47 | .newUserButton{
48 | width: 200px;
49 | border: none;
50 | background-color: darkblue;
51 | color: white;
52 | padding: 7px 10px;
53 | font-weight: 600;
54 | border-radius: 10px;
55 | margin-top: 30px;
56 | cursor: pointer;
57 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/product/Product.jsx:
--------------------------------------------------------------------------------
1 | import { Link, useLocation } from "react-router-dom";
2 | import "./product.css";
3 | import Chart from "../../components/chart/Chart";
4 | import { productData } from "../../dummyData";
5 | import { Publish } from "@material-ui/icons";
6 | import { useSelector } from "react-redux";
7 | import { useEffect, useMemo, useState } from "react";
8 | import { userRequest } from "../../requestMethods";
9 |
10 | export default function Product() {
11 | const location = useLocation();
12 | const productId = location.pathname.split("/")[2];
13 | const [pStats, setPStats] = useState([]);
14 |
15 | const product = useSelector((state) =>
16 | state.product.products.find((product) => product._id === productId)
17 | );
18 |
19 | const MONTHS = useMemo(
20 | () => [
21 | "Jan",
22 | "Feb",
23 | "Mar",
24 | "Apr",
25 | "May",
26 | "Jun",
27 | "Jul",
28 | "Agu",
29 | "Sep",
30 | "Oct",
31 | "Nov",
32 | "Dec",
33 | ],
34 | []
35 | );
36 |
37 | useEffect(() => {
38 | const getStats = async () => {
39 | try {
40 | const res = await userRequest.get("orders/income?pid=" + productId);
41 | const list = res.data.sort((a,b)=>{
42 | return a._id - b._id
43 | })
44 | list.map((item) =>
45 | setPStats((prev) => [
46 | ...prev,
47 | { name: MONTHS[item._id - 1], Sales: item.total },
48 | ])
49 | );
50 | } catch (err) {
51 | console.log(err);
52 | }
53 | };
54 | getStats();
55 | }, [productId, MONTHS]);
56 |
57 | return (
58 |
59 |
60 |
Product
61 |
62 | Create
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
{product.title}
73 |
74 |
75 |
76 | id:
77 | {product._id}
78 |
79 |
80 | sales:
81 | 5123
82 |
83 |
84 | in stock:
85 | {product.inStock}
86 |
87 |
88 |
89 |
90 |
117 |
118 | );
119 | }
120 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/product/product.css:
--------------------------------------------------------------------------------
1 | .product {
2 | flex: 4;
3 | padding: 20px;
4 | }
5 |
6 | .productTitleContainer {
7 | display: flex;
8 | align-items: center;
9 | justify-content: space-between;
10 | }
11 |
12 | .productAddButton {
13 | width: 80px;
14 | border: none;
15 | padding: 5px;
16 | background-color: teal;
17 | color: white;
18 | border-radius: 5px;
19 | font-size: 16px;
20 | cursor: pointer;
21 | }
22 |
23 | .productTop {
24 | display: flex;
25 | }
26 |
27 | .productTopLeft,
28 | .productTopRight {
29 | flex: 1;
30 | }
31 |
32 | .productTopRight {
33 | padding: 20px;
34 | margin: 20px;
35 | -webkit-box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
36 | box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
37 | }
38 |
39 | .productInfoImg {
40 | width: 40px;
41 | height: 40px;
42 | border-radius: 50%;
43 | object-fit: cover;
44 | margin-right: 20px;
45 | }
46 |
47 | .productInfoTop {
48 | display: flex;
49 | align-items: center;
50 | }
51 |
52 | .productName {
53 | font-weight: 600;
54 | }
55 |
56 | .productInfoBottom {
57 | margin-top: 10px;
58 | }
59 |
60 | .productInfoItem {
61 | width: 150px;
62 | display: flex;
63 | justify-content: space-between;
64 | }
65 |
66 | .productInfoValue {
67 | font-weight: 300;
68 | }
69 |
70 | .productBottom {
71 | padding: 20px;
72 | margin: 20px;
73 | -webkit-box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
74 | box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
75 | }
76 |
77 | .productForm {
78 | display: flex;
79 | justify-content: space-between;
80 | }
81 |
82 | .productFormLeft {
83 | display: flex;
84 | flex-direction: column;
85 | }
86 |
87 | .productFormLeft > label {
88 | margin-bottom: 10px;
89 | color: gray;
90 | }
91 |
92 | .productFormLeft > input {
93 | margin-bottom: 10px;
94 | border: none;
95 | padding: 5px;
96 | border-bottom: 1px solid gray;
97 | }
98 |
99 | .productFormLeft >select{
100 | margin-bottom: 10px;
101 | }
102 |
103 | .productUploadImg{
104 | width: 100px;
105 | height: 100px;
106 | border-radius: 10px;
107 | object-fit: cover;
108 | margin-right: 20px;
109 | }
110 |
111 | .productFormRight{
112 | display: flex;
113 | flex-direction: column;
114 | justify-content: space-around;
115 | }
116 |
117 | .productUpload{
118 | display: flex;
119 | align-items: center;
120 | }
121 |
122 | .productButton{
123 | border: none;
124 | padding: 5px;
125 | border-radius: 5px;
126 | background-color: darkblue;
127 | color:white;
128 | font-weight: 600;
129 | cursor: pointer;
130 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/productList/ProductList.jsx:
--------------------------------------------------------------------------------
1 | import "./productList.css";
2 | import { DataGrid } from "@material-ui/data-grid";
3 | import { DeleteOutline } from "@material-ui/icons";
4 | import { Link } from "react-router-dom";
5 | import { useEffect } from "react";
6 | import { useDispatch, useSelector } from "react-redux";
7 | import { deleteProduct, getProducts } from "../../redux/apiCalls";
8 |
9 | export default function ProductList() {
10 | const dispatch = useDispatch();
11 | const products = useSelector((state) => state.product.products);
12 |
13 | useEffect(() => {
14 | getProducts(dispatch);
15 | }, [dispatch]);
16 |
17 | const handleDelete = (id) => {
18 | deleteProduct(id, dispatch);
19 | };
20 |
21 | const columns = [
22 | { field: "_id", headerName: "ID", width: 220 },
23 | {
24 | field: "product",
25 | headerName: "Product",
26 | width: 200,
27 | renderCell: (params) => {
28 | return (
29 |
30 |
31 | {params.row.title}
32 |
33 | );
34 | },
35 | },
36 | { field: "inStock", headerName: "Stock", width: 200 },
37 | {
38 | field: "price",
39 | headerName: "Price",
40 | width: 160,
41 | },
42 | {
43 | field: "action",
44 | headerName: "Action",
45 | width: 150,
46 | renderCell: (params) => {
47 | return (
48 | <>
49 |
50 | Edit
51 |
52 | handleDelete(params.row._id)}
55 | />
56 | >
57 | );
58 | },
59 | },
60 | ];
61 |
62 | return (
63 |
64 | row._id}
69 | pageSize={8}
70 | checkboxSelection
71 | />
72 |
73 | );
74 | }
75 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/productList/productList.css:
--------------------------------------------------------------------------------
1 | .productList{
2 | flex: 4;
3 | }
4 |
5 | .productListItem{
6 | display: flex;
7 | align-items: center;
8 | }
9 |
10 | .productListImg {
11 | width: 32px;
12 | height: 32px;
13 | border-radius: 50%;
14 | object-fit: cover;
15 | margin-right: 10px;
16 | }
17 |
18 | .productListEdit{
19 | border: none;
20 | border-radius: 10px;
21 | padding: 5px 10px;
22 | background-color: #3bb077;
23 | color: white;
24 | cursor: pointer;
25 | margin-right: 20px;
26 | }
27 |
28 | .productListDelete{
29 | color: red;
30 | cursor: pointer;
31 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/user/User.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | CalendarToday,
3 | LocationSearching,
4 | MailOutline,
5 | PermIdentity,
6 | PhoneAndroid,
7 | Publish,
8 | } from "@material-ui/icons";
9 | import { Link } from "react-router-dom";
10 | import "./user.css";
11 |
12 | export default function User() {
13 | return (
14 |
15 |
16 |
Edit User
17 |
18 | Create
19 |
20 |
21 |
22 |
23 |
24 |
29 |
30 | Anna Becker
31 | Software Engineer
32 |
33 |
34 |
35 |
Account Details
36 |
37 |
38 |
annabeck99
39 |
40 |
41 |
42 | 10.12.1999
43 |
44 |
Contact Details
45 |
46 |
47 |
+1 123 456 67
48 |
49 |
50 |
51 | annabeck99@gmail.com
52 |
53 |
54 |
55 | New York | USA
56 |
57 |
58 |
59 |
120 |
121 |
122 | );
123 | }
124 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/user/user.css:
--------------------------------------------------------------------------------
1 | .user {
2 | flex: 4;
3 | padding: 20px;
4 | }
5 |
6 | .userTitleContainer {
7 | display: flex;
8 | align-items: center;
9 | justify-content: space-between;
10 | }
11 |
12 | .userAddButton {
13 | width: 80px;
14 | border: none;
15 | padding: 5px;
16 | background-color: teal;
17 | border-radius: 5px;
18 | cursor: pointer;
19 | color: white;
20 | font-size: 16px;
21 | }
22 |
23 | .userContainer {
24 | display: flex;
25 | margin-top: 20px;
26 | }
27 |
28 | .userShow {
29 | flex: 1;
30 | padding: 20px;
31 | -webkit-box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
32 | box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
33 | }
34 |
35 | .userUpdate {
36 | flex: 2;
37 | padding: 20px;
38 | -webkit-box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
39 | box-shadow: 0px 0px 15px -10px rgba(0, 0, 0, 0.75);
40 | margin-left: 20px;
41 | }
42 |
43 | .userShowTop {
44 | display: flex;
45 | align-items: center;
46 | }
47 |
48 | .userShowImg {
49 | width: 40px;
50 | height: 40px;
51 | border-radius: 50%;
52 | object-fit: cover;
53 | }
54 |
55 | .userShowTopTitle {
56 | display: flex;
57 | flex-direction: column;
58 | margin-left: 20px;
59 | }
60 |
61 | .userShowUsername {
62 | font-weight: 600;
63 | }
64 |
65 | .userShowUserTitle {
66 | font-weight: 300;
67 | }
68 |
69 | .userShowBottom{
70 | margin-top: 20px;
71 | }
72 |
73 | .userShowTitle {
74 | font-size: 14px;
75 | font-weight: 600;
76 | color: rgb(175, 170, 170);
77 | }
78 |
79 | .userShowInfo{
80 | display: flex;
81 | align-items: center;
82 | margin: 20px 0px;
83 | color: #444;
84 | }
85 |
86 | .userShowIcon{
87 | font-size: 16px !important;
88 | }
89 |
90 | .userShowInfoTitle{
91 | margin-left: 10px;
92 | }
93 |
94 | .userUpdateTitle{
95 | font-size: 24px;
96 | font-weight: 600;
97 | }
98 |
99 | .userUpdateForm{
100 | display: flex;
101 | justify-content: space-between;
102 | margin-top: 20px;
103 | }
104 |
105 | .userUpdateItem{
106 | display: flex;
107 | flex-direction: column;
108 | margin-top: 10px;
109 | }
110 |
111 | .userUpdateItem>label{
112 | margin-bottom: 5px;
113 | font-size: 14px;
114 | }
115 |
116 | .userUpdateInput{
117 | border: none;
118 | width: 250px;
119 | height: 30px;
120 | border-bottom: 1px solid gray;
121 | }
122 |
123 | .userUpdateRight{
124 | display: flex;
125 | flex-direction: column;
126 | justify-content: space-between;
127 | }
128 |
129 | .userUpdateUpload{
130 | display: flex;
131 | align-items: center;
132 | }
133 |
134 | .userUpdateImg{
135 | width: 100px;
136 | height: 100px;
137 | border-radius: 10px;
138 | object-fit: cover;
139 | margin-right: 20px;
140 | }
141 |
142 | .userUpdateIcon{
143 | cursor: pointer;
144 | }
145 |
146 | .userUpdateButton{
147 | border-radius: 5px;
148 | border: none;
149 | padding: 5px;
150 | cursor: pointer;
151 | background-color: darkblue;
152 | color: white;
153 | font-weight: 600;
154 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/userList/UserList.jsx:
--------------------------------------------------------------------------------
1 | import "./userList.css";
2 | import { DataGrid } from "@material-ui/data-grid";
3 | import { DeleteOutline } from "@material-ui/icons";
4 | import { userRows } from "../../dummyData";
5 | import { Link } from "react-router-dom";
6 | import { useState } from "react";
7 |
8 | export default function UserList() {
9 | const [data, setData] = useState(userRows);
10 |
11 | const handleDelete = (id) => {
12 | setData(data.filter((item) => item.id !== id));
13 | };
14 |
15 | const columns = [
16 | { field: "id", headerName: "ID", width: 90 },
17 | {
18 | field: "user",
19 | headerName: "User",
20 | width: 200,
21 | renderCell: (params) => {
22 | return (
23 |
24 |
25 | {params.row.username}
26 |
27 | );
28 | },
29 | },
30 | { field: "email", headerName: "Email", width: 200 },
31 | {
32 | field: "status",
33 | headerName: "Status",
34 | width: 120,
35 | },
36 | {
37 | field: "transaction",
38 | headerName: "Transaction Volume",
39 | width: 160,
40 | },
41 | {
42 | field: "action",
43 | headerName: "Action",
44 | width: 150,
45 | renderCell: (params) => {
46 | return (
47 | <>
48 |
49 | Edit
50 |
51 | handleDelete(params.row.id)}
54 | />
55 | >
56 | );
57 | },
58 | },
59 | ];
60 |
61 | return (
62 |
63 |
70 |
71 | );
72 | }
73 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/pages/userList/userList.css:
--------------------------------------------------------------------------------
1 | .userList {
2 | flex: 4;
3 | }
4 |
5 | .userListUser {
6 | display: flex;
7 | align-items: center;
8 | }
9 |
10 | .userListImg {
11 | width: 32px;
12 | height: 32px;
13 | border-radius: 50%;
14 | object-fit: cover;
15 | margin-right: 10px;
16 | }
17 |
18 | .userListEdit{
19 | border: none;
20 | border-radius: 10px;
21 | padding: 5px 10px;
22 | background-color: #3bb077;
23 | color: white;
24 | cursor: pointer;
25 | margin-right: 20px;
26 | }
27 |
28 | .userListDelete{
29 | color: red;
30 | cursor: pointer;
31 | }
--------------------------------------------------------------------------------
/MERN Project/admin/src/redux/apiCalls.js:
--------------------------------------------------------------------------------
1 | import { loginFailure, loginStart, loginSuccess } from "./userRedux";
2 | import { publicRequest, userRequest } from "../requestMethods";
3 | import {
4 | getProductFailure,
5 | getProductStart,
6 | getProductSuccess,
7 | deleteProductFailure,
8 | deleteProductStart,
9 | deleteProductSuccess,
10 | updateProductFailure,
11 | updateProductStart,
12 | updateProductSuccess,
13 | addProductFailure,
14 | addProductStart,
15 | addProductSuccess,
16 | } from "./productRedux";
17 |
18 | export const login = async (dispatch, user) => {
19 | dispatch(loginStart());
20 | try {
21 | const res = await publicRequest.post("/auth/login", user);
22 | dispatch(loginSuccess(res.data));
23 | } catch (err) {
24 | dispatch(loginFailure());
25 | }
26 | };
27 |
28 | export const getProducts = async (dispatch) => {
29 | dispatch(getProductStart());
30 | try {
31 | const res = await publicRequest.get("/products");
32 | dispatch(getProductSuccess(res.data));
33 | } catch (err) {
34 | dispatch(getProductFailure());
35 | }
36 | };
37 |
38 | export const deleteProduct = async (id, dispatch) => {
39 | dispatch(deleteProductStart());
40 | try {
41 | // const res = await userRequest.delete(`/products/${id}`);
42 | dispatch(deleteProductSuccess(id));
43 | } catch (err) {
44 | dispatch(deleteProductFailure());
45 | }
46 | };
47 |
48 | export const updateProduct = async (id, product, dispatch) => {
49 | dispatch(updateProductStart());
50 | try {
51 | // update
52 | dispatch(updateProductSuccess({ id, product }));
53 | } catch (err) {
54 | dispatch(updateProductFailure());
55 | }
56 | };
57 | export const addProduct = async (product, dispatch) => {
58 | dispatch(addProductStart());
59 | try {
60 | const res = await userRequest.post(`/products`, product);
61 | dispatch(addProductSuccess(res.data));
62 | } catch (err) {
63 | dispatch(addProductFailure());
64 | }
65 | };
66 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/redux/productRedux.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | export const productSlice = createSlice({
4 | name: "product",
5 | initialState: {
6 | products: [],
7 | isFetching: false,
8 | error: false,
9 | },
10 | reducers: {
11 | //GET ALL
12 | getProductStart: (state) => {
13 | state.isFetching = true;
14 | state.error = false;
15 | },
16 | getProductSuccess: (state, action) => {
17 | state.isFetching = false;
18 | state.products = action.payload;
19 | },
20 | getProductFailure: (state) => {
21 | state.isFetching = false;
22 | state.error = true;
23 | },
24 | //DELETE
25 | deleteProductStart: (state) => {
26 | state.isFetching = true;
27 | state.error = false;
28 | },
29 | deleteProductSuccess: (state, action) => {
30 | state.isFetching = false;
31 | state.products.splice(
32 | state.products.findIndex((item) => item._id === action.payload),
33 | 1
34 | );
35 | },
36 | deleteProductFailure: (state) => {
37 | state.isFetching = false;
38 | state.error = true;
39 | },
40 | //UPDATE
41 | updateProductStart: (state) => {
42 | state.isFetching = true;
43 | state.error = false;
44 | },
45 | updateProductSuccess: (state, action) => {
46 | state.isFetching = false;
47 | state.products[
48 | state.products.findIndex((item) => item._id === action.payload.id)
49 | ] = action.payload.product;
50 | },
51 | updateProductFailure: (state) => {
52 | state.isFetching = false;
53 | state.error = true;
54 | },
55 | //UPDATE
56 | addProductStart: (state) => {
57 | state.isFetching = true;
58 | state.error = false;
59 | },
60 | addProductSuccess: (state, action) => {
61 | state.isFetching = false;
62 | state.products.push(action.payload);
63 | },
64 | addProductFailure: (state) => {
65 | state.isFetching = false;
66 | state.error = true;
67 | },
68 | },
69 | });
70 |
71 | export const {
72 | getProductStart,
73 | getProductSuccess,
74 | getProductFailure,
75 | deleteProductStart,
76 | deleteProductSuccess,
77 | deleteProductFailure,
78 | updateProductStart,
79 | updateProductSuccess,
80 | updateProductFailure,
81 | addProductStart,
82 | addProductSuccess,
83 | addProductFailure,
84 | } = productSlice.actions;
85 |
86 | export default productSlice.reducer;
87 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/redux/store.js:
--------------------------------------------------------------------------------
1 | import { configureStore, combineReducers } from "@reduxjs/toolkit";
2 | import userReducer from "./userRedux";
3 | import productReducer from "./productRedux";
4 | import {
5 | persistStore,
6 | persistReducer,
7 | FLUSH,
8 | REHYDRATE,
9 | PAUSE,
10 | PERSIST,
11 | PURGE,
12 | REGISTER,
13 | } from "redux-persist";
14 | import storage from "redux-persist/lib/storage";
15 |
16 | const persistConfig = {
17 | key: "root",
18 | version: 1,
19 | storage,
20 | };
21 |
22 | const rootReducer = combineReducers({
23 | user: userReducer,
24 | product: productReducer,
25 | });
26 |
27 | const persistedReducer = persistReducer(persistConfig, rootReducer);
28 |
29 | export const store = configureStore({
30 | reducer: persistedReducer,
31 | middleware: (getDefaultMiddleware) =>
32 | getDefaultMiddleware({
33 | serializableCheck: {
34 | ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
35 | },
36 | }),
37 | });
38 |
39 | export let persistor = persistStore(store);
40 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/redux/userRedux.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const userSlice = createSlice({
4 | name: "user",
5 | initialState: {
6 | currentUser: null,
7 | isFetching: false,
8 | error: false,
9 | },
10 | reducers: {
11 | loginStart: (state) => {
12 | state.isFetching = true;
13 | },
14 | loginSuccess: (state, action) => {
15 | state.isFetching = false;
16 | state.currentUser = action.payload;
17 | },
18 | loginFailure: (state) => {
19 | state.isFetching = false;
20 | state.error = true;
21 | },
22 | logout: (state) => {
23 | state.currentUser = null;
24 | },
25 | },
26 | });
27 |
28 | export const { loginStart, loginSuccess, loginFailure } = userSlice.actions;
29 | export default userSlice.reducer;
30 |
--------------------------------------------------------------------------------
/MERN Project/admin/src/requestMethods.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | const BASE_URL = "http://localhost:5000/api/";
4 | const TOKEN = JSON.parse(JSON.parse(localStorage.getItem("persist:root")).user).currentUser.accessToken;
5 |
6 | export const publicRequest = axios.create({
7 | baseURL: BASE_URL,
8 | });
9 |
10 | export const userRequest = axios.create({
11 | baseURL: BASE_URL,
12 | headers: { token: `Bearer ${TOKEN}` },
13 | });
14 |
--------------------------------------------------------------------------------
/MERN Project/api/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | .env.local
3 | .env.development.local
4 | .env.test.local
5 | .env.production.local
6 | node_modules
--------------------------------------------------------------------------------
/MERN Project/api/index.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const app = express();
3 | const mongoose = require("mongoose");
4 | const dotenv = require("dotenv");
5 | dotenv.config();
6 | const userRoute = require("./routes/user");
7 | const authRoute = require("./routes/auth");
8 | const productRoute = require("./routes/product");
9 | const cartRoute = require("./routes/cart");
10 | const orderRoute = require("./routes/order");
11 | const stripeRoute = require("./routes/stripe");
12 | const cors = require("cors");
13 |
14 |
15 | mongoose
16 | .connect(process.env.MONGO_URL)
17 | .then(() => console.log("DB Connection Successfull!"))
18 | .catch((err) => {
19 | console.log(err);
20 | });
21 |
22 | app.use(cors());
23 | app.use(express.json());
24 | app.use("/api/auth", authRoute);
25 | app.use("/api/users", userRoute);
26 | app.use("/api/products", productRoute);
27 | app.use("/api/carts", cartRoute);
28 | app.use("/api/orders", orderRoute);
29 | app.use("/api/checkout", stripeRoute);
30 |
31 | app.listen(process.env.PORT || 5000, () => {
32 | console.log("Backend server is running!");
33 | });
34 |
--------------------------------------------------------------------------------
/MERN Project/api/models/Cart.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const CartSchema = new mongoose.Schema(
4 | {
5 | userId: { type: String, required: true },
6 | products: [
7 | {
8 | productId: {
9 | type: String,
10 | },
11 | quantity: {
12 | type: Number,
13 | default: 1,
14 | },
15 | },
16 | ],
17 | },
18 | { timestamps: true }
19 | );
20 |
21 | module.exports = mongoose.model("Cart", CartSchema);
22 |
--------------------------------------------------------------------------------
/MERN Project/api/models/Order.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const OrderSchema = new mongoose.Schema(
4 | {
5 | userId: { type: String, required: true },
6 | products: [
7 | {
8 | productId: {
9 | type: String,
10 | },
11 | quantity: {
12 | type: Number,
13 | default: 1,
14 | },
15 | },
16 | ],
17 | amount: { type: Number, required: true },
18 | address: { type: Object, required: true },
19 | status: { type: String, default: "pending" },
20 | },
21 | { timestamps: true }
22 | );
23 |
24 | module.exports = mongoose.model("Order", OrderSchema);
25 |
--------------------------------------------------------------------------------
/MERN Project/api/models/Product.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const ProductSchema = new mongoose.Schema(
4 | {
5 | title: { type: String, required: true, unique: true },
6 | desc: { type: String, required: true },
7 | img: { type: String, required: true },
8 | categories: { type: Array },
9 | size: { type: Array },
10 | color: { type: Array },
11 | price: { type: Number, required: true },
12 | inStock: { type: Boolean, default: true },
13 | },
14 | { timestamps: true }
15 | );
16 |
17 | module.exports = mongoose.model("Product", ProductSchema);
18 |
--------------------------------------------------------------------------------
/MERN Project/api/models/User.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const UserSchema = new mongoose.Schema(
4 | {
5 | username: { type: String, required: true, unique: true },
6 | email: { type: String, required: true, unique: true },
7 | password: { type: String, required: true },
8 | isAdmin: {
9 | type: Boolean,
10 | default: false,
11 | },
12 | img: { type: String },
13 | },
14 | { timestamps: true }
15 | );
16 |
17 | module.exports = mongoose.model("User", UserSchema);
18 |
--------------------------------------------------------------------------------
/MERN Project/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ecommerceapi",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "nodemon index.js"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "cors": "^2.8.5",
14 | "crypto-js": "^4.1.1",
15 | "dotenv": "^10.0.0",
16 | "express": "^4.17.1",
17 | "jsonwebtoken": "^8.5.1",
18 | "mongoose": "^6.0.5",
19 | "nodemon": "^2.0.12",
20 | "stripe": "^8.174.0"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/MERN Project/api/routes/auth.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const User = require("../models/User");
3 | const CryptoJS = require("crypto-js");
4 | const jwt = require("jsonwebtoken");
5 |
6 | //REGISTER
7 | router.post("/register", async (req, res) => {
8 | const newUser = new User({
9 | username: req.body.username,
10 | email: req.body.email,
11 | password: CryptoJS.AES.encrypt(
12 | req.body.password,
13 | process.env.PASS_SEC
14 | ).toString(),
15 | });
16 |
17 | try {
18 | const savedUser = await newUser.save();
19 | res.status(201).json(savedUser);
20 | } catch (err) {
21 | res.status(500).json(err);
22 | }
23 | });
24 |
25 | //LOGIN
26 |
27 | router.post("/login", async (req, res) => {
28 | try {
29 | const user = await User.findOne({ username: req.body.username });
30 | !user && res.status(401).json("Wrong credentials!");
31 |
32 | const hashedPassword = CryptoJS.AES.decrypt(
33 | user.password,
34 | process.env.PASS_SEC
35 | );
36 | const OriginalPassword = hashedPassword.toString(CryptoJS.enc.Utf8);
37 |
38 | OriginalPassword !== req.body.password &&
39 | res.status(401).json("Wrong credentials!");
40 |
41 | const accessToken = jwt.sign(
42 | {
43 | id: user._id,
44 | isAdmin: user.isAdmin,
45 | },
46 | process.env.JWT_SEC,
47 | {expiresIn:"3d"}
48 | );
49 |
50 | const { password, ...others } = user._doc;
51 |
52 | res.status(200).json({...others, accessToken});
53 | } catch (err) {
54 | res.status(500).json(err);
55 | }
56 | });
57 |
58 | module.exports = router;
59 |
--------------------------------------------------------------------------------
/MERN Project/api/routes/cart.js:
--------------------------------------------------------------------------------
1 | const Cart = require("../models/Cart");
2 | const {
3 | verifyToken,
4 | verifyTokenAndAuthorization,
5 | verifyTokenAndAdmin,
6 | } = require("./verifyToken");
7 |
8 | const router = require("express").Router();
9 |
10 | //CREATE
11 |
12 | router.post("/", verifyToken, async (req, res) => {
13 | const newCart = new Cart(req.body);
14 |
15 | try {
16 | const savedCart = await newCart.save();
17 | res.status(200).json(savedCart);
18 | } catch (err) {
19 | res.status(500).json(err);
20 | }
21 | });
22 |
23 | //UPDATE
24 | router.put("/:id", verifyTokenAndAuthorization, async (req, res) => {
25 | try {
26 | const updatedCart = await Cart.findByIdAndUpdate(
27 | req.params.id,
28 | {
29 | $set: req.body,
30 | },
31 | { new: true }
32 | );
33 | res.status(200).json(updatedCart);
34 | } catch (err) {
35 | res.status(500).json(err);
36 | }
37 | });
38 |
39 | //DELETE
40 | router.delete("/:id", verifyTokenAndAuthorization, async (req, res) => {
41 | try {
42 | await Cart.findByIdAndDelete(req.params.id);
43 | res.status(200).json("Cart has been deleted...");
44 | } catch (err) {
45 | res.status(500).json(err);
46 | }
47 | });
48 |
49 | //GET USER CART
50 | router.get("/find/:userId", verifyTokenAndAuthorization, async (req, res) => {
51 | try {
52 | const cart = await Cart.findOne({ userId: req.params.userId });
53 | res.status(200).json(cart);
54 | } catch (err) {
55 | res.status(500).json(err);
56 | }
57 | });
58 |
59 | // //GET ALL
60 |
61 | router.get("/", verifyTokenAndAdmin, async (req, res) => {
62 | try {
63 | const carts = await Cart.find();
64 | res.status(200).json(carts);
65 | } catch (err) {
66 | res.status(500).json(err);
67 | }
68 | });
69 |
70 | module.exports = router;
71 |
--------------------------------------------------------------------------------
/MERN Project/api/routes/order.js:
--------------------------------------------------------------------------------
1 | const Order = require("../models/Order");
2 | const {
3 | verifyToken,
4 | verifyTokenAndAuthorization,
5 | verifyTokenAndAdmin,
6 | } = require("./verifyToken");
7 |
8 | const router = require("express").Router();
9 |
10 | //CREATE
11 |
12 | router.post("/", verifyToken, async (req, res) => {
13 | const newOrder = new Order(req.body);
14 |
15 | try {
16 | const savedOrder = await newOrder.save();
17 | res.status(200).json(savedOrder);
18 | } catch (err) {
19 | res.status(500).json(err);
20 | }
21 | });
22 |
23 | //UPDATE
24 | router.put("/:id", verifyTokenAndAdmin, async (req, res) => {
25 | try {
26 | const updatedOrder = await Order.findByIdAndUpdate(
27 | req.params.id,
28 | {
29 | $set: req.body,
30 | },
31 | { new: true }
32 | );
33 | res.status(200).json(updatedOrder);
34 | } catch (err) {
35 | res.status(500).json(err);
36 | }
37 | });
38 |
39 | //DELETE
40 | router.delete("/:id", verifyTokenAndAdmin, async (req, res) => {
41 | try {
42 | await Order.findByIdAndDelete(req.params.id);
43 | res.status(200).json("Order has been deleted...");
44 | } catch (err) {
45 | res.status(500).json(err);
46 | }
47 | });
48 |
49 | //GET USER ORDERS
50 | router.get("/find/:userId", verifyTokenAndAuthorization, async (req, res) => {
51 | try {
52 | const orders = await Order.find({ userId: req.params.userId });
53 | res.status(200).json(orders);
54 | } catch (err) {
55 | res.status(500).json(err);
56 | }
57 | });
58 |
59 | // //GET ALL
60 |
61 | router.get("/", verifyTokenAndAdmin, async (req, res) => {
62 | try {
63 | const orders = await Order.find();
64 | res.status(200).json(orders);
65 | } catch (err) {
66 | res.status(500).json(err);
67 | }
68 | });
69 |
70 | // GET MONTHLY INCOME
71 |
72 | router.get("/income", verifyTokenAndAdmin, async (req, res) => {
73 | const productId = req.query.pid;
74 | const date = new Date();
75 | const lastMonth = new Date(date.setMonth(date.getMonth() - 1));
76 | const previousMonth = new Date(new Date().setMonth(lastMonth.getMonth() - 1));
77 |
78 | try {
79 | const income = await Order.aggregate([
80 | {
81 | $match: {
82 | createdAt: { $gte: previousMonth },
83 | ...(productId && {
84 | products: { $elemMatch: { productId } },
85 | }),
86 | },
87 | },
88 | {
89 | $project: {
90 | month: { $month: "$createdAt" },
91 | sales: "$amount",
92 | },
93 | },
94 | {
95 | $group: {
96 | _id: "$month",
97 | total: { $sum: "$sales" },
98 | },
99 | },
100 | ]);
101 | res.status(200).json(income);
102 | } catch (err) {
103 | res.status(500).json(err);
104 | }
105 | });
106 |
107 | module.exports = router;
108 |
--------------------------------------------------------------------------------
/MERN Project/api/routes/product.js:
--------------------------------------------------------------------------------
1 | const Product = require("../models/Product");
2 | const {
3 | verifyToken,
4 | verifyTokenAndAuthorization,
5 | verifyTokenAndAdmin,
6 | } = require("./verifyToken");
7 |
8 | const router = require("express").Router();
9 |
10 | //CREATE
11 |
12 | router.post("/", verifyTokenAndAdmin, async (req, res) => {
13 | const newProduct = new Product(req.body);
14 |
15 | try {
16 | const savedProduct = await newProduct.save();
17 | res.status(200).json(savedProduct);
18 | } catch (err) {
19 | res.status(500).json(err);
20 | }
21 | });
22 |
23 | //UPDATE
24 | router.put("/:id", verifyTokenAndAdmin, async (req, res) => {
25 | try {
26 | const updatedProduct = await Product.findByIdAndUpdate(
27 | req.params.id,
28 | {
29 | $set: req.body,
30 | },
31 | { new: true }
32 | );
33 | res.status(200).json(updatedProduct);
34 | } catch (err) {
35 | res.status(500).json(err);
36 | }
37 | });
38 |
39 | //DELETE
40 | router.delete("/:id", verifyTokenAndAdmin, async (req, res) => {
41 | try {
42 | await Product.findByIdAndDelete(req.params.id);
43 | res.status(200).json("Product has been deleted...");
44 | } catch (err) {
45 | res.status(500).json(err);
46 | }
47 | });
48 |
49 | //GET PRODUCT
50 | router.get("/find/:id", async (req, res) => {
51 | try {
52 | const product = await Product.findById(req.params.id);
53 | res.status(200).json(product);
54 | } catch (err) {
55 | res.status(500).json(err);
56 | }
57 | });
58 |
59 | //GET ALL PRODUCTS
60 | router.get("/", async (req, res) => {
61 | const qNew = req.query.new;
62 | const qCategory = req.query.category;
63 | try {
64 | let products;
65 |
66 | if (qNew) {
67 | products = await Product.find().sort({ createdAt: -1 }).limit(1);
68 | } else if (qCategory) {
69 | products = await Product.find({
70 | categories: {
71 | $in: [qCategory],
72 | },
73 | });
74 | } else {
75 | products = await Product.find();
76 | }
77 |
78 | res.status(200).json(products);
79 | } catch (err) {
80 | res.status(500).json(err);
81 | }
82 | });
83 |
84 | module.exports = router;
85 |
--------------------------------------------------------------------------------
/MERN Project/api/routes/stripe.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const stripe = require("stripe")(process.env.STRIPE_KEY);
3 |
4 | router.post("/payment", (req, res) => {
5 | stripe.charges.create(
6 | {
7 | source: req.body.tokenId,
8 | amount: req.body.amount,
9 | currency: "usd",
10 | },
11 | (stripeErr, stripeRes) => {
12 | if (stripeErr) {
13 | res.status(500).json(stripeErr);
14 | } else {
15 | res.status(200).json(stripeRes);
16 | }
17 | }
18 | );
19 | });
20 |
21 | module.exports = router;
22 |
--------------------------------------------------------------------------------
/MERN Project/api/routes/user.js:
--------------------------------------------------------------------------------
1 | const User = require("../models/User");
2 | const {
3 | verifyToken,
4 | verifyTokenAndAuthorization,
5 | verifyTokenAndAdmin,
6 | } = require("./verifyToken");
7 |
8 | const router = require("express").Router();
9 |
10 | //UPDATE
11 | router.put("/:id", verifyTokenAndAuthorization, async (req, res) => {
12 | if (req.body.password) {
13 | req.body.password = CryptoJS.AES.encrypt(
14 | req.body.password,
15 | process.env.PASS_SEC
16 | ).toString();
17 | }
18 |
19 | try {
20 | const updatedUser = await User.findByIdAndUpdate(
21 | req.params.id,
22 | {
23 | $set: req.body,
24 | },
25 | { new: true }
26 | );
27 | res.status(200).json(updatedUser);
28 | } catch (err) {
29 | res.status(500).json(err);
30 | }
31 | });
32 |
33 | //DELETE
34 | router.delete("/:id", verifyTokenAndAuthorization, async (req, res) => {
35 | try {
36 | await User.findByIdAndDelete(req.params.id);
37 | res.status(200).json("User has been deleted...");
38 | } catch (err) {
39 | res.status(500).json(err);
40 | }
41 | });
42 |
43 | //GET USER
44 | router.get("/find/:id", verifyTokenAndAdmin, async (req, res) => {
45 | try {
46 | const user = await User.findById(req.params.id);
47 | const { password, ...others } = user._doc;
48 | res.status(200).json(others);
49 | } catch (err) {
50 | res.status(500).json(err);
51 | }
52 | });
53 |
54 | //GET ALL USER
55 | router.get("/", verifyTokenAndAdmin, async (req, res) => {
56 | const query = req.query.new;
57 | try {
58 | const users = query
59 | ? await User.find().sort({ _id: -1 }).limit(5)
60 | : await User.find();
61 | res.status(200).json(users);
62 | } catch (err) {
63 | res.status(500).json(err);
64 | }
65 | });
66 |
67 | //GET USER STATS
68 |
69 | router.get("/stats", verifyTokenAndAdmin, async (req, res) => {
70 | const date = new Date();
71 | const lastYear = new Date(date.setFullYear(date.getFullYear() - 1));
72 |
73 | try {
74 | const data = await User.aggregate([
75 | { $match: { createdAt: { $gte: lastYear } } },
76 | {
77 | $project: {
78 | month: { $month: "$createdAt" },
79 | },
80 | },
81 | {
82 | $group: {
83 | _id: "$month",
84 | total: { $sum: 1 },
85 | },
86 | },
87 | ]);
88 | res.status(200).json(data)
89 | } catch (err) {
90 | res.status(500).json(err);
91 | }
92 | });
93 |
94 | module.exports = router;
95 |
--------------------------------------------------------------------------------
/MERN Project/api/routes/verifyToken.js:
--------------------------------------------------------------------------------
1 | const jwt = require("jsonwebtoken");
2 |
3 | const verifyToken = (req, res, next) => {
4 | const authHeader = req.headers.token;
5 | if (authHeader) {
6 | const token = authHeader.split(" ")[1];
7 | jwt.verify(token, process.env.JWT_SEC, (err, user) => {
8 | if (err) res.status(403).json("Token is not valid!");
9 | req.user = user;
10 | next();
11 | });
12 | } else {
13 | return res.status(401).json("You are not authenticated!");
14 | }
15 | };
16 |
17 | const verifyTokenAndAuthorization = (req, res, next) => {
18 | verifyToken(req, res, () => {
19 | if (req.user.id === req.params.id || req.user.isAdmin) {
20 | next();
21 | } else {
22 | res.status(403).json("You are not alowed to do that!");
23 | }
24 | });
25 | };
26 |
27 | const verifyTokenAndAdmin = (req, res, next) => {
28 | verifyToken(req, res, () => {
29 | if (req.user.isAdmin) {
30 | next();
31 | } else {
32 | res.status(403).json("You are not alowed to do that!");
33 | }
34 | });
35 | };
36 |
37 | module.exports = {
38 | verifyToken,
39 | verifyTokenAndAuthorization,
40 | verifyTokenAndAdmin,
41 | };
42 |
--------------------------------------------------------------------------------
/MERN Project/client/.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
17 | .env.local
18 | .env.development.local
19 | .env.test.local
20 | .env.production.local
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
--------------------------------------------------------------------------------
/MERN Project/client/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 | ### `yarn start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `yarn 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 | ### `yarn 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 | ### `yarn 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 | ### `yarn 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 |
--------------------------------------------------------------------------------
/MERN Project/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "new",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@material-ui/core": "^4.12.3",
7 | "@material-ui/icons": "^4.11.2",
8 | "@reduxjs/toolkit": "^1.6.1",
9 | "@testing-library/jest-dom": "^5.11.4",
10 | "@testing-library/react": "^11.1.0",
11 | "@testing-library/user-event": "^12.1.10",
12 | "axios": "^0.21.4",
13 | "react": "^17.0.2",
14 | "react-dom": "^17.0.2",
15 | "react-redux": "^7.2.5",
16 | "react-router-dom": "^5.3.0",
17 | "react-scripts": "4.0.3",
18 | "react-stripe-checkout": "^2.6.3",
19 | "redux-persist": "^6.0.0",
20 | "styled-components": "^5.3.1",
21 | "web-vitals": "^1.0.1"
22 | },
23 | "scripts": {
24 | "start": "react-scripts start",
25 | "build": "react-scripts build",
26 | "test": "react-scripts test",
27 | "eject": "react-scripts eject"
28 | },
29 | "eslintConfig": {
30 | "extends": [
31 | "react-app",
32 | "react-app/jest"
33 | ]
34 | },
35 | "browserslist": {
36 | "production": [
37 | ">0.2%",
38 | "not dead",
39 | "not op_mini all"
40 | ],
41 | "development": [
42 | "last 1 chrome version",
43 | "last 1 firefox version",
44 | "last 1 safari version"
45 | ]
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/MERN Project/client/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
11 |
17 | React App
18 |
19 |
20 |
21 | You need to enable JavaScript to run this app.
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/MERN Project/client/src/App.jsx:
--------------------------------------------------------------------------------
1 | import Product from "./pages/Product";
2 | import Home from "./pages/Home";
3 | import ProductList from "./pages/ProductList";
4 | import Register from "./pages/Register";
5 | import Login from "./pages/Login";
6 | import Cart from "./pages/Cart";
7 | import {
8 | BrowserRouter as Router,
9 | Switch,
10 | Route,
11 | Redirect,
12 | } from "react-router-dom";
13 | import Success from "./pages/Success";
14 | import { useSelector } from "react-redux";
15 |
16 | const App = () => {
17 | const user = useSelector((state) => state.user.currentUser);
18 | return (
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | {user ? : }
37 |
38 | {user ? : }
39 |
40 |
41 |
42 | );
43 | };
44 |
45 | export default App;
46 |
--------------------------------------------------------------------------------
/MERN Project/client/src/components/Announcement.jsx:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 |
3 | const Container = styled.div`
4 | height: 30px;
5 | background-color: teal;
6 | color: white;
7 | display: flex;
8 | align-items: center;
9 | justify-content: center;
10 | font-size: 14px;
11 | font-weight: 500;
12 | `;
13 |
14 | const Announcement = () => {
15 | return Super Deal! Free Shipping on Orders Over $50 ;
16 | };
17 |
18 | export default Announcement;
19 |
--------------------------------------------------------------------------------
/MERN Project/client/src/components/Categories.jsx:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 | import { categories } from "../data";
3 | import { mobile } from "../responsive";
4 | import CategoryItem from "./CategoryItem";
5 |
6 | const Container = styled.div`
7 | display: flex;
8 | padding: 20px;
9 | justify-content: space-between;
10 | ${mobile({ padding: "0px", flexDirection:"column" })}
11 |
12 | `;
13 |
14 | const Categories = () => {
15 | return (
16 |
17 | {categories.map((item) => (
18 |
19 | ))}
20 |
21 | );
22 | };
23 |
24 | export default Categories;
25 |
--------------------------------------------------------------------------------
/MERN Project/client/src/components/CategoryItem.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 | import styled from "styled-components";
3 | import { mobile } from "../responsive";
4 |
5 | const Container = styled.div`
6 | flex: 1;
7 | margin: 3px;
8 | height: 70vh;
9 | position: relative;
10 | `;
11 |
12 | const Image = styled.img`
13 | width: 100%;
14 | height: 100%;
15 | object-fit: cover;
16 | ${mobile({ height: "20vh" })}
17 |
18 | `;
19 |
20 | const Info = styled.div`
21 | position: absolute;
22 | top: 0;
23 | left: 0;
24 | width: 100%;
25 | height: 100%;
26 | display: flex;
27 | flex-direction: column;
28 | align-items: center;
29 | justify-content: center;
30 | `;
31 |
32 | const Title = styled.h1`
33 | color:white;
34 | margin-bottom: 20px;
35 | `;
36 |
37 | const Button = styled.button`
38 | border:none;
39 | padding: 10px;
40 | background-color: white;
41 | color:gray;
42 | cursor: pointer;
43 | font-weight: 600;
44 | `;
45 |
46 | const CategoryItem = ({ item }) => {
47 | return (
48 |
49 |
50 |
51 |
52 | {item.title}
53 | SHOP NOW
54 |
55 |
56 |
57 | );
58 | };
59 |
60 | export default CategoryItem;
61 |
--------------------------------------------------------------------------------
/MERN Project/client/src/components/Footer.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | Facebook,
3 | Instagram,
4 | MailOutline,
5 | Phone,
6 | Pinterest,
7 | Room,
8 | Twitter,
9 | } from "@material-ui/icons";
10 | import styled from "styled-components";
11 | import { mobile } from "../responsive";
12 |
13 | const Container = styled.div`
14 | display: flex;
15 | ${mobile({ flexDirection: "column" })}
16 | `;
17 |
18 | const Left = styled.div`
19 | flex: 1;
20 | display: flex;
21 | flex-direction: column;
22 | padding: 20px;
23 | `;
24 |
25 | const Logo = styled.h1``;
26 |
27 | const Desc = styled.p`
28 | margin: 20px 0px;
29 | `;
30 |
31 | const SocialContainer = styled.div`
32 | display: flex;
33 | `;
34 |
35 | const SocialIcon = styled.div`
36 | width: 40px;
37 | height: 40px;
38 | border-radius: 50%;
39 | color: white;
40 | background-color: #${(props) => props.color};
41 | display: flex;
42 | align-items: center;
43 | justify-content: center;
44 | margin-right: 20px;
45 | `;
46 |
47 | const Center = styled.div`
48 | flex: 1;
49 | padding: 20px;
50 | ${mobile({ display: "none" })}
51 | `;
52 |
53 | const Title = styled.h3`
54 | margin-bottom: 30px;
55 | `;
56 |
57 | const List = styled.ul`
58 | margin: 0;
59 | padding: 0;
60 | list-style: none;
61 | display: flex;
62 | flex-wrap: wrap;
63 | `;
64 |
65 | const ListItem = styled.li`
66 | width: 50%;
67 | margin-bottom: 10px;
68 | `;
69 |
70 | const Right = styled.div`
71 | flex: 1;
72 | padding: 20px;
73 | ${mobile({ backgroundColor: "#fff8f8" })}
74 |
75 | `;
76 |
77 | const ContactItem = styled.div`
78 | margin-bottom: 20px;
79 | display: flex;
80 | align-items: center;
81 | `;
82 |
83 | const Payment = styled.img`
84 | width: 50%;
85 | `;
86 |
87 | const Footer = () => {
88 | return (
89 |
90 |
91 | LAMA.
92 |
93 | There are many variations of passages of Lorem Ipsum available, but
94 | the majority have suffered alteration in some form, by injected
95 | humour, or randomised words which don’t look even slightly believable.
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | Useful Links
114 |
115 | Home
116 | Cart
117 | Man Fashion
118 | Woman Fashion
119 | Accessories
120 | My Account
121 | Order Tracking
122 | Wishlist
123 | Wishlist
124 | Terms
125 |
126 |
127 |
128 | Contact
129 |
130 | 622 Dixie Path , South Tobinchester 98336
131 |
132 |
133 | +1 234 56 78
134 |
135 |
136 | contact@lama.dev
137 |
138 |
139 |
140 |
141 | );
142 | };
143 |
144 | export default Footer;
145 |
--------------------------------------------------------------------------------
/MERN Project/client/src/components/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import { Badge } from "@material-ui/core";
2 | import { Search, ShoppingCartOutlined } from "@material-ui/icons";
3 | import React from "react";
4 | import styled from "styled-components";
5 | import { mobile } from "../responsive";
6 | import { useSelector } from "react-redux";
7 | import { Link } from "react-router-dom";
8 |
9 | const Container = styled.div`
10 | height: 60px;
11 | ${mobile({ height: "50px" })}
12 | `;
13 |
14 | const Wrapper = styled.div`
15 | padding: 10px 20px;
16 | display: flex;
17 | align-items: center;
18 | justify-content: space-between;
19 | ${mobile({ padding: "10px 0px" })}
20 | `;
21 |
22 | const Left = styled.div`
23 | flex: 1;
24 | display: flex;
25 | align-items: center;
26 | `;
27 |
28 | const Language = styled.span`
29 | font-size: 14px;
30 | cursor: pointer;
31 | ${mobile({ display: "none" })}
32 | `;
33 |
34 | const SearchContainer = styled.div`
35 | border: 0.5px solid lightgray;
36 | display: flex;
37 | align-items: center;
38 | margin-left: 25px;
39 | padding: 5px;
40 | `;
41 |
42 | const Input = styled.input`
43 | border: none;
44 | ${mobile({ width: "50px" })}
45 | `;
46 |
47 | const Center = styled.div`
48 | flex: 1;
49 | text-align: center;
50 | `;
51 |
52 | const Logo = styled.h1`
53 | font-weight: bold;
54 | ${mobile({ fontSize: "24px" })}
55 | `;
56 | const Right = styled.div`
57 | flex: 1;
58 | display: flex;
59 | align-items: center;
60 | justify-content: flex-end;
61 | ${mobile({ flex: 2, justifyContent: "center" })}
62 | `;
63 |
64 | const MenuItem = styled.div`
65 | font-size: 14px;
66 | cursor: pointer;
67 | margin-left: 25px;
68 | ${mobile({ fontSize: "12px", marginLeft: "10px" })}
69 | `;
70 |
71 | const Navbar = () => {
72 | const quantity = useSelector(state=>state.cart.quantity)
73 | return (
74 |
75 |
76 |
77 | EN
78 |
79 |
80 |
81 |
82 |
83 |
84 | LAMA.
85 |
86 |
87 | REGISTER
88 | SIGN IN
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | );
100 | };
101 |
102 | export default Navbar;
103 |
--------------------------------------------------------------------------------
/MERN Project/client/src/components/Newsletter.jsx:
--------------------------------------------------------------------------------
1 | import { Send } from "@material-ui/icons";
2 | import styled from "styled-components";
3 | import { mobile } from "../responsive";
4 |
5 | const Container = styled.div`
6 | height: 60vh;
7 | background-color: #fcf5f5;
8 | display: flex;
9 | align-items: center;
10 | justify-content: center;
11 | flex-direction: column;
12 | `;
13 | const Title = styled.h1`
14 | font-size: 70px;
15 | margin-bottom: 20px;
16 | `;
17 |
18 | const Desc = styled.div`
19 | font-size: 24px;
20 | font-weight: 300;
21 | margin-bottom: 20px;
22 | ${mobile({ textAlign: "center" })}
23 |
24 | `;
25 |
26 | const InputContainer = styled.div`
27 | width: 50%;
28 | height: 40px;
29 | background-color: white;
30 | display: flex;
31 | justify-content: space-between;
32 | border: 1px solid lightgray;
33 | ${mobile({ width: "80%" })}
34 | `;
35 |
36 | const Input = styled.input`
37 | border: none;
38 | flex: 8;
39 | padding-left: 20px;
40 | `;
41 |
42 | const Button = styled.button`
43 | flex: 1;
44 | border: none;
45 | background-color: teal;
46 | color: white;
47 | `;
48 |
49 | const Newsletter = () => {
50 | return (
51 |
52 | Newsletter
53 | Get timely updates from your favorite products.
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | );
62 | };
63 |
64 | export default Newsletter;
65 |
--------------------------------------------------------------------------------
/MERN Project/client/src/components/Product.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | FavoriteBorderOutlined,
3 | SearchOutlined,
4 | ShoppingCartOutlined,
5 | } from "@material-ui/icons";
6 | import { Link } from "react-router-dom";
7 | import styled from "styled-components";
8 |
9 | const Info = styled.div`
10 | opacity: 0;
11 | width: 100%;
12 | height: 100%;
13 | position: absolute;
14 | top: 0;
15 | left: 0;
16 | background-color: rgba(0, 0, 0, 0.2);
17 | z-index: 3;
18 | display: flex;
19 | align-items: center;
20 | justify-content: center;
21 | transition: all 0.5s ease;
22 | cursor: pointer;
23 | `;
24 |
25 | const Container = styled.div`
26 | flex: 1;
27 | margin: 5px;
28 | min-width: 280px;
29 | height: 350px;
30 | display: flex;
31 | align-items: center;
32 | justify-content: center;
33 | background-color: #f5fbfd;
34 | position: relative;
35 |
36 | &:hover ${Info}{
37 | opacity: 1;
38 | }
39 | `;
40 |
41 | const Circle = styled.div`
42 | width: 200px;
43 | height: 200px;
44 | border-radius: 50%;
45 | background-color: white;
46 | position: absolute;
47 | `;
48 |
49 | const Image = styled.img`
50 | height: 75%;
51 | z-index: 2;
52 | `;
53 |
54 | const Icon = styled.div`
55 | width: 40px;
56 | height: 40px;
57 | border-radius: 50%;
58 | background-color: white;
59 | display: flex;
60 | align-items: center;
61 | justify-content: center;
62 | margin: 10px;
63 | transition: all 0.5s ease;
64 | &:hover {
65 | background-color: #e9f5f5;
66 | transform: scale(1.1);
67 | }
68 | `;
69 |
70 | const Product = ({ item }) => {
71 | return (
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | );
90 | };
91 |
92 | export default Product;
93 |
--------------------------------------------------------------------------------
/MERN Project/client/src/components/Products.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import styled from "styled-components";
3 | import { popularProducts } from "../data";
4 | import Product from "./Product";
5 | import axios from "axios";
6 |
7 | const Container = styled.div`
8 | padding: 20px;
9 | display: flex;
10 | flex-wrap: wrap;
11 | justify-content: space-between;
12 | `;
13 |
14 | const Products = ({ cat, filters, sort }) => {
15 | const [products, setProducts] = useState([]);
16 | const [filteredProducts, setFilteredProducts] = useState([]);
17 |
18 | useEffect(() => {
19 | const getProducts = async () => {
20 | try {
21 | const res = await axios.get(
22 | cat
23 | ? `http://localhost:5000/api/products?category=${cat}`
24 | : "http://localhost:5000/api/products"
25 | );
26 | setProducts(res.data);
27 | } catch (err) {}
28 | };
29 | getProducts();
30 | }, [cat]);
31 |
32 | useEffect(() => {
33 | cat &&
34 | setFilteredProducts(
35 | products.filter((item) =>
36 | Object.entries(filters).every(([key, value]) =>
37 | item[key].includes(value)
38 | )
39 | )
40 | );
41 | }, [products, cat, filters]);
42 |
43 | useEffect(() => {
44 | if (sort === "newest") {
45 | setFilteredProducts((prev) =>
46 | [...prev].sort((a, b) => a.createdAt - b.createdAt)
47 | );
48 | } else if (sort === "asc") {
49 | setFilteredProducts((prev) =>
50 | [...prev].sort((a, b) => a.price - b.price)
51 | );
52 | } else {
53 | setFilteredProducts((prev) =>
54 | [...prev].sort((a, b) => b.price - a.price)
55 | );
56 | }
57 | }, [sort]);
58 |
59 | return (
60 |
61 | {cat
62 | ? filteredProducts.map((item) => )
63 | : products
64 | .slice(0, 8)
65 | .map((item) => )}
66 |
67 | );
68 | };
69 |
70 | export default Products;
71 |
--------------------------------------------------------------------------------
/MERN Project/client/src/components/Slider.jsx:
--------------------------------------------------------------------------------
1 | import { ArrowLeftOutlined, ArrowRightOutlined } from "@material-ui/icons";
2 | import { useState } from "react";
3 | import styled from "styled-components";
4 | import { sliderItems } from "../data";
5 | import { mobile } from "../responsive";
6 |
7 | const Container = styled.div`
8 | width: 100%;
9 | height: 100vh;
10 | display: flex;
11 | position: relative;
12 | overflow: hidden;
13 | ${mobile({ display: "none" })}
14 | `;
15 |
16 | const Arrow = styled.div`
17 | width: 50px;
18 | height: 50px;
19 | background-color: #fff7f7;
20 | border-radius: 50%;
21 | display: flex;
22 | align-items: center;
23 | justify-content: center;
24 | position: absolute;
25 | top: 0;
26 | bottom: 0;
27 | left: ${(props) => props.direction === "left" && "10px"};
28 | right: ${(props) => props.direction === "right" && "10px"};
29 | margin: auto;
30 | cursor: pointer;
31 | opacity: 0.5;
32 | z-index: 2;
33 | `;
34 |
35 | const Wrapper = styled.div`
36 | height: 100%;
37 | display: flex;
38 | transition: all 1.5s ease;
39 | transform: translateX(${(props) => props.slideIndex * -100}vw);
40 | `;
41 |
42 | const Slide = styled.div`
43 | width: 100vw;
44 | height: 100vh;
45 | display: flex;
46 | align-items: center;
47 | background-color: #${(props) => props.bg};
48 | `;
49 |
50 | const ImgContainer = styled.div`
51 | height: 100%;
52 | flex: 1;
53 | `;
54 |
55 | const Image = styled.img`
56 | height: 80%;
57 | `;
58 |
59 | const InfoContainer = styled.div`
60 | flex: 1;
61 | padding: 50px;
62 | `;
63 |
64 | const Title = styled.h1`
65 | font-size: 70px;
66 | `;
67 |
68 | const Desc = styled.p`
69 | margin: 50px 0px;
70 | font-size: 20px;
71 | font-weight: 500;
72 | letter-spacing: 3px;
73 | `;
74 |
75 | const Button = styled.button`
76 | padding: 10px;
77 | font-size: 20px;
78 | background-color: transparent;
79 | cursor: pointer;
80 | `;
81 |
82 | const Slider = () => {
83 | const [slideIndex, setSlideIndex] = useState(0);
84 | const handleClick = (direction) => {
85 | if (direction === "left") {
86 | setSlideIndex(slideIndex > 0 ? slideIndex - 1 : 2);
87 | } else {
88 | setSlideIndex(slideIndex < 2 ? slideIndex + 1 : 0);
89 | }
90 | };
91 |
92 | return (
93 |
94 | handleClick("left")}>
95 |
96 |
97 |
98 | {sliderItems.map((item) => (
99 |
100 |
101 |
102 |
103 |
104 | {item.title}
105 | {item.desc}
106 | SHOW NOW
107 |
108 |
109 | ))}
110 |
111 | handleClick("right")}>
112 |
113 |
114 |
115 | );
116 | };
117 |
118 | export default Slider;
119 |
--------------------------------------------------------------------------------
/MERN Project/client/src/data.js:
--------------------------------------------------------------------------------
1 | export const sliderItems = [
2 | {
3 | id: 1,
4 | img: "https://i.ibb.co/XsdmR2c/1.png",
5 | title: "SUMMER SALE",
6 | desc: "DON'T COMPROMISE ON STYLE! GET FLAT 30% OFF FOR NEW ARRIVALS.",
7 | bg: "f5fafd",
8 | },
9 | {
10 | id: 2,
11 | img: "https://i.ibb.co/DG69bQ4/2.png",
12 | title: "AUTUMN COLLECTION",
13 | desc: "DON'T COMPROMISE ON STYLE! GET FLAT 30% OFF FOR NEW ARRIVALS.",
14 | bg: "fcf1ed",
15 | },
16 | {
17 | id: 3,
18 | img: "https://i.ibb.co/cXFnLLV/3.png",
19 | title: "LOUNGEWEAR LOVE",
20 | desc: "DON'T COMPROMISE ON STYLE! GET FLAT 30% OFF FOR NEW ARRIVALS.",
21 | bg: "fbf0f4",
22 | },
23 | ];
24 |
25 | export const categories = [
26 | {
27 | id: 1,
28 | img: "https://images.pexels.com/photos/5886041/pexels-photo-5886041.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
29 | title: "SHIRT STYLE!",
30 | cat:"women"
31 | },
32 | {
33 | id: 2,
34 | img: "https://images.pexels.com/photos/2983464/pexels-photo-2983464.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940",
35 | title: "LOUNGEWEAR LOVE",
36 | cat:"coat"
37 | },
38 | {
39 | id: 3,
40 | img: "https://images.pexels.com/photos/5480696/pexels-photo-5480696.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500",
41 | title: "LIGHT JACKETS",
42 | cat:"jeans"
43 | },
44 | ];
45 |
46 | export const popularProducts = [
47 | {
48 | id:1,
49 | img:"https://d3o2e4jr3mxnm3.cloudfront.net/Mens-Jake-Guitar-Vintage-Crusher-Tee_68382_1_lg.png",
50 | },
51 | {
52 | id:2,
53 | img:"https://cdn.shopify.com/s/files/1/0101/4832/products/Angela_Natural_Tee.png?v=1606780388",
54 | },
55 | {
56 | id:3,
57 | img:"https://www.prada.com/content/dam/pradanux_products/U/UCS/UCS319/1YOTF010O/UCS319_1YOT_F010O_S_182_SLF.png",
58 | },
59 | {
60 | id:4,
61 | img:"https://www.burdastyle.com/pub/media/catalog/product/cache/7bd3727382ce0a860b68816435d76e26/107/BUS-PAT-BURTE-1320516/1170x1470_BS_2016_05_132_front.png",
62 | },
63 | {
64 | id:5,
65 | img:"https://images.ctfassets.net/5gvckmvm9289/3BlDoZxSSjqAvv1jBJP7TH/65f9a95484117730ace42abf64e89572/Noissue-x-Creatsy-Tote-Bag-Mockup-Bundle-_4_-2.png",
66 | },
67 | {
68 | id:6,
69 | img:"https://d3o2e4jr3mxnm3.cloudfront.net/Rocket-Vintage-Chill-Cap_66374_1_lg.png",
70 | },
71 | {
72 | id:7,
73 | img:"https://www.vintageindustries.nl/download_front/qympzk1762/2217_Arrow_Jacket_Forest.png",
74 | },
75 | {
76 | id:8,
77 | img:"https://www.pngarts.com/files/3/Women-Jacket-PNG-High-Quality-Image.png",
78 | },
79 | ]
--------------------------------------------------------------------------------
/MERN Project/client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import App from "./App";
4 | import { Provider } from "react-redux";
5 | import { store, persistor } from "./redux/store";
6 | import { PersistGate } from 'redux-persist/integration/react'
7 |
8 | ReactDOM.render(
9 |
10 |
11 |
12 |
13 | ,
14 | document.getElementById("root")
15 | );
16 |
--------------------------------------------------------------------------------
/MERN Project/client/src/pages/Home.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Announcement from "../components/Announcement";
3 | import Categories from "../components/Categories";
4 | import Footer from "../components/Footer";
5 | import Navbar from "../components/Navbar";
6 | import Newsletter from "../components/Newsletter";
7 | import Products from "../components/Products";
8 | import Slider from "../components/Slider";
9 |
10 | const Home = () => {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | );
22 | };
23 |
24 | export default Home;
25 |
--------------------------------------------------------------------------------
/MERN Project/client/src/pages/Login.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import styled from "styled-components";
3 | import { login } from "../redux/apiCalls";
4 | import { mobile } from "../responsive";
5 | import { useDispatch, useSelector } from "react-redux";
6 |
7 | const Container = styled.div`
8 | width: 100vw;
9 | height: 100vh;
10 | background: linear-gradient(
11 | rgba(255, 255, 255, 0.5),
12 | rgba(255, 255, 255, 0.5)
13 | ),
14 | url("https://images.pexels.com/photos/6984650/pexels-photo-6984650.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940")
15 | center;
16 | background-size: cover;
17 | display: flex;
18 | align-items: center;
19 | justify-content: center;
20 | `;
21 |
22 | const Wrapper = styled.div`
23 | width: 25%;
24 | padding: 20px;
25 | background-color: white;
26 | ${mobile({ width: "75%" })}
27 | `;
28 |
29 | const Title = styled.h1`
30 | font-size: 24px;
31 | font-weight: 300;
32 | `;
33 |
34 | const Form = styled.form`
35 | display: flex;
36 | flex-direction: column;
37 | `;
38 |
39 | const Input = styled.input`
40 | flex: 1;
41 | min-width: 40%;
42 | margin: 10px 0;
43 | padding: 10px;
44 | `;
45 |
46 | const Button = styled.button`
47 | width: 40%;
48 | border: none;
49 | padding: 15px 20px;
50 | background-color: teal;
51 | color: white;
52 | cursor: pointer;
53 | margin-bottom: 10px;
54 | &:disabled {
55 | color: green;
56 | cursor: not-allowed;
57 | }
58 | `;
59 |
60 | const Link = styled.a`
61 | margin: 5px 0px;
62 | font-size: 12px;
63 | text-decoration: underline;
64 | cursor: pointer;
65 | `;
66 |
67 | const Error = styled.span`
68 | color: red;
69 | `;
70 |
71 | const Login = () => {
72 | const [username, setUsername] = useState("");
73 | const [password, setPassword] = useState("");
74 | const dispatch = useDispatch();
75 | const { isFetching, error } = useSelector((state) => state.user);
76 |
77 | const handleClick = (e) => {
78 | e.preventDefault();
79 | login(dispatch, { username, password });
80 | };
81 | return (
82 |
83 |
84 | SIGN IN
85 |
102 |
103 |
104 | );
105 | };
106 |
107 | export default Login;
108 |
--------------------------------------------------------------------------------
/MERN Project/client/src/pages/Product.jsx:
--------------------------------------------------------------------------------
1 | import { Add, Remove } from "@material-ui/icons";
2 | import styled from "styled-components";
3 | import Announcement from "../components/Announcement";
4 | import Footer from "../components/Footer";
5 | import Navbar from "../components/Navbar";
6 | import Newsletter from "../components/Newsletter";
7 | import { mobile } from "../responsive";
8 | import { useLocation } from "react-router-dom";
9 | import { useEffect, useState } from "react";
10 | import { publicRequest } from "../requestMethods";
11 | import { addProduct } from "../redux/cartRedux";
12 | import { useDispatch } from "react-redux";
13 |
14 | const Container = styled.div``;
15 |
16 | const Wrapper = styled.div`
17 | padding: 50px;
18 | display: flex;
19 | ${mobile({ padding: "10px", flexDirection: "column" })}
20 | `;
21 |
22 | const ImgContainer = styled.div`
23 | flex: 1;
24 | `;
25 |
26 | const Image = styled.img`
27 | width: 100%;
28 | height: 90vh;
29 | object-fit: cover;
30 | ${mobile({ height: "40vh" })}
31 | `;
32 |
33 | const InfoContainer = styled.div`
34 | flex: 1;
35 | padding: 0px 50px;
36 | ${mobile({ padding: "10px" })}
37 | `;
38 |
39 | const Title = styled.h1`
40 | font-weight: 200;
41 | `;
42 |
43 | const Desc = styled.p`
44 | margin: 20px 0px;
45 | `;
46 |
47 | const Price = styled.span`
48 | font-weight: 100;
49 | font-size: 40px;
50 | `;
51 |
52 | const FilterContainer = styled.div`
53 | width: 50%;
54 | margin: 30px 0px;
55 | display: flex;
56 | justify-content: space-between;
57 | ${mobile({ width: "100%" })}
58 | `;
59 |
60 | const Filter = styled.div`
61 | display: flex;
62 | align-items: center;
63 | `;
64 |
65 | const FilterTitle = styled.span`
66 | font-size: 20px;
67 | font-weight: 200;
68 | `;
69 |
70 | const FilterColor = styled.div`
71 | width: 20px;
72 | height: 20px;
73 | border-radius: 50%;
74 | background-color: ${(props) => props.color};
75 | margin: 0px 5px;
76 | cursor: pointer;
77 | `;
78 |
79 | const FilterSize = styled.select`
80 | margin-left: 10px;
81 | padding: 5px;
82 | `;
83 |
84 | const FilterSizeOption = styled.option``;
85 |
86 | const AddContainer = styled.div`
87 | width: 50%;
88 | display: flex;
89 | align-items: center;
90 | justify-content: space-between;
91 | ${mobile({ width: "100%" })}
92 | `;
93 |
94 | const AmountContainer = styled.div`
95 | display: flex;
96 | align-items: center;
97 | font-weight: 700;
98 | `;
99 |
100 | const Amount = styled.span`
101 | width: 30px;
102 | height: 30px;
103 | border-radius: 10px;
104 | border: 1px solid teal;
105 | display: flex;
106 | align-items: center;
107 | justify-content: center;
108 | margin: 0px 5px;
109 | `;
110 |
111 | const Button = styled.button`
112 | padding: 15px;
113 | border: 2px solid teal;
114 | background-color: white;
115 | cursor: pointer;
116 | font-weight: 500;
117 |
118 | &:hover {
119 | background-color: #f8f4f4;
120 | }
121 | `;
122 |
123 | const Product = () => {
124 | const location = useLocation();
125 | const id = location.pathname.split("/")[2];
126 | const [product, setProduct] = useState({});
127 | const [quantity, setQuantity] = useState(1);
128 | const [color, setColor] = useState("");
129 | const [size, setSize] = useState("");
130 | const dispatch = useDispatch();
131 |
132 | useEffect(() => {
133 | const getProduct = async () => {
134 | try {
135 | const res = await publicRequest.get("/products/find/" + id);
136 | setProduct(res.data);
137 | } catch {}
138 | };
139 | getProduct();
140 | }, [id]);
141 |
142 | const handleQuantity = (type) => {
143 | if (type === "dec") {
144 | quantity > 1 && setQuantity(quantity - 1);
145 | } else {
146 | setQuantity(quantity + 1);
147 | }
148 | };
149 |
150 | const handleClick = () => {
151 | dispatch(
152 | addProduct({ ...product, quantity, color, size })
153 | );
154 | };
155 | return (
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | {product.title}
165 | {product.desc}
166 | $ {product.price}
167 |
168 |
169 | Color
170 | {product.color?.map((c) => (
171 | setColor(c)} />
172 | ))}
173 |
174 |
175 | Size
176 | setSize(e.target.value)}>
177 | {product.size?.map((s) => (
178 | {s}
179 | ))}
180 |
181 |
182 |
183 |
184 |
185 | handleQuantity("dec")} />
186 | {quantity}
187 | handleQuantity("inc")} />
188 |
189 | ADD TO CART
190 |
191 |
192 |
193 |
194 |
195 |
196 | );
197 | };
198 |
199 | export default Product;
200 |
--------------------------------------------------------------------------------
/MERN Project/client/src/pages/ProductList.jsx:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 | import Navbar from "../components/Navbar";
3 | import Announcement from "../components/Announcement";
4 | import Products from "../components/Products";
5 | import Newsletter from "../components/Newsletter";
6 | import Footer from "../components/Footer";
7 | import { mobile } from "../responsive";
8 | import { useLocation } from "react-router";
9 | import { useState } from "react";
10 |
11 | const Container = styled.div``;
12 |
13 | const Title = styled.h1`
14 | margin: 20px;
15 | `;
16 |
17 | const FilterContainer = styled.div`
18 | display: flex;
19 | justify-content: space-between;
20 | `;
21 |
22 | const Filter = styled.div`
23 | margin: 20px;
24 | ${mobile({ width: "0px 20px", display: "flex", flexDirection: "column" })}
25 | `;
26 |
27 | const FilterText = styled.span`
28 | font-size: 20px;
29 | font-weight: 600;
30 | margin-right: 20px;
31 | ${mobile({ marginRight: "0px" })}
32 | `;
33 |
34 | const Select = styled.select`
35 | padding: 10px;
36 | margin-right: 20px;
37 | ${mobile({ margin: "10px 0px" })}
38 | `;
39 | const Option = styled.option``;
40 |
41 | const ProductList = () => {
42 | const location = useLocation();
43 | const cat = location.pathname.split("/")[2];
44 | const [filters, setFilters] = useState({});
45 | const [sort, setSort] = useState("newest");
46 |
47 | const handleFilters = (e) => {
48 | const value = e.target.value;
49 | setFilters({
50 | ...filters,
51 | [e.target.name]: value,
52 | });
53 | };
54 |
55 | return (
56 |
57 |
58 |
59 | {cat}
60 |
61 |
62 | Filter Products:
63 |
64 | Color
65 | white
66 | black
67 | red
68 | blue
69 | yellow
70 | green
71 |
72 |
73 | Size
74 | XS
75 | S
76 | M
77 | L
78 | XL
79 |
80 |
81 |
82 | Sort Products:
83 | setSort(e.target.value)}>
84 | Newest
85 | Price (asc)
86 | Price (desc)
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | );
95 | };
96 |
97 | export default ProductList;
98 |
--------------------------------------------------------------------------------
/MERN Project/client/src/pages/Register.jsx:
--------------------------------------------------------------------------------
1 | import styled from "styled-components";
2 | import { mobile } from "../responsive";
3 |
4 | const Container = styled.div`
5 | width: 100vw;
6 | height: 100vh;
7 | background: linear-gradient(
8 | rgba(255, 255, 255, 0.5),
9 | rgba(255, 255, 255, 0.5)
10 | ),
11 | url("https://images.pexels.com/photos/6984661/pexels-photo-6984661.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940")
12 | center;
13 | background-size: cover;
14 | display: flex;
15 | align-items: center;
16 | justify-content: center;
17 | `;
18 |
19 | const Wrapper = styled.div`
20 | width: 40%;
21 | padding: 20px;
22 | background-color: white;
23 | ${mobile({ width: "75%" })}
24 | `;
25 |
26 | const Title = styled.h1`
27 | font-size: 24px;
28 | font-weight: 300;
29 | `;
30 |
31 | const Form = styled.form`
32 | display: flex;
33 | flex-wrap: wrap;
34 | `;
35 |
36 | const Input = styled.input`
37 | flex: 1;
38 | min-width: 40%;
39 | margin: 20px 10px 0px 0px;
40 | padding: 10px;
41 | `;
42 |
43 | const Agreement = styled.span`
44 | font-size: 12px;
45 | margin: 20px 0px;
46 | `;
47 |
48 | const Button = styled.button`
49 | width: 40%;
50 | border: none;
51 | padding: 15px 20px;
52 | background-color: teal;
53 | color: white;
54 | cursor: pointer;
55 | `;
56 |
57 | const Register = () => {
58 | return (
59 |
60 |
61 | CREATE AN ACCOUNT
62 |
75 |
76 |
77 | );
78 | };
79 |
80 | export default Register;
81 |
--------------------------------------------------------------------------------
/MERN Project/client/src/pages/Success.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import { useSelector } from "react-redux";
3 | import { useLocation } from "react-router";
4 | import { userRequest } from "../requestMethods";
5 |
6 | const Success = () => {
7 | const location = useLocation();
8 | //in Cart.jsx I sent data and cart. Please check that page for the changes.(in video it's only data)
9 | const data = location.state.stripeData;
10 | const cart = location.state.cart;
11 | const currentUser = useSelector((state) => state.user.currentUser);
12 | const [orderId, setOrderId] = useState(null);
13 |
14 | useEffect(() => {
15 | const createOrder = async () => {
16 | try {
17 | const res = await userRequest.post("/orders", {
18 | userId: currentUser._id,
19 | products: cart.products.map((item) => ({
20 | productId: item._id,
21 | quantity: item._quantity,
22 | })),
23 | amount: cart.total,
24 | address: data.billing_details.address,
25 | });
26 | setOrderId(res.data._id);
27 | } catch {}
28 | };
29 | data && createOrder();
30 | }, [cart, data, currentUser]);
31 |
32 | return (
33 |
42 | {orderId
43 | ? `Order has been created successfully. Your order number is ${orderId}`
44 | : `Successfull. Your order is being prepared...`}
45 | Go to Homepage
46 |
47 | );
48 | };
49 |
50 | export default Success;
51 |
--------------------------------------------------------------------------------
/MERN Project/client/src/redux/apiCalls.js:
--------------------------------------------------------------------------------
1 | import { loginFailure, loginStart, loginSuccess } from "./userRedux";
2 | import { publicRequest } from "../requestMethods";
3 |
4 | export const login = async (dispatch, user) => {
5 | dispatch(loginStart());
6 | try {
7 | const res = await publicRequest.post("/auth/login", user);
8 | dispatch(loginSuccess(res.data));
9 | } catch (err) {
10 | dispatch(loginFailure());
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/MERN Project/client/src/redux/cartRedux.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const cartSlice = createSlice({
4 | name: "cart",
5 | initialState: {
6 | products: [],
7 | quantity: 0,
8 | total: 0,
9 | },
10 | reducers: {
11 | addProduct: (state, action) => {
12 | state.quantity += 1;
13 | state.products.push(action.payload);
14 | state.total += action.payload.price * action.payload.quantity;
15 | },
16 | },
17 | });
18 |
19 | export const { addProduct } = cartSlice.actions;
20 | export default cartSlice.reducer;
21 |
--------------------------------------------------------------------------------
/MERN Project/client/src/redux/store.js:
--------------------------------------------------------------------------------
1 | import { configureStore, combineReducers } from "@reduxjs/toolkit";
2 | import cartReducer from "./cartRedux";
3 | import userReducer from "./userRedux";
4 | import {
5 | persistStore,
6 | persistReducer,
7 | FLUSH,
8 | REHYDRATE,
9 | PAUSE,
10 | PERSIST,
11 | PURGE,
12 | REGISTER,
13 | } from "redux-persist";
14 | import storage from "redux-persist/lib/storage";
15 |
16 | const persistConfig = {
17 | key: "root",
18 | version: 1,
19 | storage,
20 | };
21 |
22 | const rootReducer = combineReducers({ user: userReducer, cart: cartReducer });
23 |
24 | const persistedReducer = persistReducer(persistConfig, rootReducer);
25 |
26 | export const store = configureStore({
27 | reducer: persistedReducer,
28 | middleware: (getDefaultMiddleware) =>
29 | getDefaultMiddleware({
30 | serializableCheck: {
31 | ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
32 | },
33 | }),
34 | });
35 |
36 | export let persistor = persistStore(store);
37 |
--------------------------------------------------------------------------------
/MERN Project/client/src/redux/userRedux.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const userSlice = createSlice({
4 | name: "user",
5 | initialState: {
6 | currentUser: null,
7 | isFetching: false,
8 | error: false,
9 | },
10 | reducers: {
11 | loginStart: (state) => {
12 | state.isFetching = true;
13 | },
14 | loginSuccess: (state, action) => {
15 | state.isFetching = false;
16 | state.currentUser = action.payload;
17 | },
18 | loginFailure: (state) => {
19 | state.isFetching = false;
20 | state.error = true;
21 | },
22 | },
23 | });
24 |
25 | export const { loginStart, loginSuccess, loginFailure } = userSlice.actions;
26 | export default userSlice.reducer;
27 |
--------------------------------------------------------------------------------
/MERN Project/client/src/requestMethods.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | const BASE_URL = "http://localhost:5000/api/";
4 | const TOKEN =
5 | JSON.parse(JSON.parse(localStorage.getItem("persist:root")).user).currentUser
6 | .accessToken || "";
7 |
8 | export const publicRequest = axios.create({
9 | baseURL: BASE_URL,
10 | });
11 |
12 | export const userRequest = axios.create({
13 | baseURL: BASE_URL,
14 | header: { token: `Bearer ${TOKEN}` },
15 | });
16 |
--------------------------------------------------------------------------------
/MERN Project/client/src/responsive.js:
--------------------------------------------------------------------------------
1 | import { css } from "styled-components";
2 |
3 | export const mobile = (props) => {
4 | return css`
5 | @media only screen and (max-width: 380px) {
6 | ${props}
7 | }
8 | `;
9 | };
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ReactJs-Advanced-Projects
2 |
3 | ## Tech We Used
4 |
5 | - ReactJs
6 | - Firebase Hosting
7 | - Firebase Auth
8 | - Firebase Storage
9 | - React-Dom
10 | - React Redux
11 |
12 |
13 | ## Steps to run in your machine
14 |
15 | #### Run the following commands
16 | ```
17 | npm i
18 | npm run start
19 | ```
20 |
21 |
22 |
23 |
24 | #### Hope you liked this project, dont forget to ⭐ the repo.
25 |
--------------------------------------------------------------------------------
/React Quiz/.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 |
--------------------------------------------------------------------------------
/React Quiz/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 | ### `yarn start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `yarn 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 | ### `yarn 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 | ### `yarn 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 | ### `yarn 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 |
--------------------------------------------------------------------------------
/React Quiz/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "milionaire",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.11.4",
7 | "@testing-library/react": "^11.1.0",
8 | "@testing-library/user-event": "^12.1.10",
9 | "react": "^17.0.2",
10 | "react-dom": "^17.0.2",
11 | "react-scripts": "4.0.3",
12 | "use-sound": "^3.0.0",
13 | "web-vitals": "^1.0.1"
14 | },
15 | "scripts": {
16 | "start": "react-scripts start",
17 | "build": "react-scripts build",
18 | "test": "react-scripts test",
19 | "eject": "react-scripts eject"
20 | },
21 | "eslintConfig": {
22 | "extends": [
23 | "react-app",
24 | "react-app/jest"
25 | ]
26 | },
27 | "browserslist": {
28 | "production": [
29 | ">0.2%",
30 | "not dead",
31 | "not op_mini all"
32 | ],
33 | "development": [
34 | "last 1 chrome version",
35 | "last 1 firefox version",
36 | "last 1 safari version"
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/React Quiz/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
14 |
20 | React Quiz
21 |
22 |
23 |
24 | You need to enable JavaScript to run this app.
25 |
26 |
45 |
46 |
52 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/React Quiz/src/App.css:
--------------------------------------------------------------------------------
1 | .app {
2 | height: 100vh;
3 | display: flex;
4 | color: white;
5 | background-color: #020230;
6 | }
7 |
8 | .main {
9 | width: 75%;
10 | background: linear-gradient(to bottom, rgba(0, 0, 0, 0), #020230),
11 | url("https://i.ytimg.com/vi/yQbJRGs0fy8/maxresdefault.jpg") center;
12 | display: flex;
13 | flex-direction: column;
14 | }
15 |
16 | .pyramid {
17 | width: 25%;
18 | background-color: #020230;
19 | display: flex;
20 | align-items: center;
21 | justify-content: center;
22 | }
23 |
24 | .moneyList {
25 | padding: 20px;
26 | list-style: none;
27 | width: 100%;
28 | }
29 |
30 | .moneyListItem {
31 | display: flex;
32 | align-items: center;
33 | padding: 5px;
34 | border-radius: 5px;
35 | }
36 |
37 | .moneyListItem.active {
38 | background-color: teal;
39 | }
40 |
41 | .moneyListItemNumber {
42 | width: 30%;
43 | font-size: 18px;
44 | font-weight: 100;
45 | }
46 |
47 | .moneyListItemAmount {
48 | font-size: 20px;
49 | font-weight: 300;
50 | }
51 |
52 | .top {
53 | height: 50%;
54 | position: relative;
55 | }
56 |
57 | .timer {
58 | width: 70px;
59 | height: 70px;
60 | border-radius: 50%;
61 | border: 5px solid white;
62 | display: flex;
63 | align-items: center;
64 | justify-content: center;
65 | position: absolute;
66 | bottom: 10px;
67 | left: 80px;
68 | font-size: 30px;
69 | font-weight: 700;
70 | }
71 |
72 | .bottom {
73 | height: 50%;
74 | }
75 |
76 | .trivia {
77 | height: 100%;
78 | display: flex;
79 | flex-direction: column;
80 | align-items: center;
81 | justify-content: space-around;
82 | }
83 |
84 | .question {
85 | width: 80%;
86 | background: linear-gradient(#100241, black);
87 | text-align: center;
88 | padding: 20px;
89 | border-radius: 10px;
90 | border: 2px solid white;
91 | font-size: 20px;
92 | }
93 |
94 | .answers {
95 | width: 100%;
96 | display: flex;
97 | justify-content: center;
98 | flex-wrap: wrap;
99 | }
100 |
101 | .answer {
102 | width: 40%;
103 | padding: 10px;
104 | margin: 0 10px 20px 10px;
105 | text-align: center;
106 | background: linear-gradient(#0e0124, #22074d);
107 | border: 1px solid white;
108 | border-radius: 15px;
109 | font-weight: 300;
110 | font-size: 20px;
111 | cursor: pointer;
112 | }
113 |
114 | .answer:hover,
115 | .answer.active {
116 | background: mediumblue;
117 | }
118 |
119 | .answer.correct {
120 | animation: correct 3s ease forwards;
121 | }
122 |
123 | @keyframes correct {
124 | 0%,
125 | 22%,
126 | 42% {
127 | background: mediumblue;
128 | }
129 | 20%,
130 | 40%,
131 | 60% {
132 | background: linear-gradient(#0e0124, #22074d);
133 | }
134 | 62%,
135 | 100% {
136 | background: green;
137 | }
138 | }
139 |
140 | .answer.wrong {
141 | animation: wrong 3s ease forwards;
142 | }
143 |
144 | @keyframes wrong {
145 | 0%,
146 | 22%,
147 | 42% {
148 | background: mediumblue;
149 | }
150 | 20%,
151 | 40%,
152 | 60% {
153 | background: linear-gradient(#0e0124, #22074d);
154 | }
155 | 62%,
156 | 100% {
157 | background: crimson;
158 | }
159 | }
160 |
161 | .endText {
162 | position: relative;
163 | top: 0;
164 | bottom: 0;
165 | left: 0;
166 | right: 0;
167 | margin: auto;
168 | }
169 |
170 | .start {
171 | width: 250px;
172 | height: 100px;
173 | display: flex;
174 | flex-direction: column;
175 | align-items: center;
176 | justify-content: space-around;
177 | position: relative;
178 | top: 0;
179 | bottom: 0;
180 | left: 0;
181 | right: 0;
182 | margin: auto;
183 | }
184 |
185 | .startInput {
186 | width: 100%;
187 | height: 30px;
188 | border: none;
189 | border-radius: 5px;
190 | text-align: center;
191 | font-size: 18px;
192 | }
193 |
194 | .startInput:focus {
195 | outline: none;
196 | }
197 |
198 | .startButton {
199 | width: 100%;
200 | height: 30px;
201 | border: none;
202 | border-radius: 5px;
203 | cursor: pointer;
204 | font-size: 18px;
205 | font-weight: 500;
206 | }
--------------------------------------------------------------------------------
/React Quiz/src/App.jsx:
--------------------------------------------------------------------------------
1 | import "./App.css";
2 | import { useEffect, useMemo, useState } from "react";
3 | import Start from "./components/Start";
4 | import Timer from "./components/Timer";
5 | import Trivia from "./components/Trivia";
6 |
7 | function App() {
8 | const [username, setUsername] = useState(null);
9 | const [timeOut, setTimeOut] = useState(false);
10 | const [questionNumber, setQuestionNumber] = useState(1);
11 | const [earned, setEarned] = useState("$ 0");
12 |
13 | const data = [
14 | {
15 | id: 1,
16 | question: "Rolex is a company that specializes in what type of product?",
17 | answers: [
18 | {
19 | text: "Phone",
20 | correct: false,
21 | },
22 | {
23 | text: "Watches",
24 | correct: true,
25 | },
26 | {
27 | text: "Food",
28 | correct: false,
29 | },
30 | {
31 | text: "Cosmetic",
32 | correct: false,
33 | },
34 | ],
35 | },
36 | {
37 | id: 2,
38 | question: "When did the website `Facebook` launch?",
39 | answers: [
40 | {
41 | text: "2004",
42 | correct: true,
43 | },
44 | {
45 | text: "2005",
46 | correct: false,
47 | },
48 | {
49 | text: "2006",
50 | correct: false,
51 | },
52 | {
53 | text: "2007",
54 | correct: false,
55 | },
56 | ],
57 | },
58 | {
59 | id: 3,
60 | question: "Who played the character of harry potter in movie?",
61 | answers: [
62 | {
63 | text: "Johnny Deep",
64 | correct: false,
65 | },
66 | {
67 | text: "Leonardo Di Caprio",
68 | correct: false,
69 | },
70 | {
71 | text: "Denzel Washington",
72 | correct: false,
73 | },
74 | {
75 | text: "Daniel Red Cliff",
76 | correct: true,
77 | },
78 | ],
79 | },
80 | ];
81 |
82 | const moneyPyramid = useMemo(
83 | () =>
84 | [
85 | { id: 1, amount: "$ 100" },
86 | { id: 2, amount: "$ 200" },
87 | { id: 3, amount: "$ 300" },
88 | { id: 4, amount: "$ 500" },
89 | { id: 5, amount: "$ 1.000" },
90 | { id: 6, amount: "$ 2.000" },
91 | { id: 7, amount: "$ 4.000" },
92 | { id: 8, amount: "$ 8.000" },
93 | { id: 9, amount: "$ 16.000" },
94 | { id: 10, amount: "$ 32.000" },
95 | { id: 11, amount: "$ 64.000" },
96 | { id: 12, amount: "$ 125.000" },
97 | { id: 13, amount: "$ 250.000" },
98 | { id: 14, amount: "$ 500.000" },
99 | { id: 15, amount: "$ 1.000.000" },
100 | ].reverse(),
101 | []
102 | );
103 |
104 | useEffect(() => {
105 | questionNumber > 1 &&
106 | setEarned(moneyPyramid.find((m) => m.id === questionNumber - 1).amount);
107 | }, [questionNumber, moneyPyramid]);
108 |
109 | return (
110 |
111 | {!username ? (
112 |
113 | ) : (
114 | <>
115 |
116 | {timeOut ? (
117 |
You earned: {earned}
118 | ) : (
119 | <>
120 |
128 |
129 |
135 |
136 | >
137 | )}
138 |
139 |
140 |
141 | {moneyPyramid.map((m) => (
142 |
149 | {m.id}
150 | {m.amount}
151 |
152 | ))}
153 |
154 |
155 | >
156 | )}
157 |
158 | );
159 | }
160 |
161 | export default App;
162 |
--------------------------------------------------------------------------------
/React Quiz/src/assets/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlanBinu007/ReactJs-Advanced-Projects/c605f6174be918377ea18f1832ed875a2c093500/React Quiz/src/assets/bg.jpg
--------------------------------------------------------------------------------
/React Quiz/src/components/Start.jsx:
--------------------------------------------------------------------------------
1 | import { useRef } from "react";
2 |
3 | export default function Start({ setUsername }) {
4 | const inputRef = useRef();
5 |
6 | const handleClick = () => {
7 | inputRef.current.value && setUsername(inputRef.current.value);
8 | };
9 |
10 | return (
11 |
12 |
17 |
18 | Start
19 |
20 |
21 | );
22 | }
23 |
--------------------------------------------------------------------------------
/React Quiz/src/components/Timer.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 |
3 | export default function Timer({ setTimeOut, questionNumber }) {
4 | const [timer, setTimer] = useState(30);
5 |
6 | useEffect(() => {
7 | if (timer === 0) return setTimeOut(true);
8 | const interval = setInterval(() => {
9 | setTimer((prev) => prev - 1);
10 | }, 1000);
11 | return () => clearInterval(interval);
12 | }, [timer, setTimeOut]);
13 |
14 | useEffect(() => {
15 | setTimer(30);
16 | }, [questionNumber]);
17 | return timer;
18 | }
19 |
--------------------------------------------------------------------------------
/React Quiz/src/components/Trivia.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import useSound from "use-sound";
3 | import play from "../sounds/play.mp3";
4 | import correct from "../sounds/correct.mp3";
5 | import wrong from "../sounds/wrong.mp3";
6 |
7 | export default function Trivia({
8 | data,
9 | questionNumber,
10 | setQuestionNumber,
11 | setTimeOut,
12 | }) {
13 | const [question, setQuestion] = useState(null);
14 | const [selectedAnswer, setSelectedAnswer] = useState(null);
15 | const [className, setClassName] = useState("answer");
16 | const [letsPlay] = useSound(play);
17 | const [correctAnswer] = useSound(correct);
18 | const [wrongAnswer] = useSound(wrong);
19 |
20 | useEffect(() => {
21 | letsPlay();
22 | }, [letsPlay]);
23 |
24 | useEffect(() => {
25 | setQuestion(data[questionNumber - 1]);
26 | }, [data, questionNumber]);
27 |
28 | const delay = (duration, callback) => {
29 | setTimeout(() => {
30 | callback();
31 | }, duration);
32 | };
33 |
34 | const handleClick = (a) => {
35 | setSelectedAnswer(a);
36 | setClassName("answer active");
37 | delay(3000, () => {
38 | setClassName(a.correct ? "answer correct" : "answer wrong");
39 | });
40 | // setTimeout(() => {
41 | // setClassName(a.correct ? "answer correct" : "answer wrong");
42 | // }, 3000);
43 |
44 | // setTimeout(() => {
45 | delay(5000, () => {
46 | if (a.correct) {
47 | correctAnswer();
48 | delay(1000, () => {
49 | setQuestionNumber((prev) => prev + 1);
50 | setSelectedAnswer(null);
51 | });
52 | // setTimeout(() => {
53 | // setQuestionNumber((prev) => prev + 1);
54 | // setSelectedAnswer(null);
55 | // }, 1000);
56 | } else {
57 | wrongAnswer();
58 | delay(1000, () => {
59 | setTimeOut(true);
60 | });
61 | // setTimeout(() => {
62 | // setTimeOut(true);
63 | // }, 1000);
64 | }
65 | // }, 5000);
66 | })
67 | };
68 | return (
69 |
70 |
{question?.question}
71 |
72 | {question?.answers.map((a) => (
73 |
!selectedAnswer && handleClick(a)}
76 | >
77 | {a.text}
78 |
79 | ))}
80 |
81 |
82 | );
83 | }
84 |
--------------------------------------------------------------------------------
/React Quiz/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(
6 |
7 |
8 | ,
9 | document.getElementById('root')
10 | );
11 |
--------------------------------------------------------------------------------
/React Quiz/src/sounds/correct.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlanBinu007/ReactJs-Advanced-Projects/c605f6174be918377ea18f1832ed875a2c093500/React Quiz/src/sounds/correct.mp3
--------------------------------------------------------------------------------
/React Quiz/src/sounds/play.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlanBinu007/ReactJs-Advanced-Projects/c605f6174be918377ea18f1832ed875a2c093500/React Quiz/src/sounds/play.mp3
--------------------------------------------------------------------------------
/React Quiz/src/sounds/wait.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlanBinu007/ReactJs-Advanced-Projects/c605f6174be918377ea18f1832ed875a2c093500/React Quiz/src/sounds/wait.mp3
--------------------------------------------------------------------------------
/React Quiz/src/sounds/wrong.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlanBinu007/ReactJs-Advanced-Projects/c605f6174be918377ea18f1832ed875a2c093500/React Quiz/src/sounds/wrong.mp3
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/mern-blog-app/api/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | .env
--------------------------------------------------------------------------------
/mern-blog-app/api/index.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const app = express();
3 | const dotenv = require("dotenv");
4 | const mongoose = require("mongoose");
5 | const authRoute = require("./routes/auth");
6 | const userRoute = require("./routes/users");
7 | const postRoute = require("./routes/posts");
8 | const categoryRoute = require("./routes/categories");
9 | const multer = require("multer");
10 | const path = require("path");
11 |
12 | dotenv.config();
13 | app.use(express.json());
14 | app.use("/images", express.static(path.join(__dirname, "/images")));
15 |
16 | mongoose
17 | .connect(process.env.MONGO_URL, {
18 | useNewUrlParser: true,
19 | useUnifiedTopology: true,
20 | useCreateIndex: true,
21 | useFindAndModify:true
22 | })
23 | .then(console.log("Connected to MongoDB"))
24 | .catch((err) => console.log(err));
25 |
26 | const storage = multer.diskStorage({
27 | destination: (req, file, cb) => {
28 | cb(null, "images");
29 | },
30 | filename: (req, file, cb) => {
31 | cb(null, req.body.name);
32 | },
33 | });
34 |
35 | const upload = multer({ storage: storage });
36 | app.post("/api/upload", upload.single("file"), (req, res) => {
37 | res.status(200).json("File has been uploaded");
38 | });
39 |
40 | app.use("/api/auth", authRoute);
41 | app.use("/api/users", userRoute);
42 | app.use("/api/posts", postRoute);
43 | app.use("/api/categories", categoryRoute);
44 |
45 | app.listen("5000", () => {
46 | console.log("Backend is running.");
47 | });
48 |
--------------------------------------------------------------------------------
/mern-blog-app/api/models/Category.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const CategorySchema = new mongoose.Schema(
4 | {
5 | name: {
6 | type: String,
7 | required: true,
8 | },
9 | },
10 | { timestamps: true }
11 | );
12 |
13 | module.exports = mongoose.model("Category", CategorySchema);
14 |
--------------------------------------------------------------------------------
/mern-blog-app/api/models/Post.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const PostSchema = new mongoose.Schema(
4 | {
5 | title: {
6 | type: String,
7 | required: true,
8 | unique: true,
9 | },
10 | desc: {
11 | type: String,
12 | required: true,
13 | },
14 | photo: {
15 | type: String,
16 | required: false,
17 | },
18 | username: {
19 | type: String,
20 | required: true,
21 | },
22 | categories: {
23 | type: Array,
24 | required: false,
25 | },
26 | },
27 | { timestamps: true }
28 | );
29 |
30 | module.exports = mongoose.model("Post", PostSchema);
31 |
--------------------------------------------------------------------------------
/mern-blog-app/api/models/User.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 |
3 | const UserSchema = new mongoose.Schema(
4 | {
5 | username: {
6 | type: String,
7 | required: true,
8 | unique: true,
9 | },
10 | email: {
11 | type: String,
12 | required: true,
13 | unique: true,
14 | },
15 | password: {
16 | type: String,
17 | required: true,
18 | },
19 | profilePic: {
20 | type: String,
21 | default: "",
22 | },
23 | },
24 | { timestamps: true }
25 | );
26 |
27 | module.exports = mongoose.model("User", UserSchema);
28 |
--------------------------------------------------------------------------------
/mern-blog-app/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "bcrypt": "^5.0.1",
4 | "dotenv": "^9.0.2",
5 | "express": "^4.17.1",
6 | "mongoose": "^5.12.9",
7 | "multer": "^1.4.2",
8 | "nodemon": "^2.0.7",
9 | "path": "^0.12.7"
10 | },
11 | "name": "api",
12 | "version": "1.0.0",
13 | "main": "index.js",
14 | "devDependencies": {},
15 | "scripts": {
16 | "start": "nodemon index.js"
17 | },
18 | "author": "",
19 | "license": "ISC",
20 | "description": ""
21 | }
22 |
--------------------------------------------------------------------------------
/mern-blog-app/api/routes/auth.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const User = require("../models/User");
3 | const bcrypt = require("bcrypt");
4 |
5 | //REGISTER
6 | router.post("/register", async (req, res) => {
7 | try {
8 | const salt = await bcrypt.genSalt(10);
9 | const hashedPass = await bcrypt.hash(req.body.password, salt);
10 | const newUser = new User({
11 | username: req.body.username,
12 | email: req.body.email,
13 | password: hashedPass,
14 | });
15 |
16 | const user = await newUser.save();
17 | res.status(200).json(user);
18 | } catch (err) {
19 | res.status(500).json(err);
20 | }
21 | });
22 |
23 | //LOGIN
24 | router.post("/login", async (req, res) => {
25 | try {
26 | const user = await User.findOne({ username: req.body.username });
27 | !user && res.status(400).json("Wrong credentials!");
28 |
29 | const validated = await bcrypt.compare(req.body.password, user.password);
30 | !validated && res.status(400).json("Wrong credentials!");
31 |
32 | const { password, ...others } = user._doc;
33 | res.status(200).json(others);
34 | } catch (err) {
35 | res.status(500).json(err);
36 | }
37 | });
38 |
39 | module.exports = router;
40 |
--------------------------------------------------------------------------------
/mern-blog-app/api/routes/categories.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const Category = require("../models/Category");
3 |
4 | router.post("/", async (req, res) => {
5 | const newCat = new Category(req.body);
6 | try {
7 | const savedCat = await newCat.save();
8 | res.status(200).json(savedCat);
9 | } catch (err) {
10 | res.status(500).json(err);
11 | }
12 | });
13 |
14 | router.get("/", async (req, res) => {
15 | try {
16 | const cats = await Category.find();
17 | res.status(200).json(cats);
18 | } catch (err) {
19 | res.status(500).json(err);
20 | }
21 | });
22 |
23 | module.exports = router;
24 |
--------------------------------------------------------------------------------
/mern-blog-app/api/routes/posts.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const User = require("../models/User");
3 | const Post = require("../models/Post");
4 |
5 | //CREATE POST
6 | router.post("/", async (req, res) => {
7 | const newPost = new Post(req.body);
8 | try {
9 | const savedPost = await newPost.save();
10 | res.status(200).json(savedPost);
11 | } catch (err) {
12 | res.status(500).json(err);
13 | }
14 | });
15 |
16 | //UPDATE POST
17 | router.put("/:id", async (req, res) => {
18 | try {
19 | const post = await Post.findById(req.params.id);
20 | if (post.username === req.body.username) {
21 | try {
22 | const updatedPost = await Post.findByIdAndUpdate(
23 | req.params.id,
24 | {
25 | $set: req.body,
26 | },
27 | { new: true }
28 | );
29 | res.status(200).json(updatedPost);
30 | } catch (err) {
31 | res.status(500).json(err);
32 | }
33 | } else {
34 | res.status(401).json("You can update only your post!");
35 | }
36 | } catch (err) {
37 | res.status(500).json(err);
38 | }
39 | });
40 |
41 | //DELETE POST
42 | router.delete("/:id", async (req, res) => {
43 | try {
44 | const post = await Post.findById(req.params.id);
45 | if (post.username === req.body.username) {
46 | try {
47 | await post.delete();
48 | res.status(200).json("Post has been deleted...");
49 | } catch (err) {
50 | res.status(500).json(err);
51 | }
52 | } else {
53 | res.status(401).json("You can delete only your post!");
54 | }
55 | } catch (err) {
56 | res.status(500).json(err);
57 | }
58 | });
59 |
60 | //GET POST
61 | router.get("/:id", async (req, res) => {
62 | try {
63 | const post = await Post.findById(req.params.id);
64 | res.status(200).json(post);
65 | } catch (err) {
66 | res.status(500).json(err);
67 | }
68 | });
69 |
70 | //GET ALL POSTS
71 | router.get("/", async (req, res) => {
72 | const username = req.query.user;
73 | const catName = req.query.cat;
74 | try {
75 | let posts;
76 | if (username) {
77 | posts = await Post.find({ username });
78 | } else if (catName) {
79 | posts = await Post.find({
80 | categories: {
81 | $in: [catName],
82 | },
83 | });
84 | } else {
85 | posts = await Post.find();
86 | }
87 | res.status(200).json(posts);
88 | } catch (err) {
89 | res.status(500).json(err);
90 | }
91 | });
92 |
93 | module.exports = router;
94 |
--------------------------------------------------------------------------------
/mern-blog-app/api/routes/users.js:
--------------------------------------------------------------------------------
1 | const router = require("express").Router();
2 | const User = require("../models/User");
3 | const Post = require("../models/Post");
4 | const bcrypt = require("bcrypt");
5 |
6 | //UPDATE
7 | router.put("/:id", async (req, res) => {
8 | if (req.body.userId === req.params.id) {
9 | if (req.body.password) {
10 | const salt = await bcrypt.genSalt(10);
11 | req.body.password = await bcrypt.hash(req.body.password, salt);
12 | }
13 | try {
14 | const updatedUser = await User.findByIdAndUpdate(
15 | req.params.id,
16 | {
17 | $set: req.body,
18 | },
19 | { new: true }
20 | );
21 | res.status(200).json(updatedUser);
22 | } catch (err) {
23 | res.status(500).json(err);
24 | }
25 | } else {
26 | res.status(401).json("You can update only your account!");
27 | }
28 | });
29 |
30 | //DELETE
31 | router.delete("/:id", async (req, res) => {
32 | if (req.body.userId === req.params.id) {
33 | try {
34 | const user = await User.findById(req.params.id);
35 | try {
36 | await Post.deleteMany({ username: user.username });
37 | await User.findByIdAndDelete(req.params.id);
38 | res.status(200).json("User has been deleted...");
39 | } catch (err) {
40 | res.status(500).json(err);
41 | }
42 | } catch (err) {
43 | res.status(404).json("User not found!");
44 | }
45 | } else {
46 | res.status(401).json("You can delete only your account!");
47 | }
48 | });
49 |
50 | //GET USER
51 | router.get("/:id", async (req, res) => {
52 | try {
53 | const user = await User.findById(req.params.id);
54 | const { password, ...others } = user._doc;
55 | res.status(200).json(others);
56 | } catch (err) {
57 | res.status(500).json(err);
58 | }
59 | });
60 |
61 | module.exports = router;
62 |
--------------------------------------------------------------------------------
/mern-blog-app/client/.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 |
--------------------------------------------------------------------------------
/mern-blog-app/client/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 | ### `yarn start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `yarn 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 | ### `yarn 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 | ### `yarn 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 | ### `yarn 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 |
--------------------------------------------------------------------------------
/mern-blog-app/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-blog",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.11.4",
7 | "@testing-library/react": "^11.1.0",
8 | "@testing-library/user-event": "^12.1.10",
9 | "axios": "^0.21.1",
10 | "react": "^17.0.2",
11 | "react-dom": "^17.0.2",
12 | "react-router-dom": "^5.2.0",
13 | "react-scripts": "4.0.3",
14 | "web-vitals": "^1.0.1"
15 | },
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "test": "react-scripts test",
20 | "eject": "react-scripts eject"
21 | },
22 | "eslintConfig": {
23 | "extends": [
24 | "react-app",
25 | "react-app/jest"
26 | ]
27 | },
28 | "browserslist": {
29 | "production": [
30 | ">0.2%",
31 | "not dead",
32 | "not op_mini all"
33 | ],
34 | "development": [
35 | "last 1 chrome version",
36 | "last 1 firefox version",
37 | "last 1 safari version"
38 | ]
39 | },
40 | "proxy": "http://localhost:5000/api/"
41 | }
42 |
--------------------------------------------------------------------------------
/mern-blog-app/client/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
15 |
20 |
26 | Blog React App
27 |
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/App.js:
--------------------------------------------------------------------------------
1 | import Home from "./pages/home/Home";
2 | import TopBar from "./components/topbar/TopBar";
3 | import Single from "./pages/single/Single";
4 | import Write from "./pages/write/Write";
5 | import Settings from "./pages/settings/Settings";
6 | import Login from "./pages/login/Login";
7 | import Register from "./pages/register/Register";
8 | import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
9 | import { useContext } from "react";
10 | import { Context } from "./context/Context";
11 |
12 | function App() {
13 | const { user } = useContext(Context);
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 | {user ? : }
22 | {user ? : }
23 | {user ? : }
24 | {user ? : }
25 |
26 |
27 |
28 |
29 |
30 | );
31 | }
32 |
33 | export default App;
34 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/header/Header.jsx:
--------------------------------------------------------------------------------
1 | import "./header.css";
2 |
3 | export default function Header() {
4 | return (
5 |
6 |
7 | React & Node
8 | Blog
9 |
10 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/header/header.css:
--------------------------------------------------------------------------------
1 | .header {
2 | margin-top: 60px;
3 | }
4 |
5 | .headerTitles {
6 | display: flex;
7 | flex-direction: column;
8 | align-items: center;
9 | font-family: "Lora", serif;
10 | color: #444;
11 | }
12 |
13 | .headerTitleSm {
14 | position: absolute;
15 | top: 18%;
16 | font-size: 20px;
17 | }
18 |
19 | .headerTitleLg {
20 | position: absolute;
21 | top: 20%;
22 | font-size: 100px;
23 | }
24 |
25 | .headerImg{
26 | width: 100%;
27 | height: 450px;
28 | margin-top: 80px;
29 | object-fit: cover;
30 | }
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/post/Post.jsx:
--------------------------------------------------------------------------------
1 | import "./post.css";
2 | import { Link } from "react-router-dom";
3 |
4 | export default function Post({ post }) {
5 | const PF = "http://localhost:5000/images/";
6 | return (
7 |
8 | {post.photo &&
}
9 |
10 |
11 | {post.categories.map((c) => (
12 | {c.name}
13 | ))}
14 |
15 |
16 |
{post.title}
17 |
18 |
19 |
20 | {new Date(post.createdAt).toDateString()}
21 |
22 |
23 |
{post.desc}
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/post/post.css:
--------------------------------------------------------------------------------
1 | .post {
2 | width: 385px;
3 | margin: 0px 25px 40px 25px;
4 | }
5 |
6 | .postImg {
7 | width: 100%;
8 | height: 280px;
9 | object-fit: cover;
10 | border-radius: 7px;
11 | }
12 |
13 | .postInfo {
14 | display: flex;
15 | flex-direction: column;
16 | align-items: center;
17 | }
18 |
19 | .postCat {
20 | font-family: "Varela Round", sans-serif;
21 | font-size: 11px;
22 | color: #be9656;
23 | line-height: 20px;
24 | margin-top: 15px;
25 | margin-right: 10px;
26 | cursor: pointer;
27 | }
28 |
29 | .postTitle {
30 | font-family: "Josefin Sans", sans-serif;
31 | font-size: 24px;
32 | font-weight: 700;
33 | margin-top: 15px;
34 | cursor: pointer;
35 | }
36 |
37 | .postDate {
38 | font-family: "Lora", serif;
39 | font-style: italic;
40 | font-size: 13px;
41 | color: #999;
42 | margin-top: 15px;
43 | }
44 |
45 | .postDesc {
46 | font-family: "Varela Round", sans-serif;
47 | font-size: 14px;
48 | color: #444;
49 | line-height: 24px;
50 | margin-top: 15px;
51 | overflow: hidden;
52 | text-overflow: ellipsis;
53 | display: -webkit-box;
54 | -webkit-line-clamp: 4;
55 | -webkit-box-orient: vertical;
56 | }
57 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/posts/Posts.jsx:
--------------------------------------------------------------------------------
1 | import Post from "../post/Post";
2 | import "./posts.css";
3 |
4 | export default function Posts({ posts }) {
5 | return (
6 |
7 | {posts.map((p) => (
8 |
9 | ))}
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/posts/posts.css:
--------------------------------------------------------------------------------
1 | .posts{
2 | flex: 9;
3 | display: flex;
4 | flex-wrap: wrap;
5 | margin: 20px;
6 | }
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/sidebar/Sidebar.jsx:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { useEffect, useState } from "react";
3 | import { Link } from "react-router-dom";
4 | import "./sidebar.css";
5 |
6 | export default function Sidebar() {
7 | const [cats, setCats] = useState([]);
8 |
9 | useEffect(() => {
10 | const getCats = async () => {
11 | const res = await axios.get("/categories");
12 | setCats(res.data);
13 | };
14 | getCats();
15 | }, []);
16 | return (
17 |
18 |
19 |
ABOUT ME
20 |
24 |
25 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptate qui
26 | necessitatibus nostrum illum reprehenderit.
27 |
28 |
29 |
30 |
CATEGORIES
31 |
32 | {cats.map((c) => (
33 |
34 | {c.name}
35 |
36 | ))}
37 |
38 |
39 |
40 |
FOLLOW US
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | );
50 | }
51 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/sidebar/sidebar.css:
--------------------------------------------------------------------------------
1 | .sidebar {
2 | flex: 3;
3 | margin: 20px;
4 | padding-bottom: 30px;
5 | background-color: #fdfbfb;
6 | border-radius: 10px;
7 | display: flex;
8 | flex-direction: column;
9 | align-items: center;
10 | }
11 |
12 | .sidebarItem {
13 | display: flex;
14 | flex-direction: column;
15 | align-items: center;
16 | }
17 |
18 | .sidebarTitle {
19 | margin: 10px;
20 | padding: 5px;
21 | width: 80%;
22 | border-top: 1px solid #a7a4a4;
23 | border-bottom: 1px solid #a7a4a4;
24 | font-family: "Varela Round", sans-serif;
25 | font-size: 12px;
26 | color: #222;
27 | font-weight: 600;
28 | line-height: 20px;
29 | text-align: center;
30 | }
31 |
32 | .sidebarItem > img {
33 | margin-top: 15px;
34 | }
35 |
36 | .sidebarItem > p {
37 | padding: 30px;
38 | }
39 |
40 | .sidebarList {
41 | list-style: none;
42 | margin-bottom: 30px;
43 | }
44 |
45 | .sidebarListItem {
46 | display: inline-block;
47 | width: 50%;
48 | margin-top: 15px;
49 | cursor: pointer;
50 | }
51 |
52 | .sidebarSocial {
53 | margin-top: 15px;
54 | width: 250px;
55 | display: flex;
56 | align-items: center;
57 | justify-content: center;
58 | }
59 |
60 | .sidebarIcon{
61 | font-size: 16px;
62 | margin-left: 10px;
63 | cursor: pointer;
64 | }
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/singlePost/SinglePost.jsx:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { useContext, useEffect, useState } from "react";
3 | import { useLocation } from "react-router";
4 | import { Link } from "react-router-dom";
5 | import { Context } from "../../context/Context";
6 | import "./singlePost.css";
7 |
8 | export default function SinglePost() {
9 | const location = useLocation();
10 | const path = location.pathname.split("/")[2];
11 | const [post, setPost] = useState({});
12 | const PF = "http://localhost:5000/images/";
13 | const { user } = useContext(Context);
14 | const [title, setTitle] = useState("");
15 | const [desc, setDesc] = useState("");
16 | const [updateMode, setUpdateMode] = useState(false);
17 |
18 | useEffect(() => {
19 | const getPost = async () => {
20 | const res = await axios.get("/posts/" + path);
21 | setPost(res.data);
22 | setTitle(res.data.title);
23 | setDesc(res.data.desc);
24 | };
25 | getPost();
26 | }, [path]);
27 |
28 | const handleDelete = async () => {
29 | try {
30 | await axios.delete(`/posts/${post._id}`, {
31 | data: { username: user.username },
32 | });
33 | window.location.replace("/");
34 | } catch (err) {}
35 | };
36 |
37 | const handleUpdate = async () => {
38 | try {
39 | await axios.put(`/posts/${post._id}`, {
40 | username: user.username,
41 | title,
42 | desc,
43 | });
44 | setUpdateMode(false)
45 | } catch (err) {}
46 | };
47 |
48 | return (
49 |
50 |
51 | {post.photo && (
52 |
53 | )}
54 | {updateMode ? (
55 |
setTitle(e.target.value)}
61 | />
62 | ) : (
63 |
64 | {title}
65 | {post.username === user?.username && (
66 |
67 | setUpdateMode(true)}
70 | >
71 |
75 |
76 | )}
77 |
78 | )}
79 |
80 |
81 | Author:
82 |
83 | {post.username}
84 |
85 |
86 |
87 | {new Date(post.createdAt).toDateString()}
88 |
89 |
90 | {updateMode ? (
91 |
105 |
106 | );
107 | }
108 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/singlePost/singlePost.css:
--------------------------------------------------------------------------------
1 | .singlePost {
2 | flex: 9;
3 | }
4 |
5 | .singlePostWrapper {
6 | padding: 20px;
7 | padding-right: 0;
8 | display: flex;
9 | flex-direction: column;
10 | }
11 |
12 | .singlePostImg {
13 | width: 100%;
14 | height: 300px;
15 | border-radius: 5px;
16 | object-fit: cover;
17 | }
18 |
19 | .singlePostTitle {
20 | text-align: center;
21 | margin: 10px;
22 | font-family: "Lora", serif;
23 | font-size: 28px;
24 | }
25 |
26 | .singlePostTitleInput {
27 | margin: 10px;
28 | font-family: "Lora", serif;
29 | font-size: 28px;
30 | text-align: center;
31 | border: none;
32 | color: gray;
33 | border-bottom: 1px solid lightgray;
34 | }
35 |
36 | .singlePostTitleInput:focus {
37 | outline: none;
38 | }
39 |
40 | .singlePostEdit {
41 | float: right;
42 | font-size: 16px;
43 | }
44 |
45 | .singlePostIcon {
46 | margin-left: 10px;
47 | cursor: pointer;
48 | }
49 |
50 | .singlePostIcon:first-child {
51 | color: teal;
52 | }
53 |
54 | .singlePostIcon:last-child {
55 | color: tomato;
56 | }
57 |
58 | .singlePostInfo {
59 | margin-bottom: 20px;
60 | display: flex;
61 | justify-content: space-between;
62 | font-size: 16px;
63 | font-family: "Varela Round", sans-serif;
64 | color: #b39656;
65 | }
66 |
67 | .singlePostDesc {
68 | color: #666;
69 | font-size: 18px;
70 | line-height: 25px;
71 | }
72 |
73 | .singlePostDesc::first-letter {
74 | margin-left: 20px;
75 | font-size: 30px;
76 | font-weight: 600;
77 | }
78 |
79 | .singlePostDescInput {
80 | border: none;
81 | color: #666;
82 | font-size: 18px;
83 | line-height: 25px;
84 | }
85 |
86 | .singlePostDescInput:focus {
87 | outline: none;
88 | }
89 | .singlePostButton {
90 | width: 100px;
91 | border: none;
92 | background-color: teal;
93 | padding: 5px;
94 | color: white;
95 | border-radius: 5px;
96 | cursor: pointer;
97 | align-self: flex-end;
98 | margin-top: 20px;
99 | }
100 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/topbar/TopBar.jsx:
--------------------------------------------------------------------------------
1 | import { useContext } from "react";
2 | import { Link } from "react-router-dom";
3 | import { Context } from "../../context/Context";
4 | import "./topbar.css";
5 |
6 | export default function TopBar() {
7 | const { user, dispatch } = useContext(Context);
8 | const PF = "http://localhost:5000/images/"
9 |
10 | const handleLogout = () => {
11 | dispatch({ type: "LOGOUT" });
12 | };
13 | return (
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | HOME
26 |
27 |
28 |
29 |
30 | ABOUT
31 |
32 |
33 |
34 |
35 | CONTACT
36 |
37 |
38 |
39 |
40 | WRITE
41 |
42 |
43 |
44 | {user && "LOGOUT"}
45 |
46 |
47 |
48 |
49 | {user ? (
50 |
51 |
52 |
53 | ) : (
54 |
55 |
56 |
57 | LOGIN
58 |
59 |
60 |
61 |
62 | REGISTER
63 |
64 |
65 |
66 | )}
67 |
68 |
69 |
70 | );
71 | }
72 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/components/topbar/topbar.css:
--------------------------------------------------------------------------------
1 | .top {
2 | width: 100%;
3 | height: 50px;
4 | background-color: white;
5 | position: sticky;
6 | top: 0;
7 | display: flex;
8 | align-items: center;
9 | font-family: "Josefin Sans", sans-serif;
10 | z-index: 999;
11 | }
12 |
13 | .topLeft,
14 | .topRight {
15 | flex: 3;
16 | display: flex;
17 | align-items: center;
18 | justify-content: center;
19 | }
20 |
21 | .topCenter {
22 | flex: 6;
23 | }
24 |
25 | .topIcon {
26 | font-size: 20px;
27 | margin-right: 10px;
28 | color: #444;
29 | cursor: pointer;
30 | }
31 |
32 | .topImg {
33 | width: 40px;
34 | height: 40px;
35 | border-radius: 50%;
36 | object-fit: cover;
37 | cursor: pointer;
38 | }
39 |
40 | .topList {
41 | display: flex;
42 | justify-content: center;
43 | margin: 0;
44 | padding: 0;
45 | list-style: none;
46 | }
47 |
48 | .topListItem {
49 | margin-right: 20px;
50 | font-size: 18px;
51 | font-weight: 300;
52 | cursor: pointer;
53 | }
54 |
55 | .topSearchIcon {
56 | font-size: 18px;
57 | color: #666;
58 | cursor: pointer;
59 | margin-left: 15px;
60 | }
61 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/context/Actions.js:
--------------------------------------------------------------------------------
1 | export const LoginStart = (userCredentials) => ({
2 | type: "LOGIN_START",
3 | });
4 |
5 | export const LoginSuccess = (user) => ({
6 | type: "LOGIN_SUCCESS",
7 | payload: user,
8 | });
9 |
10 | export const LoginFailure = () => ({
11 | type: "LOGIN_FAILURE",
12 | });
13 |
14 | export const Logout = () => ({
15 | type: "LOGOUT",
16 | });
17 |
18 | export const UpdateStart = (userCredentials) => ({
19 | type: "UPDATE_START",
20 | });
21 |
22 | export const UpdateSuccess = (user) => ({
23 | type: "UPDATE_SUCCESS",
24 | payload: user,
25 | });
26 |
27 | export const UpdateFailure = () => ({
28 | type: "UPDATE_FAILURE",
29 | });
30 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/context/Context.js:
--------------------------------------------------------------------------------
1 | import { createContext, useEffect, useReducer } from "react";
2 | import Reducer from "./Reducer";
3 |
4 | const INITIAL_STATE = {
5 | user: JSON.parse(localStorage.getItem("user")) || null,
6 | isFetching: false,
7 | error: false,
8 | };
9 |
10 | export const Context = createContext(INITIAL_STATE);
11 |
12 | export const ContextProvider = ({ children }) => {
13 | const [state, dispatch] = useReducer(Reducer, INITIAL_STATE);
14 |
15 | useEffect(() => {
16 | localStorage.setItem("user", JSON.stringify(state.user));
17 | }, [state.user]);
18 |
19 | return (
20 |
28 | {children}
29 |
30 | );
31 | };
32 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/context/Reducer.js:
--------------------------------------------------------------------------------
1 | const Reducer = (state, action) => {
2 | switch (action.type) {
3 | case "LOGIN_START":
4 | return {
5 | user: null,
6 | isFetching: true,
7 | error: false,
8 | };
9 | case "LOGIN_SUCCESS":
10 | return {
11 | user: action.payload,
12 | isFetching: false,
13 | error: false,
14 | };
15 | case "LOGIN_FAILURE":
16 | return {
17 | user: null,
18 | isFetching: false,
19 | error: true,
20 | };
21 | case "UPDATE_START":
22 | return {
23 | ...state,
24 | isFetching:true
25 | };
26 | case "UPDATE_SUCCESS":
27 | return {
28 | user: action.payload,
29 | isFetching: false,
30 | error: false,
31 | };
32 | case "UPDATE_FAILURE":
33 | return {
34 | user: state.user,
35 | isFetching: false,
36 | error: true,
37 | };
38 | case "LOGOUT":
39 | return {
40 | user: null,
41 | isFetching: false,
42 | error: false,
43 | };
44 | default:
45 | return state;
46 | }
47 | };
48 |
49 | export default Reducer;
50 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import App from "./App";
4 | import { ContextProvider } from "./context/Context";
5 |
6 | ReactDOM.render(
7 |
8 |
9 |
10 |
11 | ,
12 | document.getElementById("root")
13 | );
14 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/home/Home.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import Header from "../../components/header/Header";
3 | import Posts from "../../components/posts/Posts";
4 | import Sidebar from "../../components/sidebar/Sidebar";
5 | import "./home.css";
6 | import axios from "axios";
7 | import { useLocation } from "react-router";
8 |
9 | export default function Home() {
10 | const [posts, setPosts] = useState([]);
11 | const { search } = useLocation();
12 |
13 | useEffect(() => {
14 | const fetchPosts = async () => {
15 | const res = await axios.get("/posts" + search);
16 | setPosts(res.data);
17 | };
18 | fetchPosts();
19 | }, [search]);
20 | return (
21 | <>
22 |
23 |
27 | >
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/home/home.css:
--------------------------------------------------------------------------------
1 | .home{
2 | display: flex;
3 | }
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/login/Login.jsx:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { useContext, useRef } from "react";
3 | import { Link } from "react-router-dom";
4 | import { Context } from "../../context/Context";
5 | import "./login.css";
6 |
7 | export default function Login() {
8 | const userRef = useRef();
9 | const passwordRef = useRef();
10 | const { dispatch, isFetching } = useContext(Context);
11 |
12 | const handleSubmit = async (e) => {
13 | e.preventDefault();
14 | dispatch({ type: "LOGIN_START" });
15 | try {
16 | const res = await axios.post("/auth/login", {
17 | username: userRef.current.value,
18 | password: passwordRef.current.value,
19 | });
20 | dispatch({ type: "LOGIN_SUCCESS", payload: res.data });
21 | } catch (err) {
22 | dispatch({ type: "LOGIN_FAILURE" });
23 | }
24 | };
25 |
26 | return (
27 |
28 | Login
29 |
48 |
49 |
50 | Register
51 |
52 |
53 |
54 | );
55 | }
56 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/login/login.css:
--------------------------------------------------------------------------------
1 | .login {
2 | height: calc(100vh - 50px);
3 | display: flex;
4 | flex-direction: column;
5 | align-items: center;
6 | justify-content: center;
7 | background: linear-gradient(
8 | rgba(255, 255, 255, 0.5),
9 | rgba(255, 255, 255, 0.5)
10 | ),
11 | url("https://images.pexels.com/photos/768473/pexels-photo-768473.jpeg?auto=compress&cs=tinysrgb&dpr=2&w=500");
12 | background-size: cover;
13 | }
14 |
15 | .loginTitle {
16 | font-size: 50px;
17 | }
18 |
19 | .loginForm {
20 | margin-top: 20px;
21 | display: flex;
22 | flex-direction: column;
23 | }
24 |
25 | .loginForm > label {
26 | margin: 10px 0;
27 | }
28 |
29 | .loginInput {
30 | padding: 10px;
31 | background-color: white;
32 | border: none;
33 | }
34 |
35 | .loginButton {
36 | margin-top: 20px;
37 | cursor: pointer;
38 | background-color: lightcoral;
39 | border: none;
40 | color: white;
41 | border-radius: 10px;
42 | padding: 10px;
43 | }
44 |
45 | .loginButton:disabled{
46 | cursor: not-allowed;
47 | background-color: rgb(252, 173, 173);
48 | }
49 |
50 | .loginRegisterButton {
51 | position: absolute;
52 | top: 60px;
53 | right: 20px;
54 | background-color: teal;
55 | cursor: pointer;
56 | border: none;
57 | padding: 10px;
58 | color: white;
59 | border-radius: 10px;
60 | }
61 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/register/Register.jsx:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { useState } from "react";
3 | import { Link } from "react-router-dom";
4 | import "./register.css";
5 |
6 | export default function Register() {
7 | const [username, setUsername] = useState("");
8 | const [email, setEmail] = useState("");
9 | const [password, setPassword] = useState("");
10 | const [error, setError] = useState(false);
11 |
12 | const handleSubmit = async (e) => {
13 | e.preventDefault();
14 | setError(false);
15 | try {
16 | const res = await axios.post("/auth/register", {
17 | username,
18 | email,
19 | password,
20 | });
21 | res.data && window.location.replace("/login");
22 | } catch (err) {
23 | setError(true);
24 | }
25 | };
26 | return (
27 |
28 | Register
29 |
55 |
56 |
57 | Login
58 |
59 |
60 | {error && Something went wrong! }
61 |
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/register/register.css:
--------------------------------------------------------------------------------
1 | .register {
2 | height: calc(100vh - 50px);
3 | display: flex;
4 | flex-direction: column;
5 | align-items: center;
6 | justify-content: center;
7 | background: linear-gradient(
8 | rgba(255, 255, 255, 0.5),
9 | rgba(255, 255, 255, 0.5)
10 | ),
11 | url("https://images.pexels.com/photos/317355/pexels-photo-317355.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940");
12 | background-size: cover;
13 | }
14 |
15 | .registerTitle {
16 | font-size: 50px;
17 | }
18 |
19 | .registerForm {
20 | margin-top: 20px;
21 | display: flex;
22 | flex-direction: column;
23 | }
24 |
25 | .registerForm > label {
26 | margin: 10px 0;
27 | }
28 |
29 | .registerInput {
30 | padding: 10px;
31 | background-color: white;
32 | border: none;
33 | }
34 |
35 | .registerButton {
36 | margin-top: 20px;
37 | cursor: pointer;
38 | background-color: teal;
39 | border: none;
40 | color: white;
41 | border-radius: 10px;
42 | padding: 10px;
43 | }
44 |
45 | .registerLoginButton {
46 | position: absolute;
47 | top: 60px;
48 | right: 20px;
49 | background-color: lightcoral;
50 | cursor: pointer;
51 | border: none;
52 | padding: 10px;
53 | color: white;
54 | border-radius: 10px;
55 | }
56 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/settings/Settings.jsx:
--------------------------------------------------------------------------------
1 | import "./settings.css";
2 | import Sidebar from "../../components/sidebar/Sidebar";
3 | import { useContext, useState } from "react";
4 | import { Context } from "../../context/Context";
5 | import axios from "axios";
6 |
7 | export default function Settings() {
8 | const [file, setFile] = useState(null);
9 | const [username, setUsername] = useState("");
10 | const [email, setEmail] = useState("");
11 | const [password, setPassword] = useState("");
12 | const [success, setSuccess] = useState(false);
13 |
14 | const { user, dispatch } = useContext(Context);
15 | const PF = "http://localhost:5000/images/"
16 |
17 | const handleSubmit = async (e) => {
18 | e.preventDefault();
19 | dispatch({ type: "UPDATE_START" });
20 | const updatedUser = {
21 | userId: user._id,
22 | username,
23 | email,
24 | password,
25 | };
26 | if (file) {
27 | const data = new FormData();
28 | const filename = Date.now() + file.name;
29 | data.append("name", filename);
30 | data.append("file", file);
31 | updatedUser.profilePic = filename;
32 | try {
33 | await axios.post("/upload", data);
34 | } catch (err) {}
35 | }
36 | try {
37 | const res = await axios.put("/users/" + user._id, updatedUser);
38 | setSuccess(true);
39 | dispatch({ type: "UPDATE_SUCCESS", payload: res.data });
40 | } catch (err) {
41 | dispatch({ type: "UPDATE_FAILURE" });
42 | }
43 | };
44 | return (
45 |
46 |
47 |
48 | Update Your Account
49 | Delete Account
50 |
51 |
96 |
97 |
98 |
99 | );
100 | }
101 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/settings/settings.css:
--------------------------------------------------------------------------------
1 | .settings {
2 | display: flex;
3 | }
4 |
5 | .settingsWrapper {
6 | flex: 9;
7 | padding: 20px;
8 | }
9 |
10 | .settingsTitle {
11 | display: flex;
12 | align-items: center;
13 | justify-content: space-between;
14 | }
15 |
16 | .settingsUpdateTitle {
17 | font-size: 30px;
18 | margin-bottom: 20px;
19 | color: lightcoral;
20 | }
21 |
22 | .settingsDeleteTitle {
23 | color: red;
24 | font-size: 12px;
25 | cursor: pointer;
26 | }
27 |
28 | .settingsForm {
29 | display: flex;
30 | flex-direction: column;
31 | }
32 |
33 | .settingsPP {
34 | display: flex;
35 | align-items: center;
36 | margin: 10px 0;
37 | }
38 |
39 | .settingsPP > img {
40 | width: 70px;
41 | height: 70px;
42 | border-radius: 20px;
43 | object-fit: cover;
44 | }
45 |
46 | .settingsPPIcon {
47 | width: 25px;
48 | height: 25px;
49 | border-radius: 50%;
50 | background-color: lightcoral;
51 | color: white;
52 | display: flex;
53 | align-items: center;
54 | justify-content: center;
55 | margin-left: 10px;
56 | cursor: pointer;
57 | }
58 |
59 | .settingsForm > label {
60 | font-size: 20px;
61 | margin-top: 20px;
62 | }
63 |
64 | .settingsForm > input {
65 | color: gray;
66 | margin: 10px 0;
67 | height: 30px;
68 | border: none;
69 | border-bottom: 1px solid lightgray;
70 | }
71 |
72 | .settingsSubmit{
73 | width: 150px;
74 | align-self: center;
75 | border: none;
76 | border-radius: 10px;
77 | color: white;
78 | background-color: teal;
79 | padding: 10px;
80 | margin-top: 20px;
81 | cursor: pointer;
82 | }
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/single/Single.jsx:
--------------------------------------------------------------------------------
1 | import "./single.css";
2 | import Sidebar from "../../components/sidebar/Sidebar";
3 | import SinglePost from "../../components/singlePost/SinglePost";
4 |
5 | export default function Single() {
6 | return (
7 |
8 |
9 |
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/single/single.css:
--------------------------------------------------------------------------------
1 | .single{
2 | display: flex;
3 | }
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/write/Write.jsx:
--------------------------------------------------------------------------------
1 | import { useContext, useState } from "react";
2 | import "./write.css";
3 | import axios from "axios";
4 | import { Context } from "../../context/Context";
5 |
6 | export default function Write() {
7 | const [title, setTitle] = useState("");
8 | const [desc, setDesc] = useState("");
9 | const [file, setFile] = useState(null);
10 | const { user } = useContext(Context);
11 |
12 | const handleSubmit = async (e) => {
13 | e.preventDefault();
14 | const newPost = {
15 | username: user.username,
16 | title,
17 | desc,
18 | };
19 | if (file) {
20 | const data =new FormData();
21 | const filename = Date.now() + file.name;
22 | data.append("name", filename);
23 | data.append("file", file);
24 | newPost.photo = filename;
25 | try {
26 | await axios.post("/upload", data);
27 | } catch (err) {}
28 | }
29 | try {
30 | const res = await axios.post("/posts", newPost);
31 | window.location.replace("/post/" + res.data._id);
32 | } catch (err) {}
33 | };
34 | return (
35 |
36 | {file && (
37 |
38 | )}
39 |
70 |
71 | );
72 | }
73 |
--------------------------------------------------------------------------------
/mern-blog-app/client/src/pages/write/write.css:
--------------------------------------------------------------------------------
1 | .write {
2 | padding-top: 50px;
3 | }
4 |
5 | .writeImg {
6 | margin-left: 150px;
7 | width: 70vw;
8 | height: 250px;
9 | border-radius: 10px;
10 | object-fit: cover;
11 | }
12 |
13 | .writeForm {
14 | position: relative;
15 | }
16 |
17 | .writeFormGroup {
18 | margin-left: 150px;
19 | display: flex;
20 | align-items: center;
21 | }
22 |
23 | .writeIcon {
24 | width: 25px;
25 | height: 25px;
26 | border-radius: 50%;
27 | border: 1px solid;
28 | display: flex;
29 | align-items: center;
30 | justify-content: center;
31 | font-size: 20px;
32 | color: rgb(121, 118, 118);
33 | cursor: pointer;
34 | }
35 |
36 | .writeInput {
37 | font-size: 30px;
38 | border: none;
39 | padding: 20px;
40 | width: 70vw;
41 | }
42 |
43 | .writeInput:focus {
44 | outline: none;
45 | }
46 |
47 | .writeText {
48 | font-size: 20px;
49 | height: 100vh;
50 | }
51 |
52 | .writeSubmit {
53 | position: absolute;
54 | top: 20px;
55 | right: 50px;
56 | color: white;
57 | background-color: teal;
58 | padding: 10px;
59 | border: none;
60 | border-radius: 10px;
61 | cursor: pointer;
62 | font-size: 16px;
63 | }
64 |
--------------------------------------------------------------------------------