done
This commit is contained in:
parent
45ac17338c
commit
2773225ff9
|
@ -0,0 +1,77 @@
|
|||
import dotenv from "dotenv";
|
||||
import UserModal from "../models/user.js";
|
||||
import bcrypt from "bcryptjs";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
dotenv.config();
|
||||
const secret = process.env.SECRET_KEY;
|
||||
|
||||
// This is signup
|
||||
export const signup = async (req, res) => {
|
||||
const { email, password, firstName, lastName } = req.body;
|
||||
|
||||
try {
|
||||
// Check if user already exists
|
||||
const oldUser = await UserModal.findOne({ email });
|
||||
if (oldUser) {
|
||||
return res.status(400).json({ message: "User already exists" });
|
||||
}
|
||||
|
||||
// Hash the password
|
||||
const hashedPassword = await bcrypt.hash(password, 12);
|
||||
|
||||
// Create new user
|
||||
const result = await UserModal.create({
|
||||
email,
|
||||
password: hashedPassword,
|
||||
firstName,
|
||||
lastName,
|
||||
});
|
||||
|
||||
// Generate JWT (if needed)
|
||||
const token = jwt.sign({ email: result.email, id: result._id }, secret, { expiresIn: "7h" });
|
||||
|
||||
// Save the token in the user's tokens array
|
||||
result.tokens.push({ token });
|
||||
// Save the user
|
||||
await result.save();
|
||||
|
||||
|
||||
// console.log("ss", result)
|
||||
|
||||
// Send the user info and token back to the client
|
||||
res.status(201).json({ result, token });
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).json({ message: "Something went wrong" });
|
||||
}
|
||||
};
|
||||
|
||||
export const signin = async (req, res) => {
|
||||
const { email, password } = req.body;
|
||||
|
||||
try {
|
||||
const oldUser = await UserModal.findOne({ email });
|
||||
if (!oldUser)
|
||||
return res.status(404).json({ message: "User doesn't exist" });
|
||||
|
||||
const isPasswordCorrect = await bcrypt.compare(password, oldUser.password);
|
||||
|
||||
if (!isPasswordCorrect)
|
||||
return res.status(400).json({ message: "Invalid credentials" });
|
||||
|
||||
// if (!oldUser.verified) {
|
||||
// return res.status(401).json({ message: "User is not verified" });
|
||||
// }
|
||||
|
||||
const token = jwt.sign({ email: oldUser.email, id: oldUser._id }, secret, {
|
||||
expiresIn: "8h",
|
||||
});
|
||||
|
||||
res.status(200).json({ result: oldUser, token });
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Something went wrong" });
|
||||
console.log(error);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,57 @@
|
|||
import express from "express";
|
||||
import mongoose from "mongoose";
|
||||
import cors from "cors";
|
||||
import morgan from "morgan";
|
||||
import session from "express-session";
|
||||
import userRouter from "./routes/user.js";
|
||||
import dotenv from "dotenv";
|
||||
|
||||
|
||||
|
||||
const app = express();
|
||||
dotenv.config();
|
||||
|
||||
app.use(morgan("dev"));
|
||||
app.use(express.json({ limit: "30mb", extended: true }));
|
||||
app.use(express.urlencoded({ limit: "30mb", extended: true }));
|
||||
app.use(cors());
|
||||
|
||||
app.use(
|
||||
session({
|
||||
secret: process.env.SECRET_KEY,
|
||||
resave: false,
|
||||
saveUninitialized: true,
|
||||
})
|
||||
);
|
||||
|
||||
app.use("/users", userRouter);
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
res.send("Welcome to EF-API");
|
||||
});
|
||||
|
||||
const port = process.env.PORT || 5000;
|
||||
|
||||
|
||||
// Connect to the database
|
||||
const dbConnectionPromise = mongoose.connect(process.env.DB_ACCESS, {
|
||||
// useNewUrlParser: true,
|
||||
// useUnifiedTopology: true,
|
||||
});
|
||||
|
||||
// Start HTTP server
|
||||
const startHttpServer = () => {
|
||||
app.listen(port, () => {
|
||||
console.log(`Server is running on port ${port} (HTTP)`);
|
||||
});
|
||||
}; startHttpServer();
|
||||
|
||||
// Handle database connection success/failure
|
||||
dbConnectionPromise
|
||||
.then(() => {
|
||||
console.log("Connected to the database");
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(`${error} did not connect`);
|
||||
});
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import mongoose from "mongoose";
|
||||
|
||||
const userSchema = new mongoose.Schema({
|
||||
firstName: { type: String, required: true },
|
||||
lastName: { type: String, required: true },
|
||||
email: { type: String, required: true, unique: true },
|
||||
password: { type: String, required: true },
|
||||
tokens:[
|
||||
{
|
||||
token:{
|
||||
type:String,
|
||||
required:true
|
||||
}
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
export default mongoose.model("User", userSchema);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "ef-api",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.19.2",
|
||||
"express-session": "^1.18.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"mongoose": "^8.6.0",
|
||||
"morgan": "^1.10.0",
|
||||
"nodemailer": "^6.9.14"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import express from "express";
|
||||
const router = express.Router();
|
||||
|
||||
import { signup, signin } from "../controllers/user.js";
|
||||
|
||||
router.post("/signin", signin);
|
||||
router.post("/signup", signup);
|
||||
|
||||
|
||||
|
||||
export default router;
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -27,7 +27,7 @@
|
|||
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css">
|
||||
<!-- fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;800&family=Sen:wght@400;700;800&display=swap" rel="stylesheet">
|
||||
<script type="module" crossorigin src="/assets/index-BWSzxPyA.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-Ckttlw5i.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CyAHZLBw.css">
|
||||
</head>
|
||||
|
||||
|
|
|
@ -9,12 +9,19 @@
|
|||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@reduxjs/toolkit": "^2.2.7",
|
||||
"axios": "^1.7.7",
|
||||
"dotenv": "^16.4.5",
|
||||
"ef-ui": "file:",
|
||||
"mdb-react-ui-kit": "^8.0.0",
|
||||
"primeicons": "^7.0.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-icons": "^5.3.0",
|
||||
"react-router-dom": "^6.26.1"
|
||||
"react-loading-icons": "^1.1.0",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.26.1",
|
||||
"react-toastify": "^10.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.9.0",
|
||||
|
@ -375,6 +382,23 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/is-prop-valid": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||
"integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@emotion/memoize": "0.7.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/memoize": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
|
||||
"integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.21.5",
|
||||
"cpu": [
|
||||
|
@ -620,6 +644,40 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.5",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz",
|
||||
"integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@reduxjs/toolkit": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.7.tgz",
|
||||
"integrity": "sha512-faI3cZbSdFb8yv9dhDTmGwclW0vk0z5o1cia+kf7gCbaCwHI5e+7tP57mJUv22pNcNbeA62GSrPpfrUfdXcQ6g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immer": "^10.0.3",
|
||||
"redux": "^5.0.1",
|
||||
"redux-thunk": "^3.1.0",
|
||||
"reselect": "^5.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.9.0 || ^17.0.0 || ^18",
|
||||
"react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-redux": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/router": {
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz",
|
||||
|
@ -685,12 +743,10 @@
|
|||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.12",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.3.4",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
|
@ -699,12 +755,17 @@
|
|||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
"version": "18.3.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/use-sync-external-store": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
|
||||
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vitejs/plugin-react": {
|
||||
"version": "4.3.1",
|
||||
"dev": true,
|
||||
|
@ -907,6 +968,12 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/available-typed-arrays": {
|
||||
"version": "1.0.7",
|
||||
"dev": true,
|
||||
|
@ -921,6 +988,17 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.7.7",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
|
||||
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"dev": true,
|
||||
|
@ -1026,6 +1104,15 @@
|
|||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"dev": true,
|
||||
|
@ -1042,6 +1129,18 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"dev": true,
|
||||
|
@ -1067,7 +1166,6 @@
|
|||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.3",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
|
@ -1171,6 +1269,15 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/doctrine": {
|
||||
"version": "2.1.0",
|
||||
"dev": true,
|
||||
|
@ -1182,6 +1289,18 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.4.5",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
||||
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/ef-ui": {
|
||||
"resolved": "",
|
||||
"link": true
|
||||
|
@ -1651,6 +1770,26 @@
|
|||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/for-each": {
|
||||
"version": "0.3.3",
|
||||
"dev": true,
|
||||
|
@ -1659,6 +1798,44 @@
|
|||
"is-callable": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/framer-motion": {
|
||||
"version": "10.18.0",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.18.0.tgz",
|
||||
"integrity": "sha512-oGlDh1Q1XqYPksuTD/usb0I70hq95OUzmL9+6Zd+Hs4XV0oaISBa/UUMSjYiq6m8EUF32132mOJ8xVZS+I0S6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@emotion/is-prop-valid": "^0.8.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"dev": true,
|
||||
|
@ -1864,6 +2041,16 @@
|
|||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immer": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
|
||||
"integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/immer"
|
||||
}
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.0",
|
||||
"dev": true,
|
||||
|
@ -2360,6 +2547,54 @@
|
|||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/mdb-react-ui-kit": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mdb-react-ui-kit/-/mdb-react-ui-kit-8.0.0.tgz",
|
||||
"integrity": "sha512-4XnfUv/SkMGhKbSUcEqNgNBYz009YEPHuweodher7ba70NlbnKlfgCxXolZPX5WUPYtsV2IjDRMxu3+oLnjzTQ==",
|
||||
"license": "SEE LICENSE IN <License.txt>",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "2.11.5",
|
||||
"clsx": "1.1.1",
|
||||
"framer-motion": "^10.16.4",
|
||||
"react-popper": "2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.0.9",
|
||||
"@types/react-dom": "^18.0.3",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mdb-react-ui-kit/node_modules/clsx": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
|
||||
"integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"dev": true,
|
||||
|
@ -2631,6 +2866,12 @@
|
|||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"dev": true,
|
||||
|
@ -2683,6 +2924,12 @@
|
|||
"react": "^18.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-fast-compare": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-icons": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz",
|
||||
|
@ -2696,6 +2943,53 @@
|
|||
"version": "16.13.1",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-loading-icons": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-loading-icons/-/react-loading-icons-1.1.0.tgz",
|
||||
"integrity": "sha512-Y9eZ6HAufmUd8DIQd6rFrx5Bt/oDlTM9Nsjvf8YpajTa3dI8cLNU8jUN5z7KTANU+Yd6/KJuBjxVlrU2dMw33g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-popper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
|
||||
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-fast-compare": "^3.0.1",
|
||||
"warning": "^4.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.0.0",
|
||||
"react": "^16.8.0 || ^17 || ^18",
|
||||
"react-dom": "^16.8.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "9.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
|
||||
"integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/use-sync-external-store": "^0.0.3",
|
||||
"use-sync-external-store": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.2.25",
|
||||
"react": "^18.0",
|
||||
"redux": "^5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"redux": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-refresh": {
|
||||
"version": "0.14.2",
|
||||
"dev": true,
|
||||
|
@ -2736,6 +3030,34 @@
|
|||
"react": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-toastify": {
|
||||
"version": "10.0.5",
|
||||
"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz",
|
||||
"integrity": "sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"clsx": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18",
|
||||
"react-dom": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/redux": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/redux-thunk": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
|
||||
"integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"redux": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/reflect.getprototypeof": {
|
||||
"version": "1.0.6",
|
||||
"dev": true,
|
||||
|
@ -2773,6 +3095,12 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/reselect": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
|
||||
"integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "2.0.0-next.5",
|
||||
"dev": true,
|
||||
|
@ -3123,6 +3451,12 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
|
||||
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"dev": true,
|
||||
|
@ -3254,6 +3588,15 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
||||
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.4.2",
|
||||
"dev": true,
|
||||
|
@ -3312,6 +3655,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"dev": true,
|
||||
|
|
|
@ -11,12 +11,19 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/react-fontawesome": "^0.2.2",
|
||||
"@reduxjs/toolkit": "^2.2.7",
|
||||
"axios": "^1.7.7",
|
||||
"dotenv": "^16.4.5",
|
||||
"ef-ui": "file:",
|
||||
"mdb-react-ui-kit": "^8.0.0",
|
||||
"primeicons": "^7.0.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-icons": "^5.3.0",
|
||||
"react-router-dom": "^6.26.1"
|
||||
"react-loading-icons": "^1.1.0",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.26.1",
|
||||
"react-toastify": "^10.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.9.0",
|
||||
|
|
|
@ -1,11 +1,46 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import Footer from "./Footer";
|
||||
import Navbar from "./Navbar";
|
||||
import { toast } from "react-toastify";
|
||||
import LoadingIcons from "react-loading-icons";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { login } from "../redux/features/authSlice";
|
||||
|
||||
const initialState = {
|
||||
email: "",
|
||||
password: "",
|
||||
};
|
||||
|
||||
const Login = () => {
|
||||
const [formValue, setFormValue] = useState(initialState);
|
||||
const { loading, error } = useSelector((state) => ({ ...state.auth }));
|
||||
const { email, password } = formValue;
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
error && toast.error(error);
|
||||
}, [error]);
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
if (email && password) {
|
||||
dispatch(login({ formValue, navigate, toast }));
|
||||
}
|
||||
};
|
||||
const onInputChange = (e) => {
|
||||
let { name, value } = e.target;
|
||||
setFormValue({ ...formValue, [name]: value });
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<br /><br /><br /><br /><br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<section
|
||||
className="py-19 py-md-5 py-xl-8"
|
||||
style={{ minHeight: "100vh", backgroundColor: "#FFFFFF" }}
|
||||
|
@ -13,17 +48,13 @@ const Login = () => {
|
|||
<div className="container-fluid px-0">
|
||||
<div className="row gy-4 align-items-center justify-content-center">
|
||||
<div className="col-12 col-md-6 col-xl-20 text-center text-md-start">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div className="text-bg-primary">
|
||||
<div className="px-4">
|
||||
<hr className="border-primary-subtle mb-4" />
|
||||
|
||||
<p className="lead mb-5">
|
||||
A beautiful, easy-to-use, and secure Investor Portal that gives your investors everything they may need
|
||||
A beautiful, easy-to-use, and secure Investor Portal that
|
||||
gives your investors everything they may need
|
||||
</p>
|
||||
<div className="text-endx">
|
||||
<svg
|
||||
|
@ -41,32 +72,32 @@ const Login = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-6 col-xl-5">
|
||||
<div className="card border-0 rounded-4 shadow-lg" style={{ width: "100%" }}>
|
||||
<div
|
||||
className="card border-0 rounded-4 shadow-lg"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<div className="card-body p-3 p-md-4 p-xl-5">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="mb-4">
|
||||
<h2 className="h3">Please Login</h2>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form action="#!">
|
||||
<form method="POST">
|
||||
<div className="row gy-3 overflow-hidden">
|
||||
<div className="col-12">
|
||||
|
||||
</div>
|
||||
<div className="col-12">
|
||||
|
||||
</div>
|
||||
<div className="col-12"></div>
|
||||
<div className="col-12"></div>
|
||||
<div className="col-12">
|
||||
<div className="form-floating mb-3">
|
||||
<input
|
||||
type="email"
|
||||
className="form-control"
|
||||
name="email"
|
||||
id="email"
|
||||
placeholder="name@example.com"
|
||||
value={email}
|
||||
name="email"
|
||||
onChange={onInputChange}
|
||||
required
|
||||
/>
|
||||
<label htmlFor="email" className="form-label">
|
||||
|
@ -79,9 +110,11 @@ const Login = () => {
|
|||
<input
|
||||
type="password"
|
||||
className="form-control"
|
||||
name="password"
|
||||
id="password"
|
||||
placeholder="Password"
|
||||
value={password}
|
||||
name="password"
|
||||
onChange={onInputChange}
|
||||
required
|
||||
/>
|
||||
<label htmlFor="password" className="form-label">
|
||||
|
@ -103,7 +136,6 @@ const Login = () => {
|
|||
htmlFor="iAgree"
|
||||
>
|
||||
Remember me{" "}
|
||||
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -112,9 +144,15 @@ const Login = () => {
|
|||
<button
|
||||
className="btn btn-primary btn-lg"
|
||||
type="submit"
|
||||
style={{ backgroundColor: "#fda417", border:"#fda417" }}
|
||||
|
||||
name="signin"
|
||||
value="Sign in"
|
||||
onClick={handleSubmit}
|
||||
style={{
|
||||
backgroundColor: "#fda417",
|
||||
border: "#fda417",
|
||||
}}
|
||||
>
|
||||
{loading && <LoadingIcons.Bars />}
|
||||
Sign In
|
||||
</button>
|
||||
</div>
|
||||
|
@ -146,9 +184,8 @@ const Login = () => {
|
|||
</div>
|
||||
</section>
|
||||
<Footer />
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default Login
|
||||
export default Login;
|
||||
|
|
|
@ -1,36 +1,89 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { toast } from "react-toastify";
|
||||
import LoadingIcons from "react-loading-icons";
|
||||
import { register } from "../redux/features/authSlice";
|
||||
import "../register.css";
|
||||
import Footer from "./Footer";
|
||||
import Navbar from "./Navbar";
|
||||
import 'primeicons/primeicons.css';
|
||||
|
||||
import "primeicons/primeicons.css";
|
||||
|
||||
const initialState = {
|
||||
firstName: "",
|
||||
lastName: "",
|
||||
email: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
};
|
||||
|
||||
const Register = () => {
|
||||
const [formValue, setFormValue] = useState(initialState);
|
||||
const [isFormValid, setIsFormValid] = useState(false); // New state variable
|
||||
const { loading, error } = useSelector((state) => ({ ...state.auth }));
|
||||
const { email, password, firstName, lastName, confirmPassword } = formValue;
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
error && toast.error(error);
|
||||
}, [error]);
|
||||
|
||||
useEffect(() => {
|
||||
// Check if all fields are filled and all three checkboxes are selected
|
||||
const isValid =
|
||||
email && password && firstName && lastName && confirmPassword;
|
||||
|
||||
setIsFormValid(isValid);
|
||||
}, [email, password, firstName, lastName, confirmPassword]);
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
if (password !== confirmPassword) {
|
||||
return toast.error("Password should match");
|
||||
}
|
||||
if (isFormValid) {
|
||||
dispatch(register({ formValue, navigate, toast }));
|
||||
} else {
|
||||
toast.error("Please fill in all fields and select all checkboxes");
|
||||
}
|
||||
};
|
||||
|
||||
const onInputChange = (e) => {
|
||||
let { name, value } = e.target;
|
||||
setFormValue({ ...formValue, [name]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<br /><br /><br /><br /><br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<section
|
||||
className="py-19 py-md-5 py-xl-8"
|
||||
className="card"
|
||||
style={{ minHeight: "100vh", backgroundColor: "#FFFFFF" }}
|
||||
>
|
||||
<div className="container-fluid px-0">
|
||||
<div className="row gy-4 align-items-center justify-content-center">
|
||||
<div className="col-12 col-md-6 col-xl-20 text-center text-md-start">
|
||||
{/* <span className="pi pi-dollar" style={{ fontSize: '5rem', color:"#fda417" }} /> */}
|
||||
<i className="fa fa-dollar" style={{ fontSize: '5rem', color:"#fda417" }} aria-hidden="true" />
|
||||
|
||||
|
||||
|
||||
|
||||
<i
|
||||
className="fa fa-dollar"
|
||||
style={{ fontSize: "2.5rem", color: "#fda417" }}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div className="text-bg-primary">
|
||||
<div className="px-4">
|
||||
<hr className="border-primary-subtle mb-4" />
|
||||
<h2 className="h1 mb-4">
|
||||
Empower your investors
|
||||
</h2>
|
||||
<h2 className="h1 mb-4">Empower your investors</h2>
|
||||
<p className="lead mb-5">
|
||||
A beautiful, easy-to-use, and secure Investor Portal that gives your investors everything they may need
|
||||
A beautiful, easy-to-use, and secure Investor Portal that
|
||||
gives your investors everything they may need
|
||||
</p>
|
||||
<div className="text-endx">
|
||||
<svg
|
||||
|
@ -48,7 +101,10 @@ const Register = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-6 col-xl-5">
|
||||
<div className="card border-0 rounded-4 shadow-lg" style={{ width: "100%" }}>
|
||||
<div
|
||||
className="card border-0 rounded-4 shadow-lg"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<div className="card-body p-3 p-md-4 p-xl-5">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
|
@ -60,18 +116,20 @@ const Register = () => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form action="#!">
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="row gy-3 overflow-hidden">
|
||||
<div className="col-12">
|
||||
<div className="form-floating mb-3">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
value={firstName}
|
||||
name="firstName"
|
||||
id="firstName"
|
||||
onChange={onInputChange}
|
||||
placeholder="First Name"
|
||||
required
|
||||
required="required"
|
||||
/>
|
||||
|
||||
<label htmlFor="firstName" className="form-label">
|
||||
First Name
|
||||
</label>
|
||||
|
@ -82,11 +140,13 @@ const Register = () => {
|
|||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
value={lastName}
|
||||
name="lastName"
|
||||
id="lastName"
|
||||
onChange={onInputChange}
|
||||
placeholder="Last Name"
|
||||
required
|
||||
required="required"
|
||||
/>
|
||||
|
||||
<label htmlFor="lastName" className="form-label">
|
||||
Last Name
|
||||
</label>
|
||||
|
@ -97,10 +157,11 @@ const Register = () => {
|
|||
<input
|
||||
type="email"
|
||||
className="form-control"
|
||||
value={email}
|
||||
name="email"
|
||||
id="email"
|
||||
onChange={onInputChange}
|
||||
placeholder="name@example.com"
|
||||
required
|
||||
required="required"
|
||||
/>
|
||||
<label htmlFor="email" className="form-label">
|
||||
Email
|
||||
|
@ -112,16 +173,36 @@ const Register = () => {
|
|||
<input
|
||||
type="password"
|
||||
className="form-control"
|
||||
value={password}
|
||||
name="password"
|
||||
id="password"
|
||||
onChange={onInputChange}
|
||||
placeholder="Password"
|
||||
required
|
||||
required="required"
|
||||
/>
|
||||
|
||||
<label htmlFor="password" className="form-label">
|
||||
Password
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12">
|
||||
<div className="form-floating mb-3">
|
||||
<input
|
||||
type="password"
|
||||
className="form-control"
|
||||
value={confirmPassword}
|
||||
name="confirmPassword"
|
||||
onChange={onInputChange}
|
||||
placeholder="confirmPassword"
|
||||
required="required"
|
||||
/>
|
||||
<label htmlFor="password" className="form-label">
|
||||
Retype Password
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12">
|
||||
<div className="form-check">
|
||||
<input
|
||||
|
@ -150,9 +231,12 @@ const Register = () => {
|
|||
<button
|
||||
className="btn btn-primary btn-lg"
|
||||
type="submit"
|
||||
style={{ backgroundColor: "#fda417", border:"#fda417" }}
|
||||
|
||||
style={{
|
||||
backgroundColor: "#fda417",
|
||||
border: "#fda417",
|
||||
}}
|
||||
>
|
||||
{loading && <LoadingIcons.Bars />}
|
||||
Sign up
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { Provider } from "react-redux";
|
||||
import store from "./redux/store";
|
||||
import App from './App.jsx'
|
||||
import './index.css'
|
||||
|
||||
|
||||
|
||||
|
||||
createRoot(document.getElementById('root')).render(
|
||||
<StrictMode>
|
||||
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
|
||||
|
||||
</StrictMode>,
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import axios from "axios";
|
||||
|
||||
const BASE_URL = import.meta.env.REACT_APP_SECRET;
|
||||
|
||||
// const API = axios.create({baseURL:"http://localhost:3001"});
|
||||
// const API = axios.create({ baseURL: `${BASE_URL}` });
|
||||
const API = axios.create({ baseURL: BASE_URL });
|
||||
|
||||
|
||||
API.interceptors.request.use((req) => {
|
||||
if (localStorage.getItem("profile")) {
|
||||
req.headers.Authorization = `Bearer ${
|
||||
JSON.parse(localStorage.getItem("profile")).token
|
||||
}`;
|
||||
}
|
||||
return req;
|
||||
});
|
||||
|
||||
export const signUp = (formData) => API.post("/users/signup", formData);
|
||||
export const signIn = (formData) => API.post("/users/signin", formData);
|
|
@ -0,0 +1,85 @@
|
|||
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import * as api from "../api";
|
||||
|
||||
export const register = createAsyncThunk(
|
||||
"auth/register",
|
||||
async ({ formValue, navigate, toast }, { rejectWithValue }) => {
|
||||
try {
|
||||
const response = await api.signUp(formValue);
|
||||
toast.success("Register Successfully");
|
||||
navigate("/");
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
return rejectWithValue(err.response.data);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
export const login = createAsyncThunk(
|
||||
"auth/login",
|
||||
async ({ formValue, navigate, toast }, { rejectWithValue }) => {
|
||||
try {
|
||||
const response = await api.signIn(formValue);
|
||||
toast.success("Login Successfully");
|
||||
navigate("/register");
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
return rejectWithValue(err.response.data);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const authSlice = createSlice({
|
||||
name: "auth",
|
||||
initialState: {
|
||||
user: null,
|
||||
error: null,
|
||||
loading: false,
|
||||
},
|
||||
reducers: {
|
||||
setUser: (state, action) => {
|
||||
state.user = action.payload;
|
||||
},
|
||||
setLogout: (state) => {
|
||||
localStorage.clear();
|
||||
state.user = null;
|
||||
},
|
||||
setUserDetails: (state, action) => {
|
||||
state.user = action.payload;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder
|
||||
.addCase(register.pending, (state, action) => {
|
||||
state.loading = true;
|
||||
state.user = action.payload;
|
||||
})
|
||||
.addCase(register.fulfilled, (state, action) => {
|
||||
state.loading = false;
|
||||
state.error = null;
|
||||
localStorage.setItem("profile", JSON.stringify({ ...action.payload }));
|
||||
state.user = action.payload;
|
||||
})
|
||||
.addCase(register.rejected, (state, action) => {
|
||||
state.loading = false;
|
||||
state.error = action.payload;
|
||||
})
|
||||
.addCase(login.pending, (state) => {
|
||||
state.loading = true;
|
||||
})
|
||||
.addCase(login.fulfilled, (state, action) => {
|
||||
state.loading = false;
|
||||
localStorage.setItem("profile", JSON.stringify({ ...action.payload }));
|
||||
state.user = action.payload;
|
||||
})
|
||||
.addCase(login.rejected, (state, action) => {
|
||||
state.loading = false;
|
||||
state.error = action.payload;
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
export const { setUser, setLogout } = authSlice.actions;
|
||||
|
||||
export default authSlice.reducer;
|
|
@ -0,0 +1,10 @@
|
|||
import { configureStore } from "@reduxjs/toolkit";
|
||||
import AuthReducer from "./features/authSlice";
|
||||
|
||||
|
||||
export default configureStore({
|
||||
reducer: {
|
||||
auth: AuthReducer,
|
||||
|
||||
},
|
||||
});
|
|
@ -1,7 +1,17 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
|
||||
server: {
|
||||
proxy: {
|
||||
'/users/signup': 'http://localhost:3001', // Proxy requests to /users to the backend server
|
||||
'/users/signin': 'http://localhost:3001',
|
||||
},
|
||||
},
|
||||
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue