Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
747 changes: 420 additions & 327 deletions client/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"tailwindcss": "^3.3.6",
"vite": "^5.0.8"
"vite": "^5.3.1"
}
}
42 changes: 10 additions & 32 deletions client/src/components/Footer/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import lang from "../../utils/langaugeConstant";
import { useSelector } from "react-redux";

const Footer = () => {

const langKey=useSelector((store)=>store.config.lang)
const langKey = useSelector((store) => store.config.lang);

return (
<footer className="bg-white dark:bg-gray-900">
Expand All @@ -20,52 +19,31 @@ const Footer = () => {
</Link>
<ul className="flex flex-wrap items-center mb-6 text-sm font-medium text-gray-500 sm:mb-0 dark:text-gray-400">
<li>

<Link to="/about" className="hover:underline me-4 md:me-6">
About
</Link>

<a href="/about" className="hover:underline me-4 md:me-6">
{lang[langKey].About}
</a>

</Link>
</li>
<li>
<Link
to="/privacy-policy"
className="hover:underline me-4 md:me-6"
>
Privacy Policy
<Link to="/privacy-policy" className="hover:underline me-4 md:me-6">
{lang[langKey].PrivacyPolicy}
</Link>
</li>
<li>
<Link to="/licensing" className="hover:underline me-4 md:me-6">
Licensing
{lang[langKey].Licensing}
</Link>
</li>
<li>
<Link to="/contact" className="hover:underline">
Contact
</Link>
{lang[langKey].PrivacyPolicy}
</a>
</li>
<li>
<a href="/licensing" className="hover:underline me-4 md:me-6">
{lang[langKey].Licensing}
</a>
</li>
<li>
<a href="/contact" className="hover:underline">
{lang[langKey].Contact}
</a>
</Link>
</li>
</ul>
</div>
<hr class="my-6 border-gray-200 sm:mx-auto dark:border-gray-700 lg:my-8" />
<span class="block text-sm text-gray-500 sm:text-center dark:text-gray-400">
© {new Date().getFullYear()}
<Link to="/" class="hover:underline">
<hr className="my-6 border-gray-200 sm:mx-auto dark:border-gray-700 lg:my-8" />
<span className="block text-sm text-gray-500 sm:text-center dark:text-gray-400">
© {new Date().getFullYear()}{" "}
<Link to="/" className="hover:underline">
ExamTime
</Link>
. All Rights Reserved.
Expand Down
85 changes: 42 additions & 43 deletions client/src/components/Login/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useContext, useEffect, useState } from "react";
import React, { useContext, useState } from "react";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router";
import { useNavigate, Link } from "react-router-dom";
import axios from "axios";
import { GoEye, GoEyeClosed } from "react-icons/go";
import { UserContext } from "../../Context/UserContext";
Expand All @@ -15,19 +15,15 @@ const Login = () => {
formState: { errors },
} = useForm();

const [loginError, setloginError] = useState();
const [loginError, setLoginError] = useState();
const { user, setUser } = useContext(UserContext);
const [passToggle, setPassToggle] = useState("password");
const [loading, setLoading] = useState(false);

const navigate = useNavigate();

const togglePassword = () => {
if (passToggle === "password") {
setPassToggle("text");
} else {
setPassToggle("password");
}
setPassToggle((prev) => (prev === "password" ? "text" : "password"));
};

const loginUser = async (data) => {
Expand All @@ -38,7 +34,7 @@ const Login = () => {
if (res.data.message === "login success") {
localStorage.setItem("token", res.data.token);
setUser(res.data.user);
setloginError("");
setLoginError("");
setTimeout(() => {
navigate("/");
}, 1000);
Expand All @@ -56,8 +52,9 @@ const Login = () => {
}
})
.catch((err) => {
if (err.response.data.message === "user not found") {
setloginError("User not found");
const { message } = err.response.data;
if (message === "user not found") {
setLoginError("User not found");
toast.warning("User not found!", {
position: "top-right",
autoClose: 5000,
Expand All @@ -69,14 +66,12 @@ const Login = () => {
theme: "light",
transition: Bounce,
});
setLoading(false);
} else if (err.response.data.message === "Please verify email first") {
setloginError("Please verify email first");
} else if (message === "Please verify email first") {
setLoginError("Please verify email first");
localStorage.setItem("token", err.response.data.token);
setLoading(false);
navigate("/verifyotp");
} else if (err.response.data.message === "Invalid credentials") {
setloginError("Invalid Credentials");
} else if (message === "Invalid credentials") {
setLoginError("Invalid Credentials");
toast.error("Invalid Credentials!", {
position: "top-right",
autoClose: 5000,
Expand All @@ -88,9 +83,8 @@ const Login = () => {
theme: "light",
transition: Bounce,
});
setLoading(false);
} else {
setloginError("Something went wrong!");
setLoginError("Something went wrong!");
toast.error("An error occurred!", {
position: "top-right",
autoClose: 5000,
Expand All @@ -102,8 +96,8 @@ const Login = () => {
theme: "light",
transition: Bounce,
});
setLoading(false);
}
setLoading(false);
});
};

Expand Down Expand Up @@ -134,14 +128,12 @@ const Login = () => {
})}
>
<div>
<div className="flex items-center justify-between">
<label
htmlFor="email"
className="block text-sm font-medium leading-6 text-gray-900"
>
Email
</label>
</div>
<label
htmlFor="email"
className="block text-sm font-medium leading-6 text-gray-900"
>
Email
</label>
<div className="mt-2">
<input
id="email"
Expand All @@ -151,7 +143,7 @@ const Login = () => {
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
{...register("email", {
validate: {
matchPatern: (value) =>
matchPattern: (value) =>
/\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b/gi.test(value) ||
"Enter a valid email address",
},
Expand All @@ -161,14 +153,12 @@ const Login = () => {
</div>

<div>
<div className="flex items-center justify-between">
<label
htmlFor="password"
className="block text-sm font-medium leading-6 text-gray-900"
>
Password
</label>
</div>
<label
htmlFor="password"
className="block text-sm font-medium leading-6 text-gray-900"
>
Password
</label>
<div className="mt-2 relative">
<input
id="password"
Expand All @@ -178,8 +168,8 @@ const Login = () => {
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
{...register("password", {
validate: {
matchPatern: (value) =>
!/^$|\s+/.test(value) || "please enter password",
matchPattern: (value) =>
!/^$|\s+/.test(value) || "please enter a password",
},
})}
/>
Expand Down Expand Up @@ -207,18 +197,27 @@ const Login = () => {
</div>
</form>

<div className="mt-6">
<a href={`${import.meta.env.VITE_BASE_URL}/user/auth/google`}>
<button className="flex w-full justify-center rounded-md bg-red-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600">
Sign in with Google
</button>
</a>
</div>

<p className="mt-10 text-center text-sm text-gray-500">
Don't have an account?{" "}
<a
href="/signup"
Don&apos;t have an account?{" "}
<Link
to="/signup"
className="font-semibold leading-6 text-indigo-600 hover:text-indigo-500"
>
Sign Up
</a>
</Link>
</p>
</div>
</div>
</>
);
};

export default Login;
7 changes: 7 additions & 0 deletions client/src/components/Signup/Signup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,13 @@ const Signup = () => {
{registerError && registerError}
</p>
</div>
<div className="mt-4">
<a href={`${import.meta.env.VITE_BASE_URL}/user/auth/google`}>
<button className="flex w-full justify-center rounded-md bg-red-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600">
Sign Up with Google
</button>
</a>
</div>
</form>

<p className="mt-5 text-center text-sm text-gray-500">
Expand Down
3 changes: 2 additions & 1 deletion server/.env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ SECRET = "N()U*(#@HDF(*#XGH*&#^G)#(UXJX#)U)"
ORIGIN = "http://localhost:5173"
APP_EMAIL = "examtime.official.dev@gmail.com"
APP_PASSWORD = "eivc xnuz bmeg jutk"

GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
4 changes: 3 additions & 1 deletion server/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ MONGODB_URI =
SECRET =
ORIGIN =
APP_EMAIL =
APP_PASSWORD =
APP_PASSWORD =
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
25 changes: 21 additions & 4 deletions server/app.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,51 @@
// app.js
const express = require("express");
const cors = require("cors");
const cookieParser = require("cookie-parser");
const methodOverride = require("method-override");
const passport = require("passport");
const session = require("express-session"); // Add this line
require("./passport/passport-setup.js"); // Import passport configuration

const app = express();

app.use(cors({ origin: process.env.ORIGIN, credentials: true }));

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static("public"));
app.use(cookieParser());
app.use(methodOverride("_method"));

// Use express-session middleware
app.use(
session({
secret: process.env.SECRET, // Add a secret key in your .env file
resave: false,
saveUninitialized: true,
cookie: { secure: process.env.NODE_ENV === "production" } // Use secure cookies in production
})
);

// Initialize passport
app.use(passport.initialize());
app.use(passport.session());

// routes import
const userRoutes = require("./routes/user.routes.js");
const noteRoutes = require("./routes/note.routes.js");
const subjectRoutes = require("./routes/subject.routes.js");
const requestRoutes = require("./routes/request.routes.js");
const questionRoutes=require("./routes/question.routes.js")
const questionRoutes = require("./routes/question.routes.js");

// routes declare
app.use("/user", userRoutes);
app.use("/note", noteRoutes);
app.use("/subject", subjectRoutes);
app.use("/request", requestRoutes);
app.use("/question",questionRoutes)
app.use("/question", questionRoutes);

app.get("/", (req, res) => {
res.send("Yupp The server is runnng 🎉 !");
res.send("Yupp The server is running 🎉 !");
});

module.exports = app;
Loading