done
This commit is contained in:
parent
e66b5fc26d
commit
6b0be193a5
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
|
||||||
|
import dotenv from "dotenv";
|
||||||
|
import mongoose from 'mongoose';
|
||||||
|
import bcrypt from "bcryptjs";
|
||||||
|
import jwt from "jsonwebtoken";
|
||||||
|
import adminModal from "../models/admin.js"
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
const secret = process.env.SECRET_KEY;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const login = async (req, res) => {
|
||||||
|
const { username, password } = req.body;
|
||||||
|
try {
|
||||||
|
const user = await adminModal.findOne({ username });
|
||||||
|
if (!user) return res.status(400).json({ message: "User not found" });
|
||||||
|
|
||||||
|
const isMatch = await bcrypt.compare(password, user.password);
|
||||||
|
if (!isMatch) return res.status(400).json({ message: "Invalid password" });
|
||||||
|
|
||||||
|
const token = jwt.sign({ userId: user._id }, secret, { expiresIn: "1h" });
|
||||||
|
res.json({ token });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: "Server error" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -241,3 +241,28 @@ export const updateUser = async (req, res) => {
|
||||||
res.status(500).json({ message: "Error updating user", error });
|
res.status(500).json({ message: "Error updating user", error });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const investFunds = async (req, res) => {
|
||||||
|
const { userId,fundAmount } = req.body;
|
||||||
|
|
||||||
|
// console.log("userId", userId, fundAmount);
|
||||||
|
|
||||||
|
if (fundAmount <= 0) {
|
||||||
|
return res.status(400).json({ message: "Investment amount must be greater than 0." });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const updatedUser = await UserModal.findOneAndUpdate(
|
||||||
|
{ userId }, // Query by custom userId, not ObjectId
|
||||||
|
{ fundAmount},
|
||||||
|
{ new: true } // Return the updated document
|
||||||
|
);
|
||||||
|
if (!updatedUser) {
|
||||||
|
return res.status(404).json({ message: "User not found." });
|
||||||
|
}
|
||||||
|
res.status(200).json(updatedUser);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ message: "Something went wrong." });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -7,7 +7,10 @@ import session from "express-session";
|
||||||
import userRouter from "./routes/user.js";
|
import userRouter from "./routes/user.js";
|
||||||
import propertyRouter from "./routes/property.js";
|
import propertyRouter from "./routes/property.js";
|
||||||
import mysqlRouter from "./routes/mysqlproperty.js";
|
import mysqlRouter from "./routes/mysqlproperty.js";
|
||||||
|
import adminRouter from "./routes/admin.js"
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
|
import bcrypt from "bcryptjs";
|
||||||
|
import adminModal from "./models/admin.js";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
@ -34,6 +37,7 @@ app.use(
|
||||||
app.use("/users", userRouter);
|
app.use("/users", userRouter);
|
||||||
app.use("/properties", propertyRouter);
|
app.use("/properties", propertyRouter);
|
||||||
app.use("/mysql", mysqlRouter); // Use MySQL routes
|
app.use("/mysql", mysqlRouter); // Use MySQL routes
|
||||||
|
app.use("/admin", adminRouter);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,3 +69,14 @@ dbConnectionPromise
|
||||||
console.log(`${error} did not connect`);
|
console.log(`${error} did not connect`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const createAdminUser = async () => {
|
||||||
|
const hashedPassword = await bcrypt.hash("Uer$99#KKma-hi19", 10);
|
||||||
|
const admin = new adminModal({ username: "admin", password: hashedPassword });
|
||||||
|
await admin.save();
|
||||||
|
console.log("Admin user created.", admin);
|
||||||
|
mongoose.disconnect();
|
||||||
|
};
|
||||||
|
|
||||||
|
createAdminUser();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import mongoose from "mongoose";
|
||||||
|
|
||||||
|
const adminSchema = new mongoose.Schema({
|
||||||
|
username: { type: String, required: true, unique: true },
|
||||||
|
password: { type: String, required: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
export default mongoose.model("Admin", adminSchema);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ const userSchema = new mongoose.Schema({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
fundAmount: { type: String },
|
||||||
});
|
});
|
||||||
|
|
||||||
export default mongoose.model("User", userSchema);
|
export default mongoose.model("User", userSchema);
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
import express from "express";
|
||||||
|
const router = express.Router();
|
||||||
|
import { login } from "../controllers/admin.js"
|
||||||
|
|
||||||
|
|
||||||
|
router.post("/login", login);
|
||||||
|
|
||||||
|
|
||||||
|
export default router;
|
|
@ -1,7 +1,7 @@
|
||||||
import express from "express";
|
import express from "express";
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
import { signup, signin, verifyUser, showUser, forgotPassword, resetPassword, updateUser } from "../controllers/user.js";
|
import { signup, signin, verifyUser, showUser, forgotPassword, resetPassword, updateUser,investFunds } from "../controllers/user.js";
|
||||||
|
|
||||||
router.post("/signup", signup);
|
router.post("/signup", signup);
|
||||||
router.post("/signin", signin);
|
router.post("/signin", signin);
|
||||||
|
@ -10,6 +10,7 @@ router.get('/:userId', showUser);
|
||||||
router.post("/forgotpassword", forgotPassword);
|
router.post("/forgotpassword", forgotPassword);
|
||||||
router.post("/resetpassword/:id/:token", resetPassword);
|
router.post("/resetpassword/:id/:token", resetPassword);
|
||||||
router.put('/update', updateUser);
|
router.put('/update', updateUser);
|
||||||
|
router.patch("/invest", investFunds);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script type="module" crossorigin src="/assets/index-CFxhPaJf.js"></script>
|
<script type="module" crossorigin src="/assets/index-Cw_Jz1o9.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-DUngj0jf.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DUngj0jf.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,9 @@ import PropertyMysqlView from "./components/PropertyMysqlView";
|
||||||
import EditProperty from "./components/EditProperty";
|
import EditProperty from "./components/EditProperty";
|
||||||
import SearchProperties from "./components/SearchProperties";
|
import SearchProperties from "./components/SearchProperties";
|
||||||
import ProfileView from "./components/ProfileView";
|
import ProfileView from "./components/ProfileView";
|
||||||
|
import AdminLogin from "./components/admin/AdminLogin";
|
||||||
|
import ProtectedRoute from "./components/admin/ProtectedRoute";
|
||||||
|
import AdminDashboard from "./components/admin/Dashboard";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
|
@ -32,7 +34,6 @@ const App = () => {
|
||||||
<Route path="/contact" element={<Contact />}></Route>
|
<Route path="/contact" element={<Contact />}></Route>
|
||||||
<Route path="/register" element={<Register />}></Route>
|
<Route path="/register" element={<Register />}></Route>
|
||||||
|
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/registrationsuccess"
|
path="/registrationsuccess"
|
||||||
element={
|
element={
|
||||||
|
@ -66,10 +67,29 @@ const App = () => {
|
||||||
<Route path="/properties/:house_id" element={<PropertyMysqlView />} />
|
<Route path="/properties/:house_id" element={<PropertyMysqlView />} />
|
||||||
<Route path="/searchmyproperties" element={<SearchMysqlProperties />} />
|
<Route path="/searchmyproperties" element={<SearchMysqlProperties />} />
|
||||||
<Route path="/searchproperties" element={<SearchProperties />} />
|
<Route path="/searchproperties" element={<SearchProperties />} />
|
||||||
<Route path="/editproperty/:id" element={<PrivateRoute><EditProperty /></PrivateRoute>} />
|
<Route
|
||||||
|
path="/editproperty/:id"
|
||||||
|
element={
|
||||||
|
<PrivateRoute>
|
||||||
|
<EditProperty />
|
||||||
|
</PrivateRoute>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route path="/profile/:userId" element={<ProfileView />} />
|
<Route path="/profile/:userId" element={<ProfileView />} />
|
||||||
|
|
||||||
|
<Route path="/AdminPLogin" element={<AdminLogin />} />
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path="/AdminPLogin/dashboard"
|
||||||
|
element={
|
||||||
|
<ProtectedRoute>
|
||||||
|
<AdminDashboard />
|
||||||
|
</ProtectedRoute>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,6 +10,7 @@ import UserProfile from "./UserProfile";
|
||||||
import { NavLink } from "react-router-dom";
|
import { NavLink } from "react-router-dom";
|
||||||
import FundingsReceived from "./FundingsReceived";
|
import FundingsReceived from "./FundingsReceived";
|
||||||
import OffersSubmitted from "./OffersSubmitted";
|
import OffersSubmitted from "./OffersSubmitted";
|
||||||
|
import FundToInvest from "./FundToInvest";
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const [activeTab, setActiveTab] = useState("dashboard");
|
const [activeTab, setActiveTab] = useState("dashboard");
|
||||||
|
@ -19,6 +20,8 @@ const Dashboard = () => {
|
||||||
switch (activeTab) {
|
switch (activeTab) {
|
||||||
case "Userdetails":
|
case "Userdetails":
|
||||||
return <UserProfile />;
|
return <UserProfile />;
|
||||||
|
case "FundToInvest":
|
||||||
|
return <FundToInvest />;
|
||||||
case "addProperty":
|
case "addProperty":
|
||||||
return <Addproperty />;
|
return <Addproperty />;
|
||||||
case "activeProperties":
|
case "activeProperties":
|
||||||
|
@ -89,6 +92,17 @@ const Dashboard = () => {
|
||||||
<span>User Profile</span>
|
<span>User Profile</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
<button
|
||||||
|
className={`btn mt-3 ${
|
||||||
|
activeTab === "FundToInvest" ? "active" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() => setActiveTab("FundToInvest")}
|
||||||
|
>
|
||||||
|
<span className="fa fa-home" style={{ color: "#F74B02" }} />
|
||||||
|
<span>Fund To Invest</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={`btn mt-3 ${
|
className={`btn mt-3 ${
|
||||||
activeTab === "addProperty" ? "active" : ""
|
activeTab === "addProperty" ? "active" : ""
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { WillingToInvest } from "../redux/features/authSlice";
|
||||||
|
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
|
||||||
|
const FundToInvest = () => {
|
||||||
|
const { user } = useSelector((state) => ({ ...state.auth }));
|
||||||
|
console.log("user", user);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
userId: user?.result?.userId || "",
|
||||||
|
fundAmount: user?.result?.fundAmount || "",
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (user) {
|
||||||
|
setFormData({
|
||||||
|
userId: user?.result?.userId,
|
||||||
|
fundAmount: user?.result?.fundAmount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [user]);
|
||||||
|
|
||||||
|
const handleChange = (e) => {
|
||||||
|
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (formData.fundAmount <= 0) {
|
||||||
|
return toast.error("Please enter a valid funding amount greater than 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(WillingToInvest({formData, toast }));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="col-4">
|
||||||
|
<div className="form-floating mb-3">
|
||||||
|
Willing to Invest
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="Enter Fund Amount"
|
||||||
|
name="fundAmount"
|
||||||
|
value={formData.fundAmount}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="d-grid">
|
||||||
|
<button
|
||||||
|
className="btn btn-primary btn-lg"
|
||||||
|
type="submit"
|
||||||
|
style={{
|
||||||
|
backgroundColor: "#fda417",
|
||||||
|
border: "#fda417",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FundToInvest;
|
|
@ -40,14 +40,16 @@ const ProfileView = () => {
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="d-flex flex-column align-items-center text-center">
|
<div className="d-flex flex-column align-items-center text-center">
|
||||||
|
<img
|
||||||
<img
|
className="img-fluid"
|
||||||
// src="https://bootdey.com/img/Content/avatar/avatar7.png"
|
src={user.profileImage || profilepic}
|
||||||
src={user.profileImage}
|
alt="ProfileImage"
|
||||||
alt="Admin"
|
style={{
|
||||||
className="rounded-circle"
|
marginTop: "0px",
|
||||||
width={150}
|
maxWidth: "300px",
|
||||||
/>
|
maxHeight: "300px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<h4>
|
<h4>
|
||||||
{user.title}. {user.firstName} {user.middleName}{" "}
|
{user.title}. {user.firstName} {user.middleName}{" "}
|
||||||
|
@ -186,7 +188,7 @@ const ProfileView = () => {
|
||||||
<div className="col-md-4">
|
<div className="col-md-4">
|
||||||
<div className="card mb-3">
|
<div className="card mb-3">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h1
|
<h1
|
||||||
className="d-flex align-items-center mb-3"
|
className="d-flex align-items-center mb-3"
|
||||||
style={{ color: "#fda417", fontSize: "26px" }}
|
style={{ color: "#fda417", fontSize: "26px" }}
|
||||||
>
|
>
|
||||||
|
@ -194,25 +196,23 @@ const ProfileView = () => {
|
||||||
className="material-icons text-info mr-2"
|
className="material-icons text-info mr-2"
|
||||||
style={{ color: "#fda417", fontSize: "26px" }}
|
style={{ color: "#fda417", fontSize: "26px" }}
|
||||||
>
|
>
|
||||||
About
|
About
|
||||||
</i>
|
</i>
|
||||||
me :
|
me :
|
||||||
</h1> <hr />
|
</h1>{" "}
|
||||||
{user.aboutme}
|
<hr />
|
||||||
|
|
||||||
|
{user.aboutme}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className="col-md-4 mb-3">
|
<div className="col-md-4 mb-3">
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
|
<h1
|
||||||
|
|
||||||
|
|
||||||
<h1
|
|
||||||
className="d-flex align-items-center mb-3"
|
className="d-flex align-items-center mb-3"
|
||||||
style={{ color: "#fda417", fontSize: "26px" }}
|
style={{ color: "#fda417", fontSize: "26px" }}
|
||||||
>
|
>
|
||||||
|
@ -220,24 +220,25 @@ const ProfileView = () => {
|
||||||
className="material-icons text-info mr-2"
|
className="material-icons text-info mr-2"
|
||||||
style={{ color: "#fda417", fontSize: "26px" }}
|
style={{ color: "#fda417", fontSize: "26px" }}
|
||||||
>
|
>
|
||||||
Willing to
|
Willing to
|
||||||
</i>
|
</i>
|
||||||
invest:
|
invest:
|
||||||
</h1>
|
</h1>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<h2 className="d-flex flex-column align-items-center text-center"
|
<h2
|
||||||
style={{
|
className="d-flex flex-column align-items-center text-center"
|
||||||
color: "#fda417",
|
style={{
|
||||||
border: "#fda417",
|
color: "#fda417",
|
||||||
fontSize: "60px",
|
border: "#fda417",
|
||||||
fontWeight: "normal",
|
fontSize: "60px",
|
||||||
}}
|
fontWeight: "normal",
|
||||||
>
|
}}
|
||||||
$ 500,000
|
>
|
||||||
</h2>
|
$ {user.fundAmount}
|
||||||
|
</h2>
|
||||||
<span className="d-flex flex-column align-items-center text-center">
|
|
||||||
|
{/* <span className="d-flex flex-column align-items-center text-center">
|
||||||
<button
|
<button
|
||||||
className="btn btn-primary btn-lg "
|
className="btn btn-primary btn-lg "
|
||||||
type="submit"
|
type="submit"
|
||||||
|
@ -248,38 +249,29 @@ const ProfileView = () => {
|
||||||
>
|
>
|
||||||
Request
|
Request
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span> */}
|
||||||
{/* <button className="btn btn-outline-primary">Message</button> */}
|
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-sm-3">
|
<div className="col-sm-3">
|
||||||
<span className="mb-0">Email</span>
|
<span className="mb-0">Email</span>
|
||||||
</div>
|
</div>
|
||||||
{user.email}
|
{user.email}
|
||||||
<div className="col-sm-9 text-secondary"></div>
|
<div className="col-sm-9 text-secondary"></div>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-sm-3">
|
<div className="col-sm-3">
|
||||||
<span className="mb-0">Phone</span>
|
<span className="mb-0">Phone</span>
|
||||||
</div>
|
</div>
|
||||||
67656584687
|
67656584687
|
||||||
<div className="col-sm-9 text-secondary"></div>
|
<div className="col-sm-9 text-secondary"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div className="col-md-4 mb-3">
|
<div className="col-md-4 mb-3">
|
||||||
<div className="card">
|
<div className="card">
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
import axios from "axios";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
function AdminLogin() {
|
||||||
|
|
||||||
|
const BASE_URL = import.meta.env.VITE_REACT_APP_SECRET;
|
||||||
|
|
||||||
|
const [username, setUsername] = useState("");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
try {
|
||||||
|
const { data } = await axios.post(`${BASE_URL}/admin/login`, {
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
});
|
||||||
|
|
||||||
|
localStorage.setItem("token", data.token);
|
||||||
|
navigate("/AdminPLogin/dashboard");
|
||||||
|
} catch (error) {
|
||||||
|
alert("Invalid login credentials", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section
|
||||||
|
className="d-flex justify-content-center align-items-center col-12"
|
||||||
|
style={{
|
||||||
|
minHeight: "100vh",
|
||||||
|
backgroundColor: "#FFFFFF",
|
||||||
|
width: "100%",
|
||||||
|
paddingLeft: "500px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="col-md-6 col-lg-4">
|
||||||
|
<div className="container-fluid px-0">
|
||||||
|
<div className="row gy-4 align-items-center justify-content-center">
|
||||||
|
<div className="col-12 text-center">
|
||||||
|
<input
|
||||||
|
autoComplete="off"
|
||||||
|
type="text"
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
/>
|
||||||
|
<br /> <br />
|
||||||
|
|
||||||
|
<input
|
||||||
|
autoComplete="off"
|
||||||
|
type="password"
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="mb-3">
|
||||||
|
<button onClick={handleSubmit} className="btn btn-dark w-70">
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AdminLogin;
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
|
const AdminDashboard = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleLogout = () => {
|
||||||
|
localStorage.removeItem("token");
|
||||||
|
navigate("/AdminPLogin");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Welcome to the Sample Page!</h1>
|
||||||
|
<button onClick={handleLogout}>Logout</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AdminDashboard;
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
const Loadingredirect = () => {
|
||||||
|
const [count, setCount] = useState(3);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setCount((currentCount) => --currentCount);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
count === 0 && navigate("/login");
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [count, navigate]);
|
||||||
|
return (
|
||||||
|
<div style={{ marginTop: "100px" }}>
|
||||||
|
<h5>Redirecting you in {count} seconds</h5>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Loadingredirect
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
function ProtectedRoute({ children }) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const token = localStorage.getItem("token");
|
||||||
|
console.log("token", token)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!token) {
|
||||||
|
navigate("/AdminPLogin"); // Redirect to homepage if token is missing
|
||||||
|
}
|
||||||
|
}, [token, navigate]);
|
||||||
|
|
||||||
|
return token ? children : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectedRoute.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired, // Validate the presence of children
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProtectedRoute;
|
|
@ -0,0 +1 @@
|
||||||
|
body{background: #000}.card{border: none;height: 320px}.forms-inputs{position: relative}.forms-inputs span{position: absolute;top:-18px;left: 10px;background-color: #fff;padding: 5px 10px;font-size: 15px}.forms-inputs input{height: 50px;border: 2px solid #eee}.forms-inputs input:focus{box-shadow: none;outline: none;border: 2px solid #000}.btn{height: 50px}.success-data{display: flex;flex-direction: column}.bxs-badge-check{font-size: 90px}
|
|
@ -30,6 +30,8 @@ export const updateProperty = (id, propertyData) => API.put(`/properties/${id}`,
|
||||||
|
|
||||||
export const showUser = (userId) => API.get(`/users/${userId}`);
|
export const showUser = (userId) => API.get(`/users/${userId}`);
|
||||||
|
|
||||||
|
export const investFunds = (formData) => API.patch(`/users/invest`, formData);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,20 @@ export const updateUser = createAsyncThunk(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const WillingToInvest = createAsyncThunk(
|
||||||
|
"auth/WillingToInvest",
|
||||||
|
async ({formData, toast }, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const response = await api.investFunds(formData); // Call the backend API
|
||||||
|
toast.success("Investment amount updated successfully!");
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(error.response.data.message);
|
||||||
|
return rejectWithValue(error.response.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
const authSlice = createSlice({
|
const authSlice = createSlice({
|
||||||
name: "auth",
|
name: "auth",
|
||||||
|
@ -113,7 +127,22 @@ const authSlice = createSlice({
|
||||||
.addCase(updateUser.rejected, (state, action) => {
|
.addCase(updateUser.rejected, (state, action) => {
|
||||||
state.isLoading = false;
|
state.isLoading = false;
|
||||||
state.error = action.payload;
|
state.error = action.payload;
|
||||||
});
|
})
|
||||||
|
|
||||||
|
.addCase(WillingToInvest.pending, (state) => {
|
||||||
|
state.loading = true;
|
||||||
|
})
|
||||||
|
.addCase(WillingToInvest.fulfilled, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.user = { ...state.user, result: action.payload }; // Update the user result with the new data
|
||||||
|
})
|
||||||
|
.addCase(WillingToInvest.rejected, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.error = action.payload;
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue