This commit is contained in:
omkieit 2024-09-06 20:32:20 +05:30
parent 1f87594668
commit ad712108c0
19 changed files with 444 additions and 115 deletions

View File

@ -75,3 +75,22 @@ export const signin = async (req, res) => {
console.log(error);
}
};
//To show user
export const showUser = async (req, res) => {
const { id } = req.params;
try {
const user = await UserModal.findById({id});
if (!user) {
return res.status(404).json({ message: "User not found" });
}
res.status(200).json(user);
} catch (error) {
console.error(error);
res.status(500).json({ message: "Internal servers error" });
}
};

View File

@ -1,10 +1,11 @@
import express from "express";
const router = express.Router();
import { signup, signin } from "../controllers/user.js";
import { signup, signin,showUser } from "../controllers/user.js";
router.post("/signin", signin);
router.post("/signup", signup);
router.get('/:id', showUser);

File diff suppressed because one or more lines are too long

80
ef-ui/dist/assets/index-S1fS9cGv.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -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-Cw9IlM2k.js"></script>
<script type="module" crossorigin src="/assets/index-S1fS9cGv.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CyAHZLBw.css">
</head>

View File

@ -13,8 +13,10 @@
"axios": "^1.7.7",
"dotenv": "^16.4.5",
"ef-ui": "file:",
"jwt-decode": "^4.0.0",
"mdb-react-ui-kit": "^8.0.0",
"primeicons": "^7.0.0",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
@ -2490,6 +2492,15 @@
"node": ">=4.0"
}
},
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"dev": true,
@ -2859,6 +2870,8 @@
},
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",

View File

@ -15,8 +15,10 @@
"axios": "^1.7.7",
"dotenv": "^16.4.5",
"ef-ui": "file:",
"jwt-decode": "^4.0.0",
"mdb-react-ui-kit": "^8.0.0",
"primeicons": "^7.0.0",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",

View File

@ -4,6 +4,9 @@ import About from "./components/About";
import Contact from "./components/Contact";
import Register from "./components/Register";
import Login from "./components/Login";
import Dashboard from "./components/Dashboard";
import PrivateRoute from "./components/PrivateRoute";
const App = () => {
@ -15,6 +18,14 @@ const App = () => {
<Route path="/contact" element={<Contact/>}></Route>
<Route path="/register" element={<Register/>}></Route>
<Route path="/login" element={<Login/>}></Route>
<Route
path="/dashboard"
element={
<PrivateRoute>
<Dashboard />
</PrivateRoute>
}
/>
</Routes>
</BrowserRouter>
)

View File

@ -0,0 +1,84 @@
import { useEffect } from "react";
import Footer from "./Footer";
import Navbar from "./Navbar";
import { useDispatch, useSelector } from "react-redux";
import { showUser } from "../redux/features/userSlice";
const Dashboard = () => {
const { user } = useSelector((state) => ({ ...state.auth }));
const dispatch = useDispatch();
const userId = user?.result?._id;
useEffect(() => {
if (userId) {
dispatch(showUser(userId));
}
}, [userId, dispatch]);
return (
<div style={{ display: "flex", flexDirection: "column", minHeight: "100vh" }}>
<Navbar />
<br /> <br /> <br /> <br />
<main style={{ flex: 1 }}>
<section
className="py-19 py-md-5 py-xl-8"
style={{ 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">
<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
</p>
</div>
</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-body p-3 p-md-4 p-xl-5">
{user?.result?._id && (
<div className="form-group row">
<label htmlFor="firstName" className="col-sm-6 col-form-label">
First Name:{" "}
<span style={{ color: "#067ADC" }}>{user.result.firstName}</span>
</label>
<label htmlFor="lastName" className="col-sm-6 col-form-label">
Last Name:{" "}
<span style={{ color: "#067ADC" }}>{user.result.lastName}</span>
</label>
<label htmlFor="email" className="col-sm-6 col-form-label">
Email:{" "}
<span style={{ color: "#067ADC" }}>{user.result.email}</span>
</label>
</div>
)}
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<Footer />
</div>
);
};
export default Dashboard;

View File

@ -0,0 +1,56 @@
import { NavLink } from "react-router-dom";
const Header = () => {
return (
<>
<div className="container-fluid p-0 m-0">
<nav
className="navbar navbar-expand-lg w-100"
style={{
backgroundColor: "#000000",
position: "fixed", // Make the navbar fixed at the top
top: 0,
left: 0,
right: 0,
zIndex: 1000, // Ensure the navbar is above other elements
}}
>
<div className="container-fluid d-flex align-items-center justify-content-between">
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<form className="form-inline my-2 my-lg-0">
<div className="login_text">
<ul>
<li>
<NavLink to="/login" className="nav-link">
Login
</NavLink>
</li>
<li>
<a href="#">
<i className="fa fa-user" aria-hidden="true" />
</a>
</li>
</ul>
</div>
<div className="quote_btn">
<NavLink to="/register" className="nav-link">
Register
</NavLink>
</div>
</form>
</div>
</div>
</nav>
</div>
</>
)
}
export default Header

View File

@ -1,17 +1,12 @@
import Footer from "./Footer";
import Navbar from "./Navbar";
const Home = () => {
return (
<>
<Navbar />
<br />
<br />
<br />
<br />
<br />
<br /> <br /> <br /> <br /> <br />
<div>
<div className="header_section">
<div className="banner_section layout_padding">

View File

@ -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

View File

@ -2,6 +2,8 @@ import { NavLink } from "react-router-dom";
import logo from "../logo.png";
const Navbar = () => {
return (
<>
<div className="container-fluid p-0 m-0">

View File

@ -0,0 +1,16 @@
import { useSelector } from "react-redux";
import PropTypes from "prop-types";
import Loadingredirect from "./Loadingredirect";
const PrivateRoute = ({ children }) => {
const { user } = useSelector((state) => ({ ...state.auth }));
return user ? children : <Loadingredirect />;
};
PrivateRoute.propTypes = {
children: PropTypes.node.isRequired, // Validate the presence of children
};
export default PrivateRoute;

23
ef-ui/src/dashboard.css Normal file
View File

@ -0,0 +1,23 @@
/* Add these styles to your main CSS file */
.dashboard-wrapper {
display: flex;
flex-direction: column;
min-height: 100vh; /* Ensure the wrapper takes full height */
}
.dashboard-content {
flex: 1; /* This will make the content grow to fill the space between Navbar and Footer */
}
footer {
width: 100%;
background-color: #333;
color: white;
padding: 10px;
text-align: center;
position: relative;
bottom: 0;
}

18
ef-ui/src/footer.css Normal file
View File

@ -0,0 +1,18 @@
footer {
width: 100%;
background-color: #f8f9fa;
text-align: center;
padding: 1rem 0;
}
.header_top_section, .copyright_section {
background-color: #333;
color: #fff;
padding: 1rem 0;
}
.container {
max-width: 1200px;
margin: 0 auto;
}

View File

@ -18,3 +18,4 @@ API.interceptors.request.use((req) => {
export const signUp = (formData) => API.post("/users/signup", formData);
export const signIn = (formData) => API.post("/users/signin", formData);

View File

@ -1,6 +1,20 @@
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import * as api from "../api";
export const login = createAsyncThunk(
"auth/login",
async ({ formValue, navigate, toast }, { rejectWithValue }) => {
try {
const response = await api.signIn(formValue);
toast.success("Login Successfully");
navigate("/dashboard");
return response.data;
} catch (err) {
return rejectWithValue(err.response.data);
}
}
);
export const register = createAsyncThunk(
"auth/register",
async ({ formValue, navigate, toast }, { rejectWithValue }) => {
@ -15,14 +29,11 @@ export const register = createAsyncThunk(
}
);
export const login = createAsyncThunk(
"auth/login",
async ({ formValue, navigate, toast }, { rejectWithValue }) => {
export const updateUser = createAsyncThunk(
"auth/updateUser",
async ({ id, data }, { rejectWithValue }) => {
try {
const response = await api.signIn(formValue);
toast.success("Login Successfully");
navigate("/register");
const response = await api.updateuser(data, id);
return response.data;
} catch (err) {
return rejectWithValue(err.response.data);
@ -34,7 +45,7 @@ const authSlice = createSlice({
name: "auth",
initialState: {
user: null,
error: null,
error: "",
loading: false,
},
reducers: {
@ -51,20 +62,6 @@ const authSlice = createSlice({
},
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;
})
@ -75,11 +72,34 @@ const authSlice = createSlice({
})
.addCase(login.rejected, (state, action) => {
state.loading = false;
state.error = action.payload;
state.error = action.payload.message;
})
.addCase(register.pending, (state) => {
state.loading = true;
})
.addCase(register.fulfilled, (state, action) => {
state.loading = false;
localStorage.setItem("profile", JSON.stringify({ ...action.payload }));
state.user = action.payload;
})
.addCase(register.rejected, (state, action) => {
state.loading = false;
state.error = action.payload.message;
})
.addCase(updateUser.pending, (state) => {
state.loading = true;
})
.addCase(updateUser.fulfilled, (state, action) => {
state.loading = false;
state.user = action.payload;
})
.addCase(updateUser.rejected, (state, action) => {
state.loading = false;
state.error = action.payload.message;
});
},
});
export const { setUser, setLogout } = authSlice.actions;
export const { setUser, setLogout, setUserDetails } = authSlice.actions;
export default authSlice.reducer;

View File

@ -0,0 +1,45 @@
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import * as api from "../api";
export const showUser = createAsyncThunk(
"user/showUser",
async ({ id, data }, { rejectWithValue }) => {
try {
const response = await api.showUser(data, id);
console.log("dsdsdsds22", response);
return response.data;
} catch (err) {
return rejectWithValue(err.response.data);
}
}
);
const userSlice = createSlice({
name: "user",
initialState: {
users: [],
error: "",
loading: false,
verified: false,
},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(showUser.pending, (state) => {
state.loading = true;
})
.addCase(showUser.fulfilled, (state, action) => {
state.loading = false;
localStorage.setItem("profile", JSON.stringify({ ...action.payload }));
state.users = Array.isArray(action.payload) ? action.payload : [];
})
.addCase(showUser.rejected, (state, action) => {
state.loading = false;
state.error = action.payload;
});
},
});
export default userSlice.reducer;