├── backend ├── firebase.json ├── functions │ ├── .gitignore │ ├── package.json │ └── index.js ├── .firebaserc ├── package.json └── .gitignore ├── frontend ├── .firebaserc ├── public │ ├── robots.txt │ ├── mic.png │ ├── vbit.png │ ├── cs_logo.png │ ├── favicon.ico │ ├── abhyasLogo.jpg │ ├── VBIT_LOGO_WHITE.png │ ├── pratibhamainfin.png │ ├── PRATIBHAmaintitle.png │ ├── PRATIBHAmaintitle33.png │ ├── index.html │ └── 404.html ├── src │ ├── components │ │ ├── faculty │ │ │ ├── hod │ │ │ │ ├── deptReport.css │ │ │ │ ├── HODSearch.css │ │ │ │ ├── deptReport.js │ │ │ │ └── HODSearch.js │ │ │ ├── common │ │ │ │ ├── docViewer.css │ │ │ │ ├── LockListSubjects │ │ │ │ │ ├── addclasses.css │ │ │ │ │ ├── lockList.css │ │ │ │ │ └── addclasses.js │ │ │ │ ├── ViewSubmissions │ │ │ │ │ ├── ViewSubmissions.css │ │ │ │ │ └── ViewSubmissions.js │ │ │ │ ├── createPRA │ │ │ │ │ ├── createPra.css │ │ │ │ │ └── createPra.js │ │ │ │ ├── docviewer.js │ │ │ │ └── grading.css │ │ │ ├── coe │ │ │ │ ├── coeSearch.css │ │ │ │ ├── deadlines.css │ │ │ │ ├── deadlines.js │ │ │ │ └── coeSearch.js │ │ │ ├── generalFaculty │ │ │ │ ├── ClassList │ │ │ │ │ └── classList.css │ │ │ │ └── ListOfStudents │ │ │ │ │ └── ListOfStudents.css │ │ │ └── services │ │ │ │ ├── hodServices.js │ │ │ │ ├── praServices.js │ │ │ │ ├── gradingServices.js │ │ │ │ ├── adminDeadlinesServices.js │ │ │ │ └── studentsDataServices.js │ │ ├── admin │ │ │ ├── adminPage.module.css │ │ │ ├── manualEnroll.module.css │ │ │ ├── bulkenrolls.module.css │ │ │ └── adminPage.js │ │ ├── global_ui │ │ │ ├── download │ │ │ │ ├── download.css │ │ │ │ └── download.js │ │ │ ├── buttons │ │ │ │ ├── button.css │ │ │ │ └── button.js │ │ │ ├── card │ │ │ │ ├── stylecard.css │ │ │ │ ├── card.js │ │ │ │ ├── card.css │ │ │ │ └── card_.js │ │ │ ├── spinner │ │ │ │ ├── spinner.js │ │ │ │ └── spinner.css │ │ │ ├── dialog │ │ │ │ ├── dialog.module.css │ │ │ │ └── dialog.js │ │ │ ├── input │ │ │ │ ├── input.js │ │ │ │ └── input.module.css │ │ │ └── navbar │ │ │ │ ├── navbar.js │ │ │ │ └── navbar.css │ │ ├── context │ │ │ ├── privateRoute.js │ │ │ └── AuthContext.js │ │ ├── login │ │ │ ├── pratibhaInfo │ │ │ │ ├── pratibhaInfo.js │ │ │ │ └── pratibhaInfo.css │ │ │ ├── announcements │ │ │ │ ├── announcement.css │ │ │ │ └── announcements.js │ │ │ ├── footer │ │ │ │ ├── footer.js │ │ │ │ └── footer.css │ │ │ ├── contactPage │ │ │ │ ├── contactPage.css │ │ │ │ └── contactPage.js │ │ │ └── loginPage.js │ │ ├── student │ │ │ ├── enrollClass │ │ │ │ └── enrollClasses.css │ │ │ ├── SubjectsList │ │ │ │ └── SubjectlistStyles.css │ │ │ ├── services │ │ │ │ └── storageServices.js │ │ │ └── uploadpra │ │ │ │ └── uploadpra.module.css │ │ └── export │ │ │ └── ExportCSV.js │ ├── index.js │ ├── App.css │ ├── reportWebVitals.js │ ├── firebase.js │ └── App.js ├── firebase.json ├── .gitignore ├── .firebase │ ├── hosting.cHVibGlj.cache │ └── hosting.YnVpbGQ.cache ├── package.json └── README.md ├── README.md └── .vscode └── launch.json /backend/firebase.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /backend/functions/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /backend/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "pratibha-d4e57" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /frontend/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "pratibha-d4e57" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "firebase-admin": "^10.0.1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /frontend/public/mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-Studio-vbit/PRATIBHA/HEAD/frontend/public/mic.png -------------------------------------------------------------------------------- /frontend/public/vbit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-Studio-vbit/PRATIBHA/HEAD/frontend/public/vbit.png -------------------------------------------------------------------------------- /frontend/public/cs_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-Studio-vbit/PRATIBHA/HEAD/frontend/public/cs_logo.png -------------------------------------------------------------------------------- /frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-Studio-vbit/PRATIBHA/HEAD/frontend/public/favicon.ico -------------------------------------------------------------------------------- /frontend/public/abhyasLogo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-Studio-vbit/PRATIBHA/HEAD/frontend/public/abhyasLogo.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PRATIBHA 2 | PRATIBHA is a web application for digitizing the Participatory Report Assessment (PRA) activities. 3 | -------------------------------------------------------------------------------- /frontend/public/VBIT_LOGO_WHITE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-Studio-vbit/PRATIBHA/HEAD/frontend/public/VBIT_LOGO_WHITE.png -------------------------------------------------------------------------------- /frontend/public/pratibhamainfin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-Studio-vbit/PRATIBHA/HEAD/frontend/public/pratibhamainfin.png -------------------------------------------------------------------------------- /frontend/public/PRATIBHAmaintitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-Studio-vbit/PRATIBHA/HEAD/frontend/public/PRATIBHAmaintitle.png -------------------------------------------------------------------------------- /frontend/public/PRATIBHAmaintitle33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coding-Studio-vbit/PRATIBHA/HEAD/frontend/public/PRATIBHAmaintitle33.png -------------------------------------------------------------------------------- /frontend/src/components/faculty/hod/deptReport.css: -------------------------------------------------------------------------------- 1 | .dep-title { 2 | text-align: center; 3 | font-weight: bold; 4 | font-size: large; 5 | color: #0e72ab; 6 | margin-top: 20px; 7 | margin-bottom: 20px; 8 | } -------------------------------------------------------------------------------- /frontend/src/components/admin/adminPage.module.css: -------------------------------------------------------------------------------- 1 | .container{ 2 | width: 100%; 3 | height: 90vh; 4 | display: flex; 5 | justify-content: center; 6 | align-items: center; 7 | gap: min(1em, 10%); 8 | flex-wrap: wrap; 9 | } -------------------------------------------------------------------------------- /frontend/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | 12 | 13 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/common/docViewer.css: -------------------------------------------------------------------------------- 1 | .docModel{ 2 | border: 3px dotted rgba(0, 0, 0, 0.3); 3 | padding-top:30px; 4 | background-color: #fff; 5 | width:100%; 6 | padding-left:10px; 7 | padding-right:10px; 8 | height:600px, 9 | } 10 | -------------------------------------------------------------------------------- /frontend/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "build", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/download/download.css: -------------------------------------------------------------------------------- 1 | .download{ 2 | color: #0E72AB; 3 | font-size:40px; 4 | cursor: pointer; 5 | outline: none; 6 | border: none; 7 | background-color: transparent; 8 | } 9 | 10 | .download:hover{ 11 | font-size: 32px; 12 | transition:1ms ease-out; 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: 'Inter', sans-serif; 3 | } 4 | body{ 5 | margin: 0px !important; 6 | } 7 | 8 | 9 | /* Chrome, Safari, Edge, Opera */ 10 | input::-webkit-outer-spin-button, 11 | input::-webkit-inner-spin-button { 12 | -webkit-appearance: none; 13 | margin: 0; 14 | } 15 | 16 | /* Firefox */ 17 | input[type=number] { 18 | -moz-appearance: textfield; 19 | } -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /frontend/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /frontend/src/components/context/privateRoute.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | // import LoginPage from '../login/loginPage'; 3 | import useAuth from './AuthContext'; 4 | import { Navigate} from 'react-router-dom'; 5 | 6 | 7 | function PrivateRoute({ component: Component, ...rest }) { 8 | const { currentUser } = useAuth(); 9 | 10 | return (currentUser ? 11 | : 12 | 13 | ) 14 | } 15 | 16 | export default PrivateRoute -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "chrome", 9 | "request": "launch", 10 | "name": "Launch Chrome against localhost", 11 | "url": "http://localhost:8080", 12 | "webRoot": "${workspaceFolder}" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /frontend/src/components/login/pratibhaInfo/pratibhaInfo.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './pratibhaInfo.css' 3 | 4 | function PratibhaInfo() { 5 | return ( 6 |
7 |

8 | Pratibha 9 | Pratibha 10 | Pratibha 11 | Pratibha 12 | Pratibha 13 | Pratibha 14 |

15 | 16 |
17 | ) 18 | } 19 | 20 | export default PratibhaInfo 21 | -------------------------------------------------------------------------------- /frontend/src/components/login/announcements/announcement.css: -------------------------------------------------------------------------------- 1 | .mainCard{ 2 | margin: auto; 3 | width: min(90%,900px); 4 | box-shadow: rgba(0, 0, 0, 0.02) 0px 1px 3px 0px, rgba(27, 31, 35, 0.15) 0px 0px 0px 1px; 5 | padding: 30px 35px; 6 | border-radius: 20px; 7 | min-height: 230px; 8 | margin-bottom: 10vh; 9 | display: flex; 10 | justify-content: center; 11 | gap: 20px; 12 | align-items: center; 13 | flex-direction: row; 14 | } 15 | 16 | .micImage{ 17 | width:22%; 18 | padding: 4px 20px; 19 | 20 | } 21 | 22 | .announcementInfo{ 23 | justify-items: flex-start; 24 | align-self: flex-start; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /backend/functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "functions", 3 | "description": "Cloud Functions for Firebase", 4 | "scripts": { 5 | "serve": "firebase emulators:start --only functions", 6 | "shell": "firebase functions:shell", 7 | "start": "npm run shell", 8 | "deploy": "firebase deploy --only functions", 9 | "logs": "firebase functions:log" 10 | }, 11 | "engines": { 12 | "node": "14" 13 | }, 14 | "main": "index.js", 15 | "dependencies": { 16 | "firebase-admin": "^9.8.0", 17 | "firebase-functions": "^3.14.1" 18 | }, 19 | "devDependencies": { 20 | "firebase-functions-test": "^0.2.0" 21 | }, 22 | "private": true 23 | } 24 | -------------------------------------------------------------------------------- /frontend/src/components/student/enrollClass/enrollClasses.css: -------------------------------------------------------------------------------- 1 | .enrollPage{ 2 | display: flex; 3 | flex-direction:column; 4 | justify-content: center; 5 | align-items: center; 6 | } 7 | 8 | .instructions{ 9 | padding: 5px 10px ; 10 | } 11 | 12 | .enrollForm{ 13 | display: flex; 14 | flex-direction:column; 15 | justify-content: center; 16 | align-items: center; 17 | /* min-width: 390px; */ 18 | } 19 | 20 | .enrollBtn{ 21 | justify-self: center; 22 | text-align: center; 23 | padding: 10px 15px; 24 | color: white; 25 | display: block; 26 | /* align-self: center; */ 27 | } 28 | .inputBox{ 29 | min-width: 300px; 30 | } 31 | 32 | .btnSpinner{ 33 | margin-top: 20px; 34 | } -------------------------------------------------------------------------------- /frontend/src/components/global_ui/buttons/button.css: -------------------------------------------------------------------------------- 1 | .root { 2 | text-align: center; 3 | border-radius: 7px !important; 4 | border: none; 5 | box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px; 6 | font-size: large; 7 | width: 100px; 8 | height: 50px; 9 | } 10 | .normal { 11 | background-color: #0e72ab; 12 | color: white; 13 | width: auto !important; 14 | padding: 5px 16px !important; 15 | height: auto !important; 16 | } 17 | .rare { 18 | background-color: rgba(176, 196, 222, 0.43); 19 | color: rgba(11, 91, 138, 1); 20 | } 21 | i { 22 | margin: 5px; 23 | } 24 | 25 | .root:hover { 26 | box-shadow: none; 27 | /* border:1px solid #e5e4e2; */ 28 | } 29 | 30 | /* @media screen and (max-width: 500px) { 31 | .root { 32 | width: 70px; 33 | border-radius: 7px !important; 34 | height: 30px; 35 | font-size: 14px; 36 | } 37 | } */ 38 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/card/stylecard.css: -------------------------------------------------------------------------------- 1 | .CardContainer { 2 | height: 180px; 3 | width: 280px; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: center; 8 | text-align: center; 9 | background: rgba(176, 196, 222, 0.43); 10 | border-radius: 7px; 11 | cursor: pointer; 12 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); 13 | transition: 0.3s; 14 | } 15 | 16 | .red { 17 | background-color:#E6E6E6; 18 | } 19 | .newcard { 20 | margin: 0.5rem; 21 | font-size: 15px; 22 | } 23 | .newcardtitle { 24 | margin: 0.5rem; 25 | font-size: 20px; 26 | } 27 | 28 | .green { 29 | background-color: hsl(114, 80%, 91%); 30 | } 31 | 32 | 33 | 34 | .CardContainer:hover { 35 | box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); 36 | } 37 | 38 | @media screen and (max-width: 700px) { 39 | .CardContainer { 40 | width: 250px; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/card/card.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./card.css"; 3 | 4 | const Card = ({ 5 | text, 6 | klass, 7 | subText, 8 | onclick, 9 | children,onClickchildren 10 | }) => { 11 | return ( 12 |
onclick(klass)}> 13 | {children&& {children}} 17 | {text &&

{text}

} 18 | {subText &&

{subText}

} 19 |
20 | ); 21 | }; 22 | 23 | export default Card; 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | // Pass parameters like this : 48 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/spinner/spinner.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './spinner.css'; 3 | 4 | /** 5 | * 6 | * @param {string} radius radius of spinner 7 | * @returns Spinner component 8 | */ 9 | 10 | const Spinner = ({radius,isDark=false}) => { 11 | return ( 12 |
13 |
14 |
15 | ); 16 | } 17 | 18 | const LoadingScreen = ({isTransparent=false,height}) => { 19 | return ( 20 |
25 | 26 |
27 | ); 28 | } 29 | export {Spinner,LoadingScreen}; -------------------------------------------------------------------------------- /frontend/src/components/admin/manualEnroll.module.css: -------------------------------------------------------------------------------- 1 | .nav{ 2 | width: 100vw; 3 | } 4 | .input{ 5 | width: fit-content; 6 | size: 10px; 7 | } 8 | .body{ 9 | width:100vw; 10 | /* height: 90vh; */ 11 | display: flex; 12 | margin-top: 2%; 13 | gap: 2em; 14 | justify-content: center; 15 | /* align-items: center; */ 16 | } 17 | .form{ 18 | display: flex; 19 | flex-direction: column; 20 | gap: 1em; 21 | flex-direction: column; 22 | align-items: center; 23 | justify-content: center; 24 | } 25 | .selectcontainer{ 26 | display: flex; 27 | flex-direction: column; 28 | gap: 1em; 29 | min-width: 18rem; 30 | } 31 | .submitbutton{ 32 | text-align: center; 33 | border-radius: 7px !important; 34 | border: none; 35 | box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px; 36 | font-size: large; 37 | width: 100px; 38 | height: 50px; 39 | cursor: pointer; 40 | } -------------------------------------------------------------------------------- /frontend/src/components/admin/bulkenrolls.module.css: -------------------------------------------------------------------------------- 1 | .bodyContainer{ 2 | width:100vw; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | } 7 | 8 | .nav{ 9 | width: 100vw; 10 | } 11 | 12 | 13 | .enrollcontainer{ 14 | width: 100%; 15 | display: flex; 16 | flex-direction: column; 17 | padding: 1em; 18 | align-items: center; 19 | } 20 | 21 | .inputbox{ 22 | margin-top: 1em; 23 | min-width: 18rem; 24 | } 25 | 26 | .fileinput{ 27 | text-align: center; 28 | border: 0.5em solid #0E72AB; 29 | height: auto; 30 | padding:1em; 31 | display: flex; 32 | flex-direction: column; 33 | } 34 | 35 | .fileupload{ 36 | cursor: pointer; 37 | color:#0E72AB; 38 | display: flex; 39 | font-size: larger; 40 | font-weight: bold; 41 | flex-direction: column; 42 | margin-top: 3rem; 43 | min-width: 20rem; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/card/card.css: -------------------------------------------------------------------------------- 1 | .globalCardContainer{ 2 | height: 150px; 3 | margin: 0px; 4 | margin-bottom: 5px; 5 | display: flex; 6 | flex-direction: column; 7 | align-items: center; 8 | justify-content: center; 9 | text-align: center; 10 | padding: 12px; 11 | background:rgba(176, 196, 222, 0.43); 12 | border-radius: 7px; 13 | cursor: pointer; 14 | font-size:large; 15 | box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2); 16 | transition: 0.3s; 17 | width: 220px; 18 | 19 | } 20 | .delicon{ 21 | align-self: flex-end; 22 | font-size: small; 23 | } 24 | .delicon:hover{ 25 | color: red; 26 | scale: 1.2; 27 | font-weight: bolder; 28 | transition: color 1s cubic-bezier(0.075, 0.82, 0.165, 1) 500ms; 29 | } 30 | .globalCardContainer:hover { 31 | box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2); 32 | } 33 | 34 | .subText { 35 | text-align: center; 36 | margin-bottom: 2px; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/hod/HODSearch.css: -------------------------------------------------------------------------------- 1 | .root-hod { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | align-items: center; 6 | margin-right: auto; 7 | margin-left: auto; 8 | } 9 | 10 | .dep-title { 11 | text-align: center; 12 | font-weight: bold; 13 | font-size: large; 14 | color: #0e72ab; 15 | margin-top: 20px; 16 | margin-bottom: 20px; 17 | } 18 | 19 | .dd-text { 20 | text-align: center; 21 | font-weight: 500; 22 | padding-bottom: 5px; 23 | padding-top: 5px; 24 | } 25 | 26 | .selectHOD { 27 | max-width: 300px; 28 | min-width: 270px; 29 | justify-self: center; 30 | align-self: center; 31 | } 32 | 33 | .hod-button { 34 | margin-top: 10px; 35 | align-self: center; 36 | justify-self: center; 37 | margin-bottom: 10px; 38 | cursor: pointer; 39 | margin: 20px; 40 | } 41 | .report-button{ 42 | margin-top: 20px; 43 | cursor: pointer; 44 | display: flex; 45 | justify-content: flex-end; 46 | margin-right: 20px; 47 | } -------------------------------------------------------------------------------- /frontend/src/firebase.js: -------------------------------------------------------------------------------- 1 | import { initializeApp} from "firebase/app"; 2 | import { getAuth } from '@firebase/auth'; 3 | import { getStorage } from "firebase/storage"; 4 | import { getFirestore } from 'firebase/firestore'; 5 | import { setPersistence, browserSessionPersistence } from "firebase/auth"; 6 | 7 | const firebaseConfig = { 8 | apiKey:process.env.REACT_APP_FIREBASE_API_KEY, 9 | authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN, 10 | projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID, 11 | storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET, 12 | messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID, 13 | appId: process.env.REACT_APP_FIREBASE_APP_ID, 14 | measurementId:process.env.REACT_APP_FIREBASE_MEASUREMENT_ID 15 | }; 16 | 17 | const app = initializeApp(firebaseConfig); 18 | const auth = getAuth(); 19 | setPersistence(auth, browserSessionPersistence) 20 | 21 | const storage = getStorage(app); 22 | const db = getFirestore(); 23 | 24 | 25 | export {auth,app,db,storage}; 26 | -------------------------------------------------------------------------------- /frontend/src/components/export/ExportCSV.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import * as FileSaver from "file-saver"; 3 | import * as XLSX from "xlsx"; 4 | import Button from "..//global_ui/buttons/button"; 5 | 6 | export const ExportCSV = ({ csvData, fileName }) => { 7 | const fileType = 8 | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"; 9 | const fileExtension = ".xlsx"; 10 | 11 | const exportToCSV = (csvData, fileName) => { 12 | const ws = XLSX.utils.json_to_sheet(csvData); 13 | const wb = { Sheets: { data: ws }, SheetNames: ["data"] }; 14 | const excelBuffer = XLSX.write(wb, { bookType: "xlsx", type: "array" }); 15 | const data = new Blob([excelBuffer], { type: fileType }); 16 | FileSaver.saveAs(data, fileName + fileExtension); 17 | }; 18 | 19 | return ( 20 | 29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/coe/coeSearch.css: -------------------------------------------------------------------------------- 1 | .CoESearch-container { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: center; 6 | } 7 | .coe-button { 8 | margin-top: 16px; 9 | align-self: center; 10 | cursor: pointer; 11 | margin-left: auto; 12 | margin-right: auto; 13 | } 14 | .btnflexcoe{ 15 | display: flex; 16 | margin-top: 10px; 17 | } 18 | .deadlinesbtn{ 19 | align-self: flex-end; 20 | margin-left: auto; 21 | margin-right: 15px; 22 | } 23 | 24 | .coe-instruction{ 25 | color: #0e72ab; 26 | font-weight: bold; 27 | letter-spacing: 0.4px; 28 | margin-bottom: 0px; 29 | text-align: center; 30 | } 31 | .dropdown-title { 32 | text-align: center; 33 | margin-bottom: 0px; 34 | margin-top: 5px; 35 | } 36 | .selectCOE { 37 | max-width: 300px; 38 | min-width: 270px; 39 | margin-bottom: 5px; 40 | margin-top: 5px; 41 | margin-right: auto; 42 | margin-left: auto; 43 | } 44 | .coe-dropdown { 45 | margin: 10px; 46 | align-items: center; 47 | justify-content: center; 48 | margin-left: auto; 49 | margin-right: auto; 50 | display: flex; 51 | flex-direction: column; 52 | } 53 | -------------------------------------------------------------------------------- /frontend/.firebase/hosting.cHVibGlj.cache: -------------------------------------------------------------------------------- 1 | VBIT_LOGO_WHITE.png,1655641767997,7a727a3f4f21c7dd5b32b46f4d75b7446af81f7e22ad2d39df999d0ecce4f049 2 | index.html,1655641768007,b95667b0ecae0a58e7ccd5b4fb3177cc7497a8a1a9bad420eddaef71ef2b064a 3 | robots.txt,1655641768007,2544ca049f223a42bff01f72ad930a5edba75bbb7199d0f8430a02ff5aca16ec 4 | 404.html,1655658842537,b7bab6b83fa074653ff28c8d2a64135d3434575f70a12ab3d3ba8080461b9537 5 | vbit.png,1655641768007,3338f71fe0516b2594c6f27cb47e351640eaee5425a63fb0811c8920a40cab0f 6 | cs_logo.png,1655641768000,af8438a33d2a9ff1d56aae6b522687a9ab5e7894ca75312a6435d1afc19a36b3 7 | abhyasLogo.jpg,1655641768000,466498c8eab5ea124844650b419222aac5d709a7b5d73a1d736a9d2446fa0b03 8 | PRATIBHAmaintitle.png,1655641767997,66e0d51d206ec43d17ed1ea559e5d203bc02d7b929371e9cd1088c10993407c5 9 | PRATIBHAmaintitle33.png,1655641767997,ab2e1a3eb9b2280ce6bb59fcce37ee901c69172ea87db21035cd4406587e8a09 10 | mic.png,1655641768007,989ddc439e97cbb28a74c1265d69de1fd9150a8b6853566bed5cc8e4d47d82d4 11 | pratibhamainfin.png,1655641768007,1d5380ea88b3b7d1c7c66eb844d6c5249da69d452b63fd7abd7ce7700c455eb9 12 | favicon.ico,1655641768007,953ba552aac2231a85117b76f91b90ff9eba827cbde2995391ef264238c2ec62 13 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/card/card_.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./stylecard.css"; 3 | 4 | const Card_ = ({ 5 | subject, 6 | pra, 7 | status, 8 | date, 9 | isWeek, 10 | isSubmitted, 11 | // klass, 12 | }) => { 13 | 14 | return ( 15 |
25 | {subject && ( 26 |

30 | {subject} 31 |

32 | )} 33 | {pra && ( 34 |

35 | Topic: 36 | {pra} 37 |

38 | )} 39 | {status && ( 40 |

41 | Status: 42 | {status} 43 |

44 | )} 45 | {date && ( 46 |

47 | Submit Before: 48 | {date} 49 |

50 | )} 51 |
52 | ); 53 | }; 54 | 55 | export default Card_; 56 | -------------------------------------------------------------------------------- /frontend/src/components/student/SubjectsList/SubjectlistStyles.css: -------------------------------------------------------------------------------- 1 | .main-body-subjects { 2 | display: flex; 3 | flex-direction: column; 4 | width: 100vw; 5 | margin-right: auto; 6 | margin-left: auto; 7 | } 8 | 9 | .subBody { 10 | margin-top: 20px; 11 | display: flex; 12 | align-items: center; 13 | justify-content: center; 14 | margin-left: auto; 15 | margin-right: auto; 16 | } 17 | .userDetails{ 18 | text-align: center; 19 | color:#0e72ab; 20 | font-weight: bold; 21 | margin-bottom: 0px; 22 | font-size: large; 23 | } 24 | 25 | .list-grid { 26 | /* align-self: flex-start; */ 27 | justify-self: center; 28 | align-self: center; 29 | display: grid; 30 | grid-column-gap: 50px; 31 | grid-row-gap: 50px; 32 | grid-template-columns: auto auto auto; 33 | } 34 | .listerror{ 35 | /* align-self: center; */ 36 | text-align: center; 37 | font-size: 20px; 38 | font-weight: medium; 39 | margin-top: 30px; 40 | 41 | } 42 | 43 | @media screen and (max-width: 1100px) { 44 | .list-grid { 45 | grid-template-columns: auto auto; 46 | margin-right: auto; 47 | margin-left: auto; 48 | } 49 | } 50 | 51 | @media screen and (max-width: 700px) { 52 | .list-grid { 53 | grid-template-columns: auto; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/dialog/dialog.module.css: -------------------------------------------------------------------------------- 1 | .dialogOverlay{ 2 | padding: 0; 3 | margin: 0; 4 | display: block; 5 | position: fixed; 6 | z-index: 1000; 7 | left: 0; 8 | top: 0; 9 | padding: 0px; 10 | width: 100vw; 11 | height: 100vh; 12 | background-color: rgb(0,0,0); /* Fallback color */ 13 | background-color: rgba(0,0,0,0.3); /* Black w/ opacity */ 14 | } 15 | 16 | /* Modal Content */ 17 | .dialog{ 18 | margin: 0; 19 | border-radius: 10px; 20 | padding: 10px 20px; 21 | position: absolute; 22 | top: 50%; right: 50%; 23 | transform: translate(50%,-50%); 24 | background:white; 25 | color: darkslategrey; 26 | width: 380px; 27 | min-height: 200px; 28 | display: flex; 29 | flex-direction: column; 30 | justify-content: space-around; 31 | align-items: center; 32 | } 33 | 34 | .message{ 35 | font-size: large; 36 | font-weight: 600; 37 | text-align: center; 38 | } 39 | 40 | .btn{ 41 | background-color: #0E72AB ; 42 | color: white; 43 | outline: none; 44 | border: none; 45 | border-radius: 4px; 46 | padding: 10px 20px; 47 | cursor: pointer; 48 | } 49 | 50 | @media only screen and (max-width: 600px) { 51 | .dialog{ 52 | width: 80vw; 53 | height: 31vh; 54 | } 55 | } -------------------------------------------------------------------------------- /frontend/src/components/global_ui/input/input.js: -------------------------------------------------------------------------------- 1 | import React,{useState} from 'react'; 2 | import styles from './input.module.css' 3 | 4 | /** 5 | * 6 | * @param {*} props textAlign,size,minLength,value,placeholder,name,type,onChange,error,maxLength are the supported props 7 | * You can pass an error msg to show an error below input field 8 | * @returns a custom styled input component. 9 | */ 10 | const InputField = ({ukey,textAlign,caps=false,size,value,placeholder,name,type,onChange,error,maxLength}) => { 11 | const [flag,setFlag] = useState(false); 12 | return ( 13 | 14 |
15 | {/* */} 16 | { 17 | setFlag(true) 18 | }} placeholder={!flag?placeholder:""} className={styles.input+" "+(error?styles.errorField:styles.normalField)} type={type} name={name} value={value} onChange={onChange} required/> 19 |
20 | {error && {error}} 21 | {error &&
} 22 |
23 | ); 24 | } 25 | 26 | export default InputField; -------------------------------------------------------------------------------- /frontend/src/components/global_ui/dialog/dialog.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import styles from './dialog.module.css' 3 | import Download from '../download/download'; 4 | 5 | function Dialog({message,onOK,onConfirm,onCancel,twoButtons=false,download=false,rollNo,url,setShowDialog}) { 6 | return ( 7 |
8 |
9 |

{message}

10 | 11 | { 12 | twoButtons? ( 13 |
14 | 15 | 16 |
):download && rollNo ? 17 |
18 | 19 |
20 | : () 21 | } 22 |
23 |
24 | ) 25 | } 26 | 27 | export default Dialog; 28 | //use dialog like this -------------------------------------------------------------------------------- /frontend/src/components/login/announcements/announcements.js: -------------------------------------------------------------------------------- 1 | import React,{useState,useEffect} from 'react' 2 | import './announcement.css' 3 | import {getAnnouncements} from '../../student/services/studentServices' 4 | 5 | function Announcement() { 6 | 7 | async function getData() { 8 | const data = await getAnnouncements(); 9 | if(data!=null){ 10 | setdata(data); 11 | }else{ 12 | setdata(null); 13 | } 14 | 15 | } 16 | 17 | const [data, setdata] = useState(null); 18 | useEffect(() => { 19 | getData(); 20 | 21 | }, []) 22 | 23 | return ( 24 |
25 | 26 |
27 |

Announcements

28 |

29 | { 30 | data && 31 |

    32 | { 33 | data.map((x)=>{ 34 | return
  • {x}
  • 35 | }) 36 | } 37 |
38 | } 39 |

40 |
41 |
42 | ) 43 | } 44 | 45 | export default Announcement; -------------------------------------------------------------------------------- /frontend/src/components/faculty/coe/deadlines.css: -------------------------------------------------------------------------------- 1 | .select-deadlines { 2 | 3 | max-width: 300px; 4 | min-width: 270px; 5 | margin-bottom: 5px; 6 | margin-top: 10px; 7 | margin-right: auto; 8 | margin-left: auto; 9 | 10 | } 11 | .full-page{ 12 | display: flex; 13 | flex-direction: column; 14 | } 15 | .deadlines-flex{ 16 | display: flex; 17 | flex-direction: column; 18 | } 19 | 20 | .coeinstruction{ 21 | margin-bottom: 10px; 22 | color: #0e72ab; 23 | font-weight: bold; 24 | letter-spacing: 0.4px; 25 | text-align: center; 26 | } 27 | .dd-title-deadline{ 28 | font-weight: medium; 29 | font-size: 17px; 30 | text-align: center; 31 | margin-bottom: 0px; 32 | margin-top: 10px; 33 | } 34 | .datepicker-deadlines{ 35 | margin-top: 10px; 36 | font-size: 23px; 37 | margin-left: auto; 38 | margin-right: auto; 39 | border: none; 40 | text-align: center; 41 | padding: 4px; 42 | border-radius: 7px; 43 | background-color: rgba(176, 196, 222, 0.43); 44 | } 45 | .datepicker-flex{ 46 | display: flex; 47 | flex-direction: column; 48 | justify-content: center; 49 | align-items: center; 50 | } 51 | .deadlines-button{ 52 | margin-left: auto; 53 | margin-right: auto; 54 | margin-top: 25px; 55 | } 56 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/common/LockListSubjects/addclasses.css: -------------------------------------------------------------------------------- 1 | .addclasses-root { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: center; 6 | } 7 | .addclasses-dropdown { 8 | margin: 10px; 9 | align-items: center; 10 | justify-content: center; 11 | } 12 | .addclasses-dropdown-title { 13 | text-align: center; 14 | margin-bottom: 0px; 15 | margin-top:5px; 16 | } 17 | .addclasses-btn { 18 | text-align: center; 19 | border-radius: 7px !important; 20 | border: none; 21 | box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px; 22 | font-size: large; 23 | width: 100px; 24 | height: 50px; 25 | cursor: pointer; 26 | margin-top:5px; 27 | } 28 | .addclasses-instruction{ 29 | color: #0e72ab; 30 | font-weight: bold; 31 | letter-spacing: 0.4px; 32 | margin-bottom: 0px; 33 | } 34 | .select-addclasses{ 35 | max-width: 300px; 36 | min-width: 270px; 37 | justify-self: center; 38 | align-self: center; 39 | margin-bottom: 5px; 40 | margin-top: 5px; 41 | } 42 | .addclasses-btn:hover { 43 | box-shadow: none; 44 | cursor: pointer; 45 | } 46 | .addclasses-btn:disabled { 47 | background-color: grey; 48 | cursor: not-allowed; 49 | } 50 | .addclasses-btn-div { 51 | display: flex; 52 | align-items: center; 53 | justify-content: center; 54 | } -------------------------------------------------------------------------------- /frontend/src/components/login/pratibhaInfo/pratibhaInfo.css: -------------------------------------------------------------------------------- 1 | /* .infoComponent{ 2 | width: 100vw; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | } 7 | 8 | h1 { 9 | font-family: "Montserrat Medium"; 10 | max-width: 40ch; 11 | text-align: center; 12 | transform: scale(0.94); 13 | animation: scale 3s forwards cubic-bezier(0.5, 1, 0.89, 1); 14 | } 15 | @keyframes scale { 16 | 100% { 17 | transform: scale(1); 18 | } 19 | } 20 | 21 | span { 22 | display: inline-block; 23 | opacity: 0; 24 | filter: blur(4px); 25 | } 26 | 27 | span:nth-child(1) { 28 | animation: fade-in 0.8s 0.1s forwards cubic-bezier(0.11, 0, 0.5, 0); 29 | } 30 | 31 | span:nth-child(2) { 32 | animation: fade-in 0.8s 0.2s forwards cubic-bezier(0.11, 0, 0.5, 0); 33 | } 34 | 35 | span:nth-child(3) { 36 | animation: fade-in 0.8s 0.3s forwards cubic-bezier(0.11, 0, 0.5, 0); 37 | } 38 | 39 | span:nth-child(4) { 40 | animation: fade-in 0.8s 0.4s forwards cubic-bezier(0.11, 0, 0.5, 0); 41 | } 42 | 43 | span:nth-child(5) { 44 | animation: fade-in 0.8s 0.5s forwards cubic-bezier(0.11, 0, 0.5, 0); 45 | } 46 | 47 | span:nth-child(6) { 48 | animation: fade-in 0.8s 0.6s forwards cubic-bezier(0.11, 0, 0.5, 0); 49 | } 50 | 51 | @keyframes fade-in { 52 | 100% { 53 | opacity: 1; 54 | filter: blur(0); 55 | } 56 | } 57 | */ -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | firebase-debug.log* 8 | firebase-debug.*.log* 9 | 10 | # Firebase cache 11 | .firebase/ 12 | 13 | # Firebase config 14 | 15 | # Uncomment this if you'd like others to create their own Firebase project. 16 | # For a team working on the same Firebase project(s), it is recommended to leave 17 | # it commented so all members can deploy to the same project(s) in .firebaserc. 18 | # .firebaserc 19 | 20 | # Runtime data 21 | pids 22 | *.pid 23 | *.seed 24 | *.pid.lock 25 | 26 | # Directory for instrumented libs generated by jscoverage/JSCover 27 | lib-cov 28 | 29 | # Coverage directory used by tools like istanbul 30 | coverage 31 | 32 | # nyc test coverage 33 | .nyc_output 34 | 35 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 36 | .grunt 37 | 38 | # Bower dependency directory (https://bower.io/) 39 | bower_components 40 | 41 | # node-waf configuration 42 | .lock-wscript 43 | 44 | # Compiled binary addons (http://nodejs.org/api/addons.html) 45 | build/Release 46 | 47 | # Dependency directories 48 | node_modules/ 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Optional REPL history 57 | .node_repl_history 58 | 59 | # Output of 'npm pack' 60 | *.tgz 61 | 62 | # Yarn Integrity file 63 | .yarn-integrity 64 | 65 | # dotenv environment variables file 66 | .env 67 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/buttons/button.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./button.css"; 3 | 4 | const Button = ({ children, disabled, onClick, width, height, icon, className }) => { 5 | return ( 6 | 14 | ); 15 | }; 16 | 17 | // const Button = ({children,icon,type,onClick,buttonStyle,buttonSize}) => { 18 | // return ( 19 | // 20 | // ) 21 | // } 22 | export default Button; 23 | 24 | //without any icon do this : )} 18 |
21 | {title} 22 | { 23 | logout===true && 24 | 28 | } 29 | 30 |
34 | 35 | 36 | {children} 37 |
38 | 39 | 40 | 41 | ); 42 | } 43 | 44 | export default Navbar; 45 | 46 | //example : 47 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/generalFaculty/ClassList/classList.css: -------------------------------------------------------------------------------- 1 | .div-container-classes { 2 | display: flex; 3 | justify-content: center; 4 | flex-direction: column; 5 | align-items: flex-start; 6 | margin-right: 32px; 7 | margin-left: 32px; 8 | } 9 | 10 | .cardList { 11 | display: flex; 12 | column-gap: 20px; 13 | row-gap: 20px; 14 | flex-direction: row; 15 | flex-wrap: wrap; 16 | align-content: center; 17 | padding: 4px 10px; 18 | /* padding-right: 0px; */ 19 | } 20 | 21 | .addclass-button { 22 | margin-top: 10px; 23 | margin-left: auto; 24 | cursor: pointer; 25 | margin-right: 10px; 26 | } 27 | .viewdept-button { 28 | margin-top: 10px; 29 | margin-left: auto; 30 | /* margin-right: 10px; */ 31 | padding: 8.5px !important; 32 | cursor: pointer; 33 | } 34 | .courseTitle { 35 | text-align: left; 36 | margin: 2px 3px; 37 | font-size: 16px; 38 | padding: 4px 10px; 39 | padding-right: 0px; 40 | } 41 | 42 | .subjectsDivision { 43 | margin: 0; 44 | padding: 0; 45 | width: 100%; 46 | } 47 | 48 | @media screen and (max-width: 600px) { 49 | .cardList { 50 | justify-content: center; 51 | gap: 20px; 52 | } 53 | .courseTitle { 54 | text-align: center; 55 | font-size: 20px; 56 | } 57 | .addclass-button { 58 | margin-top: 10px; 59 | margin-left: auto; 60 | margin-right: auto; 61 | font-size: 1em; 62 | 63 | } 64 | .viewdept-button { 65 | margin-left: auto; 66 | margin-right: auto; 67 | padding: 9px !important; 68 | font-size: 1em; 69 | } 70 | .btn-container { 71 | display: flex; 72 | gap: 5px; 73 | justify-content: center; 74 | align-items: center; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/navbar/navbar.css: -------------------------------------------------------------------------------- 1 | .nav { 2 | display: flex; 3 | z-index: 0; 4 | justify-content: center; 5 | height: 64px; 6 | background-color: #0e72ab; 7 | align-items: center; 8 | color: white; 9 | align-items: center; 10 | width: 100%; 11 | } 12 | .nav > * { 13 | flex: 1; 14 | } 15 | .title { 16 | font-size: 20px; 17 | font-weight: 400; 18 | margin: auto; 19 | flex-grow: 1; 20 | text-align: center; 21 | } 22 | .createPRA > * { 23 | margin-right: 10px; 24 | } 25 | .btn { 26 | position: absolute; 27 | right: 0; 28 | z-index: 1; 29 | margin-right: 12px; 30 | font-size: x-large; 31 | width: max-content; 32 | color: white; 33 | border-style: none; 34 | background-color: #0e72ab; 35 | margin-top: 3px; 36 | cursor: pointer; 37 | display: inline-block; 38 | } 39 | .bck { 40 | position: absolute; 41 | z-index: 1; 42 | left: 8px; 43 | margin-top: auto; 44 | margin-bottom: auto; 45 | cursor: pointer; 46 | font-size: 20px; 47 | width: max-content; 48 | color: white; 49 | border-style: none; 50 | background-color: #0e72ab; 51 | justify-self: center; 52 | align-self: center; 53 | } 54 | 55 | .btn .tooltiptext { 56 | visibility: hidden; 57 | width: 120px; 58 | background-color: #4f4f4f; 59 | color: #fff; 60 | text-align: center; 61 | border-radius: 6px; 62 | border: 1px solid black; 63 | padding: 5px 0; 64 | position: absolute; 65 | z-index: 1; 66 | top: -5px; 67 | right: 105%; 68 | } 69 | 70 | .btn:hover .tooltiptext { 71 | visibility: visible; 72 | } 73 | 74 | @media screen and (max-width: 500px) { 75 | #hide { 76 | display: none; 77 | } 78 | .title { 79 | font-size: 18px; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/common/ViewSubmissions/ViewSubmissions.css: -------------------------------------------------------------------------------- 1 | .spinnerload { 2 | margin-top: 100px; 3 | display: flex; 4 | align-items: center; 5 | justify-content: center; 6 | } 7 | 8 | .sub_body { 9 | margin: 8px; 10 | display: flex; 11 | align-items: center; 12 | justify-content: center; 13 | flex-direction: column; 14 | } 15 | .subject { 16 | color: #0e72ab; 17 | text-align: center; 18 | font-size: large; 19 | } 20 | 21 | table { 22 | width: 100%; 23 | border-collapse: separate; 24 | border-spacing: 0px 5px; 25 | } 26 | th { 27 | border-bottom: 1px solid black; 28 | border-collapse: collapse; 29 | } 30 | 31 | td, 32 | th { 33 | padding: 7px; 34 | text-align: center; 35 | } 36 | 37 | .LOF_buttons { 38 | margin-top: 50px; 39 | margin-top: 20px; 40 | } 41 | 42 | tr { 43 | margin: 5px; 44 | cursor: pointer; 45 | } 46 | .viewsub-download { 47 | font-size: 15px; 48 | } 49 | 50 | .err_Display { 51 | margin-top: 20vh; 52 | color: red; 53 | font-weight: bold; 54 | text-align: center; 55 | font-size: large; 56 | } 57 | 58 | tbody tr:nth-child(odd) { 59 | background-color: rgba(176, 196, 222, 0.43); 60 | } 61 | 62 | tbody tr:nth-child(even) { 63 | background-color: rgba(176, 196, 222, 0.63); 64 | } 65 | .bold { 66 | font-weight: bold; 67 | } 68 | 69 | .btn_download { 70 | color: #0e72ab; 71 | font-size: 40px; 72 | cursor: pointer; 73 | outline: none; 74 | border: none; 75 | background-color: transparent; 76 | } 77 | 78 | @media screen and (max-width: 500px) { 79 | table { 80 | width: screen; 81 | display: block; 82 | overflow-x: scroll; 83 | } 84 | 85 | .export_ { 86 | margin-top: 20px; 87 | margin-right: 20px; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /frontend/src/components/login/footer/footer.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ContactPage from '../contactPage/contactPage' 3 | import './footer.css' 4 | 5 | function Footer() { 6 | return ( 7 |
8 | 9 |
10 |
11 | 12 | Vignana Bharathi Institute of Technology emerged as a hub for engineering excellence. At VBIT, students will discover engineering in a different light. Students will experience an engineering education that is on par with the industry requirement. 13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 |

Copyright © {new Date().getFullYear()} Vignana Bharathi Institute Of Technology All Rights Reserved

21 |
22 | Follow us on 23 | 24 | 25 | 26 |
27 |
28 | 29 |
30 | 31 | coding.Studio(); 32 | 33 |
34 | 35 |
36 | ) 37 | } 38 | 39 | export default Footer 40 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/generalFaculty/ListOfStudents/ListOfStudents.css: -------------------------------------------------------------------------------- 1 | .spinnerload { 2 | margin-top: 100px; 3 | display: flex; 4 | align-items: center; 5 | justify-content: center; 6 | } 7 | 8 | .sub_body { 9 | margin: 8px; 10 | display: flex; 11 | align-items: center; 12 | justify-content: center; 13 | flex-direction: column; 14 | } 15 | .subject{ 16 | color:#0E72AB; 17 | text-align: center; 18 | font-size:large; 19 | } 20 | .mid2err{ 21 | text-align: center; 22 | font-weight: 500; 23 | color: red; 24 | font-size: large; 25 | } 26 | 27 | table { 28 | width: 100%; 29 | border-collapse:separate; 30 | border-spacing:0px 5px; 31 | } 32 | th { 33 | border-bottom: 1px solid black; 34 | border-collapse: collapse; 35 | } 36 | 37 | td, 38 | th { 39 | padding: 15px; 40 | text-align: center; 41 | } 42 | 43 | .LOF_buttons { 44 | margin-top: 50px; 45 | padding: 20px; 46 | } 47 | 48 | .export_ { 49 | margin-top: 10px; 50 | margin-bottom: 20px; 51 | float: right; 52 | margin-right: 100px; 53 | cursor: pointer; 54 | } 55 | .grade-button{ 56 | cursor: pointer; 57 | } 58 | 59 | tr { 60 | margin: 10px; 61 | cursor: pointer; 62 | 63 | } 64 | 65 | .err_Display{ 66 | margin-top: 20vh; 67 | color:red; 68 | font-weight:bold; 69 | text-align:center; 70 | font-size: large; 71 | 72 | } 73 | 74 | tbody tr:nth-child(odd) { 75 | background-color: rgba(176, 196, 222, 0.43); 76 | } 77 | 78 | tbody tr:nth-child(even) { 79 | background-color: rgba(176, 196, 222, 0.63); 80 | } 81 | .bold { 82 | font-weight: bold; 83 | } 84 | @media screen and (max-width: 500px) { 85 | table { 86 | width: screen; 87 | display: block; 88 | overflow-x: scroll; 89 | } 90 | 91 | .export_ { 92 | margin-top: 20px; 93 | margin-right: 20px; 94 | margin-bottom: 20px; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /frontend/.firebase/hosting.YnVpbGQ.cache: -------------------------------------------------------------------------------- 1 | robots.txt,1729008245856,2544ca049f223a42bff01f72ad930a5edba75bbb7199d0f8430a02ff5aca16ec 2 | index.html,1729008321449,39388aaf75d629bac7f0ea8921810ce73f183caa7e1177e78682841a3a657cfb 3 | asset-manifest.json,1729008321449,d303fc056fb34d4627dd3631b284d13358b6803b1939229cee27bc7c76661ccd 4 | VBIT_LOGO_WHITE.png,1729008245852,7a727a3f4f21c7dd5b32b46f4d75b7446af81f7e22ad2d39df999d0ecce4f049 5 | 404.html,1729008245852,b7bab6b83fa074653ff28c8d2a64135d3434575f70a12ab3d3ba8080461b9537 6 | static/js/main.a964905a.js.LICENSE.txt,1729008321483,9b14bc27b42867505f52f4ffb565a2cefb3d69475a44bb024c4e24ed9228f735 7 | vbit.png,1729008245856,3338f71fe0516b2594c6f27cb47e351640eaee5425a63fb0811c8920a40cab0f 8 | static/css/main.69231350.css,1729008321483,a28d529c8ab3685345265b6c63f00a4d41d02e26406c851b42f9f25d591d85ae 9 | cs_logo.png,1729008245856,af8438a33d2a9ff1d56aae6b522687a9ab5e7894ca75312a6435d1afc19a36b3 10 | abhyasLogo.jpg,1729008245852,466498c8eab5ea124844650b419222aac5d709a7b5d73a1d736a9d2446fa0b03 11 | PRATIBHAmaintitle.png,1729008245852,66e0d51d206ec43d17ed1ea559e5d203bc02d7b929371e9cd1088c10993407c5 12 | static/css/main.69231350.css.map,1729008321483,b308aaa8b4f0ac12fe514ce622f567dda536a40cad0077b39a1b7ebc62609d31 13 | PRATIBHAmaintitle33.png,1729008245852,ab2e1a3eb9b2280ce6bb59fcce37ee901c69172ea87db21035cd4406587e8a09 14 | mic.png,1729008245856,989ddc439e97cbb28a74c1265d69de1fd9150a8b6853566bed5cc8e4d47d82d4 15 | pratibhamainfin.png,1729008245856,1d5380ea88b3b7d1c7c66eb844d6c5249da69d452b63fd7abd7ce7700c455eb9 16 | favicon.ico,1729008245856,953ba552aac2231a85117b76f91b90ff9eba827cbde2995391ef264238c2ec62 17 | static/js/main.a964905a.js,1729008321483,717dfb5327e946ae617e2acae08227d898cc20ad03062eb444c03bf4cb3d841b 18 | static/js/main.a964905a.js.map,1729008321483,9391b34192bb99f640e49280cd7561459c951da83fac4cf9b153cfdf15b9e849 19 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.7.0", 7 | "@emotion/styled": "^11.6.0", 8 | "@material-ui/core": "^4.12.3", 9 | "@material-ui/icons": "^4.11.2", 10 | "@mui/icons-material": "^5.2.1", 11 | "@mui/material": "^5.2.3", 12 | "@react-pdf-viewer/core": "^3.0.0", 13 | "@react-pdf-viewer/zoom": "^3.1.1", 14 | "@testing-library/jest-dom": "^5.15.1", 15 | "@testing-library/react": "^11.2.7", 16 | "@testing-library/user-event": "^12.8.3", 17 | "axios": "^0.24.0", 18 | "classnames": "^2.3.1", 19 | "file-saver": "^2.0.5", 20 | "firebase": "^9.6.1", 21 | "firebase-tools": "^11.15.0", 22 | "jszip": "^3.10.1", 23 | "pdfjs-dist": "^2.6.347", 24 | "react": "^17.0.2", 25 | "react-datepicker": "^4.5.0", 26 | "react-dom": "^17.0.2", 27 | "react-dropdown": "^1.9.2", 28 | "react-error-overlay": "^6.0.9", 29 | "react-file-viewer": "^0.5.0", 30 | "react-pro-sidebar": "^0.7.1", 31 | "react-router-dom": "^6.0.2", 32 | "react-scripts": "^5.0.1", 33 | "react-select": "^5.2.1", 34 | "web-vitals": "^1.1.2", 35 | "webpack": "^5.74.0", 36 | "xlsx": "^0.17.4" 37 | }, 38 | "scripts": { 39 | "start": "react-scripts start", 40 | "build": "react-scripts build", 41 | "test": "react-scripts test", 42 | "eject": "react-scripts eject" 43 | }, 44 | "eslintConfig": { 45 | "extends": [ 46 | "react-app", 47 | "react-app/jest" 48 | ] 49 | }, 50 | "browserslist": { 51 | "production": [ 52 | ">0.2%", 53 | "not dead", 54 | "not op_mini all" 55 | ], 56 | "development": [ 57 | "last 1 chrome version", 58 | "last 1 firefox version", 59 | "last 1 safari version" 60 | ] 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /frontend/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Page Not Found 7 | 8 | 23 | 24 | 25 |
26 |

404

27 |

Page Not Found

28 |

The specified file was not found on this website. Please check the URL for mistakes and try again.

29 |

Why am I seeing this?

30 |

This page was generated by the Firebase Command-Line Interface. To modify it, edit the 404.html file in your project's configured public directory.

31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /backend/functions/index.js: -------------------------------------------------------------------------------- 1 | const functions = require("firebase-functions"); 2 | import {functions} from 'firebase-functions' 3 | import {admin} from 'firebase-admin' 4 | 5 | // const checkNumber=(myString)=> /\d/.test(myString); 6 | function checkStudent(myString){ 7 | if(myString.slice(2,6)=="p61a"){ 8 | return true; 9 | }else{ 10 | return false; 11 | } 12 | } 13 | 14 | const domain="vbithyd.ac.in"; 15 | 16 | exports.verifyNewUser=functions.auth.user().onCreate(async(user)=>{ 17 | const splitEmail=user.email.split('@'); 18 | if(splitEmail[1]===domain){ 19 | if(checkStudent(splitEmail[0])){ 20 | try{ 21 | await admin.firestore().collection("users").doc(user.email) 22 | .set({ 23 | isEnrolled:false, 24 | role:['STUDENT'] 25 | }); 26 | }catch(e){ 27 | functions.logger.log("Domain Verification Unsuccessful - STUDENT"); 28 | } 29 | }else{ 30 | try{ 31 | await admin.firestore().collection("faculty").doc(user.email) 32 | .set({ 33 | isEnrolled:false, 34 | role:['FACULTY'] 35 | }); 36 | }catch(e){ 37 | functions.logger.log("Domain Verification Unsuccessful - FACULTY") 38 | } 39 | } 40 | } 41 | else{ 42 | try{ 43 | await admin.auth().deleteUser(user.uid); 44 | } 45 | catch(e){ 46 | functions.logger.log("Could not delete User"); 47 | } 48 | } 49 | }); 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | // exports.helloWorld = functions.https.onRequest((request, response) => { 65 | // functions.logger.info("Hello logs!", {structuredData: true}); 66 | // response.send("Hello from Firebase!"); 67 | // }); 68 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/common/createPRA/createPra.css: -------------------------------------------------------------------------------- 1 | .div-container { 2 | display: grid; 3 | justify-items: center; 4 | margin-top: 50px; 5 | margin-left: auto; 6 | margin-right: auto; 7 | gap: 1rem; 8 | width: 100vw; 9 | } 10 | .span-style { 11 | background-color: rgba(176, 196, 222, 0.43); 12 | margin-bottom: 50px; 13 | border-radius: 7px; 14 | width: min(700px, 90%); 15 | font-size: 18px; 16 | padding: 10px; 17 | outline: none; 18 | border-color:black; 19 | } 20 | 21 | .text-style { 22 | font-size: 20px; 23 | justify-self: center; 24 | font-weight: 500; 25 | } 26 | 27 | .coe-deadline { 28 | font-size: 20px; 29 | font-weight: 500; 30 | } 31 | 32 | .createPRAsub { 33 | color: #0e72ab; 34 | text-align: center; 35 | font-size: 20px; 36 | font-weight: bold; 37 | margin-top: 20px; 38 | } 39 | .createspinnerload { 40 | margin-top: 100px; 41 | display: flex; 42 | align-items: center; 43 | justify-content: center; 44 | } 45 | .text-style2 { 46 | display: flex; 47 | font-size: 20px; 48 | justify-content: center; 49 | text-align: start; 50 | gap:10px; 51 | align-items: center; 52 | font-weight: 500; 53 | } 54 | 55 | .select-dd { 56 | 57 | font-size: 17px; 58 | border: none; 59 | text-align: center; 60 | padding: 4px; 61 | border-radius: 7px; 62 | background-color: rgba(176, 196, 222, 0.43); 63 | } 64 | .create-button { 65 | margin-top: 20px; 66 | width: auto !important; 67 | padding: 5px 16px !important; 68 | height: auto !important; 69 | cursor: pointer; 70 | } 71 | .date-time { 72 | display: flex; 73 | gap: 10px; 74 | /* width: 250px; */ 75 | } 76 | 77 | @media screen and (max-width: 600px) { 78 | .text-style2 { 79 | display: flex; 80 | row-gap: 7px; 81 | flex-direction: column; 82 | font-size: 20px; 83 | justify-content: center; 84 | text-align: start; 85 | align-items: center; 86 | font-weight: 500; 87 | } 88 | } 89 | 90 | 91 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/common/LockListSubjects/lockList.css: -------------------------------------------------------------------------------- 1 | .lockList-container { 2 | text-align: center; 3 | } 4 | 5 | .locklist-button { 6 | margin: 10px; 7 | } 8 | .btn-container { 9 | display: flex; 10 | justify-content: center; 11 | } 12 | .small { 13 | padding: 0px; 14 | margin: 0px; 15 | width: 0px; 16 | border: aqua; 17 | } 18 | .list-container { 19 | border-radius: 10px; 20 | padding: 0.5rem; 21 | padding-top: 0px; 22 | display: flex; 23 | flex-direction: column; 24 | flex-wrap: wrap; 25 | } 26 | 27 | .flex-container { 28 | display: flex; 29 | gap: 30px; 30 | padding: 15px 10px; 31 | flex-wrap: wrap; 32 | justify-content: center; 33 | } 34 | .select-locklist { 35 | max-width: 300px; 36 | min-width: 270px; 37 | text-align: left; 38 | justify-self: center; 39 | align-self: center; 40 | margin-bottom: 5px; 41 | margin-top: 5px; 42 | } 43 | .list-head { 44 | padding-bottom: 5px; 45 | } 46 | .instruction { 47 | color: #0e72ab; 48 | font-weight: bold; 49 | letter-spacing: 0.4px; 50 | } 51 | .course-heading { 52 | text-align: center; 53 | margin: 0px; 54 | color: #0e72ab; 55 | font-weight: bold; 56 | padding: 10px; 57 | padding-top: 0px; 58 | } 59 | 60 | .locklist-dropdown-title { 61 | font-weight: 500; 62 | margin: 0px; 63 | margin-bottom: 10px; 64 | } 65 | .add-button { 66 | border: none; 67 | background-color: white; 68 | width: auto; 69 | font-size: 16px; 70 | margin-top: 5px; 71 | } 72 | .lock-screen-icon { 73 | text-align: right; 74 | color: #0e72ab; 75 | } 76 | .li-tag-flex { 77 | display: flex; 78 | flex-direction: row; 79 | justify-content: space-between; 80 | width: 100%; 81 | margin-bottom: 7px; 82 | box-shadow: 0px 3px 1px 1px #0e72ab; 83 | border-radius: 4px; 84 | padding: 0.5rem 0.7rem; 85 | background-color: rgb(176, 196, 222, 0.25); 86 | } 87 | .viewdept-button-locklist { 88 | margin-top: 10px; 89 | padding: 8.5px !important; 90 | cursor: pointer; 91 | align-self: flex-end; 92 | margin-left: auto; 93 | margin-right: 10px; 94 | } 95 | .viewdep-flex { 96 | display: flex; 97 | } 98 | 99 | @media screen and (max-width: 600px) { 100 | .li-tag-flex { 101 | width: 100%; 102 | } 103 | .list-container { 104 | width: 80%; 105 | } 106 | .viewdept-button-locklist { 107 | padding: 9px !important; 108 | font-size: 1em; 109 | align-self: flex-end; 110 | margin-left: auto; 111 | margin-right: 10px; 112 | } 113 | .viewdep-flex { 114 | display: flex; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/download/download.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | // import "./download.css"; 3 | import axios from "axios"; 4 | import { ref, getDownloadURL } from "firebase/storage"; 5 | import { storage } from "./../../../firebase"; 6 | 7 | function Download({ 8 | url, 9 | text = "DOWNLOAD", 10 | userID = "random", 11 | isIcon = true, 12 | setShowDialog, 13 | }) { 14 | async function download() { 15 | if (url !== null) { 16 | if (url.slice(0, 5) == "https") { 17 | //do nothing 18 | } else { 19 | await getDownloadURL(ref(storage, url)).then((ux) => { 20 | url = ux; 21 | }); 22 | } 23 | axios({ 24 | url: url, 25 | method: "GET", 26 | responseType: "blob", 27 | }).then((response) => { 28 | const url = window.URL.createObjectURL(new Blob([response.data])); 29 | const link = document.createElement("a"); 30 | link.href = url; 31 | if ( 32 | response.data.type.split("/").pop() == 33 | "vnd.openxmlformats-officedocument.presentationml.presentation" 34 | ) { 35 | link.setAttribute("download", userID + ".pptx"); 36 | } else if (response.data.type.split("/").pop() == "vnd.ms-powerpoint") { 37 | link.setAttribute("download", userID + ".ppt"); 38 | } else { 39 | link.setAttribute( 40 | "download", 41 | userID + "." + response.data.type.split("/").pop() 42 | ); 43 | } 44 | document.body.appendChild(link); 45 | link.click(); 46 | document.body.removeChild(link); 47 | }); 48 | } else { 49 | setShowDialog("File does not exist"); 50 | } 51 | } 52 | 53 | const getDownload = async() => { 54 | await download(); 55 | if(setShowDialog){ 56 | setShowDialog(false); 57 | } 58 | } 59 | 60 | return ( 61 | 87 | ); 88 | } 89 | 90 | export default Download; 91 | -------------------------------------------------------------------------------- /frontend/src/components/login/contactPage/contactPage.css: -------------------------------------------------------------------------------- 1 | .contactComponent{ 2 | padding: 20px; 3 | display: flex; 4 | justify-content: center; 5 | justify-items: center; 6 | align-items: center; 7 | } 8 | 9 | .formComponent{ 10 | display: flex; 11 | flex-direction: column; 12 | justify-content: center; 13 | padding: 0; 14 | margin: 0; 15 | } 16 | 17 | .contactTitle{ 18 | font-size: x-large; 19 | text-align: left; 20 | } 21 | 22 | .field{ 23 | margin: 8px auto; 24 | } 25 | 26 | .inputFieldStyle{ 27 | outline: none; 28 | border:none; 29 | border-radius: 6px; 30 | font-size: large; 31 | color: whitesmoke; 32 | background-color:#375C86; 33 | width: 420px; 34 | padding: 10px 20px; 35 | } 36 | 37 | .labelStyle{ 38 | margin-bottom: 6px; 39 | } 40 | 41 | .errorFieldStyle{ 42 | outline: none; 43 | box-shadow:red 0px 2px 8px 0px; 44 | border:none; 45 | border-radius: 6px; 46 | font-size: large; 47 | background-color:#e2e2e2; 48 | animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both; 49 | transform: translate3d(0, 0, 0); 50 | width: 420px; 51 | padding: 10px 20px; 52 | } 53 | 54 | 55 | /* .textareaStyle{ 56 | max-width: 420px; 57 | width: 420px; 58 | outline: none; 59 | border:none; 60 | border-radius: 6px; 61 | padding: 10px 20px; 62 | font-size: large; 63 | color: whitesmoke; 64 | background-color:#375C86; 65 | } */ 66 | 67 | .inputFieldStyle:is(:hover, :focus){ 68 | color: whitesmoke; 69 | background-color:#375C86; 70 | } 71 | 72 | .errorFieldStyle:is(:hover, :focus){ 73 | color: whitesmoke; 74 | background-color:#375C86; 75 | } 76 | 77 | .contactButton{ 78 | margin-top: 20px; 79 | outline: none; 80 | border: none; 81 | font-size: small; 82 | background-color: white; 83 | color: black; 84 | padding:15px 20px; 85 | letter-spacing: 1px; 86 | font-weight: bold; 87 | border-radius: 8px; 88 | width: 150px; 89 | cursor: pointer; 90 | } 91 | 92 | .labelStyle{ 93 | font-size: large; 94 | font-weight: 700; 95 | padding: 4px auto; 96 | } 97 | 98 | @media screen and (max-width:600px) { 99 | .inputFieldStyle{ 100 | width: 75vw; 101 | } 102 | .textareaStyle{ 103 | max-width: 75vw; 104 | } 105 | } 106 | 107 | 108 | @keyframes shake { 109 | 10%, 90% { 110 | transform: translate3d(-1px, 0, 0); 111 | } 112 | 113 | 20%, 80% { 114 | transform: translate3d(2px, 0, 0); 115 | } 116 | 117 | 30%, 50%, 70% { 118 | transform: translate3d(-4px, 0, 0); 119 | } 120 | 121 | 40%, 60% { 122 | transform: translate3d(4px, 0, 0); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/spinner/spinner.css: -------------------------------------------------------------------------------- 1 | .spinner { 2 | display: flex;justify-content: center;align-items: center; 3 | } 4 | 5 | .spinner:after { 6 | content: ""; 7 | display: block; 8 | position: absolute; 9 | border-width: 3px; 10 | border-style: solid; 11 | border-radius: 50%; 12 | } 13 | 14 | /* .spinner.spinner-1:before { 15 | width: 45px; 16 | height: 45px; 17 | border-bottom-color: #0E72AB; 18 | border-right-color: #0E72AB; 19 | border-top-color: rgba(33, 33, 33, 0); 20 | border-left-color: rgba(33, 33, 33, 0); 21 | border-width: 1px; 22 | top: 0px; 23 | left: 0px; 24 | animation: rotate-animation 1s linear 0s infinite; 25 | } */ 26 | .spinner.spinner-1:after { 27 | width: 35px; 28 | height: 35px; 29 | mask-border:unset; 30 | border-width: 5px; 31 | border-style:dashed; 32 | border-bottom-color: #0E72AB; 33 | border-right-color: #0E72AB; 34 | border-top-color: white; 35 | border-left-color: white; 36 | animation: anti-rotate-animation 1s linear 0s infinite; 37 | } 38 | 39 | .spinnerDark { 40 | position: relative; 41 | display: flex;justify-content: center;align-items: center; 42 | } 43 | 44 | .spinnerDark:after { 45 | content: ""; 46 | display: block; 47 | position: absolute; 48 | border-width: 3px; 49 | border-style: solid; 50 | border-radius: 50%; 51 | } 52 | 53 | /* .spinnerDark.spinnerDark-1:before { 54 | width: 45px; 55 | height: 45px; 56 | border-width: 2px; 57 | border-width: 1px; 58 | 59 | border-bottom-color: white; 60 | border-right-color: white; 61 | border-top-color: rgba(33, 33, 33, 0); 62 | border-left-color: rgba(33, 33, 33, 0); 63 | top: 0px; 64 | left: 0px; 65 | animation: rotate-animation 1s linear 0s infinite; 66 | } */ 67 | .spinnerDark.spinnerDark-1:after { 68 | width: 35px; 69 | height: 35px; 70 | border-width: 4px; 71 | border-bottom-color:white; 72 | border-right-color: white; 73 | border-top-color: rgba(33, 33, 33, 0); 74 | border-left-color: rgba(33, 33, 33, 0); 75 | top: 9px; 76 | left: 9px; 77 | animation: anti-rotate-animation 0.85s linear 0s infinite; 78 | } 79 | 80 | 81 | /* spinner-1 styles */ 82 | @keyframes rotate-animation { 83 | 0% { 84 | transform: rotate(0deg); 85 | } 86 | /* 60%{ 87 | transform: rotate(240deg); 88 | } */ 89 | 100% { 90 | transform: rotate(360deg); 91 | } 92 | } 93 | 94 | @keyframes anti-rotate-animation { 95 | 0% { 96 | transform: rotate(0deg); 97 | } 98 | /* 40%{ 99 | transform: rotate(120deg); 100 | } 101 | 60%{ 102 | transform: rotate(240deg); 103 | } */ 104 | 100% { 105 | transform: rotate(-360deg); 106 | } 107 | } 108 | 109 | .loadingScreen{ 110 | display: grid; 111 | justify-items: center; 112 | align-items: center; 113 | height: 100vh; 114 | } 115 | 116 | -------------------------------------------------------------------------------- /frontend/src/components/global_ui/input/input.module.css: -------------------------------------------------------------------------------- 1 | .inputField { 2 | position : relative; 3 | font-size: 1rem; 4 | height: fit-content; 5 | /* width: 100%; */ 6 | --label-top:calc(23%); 7 | } 8 | .label { 9 | position : absolute; 10 | left : 0.6em; 11 | padding-left : 0.2em; 12 | padding-right : 0.2em; 13 | color : #5a5858; 14 | font-size : 1em; 15 | top : var(--label-top); 16 | pointer-events: none; 17 | transition : top 0.2s ease, 18 | font-size 0.2s ease, 19 | color 0.2s ease; 20 | } 21 | 22 | .input { 23 | box-sizing:border-box; 24 | border : 2px solid #ddd; 25 | padding : 0.6em; 26 | font-size : 1em; 27 | border-radius: 4px; 28 | margin-left : 1em; 29 | /* width: 100%; */ 30 | outline : none; 31 | transition : border-color 0.3s ease, 32 | border-color 0.2s ease 33 | ; 34 | 35 | } 36 | 37 | .inputField span{ 38 | position: absolute; 39 | left: 0.4%; 40 | color: red; 41 | font-size: 0.8em; 42 | padding-top: 0.2em; 43 | padding-left: 0.3em; 44 | } 45 | .inputField .normalField{ 46 | --label-top:calc(50% - 10px); 47 | } 48 | .errorField{ 49 | border-color: red; 50 | } 51 | 52 | .errorField +.label{ 53 | color: red; 54 | --label-top:17%; 55 | } 56 | .input:valid+.label, 57 | .input:focus+.label { 58 | font-size : 0.7em; 59 | top : -8px; 60 | color : black; 61 | border-color: black; 62 | background : white; 63 | } 64 | 65 | .input:focus { 66 | border-color: black; 67 | } 68 | .errorField:focus{ 69 | border-color: red; 70 | } 71 | .errorField:valid+.label, 72 | .errorField:focus +.label{ 73 | color: red; 74 | } 75 | .input[type=number]::-webkit-inner-spin-button, 76 | .input[type=number]::-webkit-outer-spin-button { 77 | -webkit-appearance: none; 78 | -moz-appearance: none; 79 | appearance: none; 80 | margin: 0; 81 | } 82 | 83 | textarea { 84 | box-sizing:border-box; 85 | border : 2px solid #ddd; 86 | font-size : 1.1em; 87 | border-radius: 4px; 88 | width: 100%; 89 | outline : none; 90 | transition : border-color 0.3s ease, 91 | border-color 0.2s ease 92 | ; 93 | resize: none; 94 | padding: 10px; 95 | } 96 | textarea:focus{ 97 | border-color: black; 98 | 99 | } 100 | 101 | textarea+label{ 102 | top: 0; 103 | left:1.2em; 104 | text-align: center; 105 | margin-top: 10px; 106 | font-size:0.9em; 107 | padding: 0px; 108 | transition : top 0.2s ease, 109 | font-size 0.2s ease, 110 | color 0.2s ease; 111 | } 112 | 113 | textarea:valid+label,textarea:focus+label{ 114 | position:absolute; 115 | top:-20px; 116 | left: 0.7em; 117 | padding: 0px 2px; 118 | color: black; 119 | height: 15px; 120 | font-size : 0.7em; 121 | 122 | background-color: white; 123 | } 124 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/services/hodServices.js: -------------------------------------------------------------------------------- 1 | import { db } from "../../../firebase"; 2 | import { 3 | doc, 4 | getDoc, 5 | updateDoc, 6 | collection, 7 | query, 8 | getDocs, 9 | Timestamp, 10 | } from "firebase/firestore"; 11 | import { 12 | fetchRegulationOptions, 13 | fetchRegulationsArray, 14 | fetchSemNumber, 15 | getStudentData, 16 | fetchMidNumber 17 | } from "../../student/services/studentServices"; 18 | import { getUploadedFileByPath } from "../../student/services/storageServices"; 19 | import { 20 | getFirstYearCurriculumData, 21 | getDeptCurriculum, 22 | } from "./curriculumServices"; 23 | import { getAcademicYear } from "./adminDeadlinesServices"; 24 | 25 | 26 | //change subs collection 27 | export async function getFirstYearStatistics() { 28 | try { 29 | let semNumber = await fetchSemNumber('BTech','1'); 30 | 31 | let arr1 = await getFirstYearCurriculumData(semNumber); 32 | let mid = await fetchMidNumber("BTech",'1'); 33 | let createdPRA = []; 34 | let str = ""; 35 | let acadYearData = await getAcademicYear('BTech','1'); 36 | let acadYear = acadYearData.data; 37 | 38 | const q = query(collection(db, `classesinfo/BTech/${acadYear}`)); 39 | 40 | const allDocs = await getDocs(q); 41 | 42 | allDocs.docs.forEach((e) => { 43 | let arr = e.id.split("_"); 44 | if (arr[0] == "1" ) { 45 | for (let i = 0; i < e.data()["subjects"].length; i++) { 46 | let sub = e.data()["subjects"][i]; 47 | if (mid=='1') 48 | { 49 | 50 | if(sub.deadline1) 51 | { 52 | 53 | str = "BTech"+"_"+acadYear+"_"+e.id + "_" + sub.subject; 54 | createdPRA.push(str); 55 | } 56 | 57 | } 58 | if (mid=='2') 59 | { 60 | if(sub.deadline2) 61 | { 62 | str = "BTech"+"_"+acadYear+"_"+e.id + "_" + sub.subject; 63 | createdPRA.push(str); 64 | } 65 | } 66 | 67 | } 68 | } 69 | }); 70 | let difference = arr1.filter((x) => !createdPRA.includes(x)); 71 | return difference; 72 | } catch (e) { 73 | console.log(e); 74 | } 75 | } 76 | 77 | 78 | //change subs collection 79 | export async function getStatistics(course, dept, year) { 80 | try { 81 | let acadYear = await getAcademicYear(course,year) 82 | let arr1 = await getDeptCurriculum(dept, course, year); 83 | let createdPRA = []; 84 | let str = ""; 85 | const q = query(collection(db, "classesinfo",course,acadYear.data)); 86 | const allDocs = await getDocs(q); 87 | allDocs.docs.forEach((e) => { 88 | let arr = e.id.split("_"); 89 | if ( 90 | arr[0] == year && 91 | arr[1] == dept 92 | ) { 93 | for (let i = 0; i < e.data()["subjects"].length; i++) { 94 | str = e.id + "_" + e.data()["subjects"][i].subject; 95 | createdPRA.push(str); 96 | } 97 | } 98 | }); 99 | let difference = arr1.filter((x) => !createdPRA.includes(x)); 100 | return difference; 101 | } catch (e) { 102 | console.log(e); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/services/praServices.js: -------------------------------------------------------------------------------- 1 | import { db } from "../../../firebase"; 2 | import { 3 | doc, 4 | getDoc, 5 | updateDoc, 6 | setDoc, 7 | arrayUnion, 8 | arrayRemove, 9 | collection, 10 | query, 11 | getDocs, 12 | Timestamp, 13 | } from "firebase/firestore"; 14 | 15 | export const setPRA = async (sub, department, date, inst, isMid1, isMid2) => { 16 | //in createPRA.js 17 | //if the faculty is coming to createPRA page, it means that the faculty has enrollled. So, in the doc(BTech/2021-22/3_CSE_D), a subjects array exists and the particular subject element also exists. While setting PRA deadline, just update the array element. 18 | console.log(sub, department, date, inst); 19 | // department = "BTech_2021-22_3_CSE_D"; 20 | console.log(department.split("_")); 21 | let course = department.split("_")[0]; 22 | let acadYear = department.split("_")[1]; 23 | let classroom = 24 | department.split("_")[2] + 25 | "_" + 26 | department.split("_")[3] + 27 | "_" + 28 | department.split("_")[4]; 29 | 30 | console.log(course, acadYear, classroom); 31 | try { 32 | const docRef = doc(db, "classesinfo", course, acadYear, classroom); 33 | const docData = await getDoc(docRef); 34 | if (docData.exists()) { 35 | const subjects = docData.data()["subjects"]; 36 | 37 | for (let index = 0; index < subjects.length; index++) { 38 | const ele = subjects[index]; 39 | console.log(ele.subject === sub); 40 | if (ele.subject === sub) { 41 | console.log("subject found"); 42 | 43 | await updateDoc(docRef, { subjects: arrayRemove(ele) }); 44 | if (isMid1) { 45 | console.log("its mid1"); 46 | await updateDoc(docRef, { 47 | subjects: arrayUnion({ 48 | facultyID: ele.facultyID, 49 | deadline1: date, 50 | instructions: inst, 51 | subject: sub, 52 | }), 53 | }); 54 | } else if (isMid2) { 55 | console.log("its mid2"); 56 | await updateDoc(docRef, { 57 | subjects: arrayUnion({ 58 | deadline1: ele.deadline1, 59 | facultyID: ele.facultyID, 60 | deadline2: date, 61 | instructions: inst, 62 | subject: sub, 63 | }), 64 | }); 65 | } 66 | break; 67 | } 68 | } 69 | } 70 | } catch (error) { 71 | console.log(error); 72 | } 73 | }; 74 | //TODO 75 | //remove dept declaration 76 | export const getPRA = async (sub, department) => { 77 | //in createPra.js 78 | //department = "BTech_2021-22_3_CSE_D"; 79 | console.log(department.split("_")); 80 | let course = department.split("_")[0]; 81 | let acadYear = department.split("_")[1]; 82 | let classroom = 83 | department.split("_")[2] + 84 | "_" + 85 | department.split("_")[3] + 86 | "_" + 87 | department.split("_")[4]; 88 | console.log(sub,department) 89 | try { 90 | const docRef = doc(db, "classesinfo", course, acadYear, classroom); 91 | const docData = await getDoc(docRef); 92 | const subjects = docData.data()["subjects"]; 93 | 94 | let res = {}; 95 | subjects.forEach((v) => { 96 | if (sub === v.subject) { 97 | res = v; 98 | return; 99 | } 100 | }); 101 | return res; 102 | } catch (error) { 103 | console.log(error); 104 | } 105 | }; 106 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `npm start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `npm test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `npm run eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `npm run build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /frontend/src/components/login/footer/footer.css: -------------------------------------------------------------------------------- 1 | .customFooter{ 2 | display: flex; 3 | flex-direction: column; 4 | justify-content:center; 5 | align-items:stretch; 6 | padding: 2vw 5vw; 7 | color: white; 8 | background-color: #18395A; 9 | background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:svgjs='http://svgjs.com/svgjs' width='1440' height='560' preserveAspectRatio='none' viewBox='0 0 1440 560'%3e%3cg clip-path='url(%26quot%3b%23SvgjsClipPath1029%26quot%3b)' fill='none'%3e%3ccircle r='93.335' cx='36.33' cy='-29.91' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3ccircle r='93.335' cx='414.45' cy='337.54' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3ccircle r='93.335' cx='828.28' cy='672.35' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3ccircle r='80.125' cx='1175.99' cy='352.91' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3ccircle r='100.995' cx='211.22' cy='126.77' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3ccircle r='56.78' cx='914.21' cy='217.91' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3ccircle r='184.44' cx='984.3' cy='75.62' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3ccircle r='55.885' cx='1260.21' cy='526.11' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3ccircle r='167.375' cx='555.33' cy='493.59' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3ccircle r='166.73' cx='1.5' cy='439.53' stroke='%23566799' stroke-opacity='0.28' stroke-width='2'%3e%3c/circle%3e%3c/g%3e%3cdefs%3e%3cclipPath id='SvgjsClipPath1029'%3e%3crect width='1440' height='560' x='0' y='0'%3e%3c/rect%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e"); 10 | } 11 | 12 | .footerLogo{ 13 | margin-top: 5vw; 14 | min-width: 420px; 15 | max-width: 500px; 16 | display: flex; 17 | flex-direction: column; 18 | justify-content: start; 19 | align-items:flex-start; 20 | } 21 | 22 | .content1{ 23 | display: flex; 24 | flex-direction: row; 25 | justify-content: space-between; 26 | } 27 | 28 | 29 | hr{ 30 | border-top: 1px; 31 | border-color:grey; 32 | width: 100%; 33 | } 34 | 35 | .links{ 36 | margin: 10px; 37 | display: flex; 38 | gap: 20px; 39 | justify-content: center; 40 | align-items: center; 41 | } 42 | 43 | .links > i{ 44 | cursor: pointer; 45 | font-size: large; 46 | background-color: white; 47 | color: black; 48 | text-align: center; 49 | width: 20px; 50 | padding: 6px; 51 | border-radius: 6px; 52 | 53 | } 54 | 55 | .dev{ 56 | justify-self: center; 57 | display: flex; 58 | justify-content: center; 59 | align-items: center; 60 | gap: 10px; 61 | } 62 | 63 | .devInfo{ 64 | text-align: center; 65 | cursor: pointer; 66 | color: white; 67 | text-decoration: none; 68 | font-size: large; 69 | } 70 | .devInfo:hover{ 71 | text-decoration: underline; 72 | } 73 | 74 | @media screen and (max-width: 1000px) { 75 | .content1{ 76 | flex-direction: column; 77 | justify-content: center; 78 | align-items: center; 79 | } 80 | .footerLogo{ 81 | margin: auto; 82 | margin-top: 5vw; 83 | } 84 | 85 | 86 | /* .footerLogo{ 87 | align-items: center; 88 | justify-content: center; 89 | } */ 90 | } 91 | 92 | @media screen and (max-width:600px) { 93 | .footerLogo{ 94 | padding:auto 10px; 95 | min-width: 90%; 96 | margin: 30px; 97 | width: 90%; 98 | } 99 | .txt{ 100 | text-align: center; 101 | } 102 | } 103 | 104 | 105 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/services/gradingServices.js: -------------------------------------------------------------------------------- 1 | import { db } from "../../../firebase"; 2 | import { 3 | doc, 4 | getDoc, 5 | updateDoc, 6 | } from "firebase/firestore"; 7 | import { getAcademicYear } from "./adminDeadlinesServices"; 8 | import { fetchSemNumber } from "../../student/services/studentServices"; 9 | 10 | 11 | export async function getMarks(className, email) { 12 | 13 | 14 | //grading.js 15 | const userRef = doc(db, "students", email + "@vbithyd.ac.in"); 16 | try { 17 | const docSnap = await getDoc(userRef); 18 | const data = docSnap.data() 19 | const acadYear =( await getAcademicYear(data.course,data.year)).data 20 | const semNo = await fetchSemNumber(data.course,data.year) 21 | if (docSnap.exists()) { 22 | return { 23 | data:data 24 | [acadYear][`sem${semNo}`].find((e) => e.subject === className.split("_").pop()), 25 | error: null, 26 | }; 27 | } else { 28 | return { 29 | data: null, 30 | // status:"UNGRADED", 31 | error: "Student Not Graded", 32 | }; 33 | } 34 | } catch (error) { 35 | return { 36 | data: null, 37 | status: null, 38 | error: error.code, 39 | }; 40 | } 41 | } 42 | 43 | 44 | 45 | 46 | export async function postMarks( 47 | facultyID, 48 | className, 49 | studentID, 50 | midNo, 51 | marks, 52 | remarks 53 | ) { 54 | //grading 55 | let error = null; 56 | 57 | const userRef = doc(db, `students`, studentID + "@vbithyd.ac.in"); 58 | 59 | const userDoc = await getDoc(userRef); 60 | const data = userDoc.data() 61 | const acadYear = (await getAcademicYear(data.course,data.year)).data 62 | const semNo = await fetchSemNumber(data.course,data.year) 63 | 64 | try { 65 | if (midNo === "1") { 66 | if (userDoc.exists()) { 67 | let subs = data[acadYear][`sem${semNo}`]; 68 | let updateSubs = {} 69 | subs.find((e) => { 70 | if (e.subject === className.split("_")[5]) { 71 | e.gradeStatus1 = "GRADED"; 72 | e.mid1_marks = marks; 73 | e.mid1_remarks = remarks; 74 | } 75 | }); 76 | updateSubs[`${acadYear}.sem${semNo}`] = subs 77 | await updateDoc(userRef, updateSubs ); 78 | } else { 79 | error = "Unknown Error Occured"; 80 | } 81 | } else if (midNo === "2") { 82 | if (userDoc.exists()) { 83 | let subs = data[acadYear][`sem${semNo}`]; 84 | let updateSubs = {} 85 | 86 | subs.find((e) => { 87 | if (e.subject === className.split("_")[5]) { 88 | e.gradeStatus2 = "GRADED"; 89 | e.mid2_marks = marks; 90 | e.mid2_remarks = remarks; 91 | } 92 | }); 93 | updateSubs[`${acadYear}.sem${semNo}`] = subs 94 | 95 | await updateDoc(userRef,updateSubs); 96 | } else { 97 | error = "Unknown Error Occured"; 98 | } 99 | } 100 | console.log(error) 101 | } catch (e) { 102 | console.log(e); 103 | error = e.code; 104 | } 105 | return error; 106 | } 107 | 108 | export async function fetchRegulationsArray() { 109 | try { 110 | const adminRef = doc(db, `adminData/regulations`); 111 | const adminDoc = await getDoc(adminRef); 112 | if (adminDoc.exists()) { 113 | let regarray = adminDoc.data()["regarray"]; 114 | return regarray; 115 | } 116 | } catch (e) { 117 | console.log(e); 118 | } 119 | } 120 | 121 | export async function fetchRegulation(year) { 122 | 123 | try { 124 | const docref = doc(db, "adminData/regulations"); 125 | const document = await getDoc(docref); 126 | 127 | if (document.exists()) { 128 | return document.data().mapping[year]; 129 | } 130 | return { 131 | status: "error", 132 | message: "Please check whether regulations are properly set" 133 | } 134 | } catch (error) { 135 | console.log(error); 136 | } 137 | } -------------------------------------------------------------------------------- /frontend/src/components/login/loginPage.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect ,useState} from "react"; 2 | import "./loginPage.css"; 3 | import { useNavigate } from "react-router-dom"; 4 | import { useAuth } from "../context/AuthContext"; 5 | import { LoadingScreen } from "../global_ui/spinner/spinner"; 6 | import Footer from "./footer/footer"; 7 | import Dialog from "../global_ui/dialog/dialog"; 8 | 9 | 10 | // import Announcement from "./announcements/announcements"; 11 | 12 | export default function LoginPage() { 13 | const { signInWithGoogle, currentUser, loading } = useAuth(); 14 | const nav = useNavigate(); 15 | 16 | const [showNotEnrolledDialog, setShowNotEnrolledDialog] = useState(false); 17 | 18 | const text="Participatory Report Assessment of Theme and Innovation Based Harmonic Activities"; 19 | 20 | const [displayText, setdisplayText] = useState(""); 21 | let i=0; 22 | 23 | function animate() { 24 | 25 | setTimeout(() => { 26 | setdisplayText(text.slice(0,i)); 27 | i+=1; 28 | animate() 29 | }, 75); 30 | } 31 | 32 | useEffect(() => { 33 | animate() 34 | if (currentUser) { 35 | if (currentUser.userType === "STUDENT") { 36 | 37 | if (!currentUser.email) { 38 | setShowNotEnrolledDialog(true); 39 | } 40 | else if (currentUser.isFirstTime) { 41 | // setShowNotEnrolledDialog(true); 42 | nav("/student/subjectslist", { replace: true }); 43 | } 44 | else { 45 | nav("/student/subjectslist", { replace: true }); 46 | } 47 | } else if (currentUser.userType === "FACULTY") { 48 | if (currentUser.isFirstTime) { 49 | console.log("first time"); 50 | nav("/faculty/enroll", { replace: true }); 51 | } else if (currentUser.isCOE) { 52 | nav("/faculty/coesearch", { replace: true }); 53 | } 54 | else if (currentUser.isAdmin) { 55 | nav("/faculty/admin", { replace: true }); 56 | } 57 | else { 58 | nav("/faculty/classlist", { replace: true }); 59 | }} 60 | } 61 | else{ 62 | nav("/") 63 | } 64 | }, [currentUser]); 65 | 66 | return loading === false ? ( 67 |
68 |
69 | 70 |
71 |
72 | Pratibha 73 | {/* PRATIBHA */} 74 |
75 | vbit 76 | codingStudio 77 |
78 | 79 | { 80 | showNotEnrolledDialog && 81 | { 82 | setShowNotEnrolledDialog(false) 83 | }}/> 84 | } 85 | 86 |
87 |
88 | Pratibha 89 |
90 | 91 | {displayText} 92 | | 93 | 94 |
95 | 96 |
97 | 98 |
99 | 100 |
101 | 102 | 105 |
106 | 107 |
108 | 109 | 112 |
113 | 114 |
115 |
116 | 117 |
118 | 119 | {/* */} 120 | 121 |
122 |
123 | ) : ( 124 | 125 | ); 126 | } 127 | -------------------------------------------------------------------------------- /frontend/src/components/login/contactPage/contactPage.js: -------------------------------------------------------------------------------- 1 | import React,{useState} from 'react' 2 | import './contactPage.css' 3 | import {db} from '../../../firebase'; 4 | import { addDoc, collection, doc,setDoc} from "firebase/firestore"; 5 | import {Spinner} from '../../global_ui/spinner/spinner' 6 | 7 | function ContactPage() { 8 | const [name, setName] = useState(""); 9 | const [email, setEmail] = useState(""); 10 | const [query, setQuery] = useState(""); 11 | 12 | const [loading, setLoading] = useState(false); 13 | 14 | const [result, setResult] = useState(null); 15 | 16 | async function postAQuery() { 17 | setLoading(true); 18 | let data = { 19 | name:name, 20 | email:email, 21 | query:query 22 | } 23 | const collectionRef = collection(db, 'queries'); 24 | try{ 25 | await addDoc(collectionRef,data); 26 | setResult("Query Posted Successfully"); 27 | setName(""); 28 | setEmail(""); 29 | setQuery(""); 30 | } 31 | catch(e){ 32 | setResult(e.toString()); 33 | } 34 | setTimeout(() => { 35 | setLoading(false); 36 | setResult(null); 37 | }, 3000); 38 | 39 | } 40 | 41 | const [errors, setErrors] = useState({ 42 | nameError:null, 43 | emailError:null, 44 | queryError:null 45 | }) 46 | 47 | function validate() { 48 | setErrors({ 49 | nameError:null, 50 | emailError:null, 51 | queryError:null 52 | }) 53 | let nameError=null; 54 | let emailError=null; 55 | let queryError=null; 56 | if(name.length<6){ 57 | nameError="name cannot be less than 6 characters" 58 | } 59 | if(email.length<15){ 60 | emailError="email cannot be less than 15 characters" 61 | } 62 | if(query.length<15){ 63 | queryError="query cannot be less than 10 characters" 64 | } 65 | 66 | setErrors({ 67 | nameError:nameError, 68 | emailError:emailError, 69 | queryError:queryError 70 | }) 71 | if(nameError==null && emailError==null && queryError==null){ 72 | return true; 73 | }else{ 74 | return false; 75 | } 76 | } 77 | 78 | async function handleSubmit() { 79 | if(validate()){ 80 | await postAQuery(); 81 | }else{ 82 | console.log("Errors"); 83 | } 84 | } 85 | 86 | return ( 87 |
88 |
89 |

Contact Us

90 |
91 |

Name

92 | setName(e.target.value)} placeholder='Name' value={name} 95 | > 96 | {/* { 97 | errors.nameError &&

{errors.nameError}

98 | } */} 99 |
100 | 101 |
102 |

Email

103 | 104 | setEmail(e.target.value)} placeholder='Email'> 105 | {/* { 106 | errors.nameError &&

{errors.emailError}

107 | } */} 108 |
109 | 110 |
111 |

Query

112 | 113 | 114 | {/* { 115 | errors.nameError &&

{errors.queryError}

116 | } */} 117 |
118 | 119 | { 120 | loading? 121 | result!=null?

{result}

:: 122 | 123 | } 124 |
125 |
126 | ) 127 | } 128 | 129 | export default ContactPage 130 | -------------------------------------------------------------------------------- /frontend/src/components/student/services/storageServices.js: -------------------------------------------------------------------------------- 1 | import { db, storage } from "../../../firebase"; 2 | import { ref,uploadBytesResumable, getDownloadURL } from "firebase/storage"; 3 | import { doc, getDoc,updateDoc } from "firebase/firestore"; 4 | import { getAcademicYear } from "../../faculty/services/adminDeadlinesServices"; 5 | import { fetchSemNumber } from "./studentServices"; 6 | 7 | async function uploadFile(fileObj, course, year, academicYear, department, section, subject, midNo, email, title, fileName) { 8 | let error = null; 9 | 10 | //referring to the storage location | creating path 11 | const pra_ref = ref( 12 | storage, 13 | `${course}/${academicYear}/${year}/${department}/${section}/${subject}/${midNo}/${email.split('@')[0]}` 14 | ); 15 | 16 | //uploading files to storage 17 | return new Promise(async (resolve, reject) => { 18 | await uploadBytesResumable(pra_ref, fileObj) 19 | .then(async (snapshot) => { 20 | console.log((snapshot.bytesTransferred / snapshot.totalBytes) * 100); 21 | try { 22 | let subs = null; 23 | const semNo = await fetchSemNumber(course, year) 24 | const updateSubs = {} 25 | const docRef = doc(db, "students", email); 26 | //refers userdoc 27 | const docSnap = await getDoc(docRef); 28 | //checking doc exists to verify enrollment 29 | if (docSnap.exists()) { 30 | subs = docSnap.data()[academicYear][`sem${semNo}`]; 31 | //finding the subject and updating 32 | for (var i = 0; i < subs.length; i++) { 33 | if (subs[i].subject === subject) { 34 | let s = subs[i]; 35 | if (midNo === "1") { 36 | s.fileName1 = fileName 37 | s.topic = title 38 | s.mid_1 = snapshot.ref.fullPath; 39 | subs[i] = s; 40 | } else if (midNo === "2") { 41 | s.fileName2 = fileName 42 | s.topic = title 43 | s.mid_2 = snapshot.ref.fullPath; 44 | subs[i] = s; 45 | } 46 | break; 47 | } 48 | } 49 | try { 50 | //updating the user doc 51 | updateSubs[`${academicYear}.sem${semNo}`] = subs 52 | await updateDoc(docRef, updateSubs 53 | ); 54 | 55 | } catch (err) { 56 | error = err.toString(); 57 | } 58 | } else { 59 | error = "Student Enrollment Failed"; 60 | } 61 | } catch (err) { 62 | error = err.toString(); 63 | } 64 | }) 65 | .catch((err) => { 66 | error = err.toString(); 67 | }) 68 | if (error) { 69 | reject(error); 70 | } else { 71 | resolve(null); 72 | } 73 | }); 74 | } 75 | 76 | async function getUploadedFile(course,year,department,section,subject,midNo,email) { 77 | let academicYear = await getAcademicYear(course, year) 78 | let res={ 79 | url:null, 80 | error:null, 81 | } 82 | await getDownloadURL(ref(storage,`${course}/${academicYear}/${year}/${department}/${section}/${subject}/${midNo}/${email.split('@')[0]}`)) 83 | .then((url) => { 84 | res.url=url; 85 | }) 86 | .catch((error) => { 87 | res.error=error.toString(); 88 | }) 89 | return res; 90 | } 91 | 92 | async function getUploadedFileByPath(path) { 93 | let res={ 94 | url:null, 95 | error:null, 96 | } 97 | await getDownloadURL(ref(storage,path)) 98 | .then((url) => { 99 | res.url=url; 100 | }) 101 | .catch((error) => { 102 | res.error=error.code; 103 | }) 104 | return res; 105 | } 106 | 107 | export {uploadFile,getUploadedFile,getUploadedFileByPath} 108 | 109 | 110 | 111 | 112 | // let pra_ref; 113 | // if(fileObj.type=="application/vnd.openxmlformats-officedocument.presentationml.presentation"){ 114 | // pra_ref = ref( 115 | // storage, 116 | // `${course}/${year}/${department}/${section}/${subject}/${midNo}/${email.split('@')[0]}.pptx` 117 | // ); 118 | // }else{ 119 | // pra_ref = ref( 120 | // storage, 121 | // `${course}/${year}/${department}/${section}/${subject}/${midNo}/${email.split('@')[0]}` 122 | // ); 123 | // } -------------------------------------------------------------------------------- /frontend/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./App.css"; 3 | import { AuthProvider, useAuth } from "./components/context/AuthContext"; 4 | import { 5 | BrowserRouter as Router, 6 | Routes, 7 | Route, 8 | } from "react-router-dom"; 9 | import LoginPage from "./components/login/loginPage"; 10 | import SubjectsList from "./components/student/SubjectsList/SubjectsList"; 11 | import Upload from "./components/student/uploadpra/uploadpra"; 12 | import LockList from "./components/faculty/common/LockListSubjects/lockList"; 13 | import ClassList from "./components/faculty/generalFaculty/ClassList/classList"; 14 | import Grading from "./components/faculty/common/grading"; 15 | import ListofStudents from "./components/faculty/generalFaculty/ListOfStudents/ListOfStudents"; 16 | import CoeSearch from "./components/faculty/coe/coeSearch"; 17 | import EnrollClasses from "./components/student/enrollClass/enrollClasses"; 18 | import ViewSubmissions from "./components/faculty/common/ViewSubmissions/ViewSubmissions"; 19 | import CreatePra from "./components/faculty/common/createPRA/createPra"; 20 | import HODSearch from "./components/faculty/hod/HODSearch"; 21 | import AddClasses from "./components/faculty/common/LockListSubjects/addclasses"; 22 | import Deadlines from "./components/faculty/coe/deadlines"; 23 | import DeptReport from "./components/faculty/hod/deptReport"; 24 | import AdminPage from "./components/admin/adminPage.js"; 25 | import BulkEnrolls from "./components/admin/BulkEnrolls.js"; 26 | import ManualEnroll from "./components/admin/manualEnroll.js"; 27 | 28 | const App = () => { 29 | 30 | return ( 31 |
32 | 33 | 34 | 35 |
36 | ); 37 | }; 38 | const AllRoutes = () => { 39 | const { currentUser } = useAuth(); 40 | const studentVerified = currentUser && currentUser.userType==="STUDENT" 41 | const facultyVerified = currentUser && currentUser.userType ==='FACULTY' 42 | return ( 43 | 44 | 45 | { 46 | currentUser===null && }/> 47 | } 48 | } /> 49 | 50 | {studentVerified && ( 51 | 55 | } /> 56 | } /> 57 | 58 | } 59 | /> 60 | )} 61 | {facultyVerified && ( 62 | 66 | {currentUser.isAdmin && ( 67 | <> 68 | } /> 69 | } /> 70 | } /> 71 | 72 | )} 73 | {currentUser.isCOE && ( 74 | <> 75 | } /> 76 | } /> 77 | 78 | )} 79 | {(currentUser.isCOE || currentUser.isHOD) && ( 80 | } 84 | /> 85 | 86 | 87 | 88 | )} 89 | 90 | } /> 91 | 92 | } /> 93 | }/> 94 | 95 | } /> 96 | 97 | {currentUser.isHOD && ( 98 | <> 99 | } /> 100 | }/> 101 | 102 | )} 103 | } /> 104 | } /> 105 | 106 | 107 | } 108 | /> 109 | )} 110 | 111 | 112 | ); 113 | }; 114 | // const PrivateRoutes = ({ children }) => { 115 | // const { currentUser, loading } = useAuth(); 116 | // const location = useLocation(); 117 | 118 | // useEffect(() => { 119 | // // sessionStorage.setItem("url", location.pathname); 120 | // // sessionStorage.setItem("state", JSON.stringify(location.state)); 121 | // }, [location]); 122 | // return loading ? ( 123 | // 124 | // ) : currentUser ? ( 125 | // children 126 | // ) : ( 127 | // 128 | // ); 129 | // }; 130 | 131 | export default App; 132 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/services/adminDeadlinesServices.js: -------------------------------------------------------------------------------- 1 | import { db } from "../../../firebase"; 2 | import { 3 | doc, 4 | getDoc, 5 | updateDoc, 6 | Timestamp, 7 | } from "firebase/firestore"; 8 | import { 9 | fetchSemNumber, fetchToSetSem, 10 | } from "../../student/services/studentServices"; 11 | 12 | 13 | 14 | async function getCoeDeadline(midNo, course, year) { 15 | const adminRef = doc(db, `adminData/coeDeadline/${course}`, `${year}`); 16 | 17 | try { 18 | const docSnap = await getDoc(adminRef); 19 | if (docSnap.exists()) { 20 | if (midNo === "1") { 21 | return { 22 | data: docSnap.data()["mid1"], 23 | error: null, 24 | }; 25 | } else if (midNo === "2") { 26 | return { 27 | data: docSnap.data()["mid2"], 28 | error: null, 29 | }; 30 | } 31 | } else { 32 | return { 33 | data: null, 34 | error: "DEADLINE_NOT_SET", 35 | }; 36 | } 37 | } catch (error) { 38 | return { 39 | data: null, 40 | error: error, 41 | }; 42 | } 43 | } 44 | 45 | async function getSemDeadline(semNo, course, year) { 46 | const adminRef = doc(db, `adminData/semester/${course}`, `${year}`); 47 | 48 | try { 49 | const docSnap = await getDoc(adminRef); 50 | if (docSnap.exists()) { 51 | if (semNo == 1) { 52 | return { 53 | data: docSnap.data()["sem1"], 54 | error: null, 55 | }; 56 | } else if (semNo == 2) { 57 | return { 58 | data: docSnap.data()["sem2"], 59 | error: null, 60 | }; 61 | } 62 | } else { 63 | return { 64 | data: null, 65 | error: "DEADLINE_NOT_SET", 66 | }; 67 | } 68 | } catch (error) { 69 | return { 70 | data: null, 71 | error: error, 72 | }; 73 | } 74 | } 75 | 76 | async function getBeforeSemEnd(course, year) { 77 | const adminRef = doc(db, `adminData/coeDeadline/${course}`, `${year}`); 78 | const semRef = doc(db, `adminData/semester/${course}`, `${year}`); 79 | let mid2 = {}; 80 | let semEnd = {}; 81 | 82 | let semNum = await fetchSemNumber(course, year); 83 | try { 84 | //get mid2 deadline 85 | const docSnap = await getDoc(adminRef); 86 | if (docSnap.exists()) { 87 | mid2 = new Timestamp( 88 | docSnap.data()["mid2"]["seconds"], 89 | docSnap.data()["mid2"]["nanoseconds"] 90 | ).toDate(); 91 | } 92 | 93 | //get semEnd date 94 | const semSnap = await getDoc(semRef); 95 | if (semSnap.exists()) { 96 | semEnd = new Timestamp( 97 | semSnap.data()[`sem${semNum}`]["seconds"], 98 | semSnap.data()[`sem${semNum}`]["nanoseconds"] 99 | ).toDate(); 100 | } 101 | const currentdate = new Date(); 102 | if (mid2 < currentdate && semEnd > currentdate) { 103 | return { 104 | data: true, 105 | error: null, 106 | }; 107 | } 108 | return { 109 | data: false, 110 | error: null, 111 | }; 112 | //get current date and compare if mid2fuhhgueihg} 26 | onError={this.onError}/> 27 | ); 28 | } 29 | } 30 | 31 | 32 | 33 | const ViewPPT=({object})=>{ 34 | 35 | // const linkToPPTFile = 36 | // "https://storage.googleapis.com/slidescarnival_powerpoints/Paulina%20%C2%B7%20SlidesCarnival.pptx"; 37 | return ( 38 | <> 39 | 46 | 47 | ); 48 | } 49 | 50 | const ViewImage=({object})=>{ 51 | useEffect(() => { 52 | }, []) 53 | return( 54 | Unable to Load 56 | ); 57 | } 58 | const ViewVideo=({object})=>{ 59 | return( 60 | 63 | ); 64 | } 65 | 66 | const ViewPdf=({object})=>{ 67 | const zoomPluginInstance = zoomPlugin(); 68 | const { ZoomInButton, ZoomOutButton, ZoomPopover } = zoomPluginInstance; 69 | 70 | useEffect(() => { 71 | zoomPluginInstance.zoomTo(SpecialZoomLevel.PageWidth) 72 | }, []) 73 | 74 | 75 | 76 | return( 77 | 78 | { 79 | object ? ( 80 |
81 |
91 | 92 | 93 | 94 |
95 |
101 | 102 |
103 |
104 | ) : ( 105 |
115 | File Cannot be previewed 116 |
117 | )} 118 | 119 |
120 | ); 121 | } 122 | 123 | function Docviewer({link,rollNo}){ 124 | const forestRef = ref(storage,link); 125 | 126 | const [extension, setextension] = useState(null); 127 | const [loading, setloading] = useState(true); 128 | 129 | useEffect(() => { 130 | getMetadata(forestRef) 131 | .then((metadata) => { 132 | setextension(metadata.contentType.split("/")[1]); 133 | setloading(false); 134 | }) 135 | .catch((error) => { 136 | setextension(null) 137 | setloading(false); 138 | }); 139 | }, [link]) 140 | 141 | 142 | 143 | return ( 144 | extension!=null? 145 |
146 | 147 |
148 | { 149 | link !== null ? ( 150 | 151 | ) : ( 152 |
{`PRA not submitted yet`}
153 | ) 154 | } 155 |
156 |
157 | : 158 |
159 | { 160 | loading?: 161 |
Unknown Error Occured
162 | } 163 |
164 | ) 165 | } 166 | 167 | function Module({extension,object}) { 168 | switch(extension){ 169 | case 'pdf': 170 | return 171 | case 'vnd.openxmlformats-officedocument.presentationml.presentation': 172 | return 173 | case 'vnd.ms-powerpoint': 174 | return 175 | case "vnd.openxmlformats-officedocument.wordprocessingml.document": 176 | return
177 | case 'jpeg': 178 | return Done 179 | case 'jpg': 180 | return Done 181 | case 'png': 182 | return 183 | case 'mp4': 184 | case 'avi': 185 | case "mov": 186 | case 'm4v': 187 | case 'quicktime': 188 | return 189 | default:return ( 190 |

File Extension Not Supported

191 | ); 192 | } 193 | } 194 | 195 | export default Docviewer; 196 | 197 | 198 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/common/createPRA/createPra.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import Navbar from "../../../global_ui/navbar/navbar.js"; 3 | import "./createPra.css"; 4 | import Button from "../../../global_ui/buttons/button.js"; 5 | import DatePicker from "react-datepicker"; 6 | import "../../coe/datepicker.css"; 7 | import { useLocation, useNavigate } from "react-router-dom"; 8 | import { getCoeDeadline } from "../../services/adminDeadlinesServices.js"; 9 | import { getPRA, setPRA } from "../../services/praServices.js"; 10 | import { useAuth } from "../../../context/AuthContext.js"; 11 | import Dialog from "../../../global_ui/dialog/dialog"; 12 | import { Timestamp } from "firebase/firestore"; 13 | import { 14 | fetchisMid1, 15 | fetchisMid2, 16 | } from "../../../student/services/studentServices.js"; 17 | import { Spinner } from "../../../global_ui/spinner/spinner.js"; 18 | 19 | const CreatePra = () => { 20 | const navigate = useNavigate(); 21 | const [date, setDate] = useState(new Date(new Date().setHours(23, 59))); 22 | const [dialog, setdialog] = useState(""); 23 | const [isNewPra, setisNewPra] = useState(true); 24 | const [Loading, setLoading] = useState(true); 25 | const [mid, setmid] = useState(""); 26 | const [inst, setInst] = useState(""); 27 | const location = useLocation(); 28 | const [DeadLine, setDeadLine] = useState(""); 29 | 30 | const parts = location.state.sub.split("_"); 31 | const course = parts[0]; 32 | const year = parts[2]; 33 | 34 | const sub = parts[5]; 35 | const department = 36 | parts[0] + 37 | "_" + 38 | parts[1] + 39 | "_" + 40 | parts[2] + 41 | "_" + 42 | parts[3] + 43 | "_" + 44 | parts[4]; 45 | 46 | let title = parts[0] + " " + parts[2] + " " + parts[3] + " " + parts[4]; 47 | if (parts[3] === "Not Applicable") { 48 | title = parts[0] + " " + parts[2] + " " + parts[4]; 49 | } 50 | 51 | const deadline = async () => { 52 | const isMid1 = await fetchisMid1(course, year); 53 | const isMid2 = await fetchisMid2(course, year); 54 | 55 | const midNumber = () => { 56 | if (isMid1) { 57 | setmid("1"); 58 | } else if (isMid2) { 59 | setmid("2"); 60 | } 61 | }; 62 | midNumber(); 63 | 64 | const coeDeadline = await getCoeDeadline(mid, course, year); 65 | try { 66 | if (coeDeadline) { 67 | setDeadLine(coeDeadline.data.seconds); 68 | } else { 69 | setDeadLine(false); 70 | } 71 | } catch { 72 | console.log(coeDeadline.error); 73 | } 74 | setLoading(false); 75 | }; 76 | deadline(); 77 | var CoeDate = new Date(DeadLine * 1000); 78 | useEffect(() => { 79 | const fetchPRA = async () => { 80 | const res = await getPRA(sub, department); 81 | 82 | if (res.deadline2) { 83 | setDate( 84 | new Timestamp( 85 | res.deadline2.seconds, 86 | res.deadline2.nanoseconds 87 | ).toDate() 88 | ); 89 | } else { 90 | setDate( 91 | new Timestamp( 92 | res.deadline1.seconds, 93 | res.deadline1.nanoseconds 94 | ).toDate() 95 | ); 96 | } 97 | setInst(res.instructions); 98 | }; 99 | 100 | if (location.state.editPRA) { 101 | fetchPRA(); 102 | setisNewPra(false); 103 | } 104 | }, []); 105 | const filterPassedTime = (time) => { 106 | const currentDate = new Date(); 107 | const selectedDate = new Date(time); 108 | return currentDate.getTime() < selectedDate.getTime(); 109 | }; 110 | async function handleCreate() { 111 | setLoading(true); 112 | const isMid1 = await fetchisMid1(course, year); 113 | const isMid2 = await fetchisMid2(course, year); 114 | const parts = location.state.sub.split("_"); 115 | const sub = parts[5]; 116 | const department = 117 | parts[0] + 118 | "_" + 119 | parts[1] + 120 | "_" + 121 | parts[2] + 122 | "_" + 123 | parts[3] + 124 | "_" + 125 | parts[4]; 126 | setdialog("PRA created"); 127 | await setPRA( 128 | sub, 129 | department, 130 | date, 131 | inst, 132 | //currentUser.email, 133 | isMid1, 134 | isMid2 135 | ); 136 | setLoading(false); 137 | } 138 | 139 | return ( 140 |
145 | 150 |

Subject : {parts[5]}

151 | {dialog && ( 152 | { 155 | navigate("/faculty/studentlist", { 156 | state: { sub: location.state.sub }, 157 | }); 158 | }} 159 | /> 160 | )} 161 | 162 | {Loading ? ( 163 |
164 | 165 |
166 | ) : ( 167 |
168 | Enter instructions (if any): 169 | 176 | 177 | CoE Deadline: 178 | {CoeDate && CoeDate > new Date() ? CoeDate.toLocaleDateString("en-IN") :

CoE Deadline is not available right now

} 179 |
180 | 181 | Set mid-{mid} PRA Deadline: 182 | 183 | { 193 | setDate(newVal); 194 | }} 195 | className="select-dd" 196 | /> 197 | 198 | 199 | 200 |
211 | )} 212 |
213 | ); 214 | }; 215 | 216 | export default CreatePra; 217 | -------------------------------------------------------------------------------- /frontend/src/components/context/AuthContext.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useContext, useEffect } from "react"; 2 | import { auth, db } from "../../firebase"; 3 | import { GoogleAuthProvider } from "firebase/auth"; 4 | import { signInWithPopup } from "firebase/auth"; 5 | import { doc, getDoc } from "firebase/firestore"; 6 | import { LoadingScreen } from "../global_ui/spinner/spinner"; 7 | import { fetchSemNumber } from "../student/services/studentServices"; 8 | import { getAcademicYear } from "../faculty/services/adminDeadlinesServices"; 9 | 10 | const AuthContext = React.createContext(); 11 | 12 | // const hasNumber=(myString)=> /\d/.test(myString); 13 | function checkStudent(myString) { 14 | if (myString.slice(2, 4) === "p6") { 15 | return true; 16 | } else { 17 | return false; 18 | } 19 | } 20 | 21 | export function useAuth() { 22 | return useContext(AuthContext); 23 | } 24 | 25 | export function AuthProvider({ children }) { 26 | const [currentUser, setCurrentUser] = useState(null); 27 | const [loading, setLoading] = useState(true); 28 | async function signInWithGoogle() { 29 | const provider = new GoogleAuthProvider(); 30 | setLoading(true); 31 | try { 32 | await signInWithPopup(auth, provider); 33 | setLoading(false) 34 | } catch (e) { 35 | console.log(e); 36 | setCurrentUser(null); 37 | setLoading(false); 38 | } 39 | } 40 | 41 | async function signOut() { 42 | try { 43 | await auth.signOut(); 44 | } catch (e) { 45 | console.log(e); 46 | } 47 | } 48 | 49 | useEffect(() => { 50 | auth.onAuthStateChanged(async (user) => { 51 | console.log(user); 52 | let userType = ""; 53 | let isFirstTime = true; 54 | let isHOD = false; 55 | let isAdmin = false; 56 | 57 | let roles = []; 58 | let isFirstYearHOD = false 59 | let isCOE = false 60 | let academicYear = null 61 | let currentSem = null 62 | if (user != null) { 63 | if (user.email.split("@")[1] === "vbithyd.ac.in") { 64 | if (checkStudent(user.email.split("@")[0])) { 65 | userType = "STUDENT"; 66 | const docRef = doc(db, "students", user.email); 67 | try { 68 | const docSnap = await getDoc(docRef); 69 | if (docSnap.exists()) { 70 | const data = docSnap.data() 71 | academicYear = (await getAcademicYear(data.course, data.year)).data 72 | const semester = data.semester; 73 | currentSem = await fetchSemNumber(data.course,data.year); 74 | if(semester==currentSem){ 75 | isFirstTime=false; 76 | }else{ 77 | isFirstTime = true; 78 | } 79 | } 80 | else { 81 | console.log(user); 82 | user.email = null 83 | } 84 | } catch (e) { 85 | //Display it 86 | } 87 | } else { 88 | userType = "FACULTY"; 89 | const docRef = doc(db, "faculty", user.email); 90 | try { 91 | const docSnap = await getDoc(docRef); 92 | if (docSnap.exists()) { 93 | roles = docSnap.data().role?docSnap.data().role:[]; 94 | if(docSnap.data().isFirstYearHOD){ 95 | isFirstYearHOD = true 96 | } 97 | if(docSnap.data().isHOD){ 98 | isHOD = true; 99 | } 100 | if(docSnap.data().isCOE){ 101 | isCOE = true 102 | isFirstTime= false 103 | } 104 | if (docSnap.data().isAdmin) { 105 | isAdmin = true 106 | isFirstTime=false 107 | } 108 | if (docSnap.data().isEnrolled) { 109 | isFirstTime = false; 110 | } 111 | } 112 | } catch (e) { 113 | //TODO 114 | //DISPLAY 115 | } 116 | } 117 | setCurrentUser({ 118 | uid: user.uid, 119 | email: user.email, 120 | profileURL: user.photoURL, 121 | username: user.displayName, 122 | phoneNumber: user.phoneNumber, 123 | userType: userType, 124 | isFirstTime: isFirstTime, 125 | isHOD: isHOD, 126 | isCOE: isCOE, 127 | isAdmin: isAdmin, 128 | isFirstYearHOD:isFirstYearHOD, 129 | roles: roles, 130 | academicYear, 131 | currentSem, 132 | 133 | }); 134 | setLoading(false); 135 | } else { 136 | console.log("Domain Mismatch"); 137 | setLoading(true); 138 | try { 139 | signOut(); 140 | } catch (e) { 141 | console.log("Signout Failed"); 142 | } 143 | setLoading(false); 144 | } 145 | } else { 146 | setCurrentUser(null); 147 | sessionStorage.clear(); 148 | setLoading(false); 149 | } 150 | }); 151 | }, []); 152 | 153 | const value = { 154 | currentUser, 155 | loading, 156 | signInWithGoogle, 157 | signOut, 158 | }; 159 | 160 | 161 | return { loading? : children}; 162 | } 163 | 164 | // import React, { createContext, useReducer,useEffect } from "react"; 165 | // import {auth} from '../../firebase.js' 166 | 167 | // export const AuthReducer = (state, action) => { 168 | // switch (action.type) { 169 | // case "PROCESSING": 170 | // return { 171 | // ...state, 172 | // isLoading: action.payload, 173 | // }; 174 | // case "LOGIN": 175 | // return { 176 | // ...state, 177 | // user: action.payload, 178 | // isLoading:false 179 | // }; 180 | // case "LOGOUT": 181 | // return { 182 | // ...state, 183 | // user: action.payload, 184 | // isLoading:false 185 | // }; 186 | // default: 187 | // return { 188 | // ...state, 189 | // user: null, 190 | // isLoading:false 191 | // }; 192 | // } 193 | // }; 194 | 195 | // const initialState = { 196 | // user:null, 197 | // isLoading:false, 198 | // }; 199 | 200 | // export const AuthContext = createContext(); 201 | 202 | // export const AuthProvider = (props) => { 203 | 204 | // useEffect(() => { 205 | // dispatch({ 206 | // type: "PROCESSING", 207 | // payload:true, 208 | // }); 209 | 210 | // const unsubscribe = auth.onAuthStateChanged(user => { 211 | // dispatch({ 212 | // type: "LOGIN", 213 | // payload: user, 214 | // }); 215 | // }) 216 | // return unsubscribe 217 | // }, []) 218 | 219 | // const [state, dispatch] = useReducer(AuthReducer, initialState); 220 | 221 | // return ( 222 | // 223 | // {props.children} 224 | // 225 | // ); 226 | // }; 227 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/coe/deadlines.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import Navbar from "../../global_ui/navbar/navbar"; 3 | import Button from "../../global_ui/buttons/button"; 4 | import Select from "react-select"; 5 | import DatePicker from "react-datepicker"; 6 | import { Timestamp } from "firebase/firestore"; 7 | import { getCoeDeadline, getSemDeadline,setCoeDeadlines } from "../services/adminDeadlinesServices"; 8 | import { fetchSemNumber, fetchToSetSem } from "../../student/services/studentServices"; 9 | import "./datepicker.css"; 10 | import "./deadlines.css"; 11 | import Dialog from "../../global_ui/dialog/dialog"; 12 | import { Spinner } from "../../global_ui/spinner/spinner"; 13 | 14 | export default function Deadlines() { 15 | const [loading,setloading ] = useState(false); 16 | const [dialog,setdialog] = useState(false) 17 | const [course, setCourse] = useState({ value: "BTech", label: "BTech" }); 18 | const [year, setYear] = useState({ value: "1", label: "1" }); 19 | const [semNumber, setSemNumber] = useState(1); 20 | const [semToSet, setSemToSet] = useState(1); 21 | const [date1, setDate1] = useState(new Date(new Date().setHours(23, 59))); 22 | const [date2, setDate2] = useState(new Date(new Date().setHours(23, 59))); 23 | const [date3, setDate3] = useState(new Date(new Date().setHours(23, 59))); 24 | const filterPassedTime = (time) => { 25 | const currentDate = new Date(); 26 | const selectedDate = new Date(time); 27 | return currentDate.getTime() < selectedDate.getTime(); 28 | }; 29 | 30 | useEffect(() => { 31 | console.log(loading) 32 | async function semDeadline() { 33 | let n = await fetchSemNumber(course.value, year.value); 34 | setSemNumber(n); 35 | let val = await fetchToSetSem(course.value, year.value); 36 | setSemToSet(val); 37 | } 38 | semDeadline(); 39 | 40 | const fetchDeadlines = async () => { 41 | const res = await getCoeDeadline("1", course.value, year.value); 42 | if (res.data != null) { 43 | setDate1( 44 | new Timestamp(res.data.seconds, res.data.nanoseconds).toDate() 45 | ); 46 | } 47 | const res2 = await getCoeDeadline("2", course.value, year.value); 48 | if (res2.data != null) { 49 | setDate2( 50 | new Timestamp(res2.data.seconds, res2.data.nanoseconds).toDate() 51 | ); 52 | } 53 | 54 | let res3; 55 | if(semNumber != -1){ 56 | res3 = await getSemDeadline( 57 | semNumber, 58 | course.value, 59 | year.value 60 | ); 61 | } 62 | if(res3 != undefined){ 63 | if (res3.data != null) { 64 | setDate3( 65 | new Timestamp(res3.data.seconds, res3.data.nanoseconds).toDate() 66 | ); 67 | } 68 | } 69 | }; 70 | fetchDeadlines(); 71 | }, [course, year,semNumber]); 72 | 73 | const Years = [ 74 | //fetch from db for the selected course 75 | { value: "1", label: "1" }, 76 | { value: "2", label: "2" }, 77 | { value: "3", label: "3" }, 78 | { value: "4", label: "4" }, 79 | ]; 80 | const Courses = [ 81 | { value: "BTech", label: "BTech" }, 82 | { value: "MTech", label: "MTech" }, 83 | { value: "MBA", label: "MBA" }, 84 | ]; 85 | const MYears = [ 86 | //fetch from db for the selected course 87 | { value: "1", label: "1" }, 88 | { value: "2", label: "2" }, 89 | ]; 90 | 91 | async function handleSave(){ 92 | setloading(true) 93 | const res = await setCoeDeadlines(course.value,year.value,date1,date2,date3,semNumber) 94 | if (res.error==null){ 95 | setloading(false) 96 | setdialog('Deadlines updated succesfully') 97 | } 98 | else { 99 | setloading(false) 100 | setdialog('Could not update deadlines') 101 | 102 | } 103 | } 104 | 105 | return ( 106 | 107 |
108 | 111 | 112 | {!dialog ? ( 113 |
114 | 115 | 116 |

Select course and year

117 |

Course

118 | { 135 | setYear(selectedYear); 136 | 137 | }} 138 | /> 139 | {loading ? :
140 |

MID-I

141 |
142 | { 151 | setDate1(newVal); 152 | }} 153 | className="datepicker-deadlines" 154 | /> 155 |
156 |

MID-II

157 |
158 | { 167 | setDate2(newVal); 168 | }} 169 | className="datepicker-deadlines" 170 | /> 171 |
172 | { 173 | semNumber !== -1 ? 174 | (

SEM-{semNumber}

) : 175 | (

set SEM-{semToSet}

) 176 | } 177 | 178 |
179 | { 188 | setDate3(newVal); 189 | }} 190 | className="datepicker-deadlines" 191 | /> 192 |
193 |
} 202 |
):( 203 | { 204 | setdialog(false); 205 | }}/> 206 | )} 207 |
208 | ); 209 | } 210 | -------------------------------------------------------------------------------- /frontend/src/components/faculty/hod/deptReport.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect,useState } from 'react' 2 | import { useAuth } from '../../context/AuthContext'; 3 | import Navbar from '../../global_ui/navbar/navbar' 4 | import { getIsEnrolled } from '../services/enrollFacultyServices'; 5 | import { getFirstYearStatistics, getStatistics } from '../services/hodServices'; 6 | 7 | export default function DeptReport() { 8 | const {currentUser } = useAuth(); 9 | const [isEnrolled, setisEnrolled] = useState(false); 10 | const [dep,setDep] = useState(null); 11 | const [course,setCourse] = useState(null) 12 | const [firstyear,setfirstyear] = useState(null); 13 | const [secondyear,setsecondyear] = useState(null); 14 | const [thirdyear, setthirdyear] = useState(null); 15 | const [fourthyear, setfourthyear] = useState(null); 16 | 17 | 18 | //notCreated() function returns an array of classes& subjects that did not create a PRA yet 19 | async function notCreated(){ 20 | if (currentUser.isFirstYearHOD){ 21 | const res = await getFirstYearStatistics(); 22 | setfirstyear(res); 23 | } 24 | else { 25 | if (course == "BTech") 26 | { 27 | const res2 = await getStatistics(course,dep,'2'); 28 | if (res2 && res2.length!=0){ 29 | setsecondyear(res2) 30 | } 31 | const res3 = await getStatistics(course,dep,'3'); 32 | if (res3 && res3.length!=0){ 33 | setthirdyear(res3) 34 | } 35 | const res4 = await getStatistics(course,dep,'4'); 36 | if(res4 && res4.length!=0){ 37 | setfourthyear(res4); 38 | } 39 | } 40 | else if (course == "MTech"||course=="MBA"){ 41 | const res1 = await getStatistics(course,dep,'1'); 42 | if(res1.length!=0){ 43 | setfirstyear(res1) 44 | } 45 | const res2 = await getStatistics(course,dep,'2'); 46 | if (res2.length!=0){ 47 | setsecondyear(res2); 48 | } 49 | } 50 | } 51 | } 52 | 53 | 54 | 55 | 56 | 57 | async function findIsEnrolled() { 58 | const res = await getIsEnrolled(currentUser.email); 59 | 60 | setisEnrolled(res.data); 61 | } 62 | useEffect(()=>{ 63 | const courseRole = currentUser.roles[0].split("_")[0] 64 | setCourse(courseRole); 65 | if (course=="MBA"){ 66 | setDep("MBA") 67 | } 68 | else { 69 | 70 | const department = currentUser.roles[0].split("_")[1] 71 | setDep(department); 72 | } 73 | findIsEnrolled(); 74 | notCreated(); 75 | 76 | }); 77 | return ( 78 |
79 | 85 |

{dep} Department

86 | {currentUser.isFirstYearHOD? 87 | ( 88 |
89 | { 90 | firstyear!=null && ( 91 | <> 92 |
93 |
    94 | 95 | 96 | {firstyear.map((value, index) => { 97 | return
  1. {value.split('_')[3]+" "+value.split('_')[4]+" "+value.split('_')[5]}
  2. 98 | })} 99 |
100 | 101 |
102 | 103 | ) 104 | } 105 |
106 | ): 107 | (<> 108 | { 109 | course=="MTech"&&( 110 | <> 111 |
112 | { 113 | firstyear!=null && ( 114 | <> 115 |
116 |

117 | FIRST YEAR 118 |

119 |
    120 | {firstyear.map((value, index) => { 121 | return
  1. {value.split('_')[3]+" "+value.split('_')[4]+" "+value.split('_')[5]}
  2. 122 | })} 123 |
124 | 125 |
126 | 127 | ) 128 | } 129 |
130 | 131 | 132 | ) 133 | } 134 | { 135 | course=="MBA"&&( 136 | <> 137 |
138 | { 139 | firstyear!=null && ( 140 | <> 141 |
142 |

143 | FIRST YEAR 144 |

145 |
    146 | 147 | {firstyear.map((value, index) => { 148 | return
  1. {value.split('_')[5]}
  2. 149 | })} 150 |
151 | 152 |
153 | 154 | ) 155 | } 156 |
157 | 158 | 159 | ) 160 | } 161 | 162 |
163 | { 164 | secondyear!=null && ( 165 | <> 166 |
167 |

168 | SECOND YEAR 169 |

170 |
    171 | 172 | {secondyear.map((value, index) => { 173 | return
  1. {value.split('_')[3]+" "+value.split('_')[4]+"-"+value.split('_')[5]}
  2. 174 | })} 175 |
176 | 177 |
178 | 179 | ) 180 | } 181 | 182 |
183 |
184 | { 185 | thirdyear!=null && ( 186 | <> 187 |
188 |

189 | THIRD YEAR 190 |

191 |
    192 | 193 | {thirdyear.map((value, index) => { 194 | return
  1. {value.split('_')[3]+" "+value.split('_')[4]+" "+value.split('_')[5]}
  2. 195 | })} 196 |
197 | 198 |
199 | 200 | ) 201 | } 202 | 203 |
204 |
205 | { 206 | fourthyear!=null && ( 207 | <> 208 |
209 |

210 | FOURTH YEAR 211 |

212 |
    213 | 214 | {fourthyear.map((value, index) => { 215 | return
  1. {value.split('_')[3]+" "+value.split('_')[4]+" "+value.split('_')[5]}
  2. 216 | })} 217 |
218 | 219 |
220 | 221 | ) 222 | } 223 | 224 |
225 | 226 | ) 227 | } 228 | 229 | 230 |
231 | ) 232 | } 233 | 234 | 235 | 236 | 237 | -------------------------------------------------------------------------------- /frontend/src/components/student/uploadpra/uploadpra.module.css: -------------------------------------------------------------------------------- 1 | .uploadScreen{ 2 | display: flex; 3 | flex-direction: column; 4 | width: 100vw; 5 | margin-right: auto; 6 | margin-left: auto; 7 | flex-wrap: wrap; 8 | } 9 | .main{ 10 | display: flex; 11 | 12 | flex-direction: column; 13 | /* justify-content:center; */ 14 | align-items:center; 15 | /* font-weight: bold; */ 16 | margin-top: 50px; 17 | } 18 | 19 | input[type="file"] { 20 | display: none; 21 | } 22 | 23 | .customFileUpload { 24 | 25 | background-color: rgba(176, 196, 222, 0.43); 26 | color: rgba(11, 91, 138, 1); 27 | outline: none; 28 | padding: 13px 10px; 29 | border-radius: 5px; 30 | border: none; 31 | text-align: center; 32 | text-decoration: none; 33 | cursor: pointer; 34 | width: 100px; 35 | align-self: center; 36 | 37 | } 38 | 39 | .customFileUpload:hover{ 40 | 41 | box-shadow: none; 42 | /* border:1px solid #e5e4e2; */ 43 | 44 | } 45 | .customflex{ 46 | display: flex; 47 | flex-direction: column; 48 | } 49 | 50 | .UploadinputStyle{ 51 | display: inline-flexbox; 52 | font-size: 20px; 53 | outline: none; 54 | background-color: #e5e4e2; 55 | padding: 10px 15px; 56 | border: none; 57 | border-radius: 7px; 58 | font-weight: normal; 59 | align-items: center; 60 | margin: 0px; 61 | 62 | } 63 | 64 | 65 | .editbutton{ 66 | margin-top: 40px; 67 | text-align: center; 68 | border-radius:36px; 69 | border: none; 70 | box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px; 71 | font-size: large; 72 | background-color: #0e72ab; 73 | color: white; 74 | width:120px; 75 | height: auto; 76 | padding:8px; 77 | align-self: center; 78 | cursor: pointer; 79 | text-transform: capitalize; 80 | } 81 | 82 | .downloadBtn{ 83 | margin: auto; 84 | } 85 | 86 | .praLabel{ 87 | font-weight:800 ; 88 | font-size: 16px; 89 | color:#0e72ab ; 90 | align-self: center; 91 | justify-content: space-between; 92 | margin-left:0px; 93 | margin-right: 8px; 94 | 95 | } 96 | label{ 97 | font-weight: medium; 98 | 99 | } 100 | .uploadbutton{ 101 | margin-bottom: 25px; 102 | background-color: #0E72AB; 103 | color:white; 104 | font-size: 16px; 105 | align-self: center; 106 | justify-self: center; 107 | justify-content: space-around; 108 | cursor: pointer; 109 | display: inline; 110 | outline: none; 111 | border: none; 112 | padding: 10px 16px; 113 | border-radius: 8px; 114 | text-transform: uppercase; 115 | } 116 | 117 | .uploadbutton:disabled{ 118 | background-color: #80808046; 119 | cursor:not-allowed; 120 | box-shadow: none; 121 | color: darkslategrey; 122 | 123 | } 124 | .fileContainer{ 125 | margin-bottom: 25px; 126 | display: flex; 127 | flex-direction:row; 128 | /* flex-wrap: wrap; 129 | align-content: center; */ 130 | justify-content: center; 131 | align-items: center; 132 | } 133 | .titleErrorField{ 134 | display:inline-block; 135 | color: red; 136 | font-size: 12px; 137 | font-style:normal; 138 | font-weight: 450; 139 | margin-top: 0%; 140 | margin-left: 80px; 141 | } 142 | .errorField{ 143 | display: flex; 144 | flex-direction: column; 145 | color:red; 146 | /* padding-left: 75px; */ 147 | font-size:16px; 148 | font-weight: 450; 149 | align-self: center; 150 | } 151 | 152 | .instructions{ 153 | color:black; 154 | font-size:16px; 155 | font-weight: 500; 156 | width: min(90%,850px); 157 | margin-left: auto; 158 | margin-right: auto; 159 | margin-bottom: 30px; 160 | text-align:center; 161 | line-height: 1.4; 162 | 163 | } 164 | 165 | .praInfo{ 166 | font-size: large; 167 | font-weight: 500; 168 | text-align: center; 169 | margin-left: 0px; 170 | margin-bottom: 35px ; 171 | padding-left: 20px; 172 | margin-left: 0px; 173 | } 174 | 175 | 176 | .fileName{ 177 | color:darkslategrey; 178 | font-size:20px; 179 | margin-bottom: 20px; 180 | font-weight: 450; 181 | align-self: center; 182 | justify-content: center; 183 | display: flex; 184 | flex-wrap: wrap; 185 | justify-items: center; 186 | align-content: center; 187 | text-align: center; 188 | } 189 | 190 | .fileUploadView{ 191 | overflow: hidden; 192 | width: 250px; 193 | text-overflow:ellipsis; 194 | white-space: nowrap; 195 | padding: 8px; 196 | border:1px solid #80808086; 197 | border-radius: 6px; 198 | background-color: whitesmoke; 199 | font-size:16px; 200 | text-align: left; 201 | padding-left: 8px; 202 | text-align: left; 203 | display: flex; 204 | justify-content: start; 205 | align-items: center; 206 | } 207 | 208 | .selectList{ 209 | width: auto; 210 | min-width:200px; 211 | padding: 5px 2px; 212 | outline: none; 213 | border: none; 214 | border-radius: 14px; 215 | background-color: #e5e4e2; 216 | font-size: large; 217 | font-weight: 500; 218 | padding: 10px; 219 | 220 | -moz-appearance:none; 221 | -webkit-appearance:none; 222 | appearance:none; 223 | background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSdibGFjaycgaGVpZ2h0PScyNCcgdmlld0JveD0nMCAwIDI0IDI0JyB3aWR0aD0nMjQnIHhtbG5zPSdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Zyc+PHBhdGggZD0nTTcgMTBsNSA1IDUtNXonLz48cGF0aCBkPSdNMCAwaDI0djI0SDB6JyBmaWxsPSdub25lJy8+PC9zdmc+); 224 | background-repeat: no-repeat; 225 | background-position-x: right; 226 | background-position-y: center; 227 | 228 | } 229 | .pratitle{ 230 | font-weight: medium; 231 | font-size: 20px; 232 | letter-spacing: 0.2px; 233 | justify-content: center; 234 | font-weight: 400; 235 | display: flex; 236 | } 237 | 238 | .fileUploadModule{ 239 | display: flex; 240 | width: 100vw; 241 | flex-direction: column; 242 | margin-left: auto; 243 | margin-right: auto; 244 | justify-content: center; 245 | align-items: center; 246 | } 247 | .editflex{ 248 | display: flex; 249 | flex-direction: column; 250 | width: 100vw; 251 | 252 | } 253 | 254 | @media only screen and (max-width: 600px) { 255 | .UploadinputStyle { 256 | margin-top: 14px; 257 | width: calc(96% - 3rem); 258 | margin-left: 5%; 259 | } 260 | 261 | 262 | .praLabel{ 263 | font-weight:800 ; 264 | font-size: 16px; 265 | color:#0e72ab ; 266 | align-self: center; 267 | margin-left: 5%; 268 | margin-top: 10px; 269 | } 270 | .titleErrorField{ 271 | display:inline-block; 272 | color: red; 273 | font-size: 12px; 274 | font-style:normal; 275 | font-weight: 450; 276 | margin-top: 0%; 277 | margin-left: 18px; 278 | 279 | } 280 | 281 | .praInfo{ 282 | width: calc(96% - 3rem); 283 | margin: auto; 284 | font-size: 16px; 285 | margin-bottom: 35px; 286 | padding: 10px; 287 | } 288 | 289 | .instructions{ 290 | color:black; 291 | font-size:16px; 292 | font-weight: 600px; 293 | text-align: center; 294 | font: bolder; 295 | margin: 4%; 296 | margin-bottom: 25px; 297 | align-items: center; 298 | line-height: 1.4; 299 | } 300 | .fileUploadView{ 301 | width:150px; 302 | } 303 | 304 | } 305 | /* 306 | .btn{ 307 | background-color: rgba(14, 114, 171, 1); 308 | color: white; 309 | justify-self: bottom; 310 | margin-top: 50px; 311 | border: none; 312 | outline: none; 313 | padding: 10px 30px; 314 | border-radius: 6px; 315 | font-size: large; 316 | cursor: pointer; 317 | } */ -------------------------------------------------------------------------------- /frontend/src/components/faculty/coe/coeSearch.js: -------------------------------------------------------------------------------- 1 | import React, { useState,useEffect } from "react"; 2 | import Select from "react-select"; 3 | import Navbar from "../../global_ui/navbar/navbar"; 4 | import Button from "../../global_ui/buttons/button"; 5 | import { getCurriculumData } from "../services/curriculumServices"; 6 | import { fetchRegulationOptions, fetchSemNumber, fetchAcademicYearOptions } from "../../student/services/studentServices"; 7 | import { useNavigate } from "react-router-dom"; 8 | import Dialog from "../../global_ui/dialog/dialog"; 9 | import "./coeSearch.css"; 10 | 11 | export default function CoeSearch() { 12 | const [Course, setCourse] = useState({value:'none'}); 13 | const [Year, setYear] = useState({value:0}); 14 | const [Department, setDepartment] = useState(""); 15 | const [semester, setSemester] = useState(""); 16 | const [Section, setSection] = useState(""); 17 | const [Subject, setSubject] = useState(""); 18 | const [subjects,setSubjects] = useState([ 19 | 20 | { value: "loading", label: "Loading..." }, 21 | ]); 22 | const [departments,setDepartments] = useState([ 23 | 24 | { value: "loading", label: "Loading..." }, 25 | ]); 26 | const [sections,setSections] = useState([ 27 | 28 | { value: "loading", label: "Loading..." }, 29 | ]); 30 | 31 | const [showDialog, setShowDialog] = useState(null); 32 | const [Regulation,setRegulation]=useState(''); 33 | const [acadYear, setAcadYear] = useState(''); 34 | const [regoptionss,setregoptionss]=useState([]); 35 | const [ayoptions, setAyoptions] = useState([]); 36 | 37 | async function regoptions(){ 38 | const res = await fetchRegulationOptions(); 39 | setregoptionss(res.data); 40 | } 41 | 42 | async function getAYOptions(){ 43 | const res = await fetchAcademicYearOptions(); 44 | setAyoptions(res.data); 45 | console.log(res.data); 46 | } 47 | 48 | const nav = useNavigate(); 49 | useEffect(()=>{ 50 | const getLables = async ()=>{ 51 | // const sem = await fetchSemNumber(Course.value,Year.value); 52 | 53 | const res = await getCurriculumData(Course.value,Year.value,semester.value); 54 | if(!res) return 55 | setSubjects(res.subjects) 56 | setDepartments(res.departments) 57 | setSections(res.sections) 58 | } 59 | getLables() 60 | },[Course,Year, semester]) 61 | 62 | 63 | function handleView() { 64 | if ( 65 | Course.value != null && 66 | Year.value != null && 67 | // Regulation.value!=null&& 68 | acadYear.value != null && 69 | Department.value != null && 70 | Section.value != null && 71 | Subject.value != null 72 | ) { 73 | var passing = { 74 | Course: Course.value, 75 | Year: Year.value, 76 | // Regulation:Regulation.value, 77 | AcademicYear:acadYear.value, 78 | Dept: Department.value, 79 | Section: Section.value, 80 | Subject: Subject.value, 81 | Semester:semester.value 82 | }; 83 | nav("/faculty/viewsubmissions", { state: passing }); 84 | } else { 85 | setShowDialog("Select all the options"); 86 | } 87 | } 88 | const Courses = [ 89 | { value: "BTech", label: "BTech" }, 90 | { value: "MTech", label: "MTech" }, 91 | { value: "MBA", label: "MBA" }, 92 | ]; 93 | const Years = [ 94 | //fetch 95 | { value: "1", label: "1" }, 96 | { value: "2", label: "2" }, 97 | { value: "3", label: "3" }, 98 | { value: "4", label: "4" }, 99 | ]; 100 | 101 | const Semesters = [ 102 | { value: 1, label: "1" }, 103 | { value: 2, label: "2" }, 104 | ] 105 | const MYears = [ 106 | //fetch from db for the selected course 107 | { value: "1", label: "1" }, 108 | { value: "2", label: "2" }, 109 | ]; 110 | 111 | 112 | return ( 113 |
114 | 115 |
116 | {showDialog && ( 117 | { 120 | setShowDialog(false); 121 | }} 122 | /> 123 | )} 124 |
125 | 126 | 127 |
128 | 129 |

Select the class to view grades.

130 | 131 |
132 |

Course

133 | { 150 | setYear(selectedYear); 151 | }} 152 | /> 153 |

Academic Year

154 | { 173 | setDepartment(selectedDepartment); 174 | setSections((c)=>{return {...c}}) 175 | }} 176 | /> 177 |

Section

178 | { 194 | setSemester(selectedSemester); 195 | }} 196 | /> 197 |

Subject

198 | { 163 | setCourse(selectedCourse); 164 | regoptions(); 165 | }} 166 | /> 167 |

Year

168 | { 186 | setdisabledep(false); 187 | 188 | setRegulation(r); 189 | }} 190 | /> */} 191 |

Department

192 | { 212 | setSection(selectedSection); 213 | setdisablesub(false); 214 | }} 215 | /> 216 |

Subject

217 | 218 | { 180 | setCourse(selectedCourse); 181 | filterDep(selectedCourse); 182 | regoptions(); 183 | }} 184 | /> 185 | 186 | Year 187 | { 213 | setRegulation(r); 214 | setdisabledep(false); 215 | }} 216 | /> */} 217 | 218 | Department 219 | { 242 | setSection(selectedSection); 243 | }} 244 | /> 245 | 246 | Subject 247 | {console.log(subjects)} 248 |