diff --git a/admin/src/App.jsx b/admin/src/App.jsx
index 3c594a3..ce967ba 100644
--- a/admin/src/App.jsx
+++ b/admin/src/App.jsx
@@ -1,6 +1,5 @@
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Sidebar from "./components/Sidebar";
-import BranchRepresentatives from "./pages/BranchRepresentatives";
import Students from "./pages/Students";
import Courses from "./pages/Courses";
import CourseLinking from "./pages/CourseLinking";
@@ -20,7 +19,7 @@ function App() {
path="/admin/"
element={
-
+
}
/>
diff --git a/admin/src/apis/br.js b/admin/src/apis/br.js
index e59aada..8105f46 100644
--- a/admin/src/apis/br.js
+++ b/admin/src/apis/br.js
@@ -86,3 +86,26 @@ export const uploadBRs = async (file) => {
throw error;
}
};
+// Delete BR
+export const deleteBR = async(email) =>{
+ try {
+ const response = await
+ fetch(`${API_BASE_URL}api/br/delete`,{
+ method: "DELETE",
+ credentials: "include",
+ headers:{
+ "Content-Type":"application/json",
+ Authorization:"Bearer admin-coursehub-cc23-golang"},
+ body: JSON.stringify({email:email}),
+ });
+ const result = await response.json();
+ if(!response.ok){
+ throw new Error(result.error || result.message || "Failed to delete BR");
+ }
+ return result ;
+ }
+ catch (error){
+ console.error("Error deleting single BR:" , error);
+ throw error;
+ }
+ };
\ No newline at end of file
diff --git a/admin/src/components/Sidebar.jsx b/admin/src/components/Sidebar.jsx
index 352f03d..fd8a001 100644
--- a/admin/src/components/Sidebar.jsx
+++ b/admin/src/components/Sidebar.jsx
@@ -4,7 +4,6 @@ import { FaBook, FaUsers, FaLayerGroup, FaLink, FaUserGraduate } from "react-ico
import { adminLogout } from "@/apis/auth";
const navItems = [
- { label: "Branch Representatives", to: "/admin/", icon: FaUsers },
{ label: "Students", to: "/admin/students", icon: FaUserGraduate },
{ label: "Courses", to: "/admin/courses", icon: FaBook },
{ label: "Course Linking", to: "/admin/course-linking", icon: FaLink },
diff --git a/admin/src/components/UploadBRs.jsx b/admin/src/components/UploadBRs.jsx
deleted file mode 100644
index 8ab7405..0000000
--- a/admin/src/components/UploadBRs.jsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import React, { useState } from "react";
-import { Modal, ModalHeader, ModalFooter, ModalBody, ModalCloseButton } from "./ui/modal";
-import { uploadBRs } from "../apis/br";
-
-const UploadBRs = ({ onUpload, onClose }) => {
- const [file, setFile] = useState(null);
- const [error, setError] = useState(null);
- const [success, setSuccess] = useState(null);
- const [warnings, setWarnings] = useState(null);
-
- const handleFileChange = (e) => {
- setFile(e.target.files[0]);
- // Clear previous messages when new file is selected
- setError(null);
- setSuccess(null);
- setWarnings(null);
- };
-
- const handleSubmit = async (e) => {
- e.preventDefault();
- if (!file) {
- setError("Please select a file to upload.");
- return;
- }
-
- // Validate file type
- if (!file.name.toLowerCase().endsWith(".csv")) {
- setError("Please upload a CSV file.");
- return;
- }
-
- try {
- const response = await uploadBRs(file);
- setSuccess(response.message);
- setError(null);
- setWarnings(null);
- if (onUpload) {
- onUpload();
- }
- } catch (err) {
- // Handle partial success (409 status)
- if (err.existingEmails || err.notInUsers) {
- let warningMessage = "";
- if (err.existingEmails && err.existingEmails.length > 0) {
- warningMessage += `Already existing BRs: ${err.existingEmails.join(", ")}. `;
- }
- if (err.notInUsers && err.notInUsers.length > 0) {
- warningMessage += `Emails not found in users: ${err.notInUsers.join(", ")}.`;
- }
- setWarnings(warningMessage);
- setError(null);
- setSuccess("Partial upload completed.");
- if (onUpload) {
- onUpload();
- }
- } else {
- setError(err.error || err.message || "An error occurred during file upload.");
- setSuccess(null);
- setWarnings(null);
- }
- }
- };
-
- return (
-
- Upload BRs
-
-
-
- Upload a CSV file to update the BR list. The CSV should have one column named
- "email".
-
-
- {error && (
-
- {error}
-
- )}
- {success && (
-
- {success}
-
- )}
- {warnings && (
-
- Warning: {warnings}
-
- )}
-
-
-
-
-
- );
-};
-
-export default UploadBRs;
diff --git a/admin/src/components/brTable.jsx b/admin/src/components/brTable.jsx
index a01a6d3..d1b2dcb 100644
--- a/admin/src/components/brTable.jsx
+++ b/admin/src/components/brTable.jsx
@@ -1,6 +1,6 @@
import React from "react";
-const BrTable = ({ brs }) => {
+const BrTable = ({ brs , onDelete }) => {
return (
@@ -25,6 +25,9 @@ const BrTable = ({ brs }) => {
Semester
|
+
+ Actions
+ |
@@ -41,6 +44,13 @@ const BrTable = ({ brs }) => {
{person.semester}
|
+
+
+ |
+
))}
diff --git a/admin/src/pages/BranchRepresentatives.jsx b/admin/src/pages/BranchRepresentatives.jsx
deleted file mode 100644
index a6b244a..0000000
--- a/admin/src/pages/BranchRepresentatives.jsx
+++ /dev/null
@@ -1,140 +0,0 @@
-import React, { useState, useEffect } from "react";
-import BrTable from "../components/brTable";
-import UploadBRs from "../components/UploadBRs";
-import { fetchBRs, createBR } from "@/apis/br";
-import { FaPlus, FaUpload } from "react-icons/fa";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-
-export default function BranchRepresentatives() {
- const [brs, setBrs] = useState([]);
- const [loading, setLoading] = useState(true);
- const [error, setError] = useState(null);
- const [showUploadModal, setShowUploadModal] = useState(false);
-
- // Single BR states
- const [newBrEmail, setNewBrEmail] = useState("");
- const [addingBr, setAddingBr] = useState(false);
- const [addError, setAddError] = useState(null);
- const [addSuccess, setAddSuccess] = useState(null);
-
- const loadBRs = async () => {
- try {
- setLoading(true);
- const response = await fetchBRs();
- setBrs(response.brs);
- setLoading(false);
- } catch (err) {
- setError(err.message || "An error occurred while fetching BRs.");
- setLoading(false);
- }
- };
-
- useEffect(() => {
- loadBRs();
- }, []);
-
- const handleUploadSuccess = () => {
- setShowUploadModal(false);
- loadBRs();
- };
-
- const handleAddSingleBR = async (e) => {
- e.preventDefault();
- setAddError(null);
- setAddSuccess(null);
-
- if (!newBrEmail.trim()) {
- setAddError("Please enter an email address.");
- return;
- }
-
- if (!newBrEmail.includes("@")) {
- setAddError("Please enter a valid email address.");
- return;
- }
-
- setAddingBr(true);
- try {
- await createBR(newBrEmail.trim());
- setAddSuccess(`Successfully added ${newBrEmail}`);
- setNewBrEmail("");
- loadBRs(); // Refresh the list
- } catch (err) {
- setAddError(err.message || "Failed to add BR.");
- } finally {
- setAddingBr(false);
- // Clear success message after 3 seconds
- if (!addError) {
- setTimeout(() => setAddSuccess(null), 3000);
- }
- }
- };
-
- return (
-
-
-
-
Branch Representatives
-
Manage and upload BR data
-
-
-
-
-
-
-
-
- {/* Status Messages for Single Add */}
- {(addError || addSuccess) && (
-
- {addError || addSuccess}
-
- )}
-
-
- {loading &&
Loading...
}
- {error &&
{error}
}
- {!loading && !error &&
}
-
-
- {showUploadModal && (
-
setShowUploadModal(false)}
- />
- )}
-
- );
-}
diff --git a/admin/src/pages/Students.jsx b/admin/src/pages/Students.jsx
index f4f4814..4119455 100644
--- a/admin/src/pages/Students.jsx
+++ b/admin/src/pages/Students.jsx
@@ -4,8 +4,9 @@ import {
searchStudents,
refreshStudentCourses,
deleteStudent,
- semesterReset,
+ semesterReset,
} from "@/apis/student";
+import { deleteBR } from "@/apis/br";
import AddBRs from "../components/AddBRs";
import { FaRedo, FaSearch, FaSync, FaTrash, FaChevronDown, FaChevronUp, FaPlus, FaUserGraduate, FaUsers } from "react-icons/fa";
@@ -115,7 +116,11 @@ export default function Students() {
const handleRowDelete = async (id) => {
setRowLoadingId(id);
try {
+ const student = students.find(stud => stud._id===id);
await deleteStudent(id);
+ if(student && student.isBR) {
+ await deleteBR(student.email);
+ }
loadStudents();
} catch (err) {
setError(err.message || "Failed to delete student.");
@@ -125,6 +130,25 @@ export default function Students() {
}
};
+ const handleRemoveBR = async(id) =>{
+ setRowLoadingId(id);
+ try{
+ const student = students.find(stud => stud._id ===id);
+ if(student){
+ await deleteBR(student.email);
+ }
+ loadStudents();
+ }
+ catch(err){
+ setError(err.message || "Failed to remove BR privileges")
+ }
+ finally{
+ setRowLoadingId(null);
+ setRowConfirm(null);
+ }
+ };
+
+
const handleSemesterReset = async () => {
setResetLoading(true);
setResetError(null);
@@ -298,18 +322,34 @@ export default function Students() {
)}
-
+
+ {showBROnly && student.isBR && (
+
+ )}
+
@@ -374,10 +414,16 @@ export default function Students() {
message={
rowConfirm.type === "delete"
? `Delete ${rowConfirm.label}? This will permanently remove their student record and cannot be undone.`
+ : rowConfirm.type === "removeBR"
+ ? `Remove BR privileges from ${rowConfirm.label}? They will remain as a student but lose Branch Representative access. `
: `Reset courses for ${rowConfirm.label}? Their courses will be re-fetched the next time they log in.`
}
loading={rowLoadingId === rowConfirm.id}
- onConfirm={() => rowConfirm.type === "delete" ? handleRowDelete(rowConfirm.id) : handleRowRefresh(rowConfirm.id)}
+ onConfirm={() => rowConfirm.type === "delete"
+ ? handleRowDelete(rowConfirm.id)
+ : rowConfirm.type === "removeBR"
+ ? handleRemoveBR(rowConfirm.id)
+ : handleRowRefresh(rowConfirm.id)}
onCancel={() => setRowConfirm(null)}
/>
)}
diff --git a/client/package-lock.json b/client/package-lock.json
index 0a3109f..15e7897 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -489,6 +489,40 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.16.tgz",
+ "integrity": "sha512-nyB6CH++2mSgx3GbnrJsZSxzne5K0HMyNIWafDHqYy7IwxFc4fd/CgHVZXr8Eh+Q3KbIAcAe3vGyqIPhGblvMQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.16.tgz",
+ "integrity": "sha512-SDLfP1uoB0HZ14CdVYgagllgrG7Mdxhkt4jDJOKl/MldKrkQ6vDJMZKl2+5XsEY/Lzz37fjgLQoJBGuAw/x8kQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
@@ -917,6 +951,57 @@
"esbuild-windows-arm64": "0.15.16"
}
},
+ "node_modules/esbuild-android-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.16.tgz",
+ "integrity": "sha512-Vwkv/sT0zMSgPSVO3Jlt1pUbnZuOgtOQJkJkyyJFAlLe7BiT8e9ESzo0zQSx4c3wW4T6kGChmKDPMbWTgtliQA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-android-arm64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.16.tgz",
+ "integrity": "sha512-lqfKuofMExL5niNV3gnhMUYacSXfsvzTa/58sDlBET/hCOG99Zmeh+lz6kvdgvGOsImeo6J9SW21rFCogNPLxg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-darwin-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.16.tgz",
+ "integrity": "sha512-wo2VWk/n/9V2TmqUZ/KpzRjCEcr00n7yahEdmtzlrfQ3lfMCf3Wa+0sqHAbjk3C6CKkR3WKK/whkMq5Gj4Da9g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/esbuild-darwin-arm64": {
"version": "0.15.16",
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.16.tgz",
@@ -934,6 +1019,278 @@
"node": ">=12"
}
},
+ "node_modules/esbuild-freebsd-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.16.tgz",
+ "integrity": "sha512-UzIc0xlRx5x9kRuMr+E3+hlSOxa/aRqfuMfiYBXu2jJ8Mzej4lGL7+o6F5hzhLqWfWm1GWHNakIdlqg1ayaTNQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-freebsd-arm64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.16.tgz",
+ "integrity": "sha512-8xyiYuGc0DLZphFQIiYaLHlfoP+hAN9RHbE+Ibh8EUcDNHAqbQgUrQg7pE7Bo00rXmQ5Ap6KFgcR0b4ALZls1g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-32": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.16.tgz",
+ "integrity": "sha512-iGijUTV+0kIMyUVoynK0v+32Oi8yyp0xwMzX69GX+5+AniNy/C/AL1MjFTsozRp/3xQPl7jVux/PLe2ds10/2w==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.16.tgz",
+ "integrity": "sha512-tuSOjXdLw7VzaUj89fIdAaQT7zFGbKBcz4YxbWrOiXkwscYgE7HtTxUavreBbnRkGxKwr9iT/gmeJWNm4djy/g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.16.tgz",
+ "integrity": "sha512-XKcrxCEXDTOuoRj5l12tJnkvuxXBMKwEC5j0JISw3ziLf0j4zIwXbKbTmUrKFWbo6ZgvNpa7Y5dnbsjVvH39bQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-arm64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.16.tgz",
+ "integrity": "sha512-mPYksnfHnemNrvjrDhZyixL/AfbJN0Xn9S34ZOHYdh6/jJcNd8iTsv3JwJoEvTJqjMggjMhGUPJAdjnFBHoH8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-mips64le": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.16.tgz",
+ "integrity": "sha512-kSJO2PXaxfm0pWY39+YX+QtpFqyyrcp0ZeI8QPTrcFVQoWEPiPVtOfTZeS3ZKedfH+Ga38c4DSzmKMQJocQv6A==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-ppc64le": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.16.tgz",
+ "integrity": "sha512-NimPikwkBY0yGABw6SlhKrtT35sU4O23xkhlrTT/O6lSxv3Pm5iSc6OYaqVAHWkLdVf31bF4UDVFO+D990WpAA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-riscv64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.16.tgz",
+ "integrity": "sha512-ty2YUHZlwFOwp7pR+J87M4CVrXJIf5ZZtU/umpxgVJBXvWjhziSLEQxvl30SYfUPq0nzeWKBGw5i/DieiHeKfw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-linux-s390x": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.16.tgz",
+ "integrity": "sha512-VkZaGssvPDQtx4fvVdZ9czezmyWyzpQhEbSNsHZZN0BHvxRLOYAQ7sjay8nMQwYswP6O2KlZluRMNPYefFRs+w==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-netbsd-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.16.tgz",
+ "integrity": "sha512-ElQ9rhdY51et6MJTWrCPbqOd/YuPowD7Cxx3ee8wlmXQQVW7UvQI6nSprJ9uVFQISqSF5e5EWpwWqXZsECLvXg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-openbsd-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.16.tgz",
+ "integrity": "sha512-KgxMHyxMCT+NdLQE1zVJEsLSt2QQBAvJfmUGDmgEq8Fvjrf6vSKB00dVHUEDKcJwMID6CdgCpvYNt999tIYhqA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-sunos-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.16.tgz",
+ "integrity": "sha512-exSAx8Phj7QylXHlMfIyEfNrmqnLxFqLxdQF6MBHPdHAjT7fsKaX6XIJn+aQEFiOcE4X8e7VvdMCJ+WDZxjSRQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-32": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.16.tgz",
+ "integrity": "sha512-zQgWpY5pUCSTOwqKQ6/vOCJfRssTvxFuEkpB4f2VUGPBpdddZfdj8hbZuFRdZRPIVHvN7juGcpgCA/XCF37mAQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.16.tgz",
+ "integrity": "sha512-HjW1hHRLSncnM3MBCP7iquatHVJq9l0S2xxsHHj4yzf4nm9TU4Z7k4NkeMlD/dHQ4jPlQQhwcMvwbJiOefSuZw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/esbuild-windows-arm64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.16.tgz",
+ "integrity": "sha512-oCcUKrJaMn04Vxy9Ekd8x23O8LoU01+4NOkQ2iBToKgnGj5eo1vU9i27NQZ9qC8NFZgnQQZg5oZWAejmbsppNA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -2179,6 +2536,20 @@
"to-fast-properties": "^2.0.0"
}
},
+ "@esbuild/android-arm": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.16.tgz",
+ "integrity": "sha512-nyB6CH++2mSgx3GbnrJsZSxzne5K0HMyNIWafDHqYy7IwxFc4fd/CgHVZXr8Eh+Q3KbIAcAe3vGyqIPhGblvMQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@esbuild/linux-loong64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.16.tgz",
+ "integrity": "sha512-SDLfP1uoB0HZ14CdVYgagllgrG7Mdxhkt4jDJOKl/MldKrkQ6vDJMZKl2+5XsEY/Lzz37fjgLQoJBGuAw/x8kQ==",
+ "dev": true,
+ "optional": true
+ },
"@jridgewell/gen-mapping": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
@@ -2477,6 +2848,27 @@
"esbuild-windows-arm64": "0.15.16"
}
},
+ "esbuild-android-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.16.tgz",
+ "integrity": "sha512-Vwkv/sT0zMSgPSVO3Jlt1pUbnZuOgtOQJkJkyyJFAlLe7BiT8e9ESzo0zQSx4c3wW4T6kGChmKDPMbWTgtliQA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-android-arm64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.16.tgz",
+ "integrity": "sha512-lqfKuofMExL5niNV3gnhMUYacSXfsvzTa/58sDlBET/hCOG99Zmeh+lz6kvdgvGOsImeo6J9SW21rFCogNPLxg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-darwin-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.16.tgz",
+ "integrity": "sha512-wo2VWk/n/9V2TmqUZ/KpzRjCEcr00n7yahEdmtzlrfQ3lfMCf3Wa+0sqHAbjk3C6CKkR3WKK/whkMq5Gj4Da9g==",
+ "dev": true,
+ "optional": true
+ },
"esbuild-darwin-arm64": {
"version": "0.15.16",
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.16.tgz",
@@ -2484,6 +2876,118 @@
"dev": true,
"optional": true
},
+ "esbuild-freebsd-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.16.tgz",
+ "integrity": "sha512-UzIc0xlRx5x9kRuMr+E3+hlSOxa/aRqfuMfiYBXu2jJ8Mzej4lGL7+o6F5hzhLqWfWm1GWHNakIdlqg1ayaTNQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-freebsd-arm64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.16.tgz",
+ "integrity": "sha512-8xyiYuGc0DLZphFQIiYaLHlfoP+hAN9RHbE+Ibh8EUcDNHAqbQgUrQg7pE7Bo00rXmQ5Ap6KFgcR0b4ALZls1g==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-32": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.16.tgz",
+ "integrity": "sha512-iGijUTV+0kIMyUVoynK0v+32Oi8yyp0xwMzX69GX+5+AniNy/C/AL1MjFTsozRp/3xQPl7jVux/PLe2ds10/2w==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.16.tgz",
+ "integrity": "sha512-tuSOjXdLw7VzaUj89fIdAaQT7zFGbKBcz4YxbWrOiXkwscYgE7HtTxUavreBbnRkGxKwr9iT/gmeJWNm4djy/g==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-arm": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.16.tgz",
+ "integrity": "sha512-XKcrxCEXDTOuoRj5l12tJnkvuxXBMKwEC5j0JISw3ziLf0j4zIwXbKbTmUrKFWbo6ZgvNpa7Y5dnbsjVvH39bQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-arm64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.16.tgz",
+ "integrity": "sha512-mPYksnfHnemNrvjrDhZyixL/AfbJN0Xn9S34ZOHYdh6/jJcNd8iTsv3JwJoEvTJqjMggjMhGUPJAdjnFBHoH8A==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-mips64le": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.16.tgz",
+ "integrity": "sha512-kSJO2PXaxfm0pWY39+YX+QtpFqyyrcp0ZeI8QPTrcFVQoWEPiPVtOfTZeS3ZKedfH+Ga38c4DSzmKMQJocQv6A==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-ppc64le": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.16.tgz",
+ "integrity": "sha512-NimPikwkBY0yGABw6SlhKrtT35sU4O23xkhlrTT/O6lSxv3Pm5iSc6OYaqVAHWkLdVf31bF4UDVFO+D990WpAA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-riscv64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.16.tgz",
+ "integrity": "sha512-ty2YUHZlwFOwp7pR+J87M4CVrXJIf5ZZtU/umpxgVJBXvWjhziSLEQxvl30SYfUPq0nzeWKBGw5i/DieiHeKfw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-linux-s390x": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.16.tgz",
+ "integrity": "sha512-VkZaGssvPDQtx4fvVdZ9czezmyWyzpQhEbSNsHZZN0BHvxRLOYAQ7sjay8nMQwYswP6O2KlZluRMNPYefFRs+w==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-netbsd-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.16.tgz",
+ "integrity": "sha512-ElQ9rhdY51et6MJTWrCPbqOd/YuPowD7Cxx3ee8wlmXQQVW7UvQI6nSprJ9uVFQISqSF5e5EWpwWqXZsECLvXg==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-openbsd-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.16.tgz",
+ "integrity": "sha512-KgxMHyxMCT+NdLQE1zVJEsLSt2QQBAvJfmUGDmgEq8Fvjrf6vSKB00dVHUEDKcJwMID6CdgCpvYNt999tIYhqA==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-sunos-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.16.tgz",
+ "integrity": "sha512-exSAx8Phj7QylXHlMfIyEfNrmqnLxFqLxdQF6MBHPdHAjT7fsKaX6XIJn+aQEFiOcE4X8e7VvdMCJ+WDZxjSRQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-32": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.16.tgz",
+ "integrity": "sha512-zQgWpY5pUCSTOwqKQ6/vOCJfRssTvxFuEkpB4f2VUGPBpdddZfdj8hbZuFRdZRPIVHvN7juGcpgCA/XCF37mAQ==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.16.tgz",
+ "integrity": "sha512-HjW1hHRLSncnM3MBCP7iquatHVJq9l0S2xxsHHj4yzf4nm9TU4Z7k4NkeMlD/dHQ4jPlQQhwcMvwbJiOefSuZw==",
+ "dev": true,
+ "optional": true
+ },
+ "esbuild-windows-arm64": {
+ "version": "0.15.16",
+ "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.16.tgz",
+ "integrity": "sha512-oCcUKrJaMn04Vxy9Ekd8x23O8LoU01+4NOkQ2iBToKgnGj5eo1vU9i27NQZ9qC8NFZgnQQZg5oZWAejmbsppNA==",
+ "dev": true,
+ "optional": true
+ },
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
diff --git a/client/yarn.lock b/client/yarn.lock
index a4ff28e..c1270a6 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -492,10 +492,10 @@ electron-to-chromium@^1.4.251:
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz"
integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==
-esbuild-darwin-arm64@0.15.16:
+esbuild-windows-64@0.15.16:
version "0.15.16"
- resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.16.tgz"
- integrity sha512-fMXaUr5ou0M4WnewBKsspMtX++C1yIa3nJ5R2LSbLCfJT3uFdcRoU/NZjoM4kOMKyOD9Sa/2vlgN8G07K3SJnw==
+ resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.16.tgz"
+ integrity sha512-HjW1hHRLSncnM3MBCP7iquatHVJq9l0S2xxsHHj4yzf4nm9TU4Z7k4NkeMlD/dHQ4jPlQQhwcMvwbJiOefSuZw==
esbuild@^0.15.9:
version "0.15.16"
@@ -566,11 +566,6 @@ form-data@^4.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"
-fsevents@~2.3.2:
- version "2.3.2"
- resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
- integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
-
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
diff --git a/server/modules/br/br.controller.js b/server/modules/br/br.controller.js
index bd9a958..f5acf35 100644
--- a/server/modules/br/br.controller.js
+++ b/server/modules/br/br.controller.js
@@ -26,7 +26,7 @@ const updateBRs = async (req, res) => {
if (user) {
if (!user.isBR) {
user.isBR = true;
- await fetchCoursesForBr(user.rollNumber);
+ fetchCoursesForBr(user.rollNumber).catch((err)=>logger.error(err));
await user.save();
}
await BR.updateOne(
@@ -65,7 +65,7 @@ const createBR = async (req, res) => {
user.isBR = true;
await user.save();
}
- await fetchCoursesForBr(user.rollNumber);
+ fetchCoursesForBr(user.rollNumber).catch((err)=>logger.error(err));
}
const br = await BR.create({ email: normalizedEmail });
@@ -92,6 +92,17 @@ const deleteBR = async (req, res) => {
const br = await BR.findOneAndDelete({ email: normalizedEmail });
if (!br) return res.status(404).json({ error: "BR not found" });
+
+ // const user = await findUserByEmailInsensitive(normalizedEmail);
+ // if (user) {
+ // user.isBR = false;
+ // await user.save();
+ // }
+ await User.updateOne(
+ { email: normalizedEmail },
+ { $set: { isBR: false } },
+ { collation: { locale: "en", strength: 2 } }
+ );
res.status(200).json({ message: "BR deleted successfully" });
} catch (error) {
|