diff --git a/components/AlertModal.js b/components/AlertModal.js
new file mode 100644
index 00000000..c2b00f2e
--- /dev/null
+++ b/components/AlertModal.js
@@ -0,0 +1,21 @@
+import React from "react";
+import { useAlert } from "../contexts/AlertContext";
+
+const AlertModal = () => {
+ const { alert, closeAlert } = useAlert();
+
+ if (!alert.isOpen) return null;
+
+ return (
+
+
+
+ {faculty.personal_info.first_name || "No Name"}{" "}
+ {faculty.personal_info.last_name || ""}
+
+
Email: {faculty.personal_info?.email || "N/A"}
+
User ID: {faculty.user_id}
+
+ Address: {faculty.personal_info.present_address?.street || "N/A"},{" "}
+ {faculty.personal_info.present_address?.city || "N/A"},{" "}
+ {faculty.personal_info.present_address?.district || "N/A"},{" "}
+ {faculty.personal_info.present_address?.state || "N/A"}
+
+
Gender: {faculty.personal_info.gender || "N/A"}
+
+ DOB:{" "}
+ {faculty.personal_info.dob
+ ? new Date(faculty.personal_info.dob).toLocaleDateString()
+ : "N/A"}
+
+
Contact: {faculty.personal_info.contact || "N/A"}
+
Faculty ID: {faculty.job_info.faculty_id}
+
Room: {faculty.job_info.room || "N/A"}
+
Department: {faculty.job_info.department || "Not Assigned"}
+
+
+
+
+
+ );
+};
+
+FacultyIdCard.propTypes = {
+ faculty: PropTypes.shape({
+ user_id: PropTypes.string.isRequired,
+ image: PropTypes.string,
+ personal_info: PropTypes.shape({
+ first_name: PropTypes.string,
+ last_name: PropTypes.string,
+ email: PropTypes.string,
+ present_address: PropTypes.shape({
+ street: PropTypes.string,
+ city: PropTypes.string,
+ district: PropTypes.string,
+ state: PropTypes.string,
+ }),
+ gender: PropTypes.string,
+ dob: PropTypes.string,
+ contact: PropTypes.string,
+ }),
+ job_info: PropTypes.shape({
+ faculty_id: PropTypes.string,
+ room: PropTypes.string,
+ department: PropTypes.string,
+ }),
+ }).isRequired,
+ placeholderImage: PropTypes.string.isRequired,
+ isFavorite: PropTypes.bool.isRequired,
+ toggleFavorite: PropTypes.func.isRequired,
+};
+
+export default FacultyIdCard;
diff --git a/components/Routine.jsx b/components/Routine.jsx
new file mode 100644
index 00000000..0f185d05
--- /dev/null
+++ b/components/Routine.jsx
@@ -0,0 +1,128 @@
+import React from "react";
+
+
+const routineData = [
+ {
+ period: 1,
+ subjects: ["Mathematics", "English", "History", "Science", "Art"],
+ teachers: [
+ "Mrs. Jane Doe",
+ "Mr. John Smith",
+ "Ms. Sarah Lee",
+ "Dr. Michael Johnson",
+ "Ms. Emily Davis",
+ ],
+ },
+ {
+ period: 2,
+ subjects: ["English", "Mathematics", "Art", "History", "Science"],
+ teachers: [
+ "Mr. John Smith",
+ "Mrs. Jane Doe",
+ "Ms. Emily Davis",
+ "Ms. Sarah Lee",
+ "Dr. Michael Johnson",
+ ],
+ },
+ {
+ period: 3,
+ subjects: ["History", "Science", "Mathematics", "Art", "English"],
+ teachers: [
+ "Ms. Sarah Lee",
+ "Dr. Michael Johnson",
+ "Mrs. Jane Doe",
+ "Ms. Emily Davis",
+ "Mr. John Smith",
+ ],
+ },
+ {
+ period: 4,
+ subjects: ["Science", "Art", "English", "Mathematics", "History"],
+ teachers: [
+ "Dr. Michael Johnson",
+ "Ms. Emily Davis",
+ "Mr. John Smith",
+ "Mrs. Jane Doe",
+ "Ms. Sarah Lee",
+ ],
+ },
+ {
+ period: 5,
+ subjects: ["Art", "History", "Science", "English", "Mathematics"],
+ teachers: [
+ "Ms. Emily Davis",
+ "Ms. Sarah Lee",
+ "Dr. Michael Johnson",
+ "Mr. John Smith",
+ "Mrs. Jane Doe",
+ ],
+ },
+ {
+ period: 6,
+ subjects: ["Mathematics", "Science", "English", "Art", "History"],
+ teachers: [
+ "Mrs. Jane Doe",
+ "Dr. Michael Johnson",
+ "Mr. John Smith",
+ "Ms. Emily Davis",
+ "Ms. Sarah Lee",
+ ],
+ },
+ {
+ period: 7,
+ subjects: ["English", "Art", "History", "Science", "Mathematics"],
+ teachers: [
+ "Mr. John Smith",
+ "Ms. Emily Davis",
+ "Ms. Sarah Lee",
+ "Dr. Michael Johnson",
+ "Mrs. Jane Doe",
+ ],
+ },
+];
+
+const days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"];
+
+const colors = ["blue", "green", "yellow", "red", "purple"];
+
+export default function Routine() {
+ return (
+ setIsMenuOpen(!isMenuOpen)}
>
diff --git a/containers/Header/Navbar.jsx b/containers/Header/Navbar.jsx
index 60ff9d52..4b81c48a 100644
--- a/containers/Header/Navbar.jsx
+++ b/containers/Header/Navbar.jsx
@@ -96,6 +96,11 @@ function Navbar() {
className: "nav-item",
src: "/admin/manage/students",
},
+ {
+ label: "Manage Faculties",
+ className: "nav-item",
+ src: "/admin/manage/faculties",
+ },
{
label: "Contact Us",
className: "nav-item",
@@ -112,9 +117,7 @@ function Navbar() {
src: "/admin/scanner",
},
],
- faculty: [
- { label: "Dashboard", className: "nav-item", src: "/faculty/dashboard" },
- ],
+ faculty: [{ label: "Dashboard", className: "nav-item", src: "/faculty" }],
student: [
{ label: "Dashboard", className: "nav-item", src: "/student" },
{
diff --git a/contexts/AlertContext.js b/contexts/AlertContext.js
new file mode 100644
index 00000000..faeccf2b
--- /dev/null
+++ b/contexts/AlertContext.js
@@ -0,0 +1,18 @@
+import React, { createContext, useState, useContext } from "react";
+
+const AlertContext = createContext();
+
+export const AlertProvider = ({ children }) => {
+ const [alert, setAlert] = useState({ isOpen: false, message: "" });
+
+ const showAlert = (message) => setAlert({ isOpen: true, message });
+ const closeAlert = () => setAlert({ isOpen: false, message: "" });
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useAlert = () => useContext(AlertContext);
diff --git a/functions/generateOtp.js b/functions/generateOtp.js
index afd149aa..d84d913a 100644
--- a/functions/generateOtp.js
+++ b/functions/generateOtp.js
@@ -37,3 +37,5 @@ const generateOtpApi = async (userIdOrEmail) => {
};
export default generateOtpApi;
+
+
diff --git a/functions/logoutApi.js b/functions/logoutApi.js
index c9f854cc..b9c8662e 100644
--- a/functions/logoutApi.js
+++ b/functions/logoutApi.js
@@ -20,7 +20,6 @@ const logoutApi = async (userId, authToken) => {
if (process.env.NODE_ENV === "development") {
console.log(response);
}
- // throw new Error(`Logout request failed with status ${response.status}`);
}
if (process.env.NODE_ENV === "development") {
console.log("Response:", response);
diff --git a/layout/admin_layout/AdminLayout.jsx b/layout/admin_layout/AdminLayout.jsx
index 61c172b0..5379dbfc 100644
--- a/layout/admin_layout/AdminLayout.jsx
+++ b/layout/admin_layout/AdminLayout.jsx
@@ -1,30 +1,37 @@
-import React, { Fragment, useEffect } from "react";
+import React, { Fragment, useEffect, useRef } from "react";
import { useRouter } from "next/router";
import { Navbar, Footer, ChatBot } from "@/containers";
+
function AdminLayout({ children }) {
const router = useRouter();
+
+ const hasLogged = useRef(false);
+
useEffect(() => {
const authToken = localStorage.getItem("authToken");
const userType = localStorage.getItem("userType");
- if (process.env.NODE_ENV === "development") {
+
+ if (process.env.NODE_ENV === "development" && !hasLogged.current) {
console.log("AuthToken", authToken);
console.log("UserType", userType);
+ hasLogged.current = true;
}
+
if (!authToken) {
localStorage.clear();
router.push("/");
- }
- if (userType !== "admin") {
+ } else if (userType !== "admin") {
localStorage.clear();
router.push("/");
}
}, [router]);
+
return (
-
+
{children}
-
-
+
+
);
}
diff --git a/layout/applicant_layout/ApplicantLayout.jsx b/layout/applicant_layout/ApplicantLayout.jsx
index de3427a7..e6054bc9 100644
--- a/layout/applicant_layout/ApplicantLayout.jsx
+++ b/layout/applicant_layout/ApplicantLayout.jsx
@@ -1,24 +1,30 @@
-import { Fragment, useEffect } from "react";
+import { Fragment, useEffect, useRef } from "react";
import { useRouter } from "next/router";
import { ApplicantNavbar, Footer, ChatBot } from "@/containers";
+
function ApplicantLayout({ children }) {
const router = useRouter();
+ const hasLogged = useRef(false);
+
useEffect(() => {
const authToken = localStorage.getItem("authToken");
const userType = localStorage.getItem("userType");
- if (process.env.NODE_ENV === "development") {
+
+ if (process.env.NODE_ENV === "development" && !hasLogged.current) {
console.log("AuthToken", authToken);
console.log("UserType", userType);
+ hasLogged.current = true;
}
+
if (!authToken) {
localStorage.clear();
router.push("/");
- }
- if (userType !== "applicant") {
+ } else if (userType !== "applicant") {
localStorage.clear();
router.push("/");
}
}, [router]);
+
return (
diff --git a/layout/faculty_layout/FacultyLayout.jsx b/layout/faculty_layout/FacultyLayout.jsx
new file mode 100644
index 00000000..c642da53
--- /dev/null
+++ b/layout/faculty_layout/FacultyLayout.jsx
@@ -0,0 +1,38 @@
+import React, { Fragment, useEffect, useRef } from "react";
+import { useRouter } from "next/router";
+import { Footer, Navbar, ChatBot } from "@/containers";
+
+function FacultyLayout({ children }) {
+ const router = useRouter();
+ const hasLogged = useRef(false);
+
+ useEffect(() => {
+ const authToken = localStorage.getItem("authToken");
+ const userType = localStorage.getItem("userType");
+
+ if (process.env.NODE_ENV === "development" && !hasLogged.current) {
+ console.log("AuthToken", authToken);
+ console.log("UserType", userType);
+ hasLogged.current = true;
+ }
+
+ if (!authToken) {
+ localStorage.clear();
+ router.push("/");
+ } else if (userType !== "faculty") {
+ localStorage.clear();
+ router.push("/");
+ }
+ }, [router]);
+
+ return (
+
+
+ {children}
+
+
+
+ );
+}
+
+export default FacultyLayout;
diff --git a/layout/index.jsx b/layout/index.jsx
index 53e52ee0..863498df 100644
--- a/layout/index.jsx
+++ b/layout/index.jsx
@@ -2,3 +2,5 @@ export { default as LandingLayout } from "./landing_layout/landingLayout";
export { default as ApplicantLayout } from "./applicant_layout/ApplicantLayout";
export { default as AdminLayout } from "./admin_layout/AdminLayout";
export { default as StudentLayout } from "./student_layout/StudentLayout";
+
+export { default as FacultyLayout } from "./faculty_layout/FacultyLayout";
diff --git a/layout/landing_layout/landingLayout.jsx b/layout/landing_layout/landingLayout.jsx
index 6e989374..5704c847 100644
--- a/layout/landing_layout/landingLayout.jsx
+++ b/layout/landing_layout/landingLayout.jsx
@@ -1,38 +1,52 @@
-import { Fragment, useEffect } from "react";
+import { Fragment, useEffect, useRef } from "react";
import { LandingNavbar, LandingPage, ChatBot } from "@/containers";
import { useRouter } from "next/router";
+
function LandingLayout({ children }) {
const router = useRouter();
+ const hasLogged = useRef(false);
+
useEffect(() => {
const authToken = localStorage.getItem("authToken");
const userType = localStorage.getItem("userType");
- if (process.env.NODE_ENV === "development") {
+
+ if (process.env.NODE_ENV === "development" && !hasLogged.current) {
console.log("AuthToken", authToken);
console.log("UserType", userType);
+ hasLogged.current = true;
}
+
if (authToken) {
- if (userType === "applicant") {
- router.push("/applicant");
- } else if (userType === "student") {
- router.push("/student");
- } else if (userType === "faculty") {
- router.push("/faculty");
- } else if (userType === "admin") {
- router.push("/admin");
- } else {
- localStorage.clear();
+ switch (userType) {
+ case "applicant":
+ router.push("/applicant");
+ break;
+ case "student":
+ router.push("/student");
+ break;
+ case "faculty":
+ router.push("/faculty");
+ break;
+ case "admin":
+ router.push("/admin");
+ break;
+ default:
+ localStorage.clear();
+ break;
}
}
}, [router]);
+
return (
-
+
-
+
);
}
+
export default LandingLayout;
diff --git a/layout/student_layout/StudentLayout.jsx b/layout/student_layout/StudentLayout.jsx
index bbccfb47..a710507c 100644
--- a/layout/student_layout/StudentLayout.jsx
+++ b/layout/student_layout/StudentLayout.jsx
@@ -1,30 +1,37 @@
-import React, { Fragment, useEffect } from "react";
+import React, { Fragment, useEffect, useRef } from "react";
import { useRouter } from "next/router";
import { Footer, Navbar, ChatBot } from "@/containers";
+
function StudentLayout({ children }) {
const router = useRouter();
+
+ const hasLogged = useRef(false);
+
useEffect(() => {
const authToken = localStorage.getItem("authToken");
const userType = localStorage.getItem("userType");
- if (process.env.NODE_ENV === "development") {
+
+ if (process.env.NODE_ENV === "development" && !hasLogged.current) {
console.log("AuthToken", authToken);
console.log("UserType", userType);
+ hasLogged.current = true;
}
+
if (!authToken) {
localStorage.clear();
router.push("/");
- }
- if (userType !== "student") {
+ } else if (userType !== "student") {
localStorage.clear();
router.push("/");
}
}, [router]);
+
return (
-
+
{children}
-
-
+
+
);
}
diff --git a/layout/superadmin_layout/superAdminLayout.jsx b/layout/superadmin_layout/superAdminLayout.jsx
new file mode 100644
index 00000000..51e620ee
--- /dev/null
+++ b/layout/superadmin_layout/superAdminLayout.jsx
@@ -0,0 +1,38 @@
+import React, { Fragment, useEffect, useRef } from "react";
+import { useRouter } from "next/router";
+import { Navbar, Footer, ChatBot } from "@/containers";
+
+function SuperAdminLayout({ children }) {
+ const router = useRouter();
+ const hasLogged = useRef(false);
+
+ useEffect(() => {
+ const authToken = localStorage.getItem("authToken");
+ const userType = localStorage.getItem("userType");
+
+ if (process.env.NODE_ENV === "development" && !hasLogged.current) {
+ console.log("AuthToken", authToken);
+ console.log("UserType", userType);
+ hasLogged.current = true;
+ }
+
+ if (!authToken) {
+ localStorage.clear();
+ router.push("/");
+ } else if (userType !== "super-admin") {
+ localStorage.clear();
+ router.push("/");
+ }
+ }, [router]);
+
+ return (
+
+
+ {children}
+
+
+
+ );
+}
+
+export default SuperAdminLayout;
diff --git a/package-lock.json b/package-lock.json
index 13de16ff..83ce9ab2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,7 +15,9 @@
"axios": "^1.6.8",
"dotenv": "^16.4.5",
"express": "^4.19.2",
+ "file-saver": "^2.0.5",
"fs": "^0.0.1-security",
+ "json2csv": "^6.0.0-alpha.2",
"next": "^14.1.4",
"next-auth": "^4.24.7",
"qr-scanner": "^1.4.2",
@@ -1210,6 +1212,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@streamparser/json": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@streamparser/json/-/json-0.0.6.tgz",
+ "integrity": "sha512-vL9EVn/v+OhZ+Wcs6O4iKE9EUpwHUqHmCtNUMWjqp+6dr85+XPOSGTEsqYNq1Vn04uk9SWlOVmx9J48ggJVT2Q==",
+ "license": "MIT"
+ },
"node_modules/@swc/counter": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
@@ -2183,6 +2191,15 @@
"node": ">= 0.8"
}
},
+ "node_modules/commander": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+ "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -3309,6 +3326,12 @@
"node": "^10.12.0 || >=12.0.0"
}
},
+ "node_modules/file-saver": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
+ "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==",
+ "license": "MIT"
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -4563,6 +4586,24 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/json2csv": {
+ "version": "6.0.0-alpha.2",
+ "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-6.0.0-alpha.2.tgz",
+ "integrity": "sha512-nJ3oP6QxN8z69IT1HmrJdfVxhU1kLTBVgMfRnNZc37YEY+jZ4nU27rBGxT4vaqM/KUCavLRhntmTuBFqZLBUcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@streamparser/json": "^0.0.6",
+ "commander": "^6.2.0",
+ "lodash.get": "^4.4.2"
+ },
+ "bin": {
+ "json2csv": "bin/json2csv.js"
+ },
+ "engines": {
+ "node": ">= 12",
+ "npm": ">= 6.13.0"
+ }
+ },
"node_modules/json5": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
@@ -4679,6 +4720,12 @@
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
"license": "MIT"
},
+ "node_modules/lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
+ "license": "MIT"
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
diff --git a/package.json b/package.json
index 6b704e7c..adf37be6 100644
--- a/package.json
+++ b/package.json
@@ -48,7 +48,9 @@
"axios": "^1.6.8",
"dotenv": "^16.4.5",
"express": "^4.19.2",
+ "file-saver": "^2.0.5",
"fs": "^0.0.1-security",
+ "json2csv": "^6.0.0-alpha.2",
"next": "^14.1.4",
"next-auth": "^4.24.7",
"qr-scanner": "^1.4.2",
diff --git a/pages/_app.jsx b/pages/_app.jsx
index f8c5ca4b..f1abe858 100644
--- a/pages/_app.jsx
+++ b/pages/_app.jsx
@@ -4,6 +4,8 @@ import { SessionProvider } from "next-auth/react";
import { Analytics } from "@vercel/analytics/react";
import { SpeedInsights } from "@vercel/speed-insights/next";
import { CommonMeta } from "@/components";
+import { AlertProvider } from "@/contexts/AlertContext";
+import { AlertModal } from "@/components";
export default function App({
Component,
pageProps: { session, ...pageProps },
@@ -11,10 +13,13 @@ export default function App({
return (
-
-
-
-
+
+
+
+
+
+
+
);
diff --git a/pages/admin/manage/applicant/index.jsx b/pages/admin/manage/applicant/index.jsx
deleted file mode 100644
index a000651d..00000000
--- a/pages/admin/manage/applicant/index.jsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import { AdminLayout } from "@/layout";
-import React, { Fragment, useEffect, useState } from "react";
-import { getCollegeDetailsApi, getApplicantsByYear } from "@/functions";
-import { CollegeDropdowns } from "@/components";
-import { ManageApp } from "@/components";
-
-const ManageApplicants = () => {
- const [maincollegeData, setmaincollegeData] = useState(null);
- const [applicantData, setapplicantData] = useState([]);
- const [selectedCourse, setSelectedCourse] = useState("");
- const [selectedStream, setSelectedStream] = useState("");
- const [searchQuery, setSearchQuery] = useState("");
-
- useEffect(() => {
- fetchCollegeData();
- getApplicantData();
- }, []);
-
- const fetchCollegeData = async () => {
- try {
- const response = await getCollegeDetailsApi(304);
- if (process.env.NODE_ENV === "development") {
- console.log(response);
- }
- setmaincollegeData(response);
- } catch (error) {
- if (process.env.NODE_ENV === "development") {
- console.error("Error fetching college data:", error);
- }
- }
- };
-
- const getApplicantData = async () => {
- try {
- const response = await getApplicantsByYear(2023);
- if (process.env.NODE_ENV === "development") {
- console.log(response);
- }
- setapplicantData(response.data);
- } catch (error) {
- if (process.env.NODE_ENV == "development") {
- console.error("Error fetching applicant data:", error);
- }
- }
- };
-
- const filterData = () => {
- let filteredResult = applicantData.filter(
- (item, i) => Object.keys(item).length > 8
- );
-
- if (selectedCourse) {
- filteredResult = filteredResult.filter(
- (item) => item.course_info.course_name === selectedCourse
- );
- }
-
- if (selectedStream) {
- filteredResult = filteredResult.filter(
- (item) => item.course_info.stream === selectedStream
- );
- }
- if (searchQuery) {
- const searchLowerCase = searchQuery.toLowerCase();
- filteredResult = filteredResult.filter((item) => {
- const firstName = (item.personal_info.first_name || "").toLowerCase();
- const lastName = (item.personal_info.last_name || "").toLowerCase();
-
- return (
- firstName.includes(searchLowerCase) ||
- lastName.includes(searchLowerCase)
- );
- });
- }
-
- return filteredResult;
- };
-
- const handleCourseChange = (newCourse) => {
- setSelectedCourse(newCourse);
- };
-
- const handleStreamChange = (newStream) => {
- setSelectedStream(newStream);
- };
-
- const handleSearchChange = (query) => {
- setSearchQuery(query);
- };
-
- if (!maincollegeData || !applicantData) return Loading...
;
- return (
-
-
-
-
-
Manage Applicant
-
-
-
-
-
-
- );
-};
-
-export default ManageApplicants;
diff --git a/pages/admin/manage/applicants/index.jsx b/pages/admin/manage/applicants/index.jsx
index 8487595a..a02faaaa 100644
--- a/pages/admin/manage/applicants/index.jsx
+++ b/pages/admin/manage/applicants/index.jsx
@@ -1,13 +1,10 @@
-import { useEffect, useState, Fragment } from "react";
-import {
- getApplicantsByYearApi,
- getCollegeDetailsApi,
- deleteSingleApplicantApi,
-} from "@/functions";
-import { AllLoader } from "@/components";
+import { useEffect, useState, Fragment, useRef } from "react";
import Image from "next/image";
import { AdminLayout } from "@/layout";
import { useRouter } from "next/router";
+import { AllLoader } from "@/components";
+import { useAlert } from "@/contexts/AlertContext";
+import { withLoading, devLog, apiRequest } from "@/utils/apiUtils";
function Index() {
const [applicants, setApplicants] = useState([]);
@@ -20,33 +17,78 @@ function Index() {
const [searchTerm, setSearchTerm] = useState("");
const [submitted, setSubmitted] = useState(false);
const year = new Date().getFullYear();
+ const collegeId = 304;
const router = useRouter();
+ const { showAlert } = useAlert();
+ const effectRun = useRef(false);
+
useEffect(() => {
- setLoading(true);
- getApplicantsByYearApi(year)
- .then((data) => {
- if (Array.isArray(data.data)) {
- setApplicants(data.data);
- } else {
- console.error("Applicants data is not an array:", data.data);
+ const authToken = localStorage.getItem("authToken");
+ if (effectRun.current) return;
+ effectRun.current = true;
+
+ const getApplicantsByYear = async () => {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GetAllApplicants"
+ );
+ try {
+ const response = await wrappedApiRequest(
+ `/applicant/year?year=${year}`,
+ "GET",
+ null,
+ authToken,
+ "GetAllApplicants"
+ );
+
+ if (!response.success || !response.status) {
+ devLog("Error in fetching applicant data:", response.message);
+ showAlert(response.message || "Failed to fetch applicant data");
+ return;
}
- setLoading(false);
- })
- .catch((error) => {
- console.error("Error fetching applicants:", error);
- setLoading(false);
- });
- }, [year]);
+ setApplicants(response.data.data);
+ } catch (error) {
+ devLog("Error in fetching applicant data:", error);
+ showAlert(error.message || "Failed to fetch applicant data");
+ }
+ };
- useEffect(() => {
- getCollegeDetailsApi(304)
- .then((data) => {
- setCollegeData(data.data);
- })
- .catch((error) => {
- console.error("Error fetching college details:", error);
- });
- }, []);
+ const getCollegeDetails = async () => {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GetCollegeDetails"
+ );
+ try {
+ const response = await wrappedApiRequest(
+ `/college/?college_id=${collegeId}`,
+ "GET",
+ null,
+ authToken,
+ "GetCollegeDetails"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in fetching college details:", response.message);
+ showAlert(response.message || "Failed to fetch college details");
+ return;
+ }
+ setCollegeData(response.data.data);
+ } catch (error) {
+ devLog("Error in fetching college details:", error);
+ showAlert(error.message || "Failed to fetch college details");
+ }
+ };
+
+ const onLoadHandler = async () => {
+ await getApplicantsByYear();
+ await getCollegeDetails();
+ };
+
+ onLoadHandler();
+ }, [showAlert, year]);
const indexOfLastApplicant = currentPage * pageSize;
const indexOfFirstApplicant = indexOfLastApplicant - pageSize;
@@ -104,19 +146,37 @@ function Index() {
);
setApplicants(filteredApplicants);
} else {
- getApplicantsByYearApi()
- .then((data) => {
- if (Array.isArray(data.data)) {
- setApplicants(data.data);
- } else {
- console.error("Applicants data is not an array:", data.data);
+ const getApplicantsByYear = async () => {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GetAllApplicants"
+ );
+ try {
+ const response = await wrappedApiRequest(
+ `/applicant/year?year=${year}`,
+ "GET",
+ null,
+ authToken,
+ "GetAllApplicants"
+ );
+
+ if (!response.success || !response.status) {
+ devLog("Error in fetching applicant data:", response.message);
+ showAlert(response.message || "Failed to fetch applicant data");
+ return;
}
- })
- .catch((error) => {
- console.error("Error fetching applicants:", error);
- });
+ setApplicants(response.data.data);
+ } catch (error) {
+ devLog("Error in fetching applicant data:", error);
+ showAlert(error.message || "Failed to fetch applicant data");
+ }
+ };
+ getApplicantsByYear();
}
};
+
function handleShowProfile(id) {
console.log("Show profile for applicant with id:", id);
localStorage.setItem("selected-applicantId", id);
@@ -126,20 +186,40 @@ function Index() {
async function handleDeleteApplicant(id) {
console.log("Delete applicant with id:", id);
localStorage.setItem("selected-applicantId", id);
+ const authToken = localStorage.getItem("authToken");
const confirmDelete = confirm(
"Are you sure you want to delete this applicant?"
);
if (confirmDelete) {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "DeleteApplicant"
+ );
try {
- setLoading(true);
- await deleteSingleApplicantApi(id);
- setLoading(false);
- window.location.reload();
+ localStorage.getItem("authToken");
+ const response = await wrappedApiRequest(
+ `/applicant/?user_id=${id}`,
+ "DELETE",
+ null,
+ authToken,
+ "DeleteApplicant"
+ );
+
+ if (response.success) {
+ window.location.reload();
+ } else {
+ showAlert(
+ response.message || "Error deleting applicant. Please try again."
+ );
+ }
} catch (error) {
- console.error("Error deleting applicant:", error);
- setLoading(false);
- alert("Error deleting applicant. Please try again.");
+ devLog("Error deleting applicant:", error);
+ showAlert(
+ response.message || "Error deleting applicant. Please try again."
+ );
}
}
}
diff --git a/pages/admin/manage/applicants/profile/index.jsx b/pages/admin/manage/applicants/profile/index.jsx
index 255f1bce..e2e113ed 100644
--- a/pages/admin/manage/applicants/profile/index.jsx
+++ b/pages/admin/manage/applicants/profile/index.jsx
@@ -1,9 +1,10 @@
-import React, { Fragment, useEffect, useState } from "react";
+import React, { Fragment, useEffect, useState, useRef } from "react";
import { AdminLayout } from "@/layout";
-import { getSingleApplicantApi, approveApplicantApi } from "@/functions";
import { AllLoader } from "@/components";
import Image from "next/image";
import { useRouter } from "next/router";
+import { withLoading, devLog, apiRequest } from "@/utils/apiUtils";
+import { useAlert } from "@/contexts/AlertContext";
function generateClassName(prefix, key) {
const formattedKey = key
@@ -361,67 +362,92 @@ function renderFields(data, parentKey = "") {
function ApplicantDashboard() {
const [profileData, setProfileData] = useState({});
const [loading, setLoading] = useState(true);
+ const { showAlert } = useAlert();
const router = useRouter();
+ const effectRun = useRef(false);
+
+ useEffect(() => {
+ const applicantId = localStorage.getItem("selected-applicantId");
+ const authToken = localStorage.getItem("authToken");
+ if (effectRun.current) return;
+ effectRun.current = true;
+
+ const fetchSingleApplicantData = async () => {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GetSingleApplicant"
+ );
+ try {
+ const response = await wrappedApiRequest(
+ `/applicant/?user_id=${applicantId}`,
+ "GET",
+ null,
+ authToken,
+ "GetSingleApplicant"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in fetching single applicant data:", response);
+ showAlert(response.message || "Failed to fetch applicant data");
+ return;
+ }
+ setProfileData(response.data.data);
+ } catch (error) {
+ devLog("Error in fetching single applicant data:", error);
+ showAlert(error.message || "Failed to fetch applicant data");
+ }
+ };
+
+ fetchSingleApplicantData();
+ }, [router, showAlert]);
async function approveHandler() {
- const id = localStorage.getItem("selected-applicantId");
- console.log("Approve applicant with id:", id);
+ const applicantId = localStorage.getItem("selected-applicantId");
+ const authToken = localStorage.getItem("authToken");
+ console.log("Approve applicant with id:", applicantId);
const confirmApprove = confirm(
"Are you sure you want to approve this applicant?"
);
if (confirmApprove) {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "ApproveApplicant"
+ );
try {
- setLoading(true);
- const response = await approveApplicantApi(id);
- setLoading(false);
- alert(response.message);
+ const response = await wrappedApiRequest(
+ `/student/approve?user_id=${applicantId}`,
+ "POST",
+ null,
+ authToken,
+ "ApproveApplicant"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in approving applicant:", response);
+ showAlert(response.message || "Failed to approve applicant");
+ return;
+ }
+ showAlert(response.message);
router.push("/admin/manage/applicants");
} catch (error) {
- console.error("Error approving applicant:", error);
- setLoading(false);
- alert("Error approving applicant. Please try again.");
+ devLog("Error in approving applicant:", error);
+ showAlert(error.message || "Failed to approve applicant");
}
}
}
async function updateHandler() {
- // console.log("Approve applicant with id:", id);
-
try {
router.push("/admin/manage/applicants/profile/update");
} catch (error) {
console.error("Error updating applicant:", error);
- alert("Error updating applicant. Please try again.");
+ showAlert(
+ error.message || "Failed to update applicant, please try again"
+ );
}
}
- useEffect(() => {
- const applicantId = localStorage.getItem("selected-applicantId");
- console.log("Applicant ID:", applicantId);
-
- const fetchData = async () => {
- try {
- setLoading(true);
- const response = await getSingleApplicantApi(applicantId);
-
- if (response.status === false) {
- alert(response.message);
- setLoading(false);
- return;
- }
- setProfileData(response.data);
- localStorage.setItem(
- "applicant_profile",
- JSON.stringify(response.data)
- );
- setLoading(false);
- } catch (error) {
- console.error("Error fetching applicant data:", error.message);
- }
- };
-
- fetchData();
- // }
- }, []);
return (
diff --git a/pages/admin/manage/faculties/index.jsx b/pages/admin/manage/faculties/index.jsx
new file mode 100644
index 00000000..f40bc42f
--- /dev/null
+++ b/pages/admin/manage/faculties/index.jsx
@@ -0,0 +1,341 @@
+import {
+ useEffect,
+ useState,
+ Fragment,
+ useRef,
+ useCallback,
+ useMemo,
+} from "react";
+import { AdminLayout } from "@/layout";
+import { AllLoader } from "@/components";
+import { useAlert } from "@/contexts/AlertContext";
+import { withLoading, devLog, apiRequest } from "@/utils/apiUtils";
+import { FacultyIdCard } from "@/components";
+
+function Faculty() {
+ const [faculties, setFaculties] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [searchQuery, setSearchQuery] = useState("");
+ const [collegeData, setCollegeData] = useState(null);
+ const [selectedCourse, setSelectedCourse] = useState("");
+ const [selectedStream, setSelectedStream] = useState("");
+ const [selectedGender, setSelectedGender] = useState("");
+ const [pageSize, setPageSize] = useState(9);
+ const [currentPage, setCurrentPage] = useState(1);
+ const [favorites, setFavorites] = useState([]);
+ const [cache, setCache] = useState({});
+ const [showFavorites, setShowFavorites] = useState(false);
+ const { showAlert } = useAlert();
+ const effectRun = useRef(false);
+ const collegeId = 304;
+ const placeholderImage = "/user.png";
+
+ useEffect(() => {
+ const authToken = localStorage.getItem("authToken");
+ if (effectRun.current) return;
+ effectRun.current = true;
+
+ const getAllFaculty = async () => {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GetAllFaculties"
+ );
+
+ try {
+ const response = await wrappedApiRequest(
+ `/faculty/all`,
+ "GET",
+ null,
+ authToken,
+ "GetAllFaculties"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in getting faculties:", response.message);
+ showAlert(
+ response.message || "Error getting faculties. Please try again."
+ );
+ return;
+ }
+ setFaculties(response.data.data);
+ setCache((prevCache) => ({
+ ...prevCache,
+ faculties: response.data.data,
+ }));
+ } catch (error) {
+ devLog("Error in getting faculties:", error);
+ showAlert(error.message || "Failed to fetch faculty data.");
+ }
+ };
+
+ const getCollegeDetails = async () => {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GetCollegeDetails"
+ );
+ try {
+ const response = await wrappedApiRequest(
+ `/college/?college_id=${collegeId}`,
+ "GET",
+ null,
+ authToken,
+ "GetCollegeDetails"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in fetching college details:", response.message);
+ showAlert(response.message || "Failed to fetch college details");
+ return;
+ }
+ setCollegeData(response.data.data);
+ } catch (error) {
+ devLog("Error in fetching college details:", error);
+ showAlert(error.message || "Failed to fetch college details");
+ }
+ };
+
+ const onLoadHandler = async () => {
+ if (cache.faculties) {
+ setFaculties(cache.faculties);
+ } else {
+ await getAllFaculty();
+ await getCollegeDetails();
+ }
+ };
+
+ onLoadHandler();
+
+ const savedFavorites = JSON.parse(localStorage.getItem("favorites")) || [];
+ setFavorites(savedFavorites);
+ }, [showAlert, cache]);
+
+ const filteredFaculties = useMemo(() => {
+ return faculties.filter((faculty) => {
+ const fullName = `${faculty.personal_info.first_name || ""} ${
+ faculty.personal_info.last_name || ""
+ }`.toLowerCase();
+ const email = (faculty.personal_info?.email || "").toLowerCase();
+ const gender = (faculty.personal_info.gender || "").toLowerCase();
+ const department = (faculty.job_info.department || "").toLowerCase();
+
+ const matchesName = fullName.includes(searchQuery.toLowerCase());
+ const matchesEmail = email.includes(searchQuery.toLowerCase());
+ const matchesGender =
+ selectedGender === "" || gender === selectedGender.toLowerCase();
+ const matchesDepartment =
+ selectedStream === "" || department === selectedStream.toLowerCase();
+ const matchesFavorites =
+ !showFavorites || favorites.includes(faculty._id);
+
+ return (
+ (matchesName || matchesEmail) &&
+ matchesGender &&
+ matchesDepartment &&
+ matchesFavorites
+ );
+ });
+ }, [
+ faculties,
+ searchQuery,
+ selectedGender,
+ selectedStream,
+ showFavorites,
+ favorites,
+ ]);
+
+ const totalPages = Math.ceil(filteredFaculties.length / pageSize);
+ const paginatedFaculties = filteredFaculties.slice(
+ (currentPage - 1) * pageSize,
+ currentPage * pageSize
+ );
+
+ const courses = collegeData?.college_courses || [];
+ const streams = selectedCourse
+ ? courses.find((course) => course.code === selectedCourse)?.streams || []
+ : [];
+
+ const handleChangePageSize = (e) => {
+ setPageSize(Number(e.target.value));
+ setCurrentPage(1);
+ };
+
+ const paginate = useCallback((pageNumber) => {
+ setCurrentPage(pageNumber);
+ }, []);
+
+ const toggleFavorite = useCallback((facultyId) => {
+ setFavorites((prevFavorites) => {
+ const updatedFavorites = prevFavorites.includes(facultyId)
+ ? prevFavorites.filter((id) => id !== facultyId)
+ : [...prevFavorites, facultyId];
+
+ localStorage.setItem("favorites", JSON.stringify(updatedFavorites));
+ return updatedFavorites;
+ });
+ }, []);
+
+ const exportFacultyDataAsCSV = useCallback(() => {
+ const headers = [
+ "First Name",
+ "Last Name",
+ "Email",
+ "Gender",
+ "Department",
+ "Course",
+ "Stream",
+ ];
+ const rows = filteredFaculties.map((faculty) => [
+ faculty.personal_info.first_name || "",
+ faculty.personal_info.last_name || "",
+ faculty.personal_info?.email || "",
+ faculty.personal_info.gender || "",
+ faculty.job_info.department || "",
+ faculty.job_info.course || "",
+ faculty.job_info.stream || "",
+ ]);
+
+ const csvContent = [headers, ...rows].map((e) => e.join(",")).join("\n");
+ const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
+ const url = URL.createObjectURL(blob);
+ const link = document.createElement("a");
+ link.href = url;
+ link.download = "faculty_data.csv";
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ URL.revokeObjectURL(url);
+ }, [filteredFaculties]);
+
+ return (
+
+
+ {loading && }
+
+
Faculties of Eduversa:
+
+
setSearchQuery(e.target.value)}
+ className="manage-faculty__search-bar"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+ {paginatedFaculties.length > 0 ? (
+ paginatedFaculties.map((faculty) => (
+
toggleFavorite(faculty._id)}
+ placeholderImage={placeholderImage}
+ />
+ ))
+ ) : (
+ No faculties found.
+ )}
+
+
+
+
+ {[...Array(totalPages)].map((_, index) => (
+
+ ))}
+
+
+
+
+
+
+
+ );
+}
+
+export default Faculty;
diff --git a/pages/applicant/index.jsx b/pages/applicant/index.jsx
index 5e29b27c..b56fbabd 100644
--- a/pages/applicant/index.jsx
+++ b/pages/applicant/index.jsx
@@ -1,8 +1,10 @@
-import React, { Fragment, useEffect, useState } from "react";
+import React, { Fragment, useEffect, useState, useRef } from "react";
import { ApplicantLayout } from "@/layout";
-import { getSingleApplicantApi } from "@/functions";
import { AllLoader } from "@/components";
import Image from "next/image";
+import { withLoading, devLog, apiRequest } from "@/utils/apiUtils";
+import { useAlert } from "@/contexts/AlertContext";
+import { useRouter } from "next/router";
function generateClassName(prefix, key) {
const formattedKey = key
@@ -154,7 +156,7 @@ function renderFields(data, parentKey = "") {
"contact",
// % H3
"guardian",
- // & H4
+ // * H4
"office_address",
"first_name",
"middle_name",
@@ -359,33 +361,49 @@ function renderFields(data, parentKey = "") {
function ApplicantDashboard() {
const [profileData, setProfileData] = useState({});
const [loading, setLoading] = useState(true);
+ const { showAlert } = useAlert();
+ const router = useRouter();
+ const effectRun = useRef(false);
useEffect(() => {
- const userType = localStorage.getItem("userType");
+ const applicantId = localStorage.getItem("userid");
+ const authToken = localStorage.getItem("authToken");
+ if (effectRun.current) return;
+ effectRun.current = true;
- if (userType === "applicant") {
- const applicantId = localStorage.getItem("userid");
-
- const fetchData = async () => {
- try {
- setLoading(true);
- const response = await getSingleApplicantApi(applicantId);
-
- if (response.status === false) {
- alert(response.message);
- setLoading(false);
- return;
- }
- setProfileData(response.data);
- setLoading(false);
- } catch (error) {
- console.error("Error fetching applicant data:", error.message);
+ const fetchSingleApplicantData = async () => {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GetSingleApplicant"
+ );
+ try {
+ const response = await wrappedApiRequest(
+ `/applicant/?user_id=${applicantId}`,
+ "GET",
+ null,
+ authToken,
+ "GetSingleApplicant"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in fetching single applicant data:", response);
+ showAlert(response.message || "Failed to fetch applicant data");
+ localStorage.clear();
+ router.push("/");
+ return;
}
- };
+ setProfileData(response.data.data);
+ } catch (error) {
+ devLog("Error in fetching single applicant data:", error);
+ showAlert(error.message || "Failed to fetch applicant data");
+ localStorage.clear();
+ router.push("/");
+ }
+ };
- fetchData();
- }
- }, []);
+ fetchSingleApplicantData();
+ }, [router, showAlert]);
return (
diff --git a/pages/faculty/about/index.jsx b/pages/faculty/about/index.jsx
new file mode 100644
index 00000000..7a61e035
--- /dev/null
+++ b/pages/faculty/about/index.jsx
@@ -0,0 +1,14 @@
+import { Fragment } from "react";
+import { FacultyLayout } from "@/layout";
+import { AboutUs } from "@/containers";
+function FacultyAboutUs() {
+ return (
+
+
+
+
+
+ );
+}
+
+export default FacultyAboutUs;
diff --git a/pages/faculty/index.jsx b/pages/faculty/index.jsx
new file mode 100644
index 00000000..6362720a
--- /dev/null
+++ b/pages/faculty/index.jsx
@@ -0,0 +1,60 @@
+import { Fragment, useEffect, useState, useRef } from "react";
+import { FacultyLayout } from "@/layout";
+import { AllLoader } from "@/components";
+import { withLoading, devLog, apiRequest } from "@/utils/apiUtils";
+import { useAlert } from "@/contexts/AlertContext";
+import { useRouter } from "next/router";
+function Faculty() {
+ const [loading, setLoading] = useState(false);
+ const { showAlert } = useAlert();
+ const effectRun = useRef(false);
+ const router = useRouter();
+ useEffect(() => {
+ const facultyId = localStorage.getItem("userid");
+ const authToken = localStorage.getItem("authToken");
+ if (effectRun.current) return;
+ effectRun.current = true;
+
+ const fetchFacultyData = async () => {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GetSinglefaculty"
+ );
+ try {
+ const response = await wrappedApiRequest(
+ `/faculty/?user_id=${facultyId}`,
+ "GET",
+ null,
+ authToken,
+ "GetSinglefaculty"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in fetching single faculty data:", response);
+ showAlert(response.message || "Failed to fetch faculty data");
+ localStorage.clear();
+ router.push("/");
+ return;
+ }
+ } catch (error) {
+ devLog("Error in fetching single faculty data:", error);
+ showAlert(error.message || "Failed to fetch faculty data");
+ localStorage.clear();
+ router.push("/");
+ }
+ };
+ fetchFacultyData();
+ }, [router, showAlert]);
+
+ return (
+
+ {loading && }
+
+ Faculty Dashboard
+
+
+ );
+}
+
+export default Faculty;
diff --git a/pages/forgetpassword/index.jsx b/pages/forgetpassword/index.jsx
index 9d22b9ca..9fec7684 100644
--- a/pages/forgetpassword/index.jsx
+++ b/pages/forgetpassword/index.jsx
@@ -3,8 +3,9 @@ import Image from "next/image";
import { useRouter } from "next/router";
import { AllLoader } from "@/components";
import { LandingLayout } from "@/layout";
-import { generateOtpApi, resetPasswordApi } from "@/functions";
import Head from "next/head";
+import { useAlert } from "@/contexts/AlertContext";
+import { withLoading, devLog, apiRequest } from "@/utils/apiUtils";
function ForgetPassword() {
const [inputValue, setInputValue] = useState("");
const [newPassword, setNewPassword] = useState("");
@@ -23,35 +24,43 @@ function ForgetPassword() {
const [newPasswordFocused, setNewPasswordFocused] = useState(false);
const [confirmPasswordFocused, setConfirmPasswordFocused] = useState(false);
const router = useRouter();
+ const { showAlert } = useAlert();
+
const handleSubmit = async (e) => {
+ const authToken = localStorage.getItem("authToken");
e.preventDefault();
-
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GenerateOTP"
+ );
try {
- setLoading(true);
const userIdOrEmail = inputValue.trim();
if (!userIdOrEmail) {
alert("Please enter your userId or Email address.");
- setLoading(false);
return;
}
-
- const otpResponse = await generateOtpApi(userIdOrEmail);
- if (process.env.NODE_ENV === "development") {
- console.log(otpResponse);
- }
- alert(otpResponse.message);
-
- if (otpResponse.status) {
- setOtpResponse(otpResponse);
+ const response = await wrappedApiRequest(
+ `/account/OTP/?query=${userIdOrEmail}`,
+ "PUT",
+ null,
+ authToken,
+ "GenerateOTP"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in generating OTP:", response.message);
+ showAlert(
+ response.message || "Error generating OTP. Please try again."
+ );
+ return;
}
+ setOtpResponse(response);
+ showAlert(response.message);
} catch (error) {
- if (process.env.NODE_ENV === "development") {
- console.error("Error generating OTP:", error);
- }
- alert(otpResponse.message);
- } finally {
- setLoading(false);
+ devLog("Error generating OTP:", error.message);
+ showAlert(error.message || "An error occurred while generating OTP.");
}
};
@@ -101,52 +110,60 @@ function ForgetPassword() {
e.preventDefault();
if (!passwordMatch) {
- alert("Passwords do not match. Please make sure the passwords match.");
+ showAlert(
+ "Passwords do not match. Please make sure the passwords match."
+ );
return;
}
if (!isStrongPassword(newPassword)) {
- alert(
+ showAlert(
"Please enter a password that is at least 8 characters long, contains at least one uppercase letter, one lowercase letter, one digit, and one special character."
);
return;
}
if (!otp) {
- alert("Please enter the OTP.");
+ showAlert("Please enter the OTP sent to your email address.");
return;
}
-
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "ForgetPassword"
+ );
try {
- setLoading(true);
- const resetPasswordResponse = await resetPasswordApi(
- inputValue.trim(),
- otp,
- newPassword,
- confirmPassword
+ const userIdOrEmail = inputValue.trim();
+ const response = await wrappedApiRequest(
+ `/account/password?query=${userIdOrEmail}&otp=${otp}`,
+ "PUT",
+ {
+ password: newPassword,
+ confirm_password: confirmPassword,
+ },
+ authToken,
+ "ForgetPassword"
);
- if (process.env.NODE_ENV === "development") {
- console.log(resetPasswordResponse);
- }
- if (resetPasswordResponse.status) {
- setNewPassword("");
- setConfirmPassword("");
- setOtp("");
- setOtpResponse(null);
- alert(resetPasswordResponse.message);
- setLoading(false);
- router.push("/");
- } else {
- alert(resetPasswordResponse.message);
+ if (!response.success || !response.status) {
+ devLog("Error in updating password:", response.message);
+ showAlert(
+ response.message || "Error updating password. Please try again."
+ );
+ return;
}
+ setNewPassword("");
+ setConfirmPassword("");
+ setOtp("");
+ setOtpResponse(null);
+ showAlert(response.data.message);
+ router.push("/");
} catch (error) {
- if (process.env.NODE_ENV === "development") {
- console.error("Error updating password:", error.message);
- }
- alert("An error occurred while updating the password.");
- } finally {
- setLoading(false);
+ devLog("Error updating password:", error.message);
+ showAlert(
+ error.message || "An error occurred while updating the password."
+ );
}
};
diff --git a/pages/forgetusername/index.jsx b/pages/forgetusername/index.jsx
index 6309e538..594b70f0 100644
--- a/pages/forgetusername/index.jsx
+++ b/pages/forgetusername/index.jsx
@@ -3,83 +3,100 @@ import Image from "next/image";
import { useRouter } from "next/router";
import { LandingLayout } from "@/layout";
import { AllLoader } from "@/components";
-import { generateOtpApi, resetUserNameApi } from "@/functions";
+import { resetUserNameApi } from "@/functions";
import Head from "next/head";
+import { useAlert } from "@/contexts/AlertContext";
+import { withLoading, devLog, apiRequest } from "@/utils/apiUtils";
+
function ForgetUsername() {
const router = useRouter();
const [loading, setLoading] = useState(false);
const [inputValue, setInputValue] = useState("");
const [otp, setOtp] = useState("");
const [otpResponse, setOtpResponse] = useState(null);
+ const { showAlert } = useAlert();
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
const handleSubmit = async (e) => {
+ const authToken = localStorage.getItem("authToken");
e.preventDefault();
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "GenerateOTP"
+ );
try {
- setLoading(true);
const userIdOrEmail = inputValue.trim();
if (!userIdOrEmail) {
- alert("Please enter your Email address.");
+ showAlert("Please enter your Email address.");
setLoading(false);
return;
}
if (!isValidEmail(userIdOrEmail)) {
- alert("Please enter a valid Email address.");
+ showAlert("Please enter a valid Email address.");
setLoading(false);
return;
}
-
- const otpResponse = await generateOtpApi(userIdOrEmail);
- if (process.env.NODE_ENV === "development") {
- console.log(otpResponse);
- }
- alert(otpResponse.message);
-
- if (otpResponse.status) {
- setOtpResponse(otpResponse);
+ const response = await wrappedApiRequest(
+ `/account/OTP/?query=${userIdOrEmail}`,
+ "PUT",
+ null,
+ authToken,
+ "GenerateOTP"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in generating OTP:", response.message);
+ showAlert(
+ response.message || "Error generating OTP. Please try again."
+ );
+ return;
}
+ setOtpResponse(response);
+ showAlert(response.message);
} catch (error) {
- if (process.env.NODE_ENV === "development") {
- console.error("Error generating OTP:", error);
- }
- alert("An error occurred while generating OTP.");
- } finally {
- setLoading(false);
+ devLog("Error generating OTP:", error.message);
+ showAlert(error.message || "An error occurred while generating OTP.");
}
};
const handleVerifyOtp = async () => {
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "ForgetUsername"
+ );
try {
- setLoading(true);
if (!otp) {
- alert("Please enter the OTP.");
+ showAlert("Please enter the OTP.");
setLoading(false);
return;
}
- const verifyOtpResponse = await resetUserNameApi(inputValue.trim(), otp);
- if (process.env.NODE_ENV === "development") {
- console.log(verifyOtpResponse);
- }
-
- if (verifyOtpResponse.status) {
- alert(verifyOtpResponse.message);
- router.push("/");
- } else {
- alert("OTP verification failed. Please try again.");
+ const userIdOrEmail = inputValue.trim();
+ const response = await wrappedApiRequest(
+ `/account/userid?query=${userIdOrEmail}&otp=${otp}`,
+ "GET",
+ null,
+ authToken,
+ "ForgetUsername"
+ );
+ if (!response.success || !response.status) {
+ devLog("Error in verifying OTP:", response.message);
+ showAlert(response.message || "Error verifying OTP. Please try again.");
+ return;
}
+ showAlert(response.message || "OTP verified successfully.");
+ router.push("/");
} catch (error) {
- if (process.env.NODE_ENV === "development") {
- console.error("Error verifying OTP:", error);
- }
- alert("An error occurred while verifying OTP.");
- } finally {
- setLoading(false);
+ devLog("Error verifying OTP:", error.message);
+ showAlert(error.message || "An error occurred while verifying OTP.");
}
};
diff --git a/pages/index.jsx b/pages/index.jsx
index c7ac98df..b924fb1c 100644
--- a/pages/index.jsx
+++ b/pages/index.jsx
@@ -1,154 +1,141 @@
-import { Fragment, useEffect, useState } from "react";
+import { Fragment, useState, useEffect } from "react";
import Image from "next/image";
import Link from "next/link";
-import Head from "next/head";
import { useRouter } from "next/router";
import { LandingLayout } from "@/layout";
-import { loginUser, logIntoAccountWithSocialPlatform } from "@/functions";
+import { withLoading, devLog, apiRequest } from "@/utils/apiUtils";
import { AllLoader } from "@/components";
import { useSession, signIn, signOut } from "next-auth/react";
+import Head from "next/head";
+import { useAlert } from "@/contexts/AlertContext";
+
function Login() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const router = useRouter();
const { data: session } = useSession();
+ const { showAlert } = useAlert();
useEffect(() => {
const platformName = localStorage.getItem("platformName");
if (session) {
- console.log("session--->", session);
+ if (process.env.NODE_ENV === "development") {
+ devLog("Session detected:", session);
+ }
+
setLoading(true);
- fetch(
- `https://eduversa-api.onrender.com/account/auth/platform?platform=${platformName}`,
- {
- method: "PUT",
- headers: {
- "Content-Type": "application/json",
- },
- body: JSON.stringify(session),
- }
- )
- .then((response) => response.json())
- .then(async (res) => {
- console.log(res);
- alert(res.message);
- if (!res.status) {
- setLoading(false);
- return;
- }
- localStorage.removeItem("platformName");
- localStorage.setItem("authToken", res.authToken);
- localStorage.setItem("email", res.data.email);
- localStorage.setItem("userType", res.data.type);
- localStorage.setItem("userid", res.data.user_id);
- if (res.data.type === "applicant") {
- localStorage.setItem(
- "applicant_profile",
- JSON.stringify(res.profileData)
- );
- }
- if (process.env.NODE_ENV === "development") {
- console.log("AuthToken", localStorage.getItem("authToken"));
- console.log("Email", localStorage.getItem("email"));
- console.log("UserType", localStorage.getItem("userType"));
- console.log("UserId", localStorage.getItem("userid"));
- }
- alert(res.message);
- if (res.data.type === "applicant") {
- await signOut({ callbackUrl: "/applicant" });
- } else if (res.data.type === "student") {
- await signOut({ callbackUrl: "/student" });
- } else if (res.data.type === "faculty") {
- alert("Faculty is not ready yet");
- localStorage.clear();
- } else if (res.data.type === "admin") {
- await signOut({ callbackUrl: "/admin" });
- } else {
- alert("Invalid User Type");
- }
- })
- .catch((error) => console.log(error));
+ authenticatePlatformUser(platformName, session)
+ .catch((error) => devLog("Error in platform auth:", error))
+ .finally(() => setLoading(false));
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [session, showAlert]);
+
+ const authenticatePlatformUser = async (platformName, sessionData) => {
+ const response = await apiRequest(
+ `/account/auth/platform?platform=${platformName}`,
+ "POST",
+ sessionData
+ );
+
+ devLog("Auth platform response:", response);
+ showAlert(response.message);
+
+ if (!response.status) {
+ return;
}
- }, [session]);
+
+ localStorage.removeItem("platformName");
+ storeUserData(response.data);
+
+ await signOut({ callbackUrl: "/" });
+ };
+
+ const storeUserData = (data) => {
+ localStorage.setItem("authToken", data.authToken);
+ localStorage.setItem("email", data.data.email);
+ localStorage.setItem("userType", data.data.type);
+ localStorage.setItem("userid", data.data.user_id);
+ };
const handleSubmit = async (e) => {
e.preventDefault();
+ const wrappedApiRequest = withLoading(
+ apiRequest,
+ setLoading,
+ showAlert,
+ "Login"
+ );
+
try {
- setLoading(true);
- const apiResponse = await loginUser(username, password);
- if (apiResponse.status === false) {
- if (process.env.NODE_ENV === "development") {
- console.log("Login data:", apiResponse);
- }
- alert(apiResponse.message);
- setLoading(false);
+ const response = await wrappedApiRequest(
+ "/account/auth",
+ "POST",
+ {
+ user_id: username,
+ password,
+ },
+ localStorage.getItem("authToken"),
+ "Login"
+ );
+
+ if (!response.success || !response.status) {
+ devLog("Login error response:", response);
+ showAlert(response.message || "Login failed. Please try again.");
return;
}
- if (process.env.NODE_ENV === "development") {
- console.log("Login data:", apiResponse);
- }
- localStorage.setItem("authToken", apiResponse.authToken);
- localStorage.setItem("email", apiResponse.data.email);
- localStorage.setItem("userType", apiResponse.data.type);
- localStorage.setItem("userid", apiResponse.data.user_id);
- localStorage.setItem("security_token", apiResponse.data.security_token);
- if (apiResponse.data.type === "applicant") {
- localStorage.setItem(
- "applicant_profile",
- JSON.stringify(apiResponse.profileData)
- );
- }
- if (process.env.NODE_ENV === "development") {
- console.log("AuthToken", localStorage.getItem("authToken"));
- console.log("Email", localStorage.getItem("email"));
- console.log("UserType", localStorage.getItem("userType"));
- console.log("UserId", localStorage.getItem("userid"));
- }
- alert(apiResponse.message);
- setLoading(false);
- if (apiResponse.data.type === "applicant") {
+
+ // devLog("Login success data:", response.data);
+ storeUserData(response.data);
+
+ navigateUser(response.data.data.type);
+ } catch (error) {
+ devLog("Global Error:", error);
+ showAlert(
+ error.message || "An unexpected error occurred. Please try again."
+ );
+ }
+ };
+
+ // Navigate user based on user type
+ const navigateUser = (userType) => {
+ showAlert("Logged In Successfully!");
+
+ switch (userType) {
+ case "applicant":
router.push("/applicant");
- } else if (apiResponse.data.type === "student") {
+ break;
+ case "student":
router.push("/student");
- } else if (apiResponse.data.type === "faculty") {
- alert("Faculty is not ready yet");
- localStorage.clear();
- } else if (apiResponse.data.type === "admin") {
+ break;
+ case "faculty":
+ router.push("/faculty");
+ break;
+ case "admin":
router.push("/admin");
- } else {
- alert("Invalid User Type");
- }
- } catch (error) {
- if (process.env.NODE_ENV === "development") {
- console.error("Error in login:", error);
- }
+ break;
+ case "superadmin":
+ router.push("/superadmin");
+ default:
+ showAlert("Invalid User Type");
+ localStorage.clear();
+ window.location.reload();
+ break;
}
};
- const handleSocialLoginClick = (provider) => {
- alert(`Login with ${provider} is coming soon!`);
- console.log("Session:", session);
- console.log("signIn Fnction:", signIn);
- console.log("signOut Fnction:", signOut);
- console.log("useSession Function:", useSession);
- };
- const handleGoogleSignIn = async () => {
- await signIn("google");
- localStorage.setItem("platformName", "google");
+ const handleSocialLogin = async (provider) => {
+ await signIn(provider);
+ localStorage.setItem("platformName", provider);
};
- const handleGithubSignIn = async () => {
- await signIn("github");
- localStorage.setItem("platformName", "github");
- };
- const handleFacebookSignIn = async () => {
- await signIn("facebook");
- localStorage.setItem("platformName", "facebook");
+
+ const handleSocialLoginClick = (provider) => {
+ showAlert(`Login with ${provider} is coming soon!`);
+ devLog("Social provider login attempt:", provider);
};
- if (process.env.NODE_ENV === "development") {
- console.log("Session:", session);
- }
+
return (
@@ -165,7 +152,7 @@ function Login() {
Login
- Step Inside your Academic Realm
+ Step Inside your Academic Realm{" "}
๐
@@ -186,6 +173,7 @@ function Login() {
value={username}
onChange={(e) => setUsername(e.target.value)}
className="username-input"
+ required
/>
@@ -202,6 +190,7 @@ function Login() {
value={password}
onChange={(e) => setPassword(e.target.value)}
className="password-input"
+ required
/>
@@ -214,16 +203,16 @@ function Login() {
height={25}
width={25}
className="google-icon"
- onClick={handleGoogleSignIn}
- >
+ onClick={() => handleSocialLogin("google")}
+ />
+ onClick={() => handleSocialLogin("facebook")}
+ />
handleSocialLoginClick("Twitter")}
- >
+ />
handleSocialLoginClick("LinkedIn")}
- >
+ />
+ onClick={() => handleSocialLogin("github")}
+ />
+