├── .gitignore
├── FIGMA UI Designs
├── Login Page UI 1.png
├── Login Page UI 2.png
├── Make Request Page UI.png
├── Make a Requesst UI.png
├── Staff Homepage UI.png
└── Student Homepage UI.png
├── LICENSE
├── README.md
├── UML Diagrams
├── Activity Diagram.png
├── Sequence Diagram Login.png
├── Sequence Diagram Request Approval.png
└── Use Case.jpg
├── package-lock.json
├── package.json
├── public
└── index.html
└── src
├── App.css
├── App.js
├── Components
├── Auth
│ ├── CheckFunction.js
│ └── Navigation.js
├── Firebase
│ ├── functions.js
│ └── upload.js
├── Login
│ ├── Login.css
│ └── Login.jsx
├── Pages
│ ├── ApproversStatusPage.css
│ ├── ApproversStatusPage.jsx
│ ├── CreateDocumentFlow.css
│ ├── CreateDocumentFlow.jsx
│ ├── Loading.css
│ ├── Loading.jsx
│ ├── LoginPage.css
│ ├── LoginPage.jsx
│ ├── MakeRequest.css
│ ├── MakeRequest.jsx
│ ├── Path.css
│ ├── Path.jsx
│ ├── StatusRequest.css
│ ├── StatusRequest.jsx
│ ├── SubmitRequest.css
│ └── SubmitRequest.jsx
├── Popup
│ ├── Popup.css
│ └── Popup.jsx
├── assets
│ └── logo.png
├── general.css
└── users
│ ├── ApproversPage.jsx
│ ├── AproversPage.jsx
│ ├── StaffHomePage.jsx
│ └── StudentHomePage.jsx
├── Firebase
└── firebase.js
├── index.css
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | ```
4 |
--------------------------------------------------------------------------------
/FIGMA UI Designs/Login Page UI 1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/FIGMA UI Designs/Login Page UI 1.png
--------------------------------------------------------------------------------
/FIGMA UI Designs/Login Page UI 2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/FIGMA UI Designs/Login Page UI 2.png
--------------------------------------------------------------------------------
/FIGMA UI Designs/Make Request Page UI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/FIGMA UI Designs/Make Request Page UI.png
--------------------------------------------------------------------------------
/FIGMA UI Designs/Make a Requesst UI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/FIGMA UI Designs/Make a Requesst UI.png
--------------------------------------------------------------------------------
/FIGMA UI Designs/Staff Homepage UI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/FIGMA UI Designs/Staff Homepage UI.png
--------------------------------------------------------------------------------
/FIGMA UI Designs/Student Homepage UI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/FIGMA UI Designs/Student Homepage UI.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Krishnadasan Kajamohan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Software-Engineering-Project - Student Document Approval System
2 |
3 | This project we are doing Student Documents Approval System using React Js.
4 |
5 | ## Team Members
6 |
7 | - **Kajamohan K.**
8 | - **Thilakarathna R.M.S.S.**
9 | - **Naif A.M.M.**
10 | - **Gobishangar V.**
11 |
12 | ## Installation
13 |
14 | - initially you need to install node js and npm in your system.
15 | - after that you need to open the project in your editor. And open the terminal in the project folder.
16 | - then you need to run the command `npm install` to install all the dependencies.
17 |
18 | - create custom folder called `Firebase` in the `src` folder.
19 | - Then create a file called `firebase.js` in the `Firebase` folder.
20 |
21 | and paste the following code in the `firebase.js` file.
22 |
23 | ```javascript
24 | // import * as firebase from "firebase/app"
25 | import { initializeApp } from "firebase/app";
26 | import { getAuth } from "firebase/auth";
27 | import { getStorage } from "firebase/storage";
28 | import { getFirestore } from "firebase/firestore";
29 |
30 | // Your web app's Firebase configuration
31 | const firebaseConfig = {
32 | apiKey: "YOUR_API_KEY",
33 | authDomain: "YOUR_AUTH_DOMAIN",
34 | databaseURL: "YOUR_DATABASE_URL",
35 | projectId: "YOUR_PROJECT_ID",
36 | storageBucket: "YOUR_STORAGE_BUCKET",
37 | appId: "YOUR_APP_ID",
38 | messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
39 | };
40 |
41 | // Initialize Firebase
42 | const app = initializeApp(firebaseConfig);
43 | const auth = getAuth(app);
44 | const storage = getStorage(app);
45 | const db = getFirestore(app);
46 |
47 | // const uid = auth.currentUser?.uid;
48 |
49 | export { db, auth, app, storage };
50 | ```
51 |
52 | - after that you need to run the command `npm start` to run the project.
53 | - if any error occurs you can run the command `npm audit fix --force` to fix the errors. And then run the command `npm start` to run the project.
54 |
55 | ## Interface
56 |
57 | ### Figma UI Designs
58 |
59 | 1. Login Page UI
60 |
61 | 1.1. Login Page UI 1
62 |
63 | 
64 |
65 | 1.2. Login Page UI 2
66 | 
67 |
68 | 2. Student Homepage UI
69 | 
70 |
71 | 3. Staff Homepage UI
72 | 
73 |
74 | 4. Make Request UI
75 | 
76 |
77 | ## user Roles
78 |
79 | - Student
80 | - Staff (Academic Staff)
81 | - Admin (AR Officer)
82 |
83 | ## User Stories
84 |
85 | ### Student
86 |
87 | - As a student, I want to be able to log in to the system using my student ID and password.
88 | - As a student, I want to be able to view my requests.
89 | - As a student, I want to be able to make a request.
90 | - As a student, I want to be able to view the status of my request.
91 | - As a student, I want to be able to view the details of my request.
92 |
93 | ### Staff (Academic Staff)
94 |
95 | - As a staff, I want to be able to log in to the system using my staff ID and password.
96 | - As a staff, I want to be able to view all the requests.
97 | - As a staff, I want to be able to view the details of a request.
98 | - As a staff, I want to be able to approve a request.
99 | - As a staff, I want to be able to reject a request.
100 |
101 | ### Admin (AR Officer)
102 |
103 | - As an admin, I want to be able to log in to the system using my staff ID and password.
104 | - As an admin, I want to be able to view all the requests.
105 | - As an admin, I want to be able to view the details of a request.
106 | - As an admin, I want to be able to approve a request.
107 | - As an admin, I want to be able to reject a request.
108 |
109 | ## Use Cases
110 |
111 | ### Student Use Cases
112 |
113 | - Student Login
114 | - Student Make a Request
115 | - Student View Request Status
116 | - Student View Request Details
117 |
118 | ### Staff Use Cases
119 |
120 | - Staff Login
121 | - Staff View Request Details
122 | - Staff Approve Request
123 | - Staff Reject Request
124 |
125 | ### Admin Use Cases
126 |
127 | - Admin Login
128 | - Admin View Request Details
129 | - Admin Approve Request
130 | - Admin Reject Request
131 |
132 | ## Use Case Diagram
133 |
134 | 
135 |
136 | ## Activity Diagram
137 |
138 | 
139 |
140 | ## Database
141 |
142 | - We are using Firebase as our database for this project. We are using Firebase Storage and Firebase Firestore.
143 |
144 | ### Firebase Storage
145 |
146 | - We are using Firebase Storage to store the documents that are uploaded by the students / staff/ admin.
147 |
148 | ### Firebase Firestore
149 |
150 | - We are using Firebase Firestore to store the user details and the request details.
151 |
--------------------------------------------------------------------------------
/UML Diagrams/Activity Diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/UML Diagrams/Activity Diagram.png
--------------------------------------------------------------------------------
/UML Diagrams/Sequence Diagram Login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/UML Diagrams/Sequence Diagram Login.png
--------------------------------------------------------------------------------
/UML Diagrams/Sequence Diagram Request Approval.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/UML Diagrams/Sequence Diagram Request Approval.png
--------------------------------------------------------------------------------
/UML Diagrams/Use Case.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/UML Diagrams/Use Case.jpg
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "student-document-approval-system",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@azure/msal-browser": "^2.28.1",
7 | "@azure/msal-react": "^1.4.4",
8 | "@emotion/react": "^11.9.3",
9 | "@emotion/styled": "^11.9.3",
10 | "@mui/icons-material": "^5.8.4",
11 | "@mui/joy": "^5.0.0-alpha.38",
12 | "@mui/material": "^5.9.2",
13 | "@testing-library/jest-dom": "^5.16.4",
14 | "@testing-library/react": "^13.3.0",
15 | "@testing-library/user-event": "^13.5.0",
16 | "bootstrap": "^5.2.0",
17 | "firebase": "^9.9.2",
18 | "install": "^0.13.0",
19 | "mui": "^0.0.1",
20 | "react": "^18.2.0",
21 | "react-bootstrap": "^2.4.0",
22 | "react-dom": "^18.2.0",
23 | "react-icons": "^4.4.0",
24 | "react-microsoft-login": "^1.15.0",
25 | "react-router-dom": "^6.3.0",
26 | "react-scripts": "^5.0.1",
27 | "reactjs-popup": "^2.0.5",
28 | "web-vitals": "^2.1.4"
29 | },
30 | "scripts": {
31 | "start": "react-scripts start",
32 | "build": "react-scripts build",
33 | "test": "react-scripts test",
34 | "eject": "react-scripts eject"
35 | },
36 | "eslintConfig": {
37 | "extends": [
38 | "react-app",
39 | "react-app/jest"
40 | ]
41 | },
42 | "browserslist": {
43 | "production": [
44 | ">0.2%",
45 | "not dead",
46 | "not op_mini all"
47 | ],
48 | "development": [
49 | "last 1 chrome version",
50 | "last 1 firefox version",
51 | "last 1 safari version"
52 | ]
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
27 | Student Documents Approval System
28 |
29 |
30 |
31 | You need to enable JavaScript to run this app.
32 |
33 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 |
2 | *{
3 | box-sizing: border-box;
4 | padding: 0;
5 | margin: 0;
6 | scroll-behavior: smooth;
7 | }
8 |
9 | body{
10 | font-family: 'outfit', Tahoma, Geneva, Verdana, sans-serif;
11 | }
12 |
13 | a{
14 | color: unset;
15 | text-decoration: none;
16 | }
17 |
18 | .BGround{
19 | padding: 10px;
20 | width: 100%;
21 | height: 100%;
22 | }
23 |
24 | .App{
25 | display: flex;
26 | flex-direction: row;
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import "./App.css";
3 | import { Route, BrowserRouter, Routes } from "react-router-dom";
4 |
5 | import LoginPage from "./Components/Pages/LoginPage";
6 | import StaffHomePage from "./Components/users/StaffHomePage";
7 | import StudentHomePage from "./Components/users/StudentHomePage";
8 | import MakeRequest from "./Components/Pages/MakeRequest";
9 | import WorkFlow from "./Components/Pages/CreateDocumentFlow";
10 | import Path from "./Components/Pages/Path";
11 | import AproversPage from "./Components/users/ApproversPage";
12 | import SubmitRequest from "./Components/Pages/SubmitRequest";
13 | import StatusRequest from "./Components/Pages/StatusRequest";
14 | import ApproversStatusPage from "./Components/Pages/ApproversStatusPage";
15 | import Login from "./Components/Login/Login";
16 | import Popup from "./Components/Popup/Popup";
17 |
18 | const App = () => {
19 | return (
20 |
21 |
22 |
23 | {/* Login Page */}
24 | } />
25 | } />
26 |
27 | {/* Student */}
28 | } />
29 | } />
30 | }
33 | />
34 | }
37 | />
38 |
39 | {/* Academic Staff */}
40 | } />
41 | }
44 | />
45 |
46 | {/* Non-Academic Staff */}
47 | } />
48 | }
51 | />
52 | }
55 | />
56 | }
59 | />
60 |
61 | {/* Ongoing Request / Approved Request / Rejected Request */}
62 |
63 | } />
64 |
65 | } />
66 |
67 |
68 |
69 | );
70 | };
71 |
72 | export default App;
73 |
--------------------------------------------------------------------------------
/src/Components/Auth/CheckFunction.js:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * The forward slashes / / mark the beginning and end of the regular expression.
4 | * The \S character matches a single character other than white space.
5 | * The + character matches the preceding character one or more times.
6 | */
7 | const isValidInput = (arr)=>{
8 | let valid = true;
9 | for(let index = 1; index < arr.length; index++){
10 | valid = /\S+@eng.jfn.ac.lk/.test(arr[index]);
11 | if(valid === false)
12 | break;
13 | }
14 | return valid
15 | }
16 |
17 | export {isValidInput}
18 |
--------------------------------------------------------------------------------
/src/Components/Auth/Navigation.js:
--------------------------------------------------------------------------------
1 | const navigation = (url) => {
2 | window.location.href = url;
3 | };
4 |
5 | export default navigation;
6 |
--------------------------------------------------------------------------------
/src/Components/Firebase/functions.js:
--------------------------------------------------------------------------------
1 | import { doc, setDoc, getDoc } from "firebase/firestore";
2 | import { db } from "../../Firebase/firebase";
3 |
4 | // upload the Path Details
5 | async function PathOnSubmit(pathName, noOfApprover, Approvers) {
6 | const PathRef = doc(db, "Path", pathName);
7 |
8 | await setDoc(PathRef, {
9 | PathName: pathName,
10 | NumberOfApproves: noOfApprover,
11 | Approver: Approvers,
12 | });
13 | return true;
14 | }
15 |
16 | class PathData {
17 | constructor(pathName, Approver, NumberOfApproves) {
18 | this.pathName = pathName;
19 | this.Approver = Approver;
20 | this.NumberOfApproves = NumberOfApproves;
21 | }
22 | }
23 |
24 | const pathConverter = {
25 | toFirestore: (PathData) => {
26 | return {
27 | pathName: PathData.pathName,
28 | Approver: PathData.Approver,
29 | NumberOfApproves: PathData.NumberOfApproves,
30 | };
31 | },
32 | fromFirestore: (snapshot, options) => {
33 | const data = snapshot.data(options);
34 | return new PathData(data.pathName, data.Approver, data.NumberOfApproves);
35 | },
36 | };
37 |
38 | // Get path flow Details from the Firebase Database
39 | async function getPath(pathName) {
40 | const docRef = doc(db, "Path", pathName).withConverter(pathConverter);
41 |
42 | const docSnap = await getDoc(docRef);
43 | if (docSnap.exists()) {
44 | let pathD = docSnap.data();
45 | let Details = pathD.Approver;
46 | return Details;
47 | }
48 | }
49 |
50 | export { PathOnSubmit, getPath };
51 |
--------------------------------------------------------------------------------
/src/Components/Firebase/upload.js:
--------------------------------------------------------------------------------
1 | import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
2 | import { storage, db } from "../../Firebase/firebase";
3 | import {
4 | collection,
5 | addDoc,
6 | doc,
7 | updateDoc,
8 | getDocs,
9 | query,
10 | where,
11 | getDoc,
12 | } from "firebase/firestore";
13 |
14 | async function upload(file, requester, approvers, Request_Type) {
15 | await upload_document(file, requester, approvers, Request_Type);
16 | alert("successfully submitted");
17 | }
18 |
19 | // Upload a pdf document
20 | async function upload_document(file, requester, approvers, Request_Type) {
21 | let File_Name = requester + "_" + Date();
22 | const storageRef = await ref(storage, `/files/${File_Name}`);
23 | await uploadBytesResumable(storageRef, file);
24 | const downloadurl = await getDownloadURL(storageRef);
25 | upload_document_Details(downloadurl, approvers, requester, Request_Type);
26 | }
27 |
28 | // upload document details to database
29 | async function upload_document_Details(
30 | url,
31 | approvers,
32 | requester,
33 | Request_Type
34 | ) {
35 | const docRef = await addDoc(collection(db, "Documents"), {
36 | File_URL: url,
37 | No_of_Approvers: approvers.length,
38 | Requester_Mail: requester,
39 | File_Status: "Processing",
40 | Request_Type: Request_Type,
41 | });
42 |
43 | let status = [];
44 | let comment = [];
45 |
46 | for (var i = 0; i < approvers.length; i++) {
47 | if (i === 0) {
48 | status.push("Processing");
49 | } else {
50 | status.push("Waiting");
51 | }
52 | comment.push("");
53 | }
54 | const washingtonRef = await doc(db, "Documents", docRef.id);
55 | await updateDoc(washingtonRef, {
56 | Approvers: approvers,
57 | Status: status,
58 | Comment: comment,
59 | });
60 | }
61 |
62 | // ongoing Request / Apporoved Request / Reject Request Student Side
63 | async function readDocuments(requester, status) {
64 | const q = query(
65 | collection(db, "Documents"),
66 | where("Requester_Mail", "==", requester),
67 | where("File_Status", "==", status)
68 | );
69 | const querySnapshot = await getDocs(q);
70 | let temp = [];
71 |
72 | querySnapshot.forEach((doc) => {
73 | temp.push(doc.data());
74 | });
75 | return temp;
76 | }
77 |
78 | // ongoing Request / Apporoved Request / Reject Request Staffs Side
79 | async function readDocumentsStaff(staff, status) {
80 | const q = query(collection(db, "Documents"));
81 | const querySnapshot = await getDocs(q);
82 |
83 | let temp = [];
84 | querySnapshot.forEach((doc) => {
85 | for (let i = 0; i < doc.data().Approvers.length; i++) {
86 | if (
87 | doc.data().Approvers[i] === staff &&
88 | doc.data().Status[i] === status
89 | ) {
90 | temp.push(doc.data());
91 | }
92 | }
93 | });
94 | return temp;
95 | }
96 |
97 | // set the Document status
98 | async function submitStaff(doc_Id, decision, comment, staff) {
99 | const q = query(collection(db, "Documents"), where("File_URL", "==", doc_Id));
100 | const querySnapshot = await getDocs(q);
101 | querySnapshot.forEach((doc) => {
102 | doc_Id = doc.id;
103 | });
104 |
105 | const washingtonRef = await doc(db, "Documents", doc_Id);
106 |
107 | const docSnap = await getDoc(washingtonRef);
108 | for (let i = 0; i < docSnap.data().Approvers.length; i++) {
109 | if (
110 | docSnap.data().Approvers[i] === staff &&
111 | docSnap.data().Status[i] === "Processing"
112 | ) {
113 | let com = docSnap.data().Comment;
114 | let st = docSnap.data().Status;
115 | let fSt = docSnap.data().File_Status;
116 | com[i] = comment;
117 | if (decision === "Approved") {
118 | st[i] = "Approved";
119 |
120 | if (i + 1 === docSnap.data().Approvers.length) {
121 | fSt = "Approved";
122 | } else {
123 | st[i + 1] = "Processing";
124 | }
125 | } else if (decision === "Rejected") {
126 | st[i] = "Rejected";
127 | fSt = "Rejected";
128 | }
129 |
130 | await updateDoc(washingtonRef, {
131 | // Comment:com,
132 | Status: st,
133 | File_Status: fSt,
134 | });
135 | }
136 | }
137 | alert("Finished!!!");
138 | }
139 |
140 | // login
141 | async function login(email, role, password) {
142 | let temp = [];
143 |
144 | if (role === "Academic Staff") {
145 | role = "Staff";
146 | }
147 |
148 | if (role === "Non-Academic Staff") {
149 | role = "AR";
150 | }
151 |
152 | // console.log("UserMail:", email);
153 | // console.log("Role:", role);
154 | // console.log("Password:", password);
155 |
156 | const q = query(
157 | collection(db, "Users"),
158 | where("UserMail", "==", email),
159 | where("Password", "==", password),
160 | where("Role", "==", role)
161 | );
162 |
163 | const querySnapshot = await getDocs(q);
164 |
165 | querySnapshot.forEach((doc) => {
166 | temp.push(doc.data());
167 | });
168 |
169 | if (temp.length > 0) {
170 | let userName = await getName(email);
171 | sessionStorage.setItem("Username", userName);
172 | let url = "";
173 |
174 | if (temp.length === 1 && role === "Student") {
175 | url = "/Student-Home";
176 | window.location.href = url;
177 | sessionStorage.setItem("MainHome", url);
178 |
179 | return false;
180 | } else if (temp.length === 1 && role === "Staff") {
181 | url = "/Acc-Staff-Home";
182 | window.location.href = url;
183 | sessionStorage.setItem("MainHome", url);
184 |
185 | return false;
186 | } else if (temp.length === 1 && role === "AR") {
187 | url = "/Non-Acc-Staff-Home";
188 | window.location.href = url;
189 | sessionStorage.setItem("MainHome", url);
190 |
191 | return false;
192 | }
193 | } else {
194 | return true;
195 | }
196 | }
197 |
198 | // get user name from firebase using email
199 | async function getName(email) {
200 | let name = "";
201 | const q = query(collection(db, "Users"), where("UserMail", "==", email));
202 | const querySnapshot = await getDocs(q);
203 | querySnapshot.forEach((doc) => {
204 | name = doc.data().Username;
205 | });
206 | return name;
207 | }
208 |
209 | // read all the documents which are approved
210 | async function readApprovedDocuments(requester) {
211 | const q = query(
212 | collection(db, "Documents"),
213 | where("Requester_Mail", "==", requester),
214 | where("File_Status", "==", "Approved")
215 | );
216 | const querySnapshot = await getDocs(q);
217 |
218 | let temp = [];
219 | querySnapshot.forEach((doc) => {
220 | temp.push(doc.data());
221 | });
222 | return temp;
223 | }
224 |
225 | // read all the documents which are rejected
226 | async function readRejectDocuments(requester) {
227 | const q = query(
228 | collection(db, "Documents"),
229 | where("Requester_Mail", "==", requester),
230 | where("File_Status", "==", "Rejected")
231 | );
232 | const querySnapshot = await getDocs(q);
233 | let temp = [];
234 | querySnapshot.forEach((doc) => {
235 | temp.push(doc.data());
236 | });
237 | return temp;
238 | }
239 |
240 | export {
241 | upload,
242 | readDocuments,
243 | readDocumentsStaff,
244 | submitStaff,
245 | login,
246 | getName,
247 | readRejectDocuments,
248 | readApprovedDocuments,
249 | };
250 |
--------------------------------------------------------------------------------
/src/Components/Login/Login.css:
--------------------------------------------------------------------------------
1 | #blur-background {
2 | position: absolute;
3 | top: 0;
4 | left: 0;
5 | min-height: 100vh;
6 | min-width: 100vw;
7 |
8 | height: 100vh;
9 | width: 100vw;
10 | overflow: hidden;
11 |
12 | background-color: #cccccc98;
13 | z-index: 10;
14 | display: flex;
15 | justify-content: center;
16 | align-items: center;
17 | }
18 |
19 | .alert-danger,
20 | .alert {
21 | display: flex;
22 | align-items: center;
23 | justify-content: center;
24 | width: 90%;
25 | margin: 0 auto;
26 | height: 1rem;
27 | /* padding: 0; */
28 | line-height: 0;
29 | }
30 |
31 | .login1 {
32 | width: 400px;
33 | background: #fff;
34 | box-shadow: 0 0px 20px black;
35 | border-radius: 8px;
36 | padding: 1rem;
37 | }
38 |
39 | .login1 .form {
40 | display: flex;
41 | flex-direction: column;
42 | /* align-items: center; */
43 | }
44 |
45 | .login1 .form span {
46 | font-size: 25px;
47 | font-weight: 600;
48 | font-family: "Roboto", sans-serif;
49 | padding: 0 0 1rem 0;
50 | }
51 |
52 | .form p {
53 | text-align: left;
54 | }
55 |
56 | .form-input {
57 | border-radius: 10px;
58 | /* outline: none; */
59 | color: #1d2129;
60 | border: 1px solid #ccc;
61 | width: 100%;
62 | /* margin: 0 0.5rem; */
63 | padding: 1rem;
64 | font-size: 16px;
65 | }
66 |
67 | .button_common {
68 | background-color: rgb(7, 7, 224);
69 | color: white;
70 | padding: 15px;
71 | margin-top: 1rem;
72 | margin-bottom: 1rem;
73 | /* padding: 15px 30px; */
74 | /* border: none; */
75 | font-size: 22px;
76 | border-radius: 15px;
77 | cursor: pointer;
78 | width: 90%;
79 | }
80 |
81 | .disabled {
82 | background-color: #cccccc;
83 | color: #ffffff;
84 | cursor: not-allowed;
85 | }
86 |
87 | .error {
88 | color: red;
89 | text-align: left;
90 | margin: auto;
91 | text-indent: 1rem;
92 | font-size: 16px;
93 | /* padding: 0px 1rem; */
94 | }
95 |
96 | #Strong {
97 | display: flex;
98 | flex-direction: row-reverse;
99 | cursor: pointer;
100 | font-weight: 600;
101 | font-size: 1.5rem;
102 | color: red;
103 | padding: 0;
104 | }
105 |
--------------------------------------------------------------------------------
/src/Components/Login/Login.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "./Login.css";
3 | import { login } from "../Firebase/upload";
4 | import Loading from "../Pages/Loading";
5 | // import { useNavigate } from "react-router-dom";
6 | import navigation from "../Auth/Navigation";
7 |
8 | const Login = () => {
9 | // const navigation = useNavigate();
10 | const MainHome = sessionStorage.getItem("MainHome");
11 | const tag = sessionStorage.getItem("UserType");
12 |
13 | window.onload = function () {
14 | if (MainHome !== null && tag !== null) {
15 | window.location.href = MainHome;
16 | } else if (tag !== null && MainHome === null) {
17 | navigation("/login");
18 | } else {
19 | navigation("/");
20 | }
21 | };
22 |
23 | const [formErrors, setFormErrors] = useState({});
24 | const [isError, setIsError] = useState(false);
25 | const [isLoading, setIsLoading] = useState(false);
26 |
27 | const [user, setUserDetails] = useState({
28 | email: "",
29 | password: "",
30 | });
31 |
32 | const changeHandler = (e) => {
33 | setIsError(false);
34 | const { name, value } = e.target;
35 |
36 | setUserDetails({
37 | ...user,
38 | [name]: value,
39 | });
40 | };
41 |
42 | useEffect(() => {});
43 | const validateForm = (values) => {
44 | const error = {};
45 | const regex = /^[^\s+@]+@[^\s@]+\.[^\s@]{2,}$/i;
46 |
47 | if (!values.email.includes("eng.jfn.ac.lk")) {
48 | error.email = "Not valid Email ";
49 | }
50 |
51 | if (!values.email) {
52 | error.email = "Email is required";
53 | } else if (!regex.test(values.email)) {
54 | error.email = "Please enter a valid email address";
55 | }
56 |
57 | if (!values.password) {
58 | error.password = "Password is required";
59 | }
60 |
61 | return error;
62 | };
63 |
64 | const loginHandler = async (e) => {
65 | e.preventDefault();
66 | setIsLoading(true);
67 | setFormErrors(validateForm(user));
68 |
69 | if (user.email.trim().length !== 0 && user.password.trim().length !== 0) {
70 | let log = await login(user.email, tag, user.password);
71 | sessionStorage.setItem("UserMail", user.email);
72 | setIsError(log);
73 | }
74 |
75 | setTimeout(() => {
76 | setIsLoading(false);
77 | }, 1000);
78 | };
79 |
80 | const hideHandle = () => {
81 | sessionStorage.clear();
82 | navigation("/");
83 | };
84 |
85 | return (
86 |
87 | {isLoading &&
}
88 |
89 |
90 | X
91 |
92 | {isError && (
93 |
94 |
102 |
103 |
104 |
Invalid Password or Email!
105 |
106 | )}
107 |
148 |
149 |
150 | );
151 | };
152 | export default Login;
153 |
--------------------------------------------------------------------------------
/src/Components/Pages/ApproversStatusPage.css:
--------------------------------------------------------------------------------
1 | #Staff-Display-Area {
2 | height: 100%;
3 | min-height: 400px;
4 |
5 | background-color: rgb(210, 203, 203);
6 | font-size: 1.5rem;
7 | padding: 1rem;
8 | margin: 1rem;
9 | border-radius: 15px;
10 | box-shadow: 4px 4px 10px rgba(17, 27, 83, 0.522);
11 | border: 4px solid rgba(17, 27, 83, 0.522);
12 | }
13 |
14 |
15 | .Comment {
16 | padding: 10px;
17 | font-size: 35px;
18 | margin: 10px;
19 |
20 | border-radius: 20px;
21 | }
22 |
23 | .SetStatus {
24 | padding: 10px;
25 | font-size: 35px;
26 | margin: 10px;
27 | }
28 |
29 | .Status-Submit-Button {
30 | background-color: #90caf9;
31 | font-size: 45px;
32 | border-radius: 20px;
33 | }
34 |
35 | #Status-buttons-hover:hover {
36 | box-shadow: 6px 6px 1px rgba(67, 87, 199, 0.522);
37 | }
38 |
--------------------------------------------------------------------------------
/src/Components/Pages/ApproversStatusPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "../general.css";
3 | import "./ApproversStatusPage.css";
4 | import logo from "../assets/logo.png";
5 |
6 | import { readDocumentsStaff, submitStaff } from "../Firebase/upload";
7 | import Loading from "./Loading";
8 | // import { useNavigate } from "react-router-dom";
9 | import navigation from "../Auth/Navigation";
10 |
11 | const ApproversStatusPage = () => {
12 | const [isLoading, setIsLoading] = useState(false);
13 | // var fileLists = [];
14 | const [fileLists, setFileLists] = useState([]);
15 |
16 | window.onload = () => {
17 | handleSubmit();
18 | };
19 |
20 | let StatusType = sessionStorage.getItem("StatusType");
21 | let MainHome = sessionStorage.getItem("MainHome");
22 | let Username = sessionStorage.getItem("Username");
23 | let UserMail = sessionStorage.getItem("UserMail");
24 | let status = "";
25 |
26 | if (StatusType === "New Requests") status = "Processing";
27 | else if (StatusType === "Approved Requests") status = "Approved";
28 | else if (StatusType === "Rejected Requests") status = "Rejected";
29 |
30 | const year = () => {
31 | let VarDate = new Date().getFullYear();
32 | return VarDate;
33 | };
34 |
35 | const Set_Name = () => {
36 | return Username;
37 | };
38 |
39 | useEffect(() => {
40 | if (sessionStorage.getItem("Username") === null) {
41 | navigation("/");
42 | } else {
43 | sessionStorage.setItem("MainHome", sessionStorage.getItem("MainHome"));
44 | }
45 | }, []);
46 |
47 | const Logout = () => {
48 | setIsLoading(true);
49 |
50 | sessionStorage.clear();
51 | localStorage.clear();
52 | navigation("/");
53 |
54 | setTimeout(() => {
55 | setIsLoading(false);
56 | }, 2000);
57 | };
58 |
59 | const Home = () => {
60 | setIsLoading(true);
61 | navigation(MainHome);
62 |
63 | setTimeout(() => {
64 | setIsLoading(false);
65 | }, 2000);
66 | };
67 |
68 | let id = [];
69 | const submit = (e) => {
70 | setIsLoading(true);
71 | let decisions = document.getElementsByClassName("SetStatus");
72 | let comments = document.getElementsByClassName("Comment");
73 |
74 | console.log(id[e]);
75 | if (decisions[e].value !== "Default") {
76 | submitStaff(id[e], decisions[e].value, comments[e].value, UserMail);
77 | } else {
78 | alert("Please select Approve or Reject !!!");
79 | }
80 |
81 | setTimeout(() => {
82 | setIsLoading(false);
83 | }, 2000);
84 | };
85 |
86 | const handleSubmit = async () => {
87 | setIsLoading(true);
88 |
89 | try {
90 | setFileLists(
91 | await readDocumentsStaff(UserMail, status).then((res) => {
92 | return res;
93 | })
94 | );
95 | } catch (error) {
96 | console.log(error);
97 | }
98 |
99 | setTimeout(() => {
100 | setIsLoading(false);
101 | }, 2000);
102 | };
103 |
104 | return (
105 |
106 | {isLoading &&
}
107 |
108 |
109 |
110 |
111 | Welcome to Student Document Approval System{" "}
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | Home
120 |
121 |
Welcome {Set_Name()}
122 |
123 |
124 | Logout
125 |
126 |
127 |
{StatusType}
128 |
129 |
130 | {fileLists.length === 0 && (
131 |
No Request Found !!!
132 | )}
133 |
134 |
135 | {fileLists.length > 0 &&
136 | fileLists.map((fileList, index) => {
137 | id.push(fileList.File_URL);
138 | return (
139 |
140 |
141 |
149 |
150 | {fileList.Requester_Mail + " "}
151 | Requesting for
152 | {" " + fileList.Request_Type}
153 |
154 |
155 |
156 |
157 |
162 |
163 |
164 |
168 | Student Name
169 |
170 |
171 |
172 | {fileList.Requester_Mail}
173 |
174 |
175 |
176 |
177 |
181 | Request Type
182 |
183 |
184 |
185 | {fileList.Request_Type}
186 |
187 |
188 |
189 |
204 |
205 |
206 |
207 | No
208 | Approver Email
209 | Status
210 | Comments
211 |
212 |
213 |
214 | {fileList.Approvers.map((approver, j) => {
215 | return (
216 |
217 | {j + 1}
218 | {approver}
219 | {fileList.Status[j]}
220 | {fileList.Comment}
221 |
222 | );
223 | })}
224 |
225 |
226 |
227 |
228 |
232 | Comment
233 |
234 |
235 |
243 |
244 |
245 |
246 |
250 |
251 | Approve / Reject
252 |
253 | Approve
254 | Reject
255 |
256 |
257 |
261 | submit
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 | );
270 | })}
271 |
272 |
273 |
274 |
275 |
276 |
© Copyright {year()} University of Jaffna.
277 |
278 |
279 | );
280 | };
281 |
282 | export default ApproversStatusPage;
283 |
--------------------------------------------------------------------------------
/src/Components/Pages/CreateDocumentFlow.css:
--------------------------------------------------------------------------------
1 | .Request-Background {
2 | padding: 1.2rem;
3 | justify-content: space-between;
4 | margin: 0.5rem;
5 | background: rgba(98, 189, 255, 0.5);
6 | border-radius: 13px;
7 | }
8 |
9 | .Request-Background .text {
10 | display: flex;
11 | align-items: center;
12 | font-size: 1.2rem;
13 |
14 | flex-shrink: 1;
15 | flex-grow: 2;
16 | flex-basis: 10px;
17 | }
18 |
19 | .Request-Background .d-flex {
20 | flex-shrink: 1;
21 | flex-grow: 2;
22 | flex-basis: 10px;
23 | }
24 |
--------------------------------------------------------------------------------
/src/Components/Pages/CreateDocumentFlow.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "../general.css";
3 | import "./CreateDocumentFlow.css";
4 | import logo from "../assets/logo.png";
5 | import Loading from "./Loading";
6 | // import { useNavigate } from "react-router-dom";
7 | import navigation from "../Auth/Navigation";
8 |
9 | const MakeRequest = () => {
10 | const [isLoading, setIsLoading] = useState(false);
11 | // const navigation = useNavigate();
12 | const year = () => {
13 | let VarDate = new Date().getFullYear();
14 |
15 | return VarDate;
16 | };
17 |
18 | useEffect(() => {
19 | if (sessionStorage.getItem("Username") === null) {
20 | navigation("/");
21 | } else {
22 | sessionStorage.setItem("MainHome", sessionStorage.getItem("MainHome"));
23 | }
24 | }, []);
25 |
26 | const Staff_Name = () => {
27 | return sessionStorage.getItem("Username");
28 | };
29 |
30 | const Logout = () => {
31 | setIsLoading(true);
32 |
33 | sessionStorage.clear();
34 | localStorage.clear();
35 | navigation("/");
36 |
37 | setTimeout(() => {
38 | setIsLoading(false);
39 | }, 2000);
40 | };
41 |
42 | const Home = () => {
43 | setIsLoading(true);
44 | navigation("/Non-Acc-Staff-Home");
45 |
46 | setTimeout(() => {
47 | setIsLoading(false);
48 | }, 2000);
49 | };
50 |
51 | const setPath = (pathName) => {
52 | setIsLoading(true);
53 | navigation("/Non-Acc-Staff-Home/SetWorkFlow/Path");
54 | sessionStorage.setItem("PathName", pathName);
55 |
56 | setTimeout(() => {
57 | setIsLoading(false);
58 | }, 2000);
59 | };
60 |
61 | const updatePath = (pathName) => {
62 | // setIsLoading(true);
63 | // navigation("/Non-Acc-Staff-Home/SetWorkFlow/Path");
64 | // sessionStorage.setItem("PathName", pathName);
65 | // setTimeout(() => {
66 | // setIsLoading(false);
67 | // }, 2000);
68 | };
69 |
70 | const requestNames = [
71 | "Exam Reshedule",
72 | "Exam Re-attempt",
73 | "Labratory Session Reshedule",
74 | "Requesting Studentship Confirmation Letter",
75 | "Requesting Progress Report",
76 | "Requesting for New Student Record Book",
77 | "Requesting for New Student ID card",
78 | ];
79 |
80 | return (
81 |
82 | {isLoading &&
}
83 |
84 |
85 |
86 |
87 | Welcome to Student Document Approval System{" "}
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | Home
96 |
97 |
Welcome {Staff_Name()}
98 |
99 |
100 | Logout
101 |
102 |
103 |
104 |
105 | {requestNames.map((item, index) => {
106 | return (
107 |
108 |
{item}
109 |
110 |
111 |
115 | Update/Modify
116 |
117 |
118 | setPath(item)}
121 | >
122 | Set
123 |
124 |
125 |
126 | );
127 | })}
128 |
129 |
130 |
131 |
132 |
© Copyright {year()} University of Jaffna.
133 |
134 |
135 | );
136 | };
137 |
138 | export default MakeRequest;
139 |
--------------------------------------------------------------------------------
/src/Components/Pages/Loading.css:
--------------------------------------------------------------------------------
1 | .loading {
2 | position: fixed;
3 | top: 0;
4 | left: 0;
5 | width: 100vw;
6 | height: 100vh;
7 | background: #262626;
8 | z-index: 1000;
9 | }
10 | .ring {
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | transform: translate(-50%, -50%);
15 | width: 200px;
16 | height: 200px;
17 | background: transparent;
18 | border: 3px solid #3c3c3c;
19 |
20 | border-radius: 50%;
21 | text-align: center;
22 | line-height: 200px;
23 | font-family: sans-serif;
24 | font-size: 20px;
25 |
26 | color: #fff000;
27 | /* color: #000fff; */
28 |
29 | letter-spacing: 4px;
30 | text-transform: uppercase;
31 |
32 | text-shadow: 0 0 10px #fff000;
33 | /* text-shadow: 0 0 10px #000fff; */
34 |
35 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
36 | }
37 |
38 | .ring:before {
39 | content: "";
40 | position: absolute;
41 | top: 0px;
42 | left: 0px;
43 | width: 100%;
44 | height: 100%;
45 | border: 3px solid transparent;
46 |
47 | border-top: 3px solid #fff000;
48 | /* border-top: 3px solid #000fff; */
49 |
50 | border-right: 3px solid #fff000;
51 | /* border-right: 3px solid #000fff; */
52 |
53 | border-radius: 50%;
54 | animation: animateC 2s linear infinite;
55 | }
56 |
57 | .ring span {
58 | display: block;
59 | position: absolute;
60 | top: calc(50% - 1px);
61 | left: 50%;
62 | width: 50%;
63 | height: 2px;
64 | background: transparent;
65 | transform-origin: left;
66 | animation: animate 2s linear infinite;
67 | }
68 | .ring span:before {
69 | content: "";
70 | position: absolute;
71 | width: 16px;
72 | height: 16px;
73 | border-radius: 50%;
74 |
75 | background: #fff000;
76 | /* background: #000fff; */
77 |
78 | top: -6px;
79 | right: -8px;
80 |
81 | box-shadow: 0 0 20px #fff000;
82 | /* box-shadow: 0 0 20px #000fff; */
83 | }
84 |
85 | @keyframes animateC {
86 | 0% {
87 | transform: rotate(0deg);
88 | }
89 | 100% {
90 | transform: rotate(360deg);
91 | }
92 | }
93 |
94 | @keyframes animate {
95 | 0% {
96 | transform: rotate(45deg);
97 | }
98 | 100% {
99 | transform: rotate(405deg);
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Components/Pages/Loading.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import "./Loading.css";
3 |
4 | const Loading = () => {
5 | return (
6 |
7 |
8 | Loading
9 |
10 |
11 |
12 | );
13 | };
14 |
15 | export default Loading;
16 |
--------------------------------------------------------------------------------
/src/Components/Pages/LoginPage.css:
--------------------------------------------------------------------------------
1 | .th1 {
2 | background-color: #063137;
3 | }
4 |
5 | .th2 {
6 | background-color: #104d55;
7 | }
8 |
9 | .th3 {
10 | background-color: #063137;
11 | }
12 |
13 | .login-table {
14 | border-collapse: separate;
15 | border-radius: 30px 30px 0 0;
16 | border-spacing: 10px;
17 | }
18 |
19 | .login-table tr th {
20 | font-size: 30px;
21 | font-weight: bold;
22 | font-family: "Courier New", Courier, monospace;
23 | color: rgb(255, 255, 255);
24 | padding: 12px;
25 | border-radius: 25px;
26 | }
27 |
28 | .login-table tbody tr td {
29 | color: #205e5e;
30 | font-size: 20px;
31 | padding: 8px;
32 | width: 380px;
33 | text-align: center;
34 | font-style: italic;
35 | height: 45px;
36 | box-shadow: 0px 0px 4px rgb(0, 0, 0);
37 | }
38 |
39 | .odd {
40 | border-radius: 15px;
41 | height: 100%;
42 | }
43 |
44 | .even {
45 | /* box-shadow: 1px 1px 5px rgb(98, 11, 11); */
46 | border-radius: 15px;
47 | height: 100%;
48 | }
49 |
50 | .buttons-sets {
51 | display: flex;
52 | flex-direction: row;
53 | justify-content: space-around;
54 | align-items: center;
55 | margin: 1rem;
56 | }
57 |
58 | .buttons-sets button {
59 | font-size: 1.5rem;
60 | background: #00adee;
61 | border: none;
62 | margin: 0.5rem 1rem;
63 | border-radius: 1rem;
64 | padding: 1rem 1rem;
65 | color: white;
66 | cursor: pointer;
67 | width: 100%;
68 | }
69 |
70 | .buttons-sets button:hover {
71 | box-shadow: 0px 0px 10px rgb(0, 0, 0);
72 | }
73 |
--------------------------------------------------------------------------------
/src/Components/Pages/LoginPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from "react";
2 | import "../general.css";
3 | import "./LoginPage.css";
4 | import logo from "../assets/logo.png";
5 | import { useNavigate } from "react-router-dom";
6 |
7 | const LoginPage = () => {
8 | const navigate = useNavigate();
9 |
10 | const year = () => {
11 | let VarDate = new Date().getFullYear();
12 | return VarDate;
13 | };
14 |
15 | useEffect(() => {
16 | if (sessionStorage.getItem("MainHome") !== null) {
17 | navigate("/" + sessionStorage.getItem("MainHome"));
18 |
19 | }else if (sessionStorage.getItem("UserType") !== null) {
20 | navigate("/login");
21 | } else {
22 | navigate("/");
23 | }
24 | }, [navigate]);
25 |
26 |
27 | const Student = () => {
28 | let type = "Student";
29 | sessionStorage.setItem("UserType", type);
30 | navigate("/login");
31 | };
32 |
33 | const Academic_Staff = () => {
34 | let type = "Academic Staff";
35 |
36 | sessionStorage.setItem("UserType", type);
37 | navigate("/login");
38 | };
39 |
40 | const Non_Academic_Staff = () => {
41 | let type = "Non-Academic Staff";
42 |
43 | sessionStorage.setItem("UserType", type);
44 | navigate("/login");
45 | };
46 |
47 | const TableDisplay = () => {
48 | return (
49 |
50 |
51 |
52 | Student
53 | Academic Staff
54 | Non-Academic Staff
55 |
56 |
57 |
58 |
59 |
60 | Request Exam Reschedule
61 |
62 | Approve/Reject Exam Reschedule
63 |
64 | Approve/Reject Exam Reschedule
65 |
66 |
67 |
68 | Request Exam Re-attempt
69 | Approve/Reject Exam Re-attempt
70 |
71 |
72 |
73 | Request Lab Reschedule
74 |
75 | Sent Studentship Confirm Letter
76 |
77 |
78 |
79 | Request Studentship Confirm Letter
80 |
81 | Approve/Reject Exam Re-attempt
82 |
83 | Sent Progress Report
84 |
85 |
86 |
87 | Request Progress Report
88 |
89 | Provide New University Student Record Book
90 |
91 |
92 |
93 | Request New University Student Record Book
94 |
95 | Approve/Reject Lab Reschedule
96 |
97 |
98 | Provide New University Student Identity Card
99 |
100 |
101 |
102 |
103 |
104 | Request New University Student Identity Card
105 |
106 |
107 |
108 |
109 | );
110 | };
111 |
112 | return (
113 |
114 |
115 |
116 |
117 |
118 | Welcome to Student Document Approval System
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | Sign in as Student
129 |
130 |
131 | Sign in as Academic Staff
132 |
133 |
134 | Sign in as Asst.Registrar
135 |
136 |
137 |
138 |
139 |
140 |
© Copyright {year()} University of Jaffna.
141 |
142 |
143 | );
144 | };
145 |
146 | export default LoginPage;
147 |
--------------------------------------------------------------------------------
/src/Components/Pages/MakeRequest.css:
--------------------------------------------------------------------------------
1 | .Request-Background {
2 | display: flex;
3 | padding: 1.2rem;
4 | justify-content: space-between;
5 | margin: 0.5rem;
6 | background: rgba(98, 189, 255, 0.5);
7 | border-radius: 13px;
8 | }
9 |
10 | .Check-Requirements {
11 | cursor: pointer;
12 | font-size: 1.2rem;
13 | padding: 0.5rem 0.7rem;
14 | background: #ffe296;
15 | /* box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 4px 4px rgba(0, 0, 0, 0.25); */
16 | border-radius: 10px;
17 | }
18 |
19 | .Request {
20 | cursor: pointer;
21 | font-size: 1.2rem;
22 | padding: 0.5rem 0.7rem;
23 | background: #bcffbb;
24 | /* box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 4px 4px rgba(0, 0, 0, 0.25); */
25 | border-radius: 10px;
26 | }
27 |
28 | .Request-Background .text {
29 | display: flex;
30 | align-items: center;
31 | font-size: 1.2rem;
32 |
33 | flex-shrink: 1;
34 | flex-grow: 2;
35 | flex-basis: 10px;
36 | }
37 |
38 | .Request-Background .d-flex {
39 | flex-shrink: 1;
40 | flex-grow: 2;
41 | flex-basis: 10px;
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/src/Components/Pages/MakeRequest.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "../general.css";
3 | import "./MakeRequest.css";
4 | import logo from "../assets/logo.png";
5 | import Loading from "./Loading";
6 | // import { useNavigate } from "react-router-dom";
7 | import navigation from "../Auth/Navigation";
8 |
9 | const MakeRequest = () => {
10 | const [isLoading, setIsLoading] = useState(false);
11 | // const navigation = useNavigate();
12 |
13 | let MainHome = sessionStorage.getItem("MainHome");
14 |
15 | const year = () => {
16 | let VarDate = new Date().getFullYear();
17 | return VarDate;
18 | };
19 |
20 | useEffect(() => {
21 | if (sessionStorage.getItem("Username") === null) {
22 | navigation("/");
23 | } else {
24 | sessionStorage.setItem("MainHome", "Student-Home");
25 | }
26 | }, []);
27 |
28 | const Student_Name = () => {
29 | return sessionStorage.getItem("Username");
30 | };
31 |
32 | const Logout = () => {
33 | setIsLoading(true);
34 |
35 | sessionStorage.clear();
36 | localStorage.clear();
37 | navigation("/");
38 |
39 | setTimeout(() => {
40 | setIsLoading(false);
41 | }, 2000);
42 | };
43 |
44 | const Back = () => {
45 | setIsLoading(true);
46 | // window.location.href = "/" + MainHome;
47 | navigation(MainHome);
48 |
49 | setTimeout(() => {
50 | setIsLoading(false);
51 | }, 2000);
52 | };
53 |
54 | const Submit_Request = (ReqName) => {
55 | var RequestName = ReqName;
56 | sessionStorage.setItem("RequestName", RequestName);
57 | navigation("/Student-Home/MakeRequest/SubmitRequest");
58 | };
59 |
60 | const PopUp_Display = (e) => {
61 | setIsLoading(true);
62 |
63 | navigation("/Student-Home/MakeRequest/Requirement", {
64 | state: { RequestName: e },
65 | });
66 |
67 | setTimeout(() => {
68 | setIsLoading(false);
69 | }, 1000);
70 | };
71 |
72 | const requestNames = [
73 | "Exam Reshedule",
74 | "Exam Re-attempt",
75 | "Labratory Session Reshedule",
76 | "Requesting Studentship Confirmation Letter",
77 | "Requesting Progress Report",
78 | "Requesting for New Student Record Book",
79 | "Requesting for New Student ID card",
80 | ];
81 |
82 | return (
83 |
84 | {isLoading &&
}
85 |
86 |
87 |
88 |
89 | Welcome to Student Document Approval System
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Home
98 |
99 |
Welcome {Student_Name()}
100 |
101 |
102 | Logout
103 |
104 |
105 |
106 | {requestNames.map((item, index) => {
107 | return (
108 |
109 |
{item}
110 |
111 |
112 | PopUp_Display(item)}
115 | >
116 | Check Requirements
117 |
118 | Submit_Request(item)}
121 | >
122 | Request
123 |
124 |
125 |
126 | );
127 | })}
128 |
129 |
130 |
131 |
© Copyright {year()} University of Jaffna.
132 |
133 |
134 | );
135 | };
136 |
137 | export default MakeRequest;
138 |
--------------------------------------------------------------------------------
/src/Components/Pages/Path.css:
--------------------------------------------------------------------------------
1 | .AddPathTitle {
2 | text-align: center;
3 | /* width: 100%; */
4 |
5 | font-size: 40px;
6 | color: rgb(8, 73, 73);
7 | }
8 |
9 | .Add-Button {
10 | font-size: 1.5rem;
11 | font-weight: 500;
12 | background-color: #90caf9;
13 |
14 | border-radius: 22px;
15 | }
16 |
17 | .Remove-Button {
18 | font-size: 1.5rem;
19 | font-weight: 500;
20 | background-color: #90caf9;
21 | border-radius: 22px;
22 | }
23 |
24 | .Path-Submit-Button {
25 | font-size: 1.5rem;
26 | font-weight: 500;
27 | background-color: #90caf9;
28 | border-radius: 22px;
29 | }
30 |
31 | #Path-Area {
32 | padding: 10px;
33 | font-size: 1.5rem;
34 | display: flex;
35 | flex-direction: column;
36 | }
37 |
38 | #Select-Persons {
39 | width: 80%;
40 | font-size: 1rem;
41 | }
42 |
43 | .Box {
44 | background-color: #0c3451;
45 | margin: 50px;
46 | /* height: 80px; */
47 | text-align: center;
48 | }
49 |
50 | .Content-Background {
51 | /* background-color: #0c3451; */
52 | min-height: 60vh;
53 | }
54 |
--------------------------------------------------------------------------------
/src/Components/Pages/Path.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import logo from "../assets/logo.png";
3 | import "./Path.css";
4 | import "../general.css";
5 |
6 | import { PathOnSubmit } from "../Firebase/functions";
7 | import Loading from "./Loading";
8 | import navigation from "../Auth/Navigation";
9 |
10 | const Path = () => {
11 | const [isLoading, setIsLoading] = useState(false);
12 | const MainHome = sessionStorage.getItem("MainHome");
13 | let pathName = sessionStorage.getItem("PathName");
14 | const [i, setI] = useState(0);
15 | const [Approvers, setApprovers] = useState([]);
16 | const [errorMessage, setErrorMessage] = useState("");
17 | const [successMessage, setSuccessMessage] = useState("");
18 |
19 | const year = () => {
20 | let VarDate = new Date().getFullYear();
21 | return VarDate;
22 | };
23 |
24 | useEffect(() => {
25 | if (sessionStorage.getItem("Username") === null) {
26 | navigation("/");
27 | } else {
28 | sessionStorage.setItem("MainHome", sessionStorage.getItem("MainHome"));
29 | }
30 | }, []);
31 |
32 | const Staff_Name = () => {
33 | return sessionStorage.getItem("Username");
34 | };
35 |
36 | const Logout = () => {
37 | setIsLoading(true);
38 |
39 | sessionStorage.clear();
40 | localStorage.clear();
41 | navigation("/");
42 |
43 | setTimeout(() => {
44 | setIsLoading(false);
45 | }, 2000);
46 | };
47 |
48 | const Home = () => {
49 | setIsLoading(true);
50 | navigation(MainHome);
51 |
52 | setTimeout(() => {
53 | setIsLoading(false);
54 | }, 2000);
55 | };
56 |
57 | const hide_reset_button = () => {
58 | setIsLoading(true);
59 |
60 | setTimeout(() => {
61 | setIsLoading(false);
62 | }, 2000);
63 | };
64 |
65 | const add_Persons = () => {
66 | let SelectPersons = document.getElementById("Select-Persons");
67 |
68 | if (SelectPersons.value !== "Default" && i < 7) {
69 | setApprovers([...Approvers, SelectPersons.value]);
70 |
71 | // console.log(Approvers, i);
72 | setI(i + 1);
73 | setErrorMessage("");
74 | } else {
75 | setErrorMessage("Please Select the Staff");
76 | }
77 | };
78 |
79 | const remove_Persons = (index) => {
80 | setIsLoading(true);
81 | // console.log(index);
82 | setApprovers(Approvers.filter((_item, i) => i !== index));
83 |
84 | setTimeout(() => {
85 | setIsLoading(false);
86 | }, 2000);
87 | };
88 |
89 | async function handleSubmit() {
90 | setIsLoading(true);
91 |
92 | if (await PathOnSubmit(pathName, i, Approvers)) {
93 | alert("Path Added Successfully");
94 | setSuccessMessage(pathName + " Path Added Successfully");
95 | navigation(MainHome);
96 | }
97 |
98 | setTimeout(() => {
99 | setIsLoading(false);
100 | }, 2000);
101 | }
102 |
103 | return (
104 |
105 | {isLoading &&
}
106 |
107 |
108 |
109 |
110 | Welcome to Student Document Approval System{" "}
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | Home
119 |
120 |
Welcome {Staff_Name()}
121 |
122 |
123 | Logout
124 |
125 |
126 |
127 |
{pathName}
128 |
129 |
133 | Select the Staff
134 | Asst.Registrar
135 | Dean
136 | Head of Departments
137 | Advisor
138 | Course Coordinator
139 |
140 |
141 |
145 | Add +
146 |
147 |
148 |
149 | Submit
150 |
151 |
152 |
153 | {errorMessage &&
{errorMessage}
}
154 | {successMessage &&
{successMessage}
}
155 |
156 | {Approvers.length > 0 &&
157 | Approvers.map((item, index) => {
158 | return (
159 |
160 |
161 | {index + 1} th Approver
162 |
163 |
164 |
172 | remove_Persons(index)}
175 | >
176 | Remove
177 |
178 |
179 | );
180 | })}
181 |
182 |
183 |
184 |
185 |
© Copyright {year()} University of Jaffna.
186 |
187 |
188 | );
189 | };
190 |
191 | export default Path;
192 |
--------------------------------------------------------------------------------
/src/Components/Pages/StatusRequest.css:
--------------------------------------------------------------------------------
1 | .Status-Heading {
2 | /* position: relative; */
3 | /* top: 120px; */
4 | margin-top: 15px;
5 | text-align: center;
6 | width: 100%;
7 | font-size: 40px;
8 | color: rgb(8, 73, 73);
9 | }
10 |
11 | #Display {
12 | /* position: relative; */
13 | height: 100%;
14 | min-height: 400px;
15 | overflow: scroll;
16 | background-color: rgb(210, 203, 203);
17 | font-size: 1.5rem;
18 | padding: 1rem;
19 | margin: 1rem;
20 | border-radius: 15px;
21 | box-shadow: 4px 4px 10px rgba(17, 27, 83, 0.522);
22 | border: 4px solid rgba(17, 27, 83, 0.522);
23 | }
24 |
25 | .Status-Table2 {
26 | background-color: #90caf9;
27 | margin: 10px;
28 | width: 100%;
29 | }
30 |
31 | .Status-Table1 {
32 | background-color: #90caf9;
33 | margin: 10px;
34 | width: 100%;
35 | }
36 |
37 | .Status-Table1 th {
38 | border-collapse: collapse;
39 | margin: 10px;
40 | width: 25%;
41 | font-size: 25px;
42 | padding: 10px;
43 | justify-content: center;
44 | }
45 |
46 | .Status-Table2 th {
47 | border-collapse: collapse;
48 | margin: 10px;
49 | width: 25%;
50 | font-size: 25px;
51 | padding: 10px;
52 | overflow-x: scroll;
53 | }
54 |
55 | hr {
56 | /* position: relative; */
57 | /* height: 5px; */
58 | color: rgb(164, 150, 150);
59 | background-color: rgb(164, 150, 150);
60 | /* left: 10%; */
61 | display: flex;
62 | align-items: center;
63 | justify-content: center;
64 | width: 90%;
65 | margin: 0 auto;
66 | text-align: center;
67 | }
68 |
69 | a {
70 | color: red;
71 | }
72 |
73 | .Aprover-Display {
74 | display: flex;
75 | flex-direction: column;
76 | align-items: center;
77 | justify-content: center;
78 | margin: 1rem;
79 | font-size: 2rem;
80 | color: #05adea;
81 | }
82 |
--------------------------------------------------------------------------------
/src/Components/Pages/StatusRequest.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "../general.css";
3 | import "./StatusRequest.css";
4 | import logo from "../assets/logo.png";
5 | import { readDocuments } from "../Firebase/upload";
6 | import Loading from "./Loading";
7 | // import { useNavigate } from "react-router-dom";
8 | import navigation from "../Auth/Navigation";
9 |
10 | const StatusRequest = () => {
11 | const [isLoading, setIsLoading] = useState(false);
12 | // const navigation = useNavigate();
13 |
14 | let MainHome = sessionStorage.getItem("MainHome");
15 | let StatusType = sessionStorage.getItem("StatusType");
16 | let Username = sessionStorage.getItem("Username");
17 | let status = "";
18 |
19 | if (StatusType === "Ongoing Requests") status = "Processing";
20 | else if (StatusType === "Approved Requests") status = "Approved";
21 | else if (StatusType === "Rejected Requests") status = "Rejected";
22 |
23 | const year = () => {
24 | let VarDate = new Date().getFullYear();
25 |
26 | return VarDate;
27 | };
28 |
29 | const Set_Name = () => {
30 | return Username;
31 | };
32 |
33 | useEffect(() => {
34 | if (sessionStorage.getItem("Username") === null) {
35 | navigation("/");
36 | } else {
37 | sessionStorage.setItem("MainHome", sessionStorage.getItem("MainHome"));
38 | }
39 | }, []);
40 |
41 | const Logout = () => {
42 | setIsLoading(true);
43 |
44 | sessionStorage.clear();
45 | localStorage.clear();
46 | navigation("/");
47 |
48 | setTimeout(() => {
49 | setIsLoading(false);
50 | }, 2000);
51 | };
52 |
53 | const Home = () => {
54 | setIsLoading(true);
55 | navigation( MainHome);
56 |
57 | setTimeout(() => {
58 | setIsLoading(false);
59 | }, 2000);
60 | };
61 |
62 | const handleSubmit = async () => {
63 | setIsLoading(true);
64 |
65 | let Display = document.getElementById("Display");
66 | try {
67 | let fileLists = await readDocuments(Username, status);
68 |
69 | if (fileLists.length > 0) {
70 | for (let i = 0; i < fileLists.length; i++) {
71 | Display.innerHTML += ` Request Type : ${fileLists[i].Request_Type}
`;
72 | Display.innerHTML += `Document : Click Here... `;
73 | Display.innerHTML += `
74 |
75 |
76 | No
77 | Approver Email
78 | Status
79 | Comments
80 |
81 |
`;
82 |
83 | for (let j = 0; j < fileLists[i].No_of_Approvers; j++) {
84 | Display.innerHTML += `
85 |
86 |
87 | ${j + 1}
88 | ${fileLists[i].Approvers[j]}
89 | ${fileLists[i].Status[j]}
90 | ${fileLists[i].Comment[j]}
91 |
92 |
`;
93 | }
94 | Display.innerHTML += ` `;
95 | }
96 | } else {
97 | Display.innerHTML +=
98 | ' No Request Found !!! ';
99 | }
100 | } catch (error) {
101 | Display.innerHTML +=
102 | ' No Request Found !!! ';
103 | }
104 |
105 | setTimeout(() => {
106 | setIsLoading(false);
107 | }, 1000);
108 | };
109 |
110 | return (
111 |
112 | {isLoading &&
}
113 |
114 |
115 |
116 |
117 | Welcome to Student Document Approval System
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | Home
126 |
127 |
Welcome {Set_Name()}
128 |
129 |
130 | Logout
131 |
132 |
133 |
134 |
{StatusType}
135 |
136 |
137 |
138 |
139 |
140 |
© Copyright {year()} University of Jaffna.
141 |
142 |
143 | );
144 | };
145 |
146 | export default StatusRequest;
147 |
--------------------------------------------------------------------------------
/src/Components/Pages/SubmitRequest.css:
--------------------------------------------------------------------------------
1 | .Heading {
2 | margin-top: 15px;
3 | text-align: center;
4 | font-size: 40px;
5 | color: rgb(8, 73, 73);
6 | }
7 |
8 | .Form-Label {
9 | height: 70px;
10 | /* width: 800px; */
11 | padding: 30px;
12 | background-color: rgb(194, 203, 203);
13 | border-radius: 10px;
14 | display: flex;
15 | flex-direction: row;
16 | }
17 | .File-Label {
18 | height: 70px;
19 | font-size: 30px;
20 | font-weight: 500;
21 | vertical-align: middle;
22 | }
23 |
24 | #File-Input {
25 | height: 70px;
26 | font-size: 30px;
27 | font-weight: 500;
28 | }
29 |
30 | #Approvers-Name {
31 | font-size: 12px;
32 | padding: 10px;
33 | }
34 |
35 | #Approvers-Name h1 {
36 | height: 25px;
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/src/Components/Pages/SubmitRequest.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "../general.css";
3 | import logo from "../assets/logo.png";
4 | import "./SubmitRequest.css";
5 | import { getPath } from "../Firebase/functions.js";
6 | import { upload } from "../Firebase/upload.js";
7 |
8 | import { isValidInput } from "../Auth/CheckFunction";
9 | import Loading from "./Loading";
10 | // import { useNavigate } from "react-router-dom";
11 | import navigation from "../Auth/Navigation";
12 |
13 | const SubmitRequest = () => {
14 | const [isLoading, setIsLoading] = useState(false);
15 | // const navigation = useNavigate();
16 | let MainHome = sessionStorage.getItem("MainHome");
17 | const [file, setFile] = useState(null);
18 | let ApproversList = [];
19 | const [ApproverNames, setApproverNames] = useState([]);
20 | const [error, setError] = useState("");
21 |
22 | let RequestName = sessionStorage.getItem("RequestName");
23 | let Username = sessionStorage.getItem("Username");
24 |
25 | const year = () => {
26 | let VarDate = new Date().getFullYear();
27 | return VarDate;
28 | };
29 |
30 | const Student_Name = () => {
31 | return Username;
32 | };
33 |
34 | window.onload = async () => {
35 | let ApproverNamesDetails = await displayApprovers();
36 | setApproverNames(ApproverNamesDetails);
37 | };
38 |
39 | const displayApprovers = async () => {
40 | setIsLoading(true);
41 | try {
42 | let ApproverNamesDetails = await getPath(RequestName);
43 |
44 | setTimeout(() => {
45 | setIsLoading(false);
46 | }, 2000);
47 |
48 | return ApproverNamesDetails;
49 | } catch (error) {
50 | console.log(error);
51 |
52 | setTimeout(() => {
53 | setIsLoading(false);
54 | }, 2000);
55 | return [];
56 | }
57 | };
58 |
59 | useEffect(() => {
60 | if (sessionStorage.getItem("Username") === null) {
61 | navigation("/");
62 | } else {
63 | sessionStorage.setItem("MainHome", sessionStorage.getItem("MainHome"));
64 |
65 | // console.log(ApproverNames);
66 | }
67 | }, []);
68 |
69 | const Logout = () => {
70 | setIsLoading(true);
71 |
72 | sessionStorage.clear();
73 | localStorage.clear();
74 | navigation("/");
75 |
76 | setTimeout(() => {
77 | setIsLoading(false);
78 | }, 2000);
79 | };
80 |
81 | const Back = () => {
82 | setIsLoading(true);
83 | navigation(MainHome);
84 |
85 | setTimeout(() => {
86 | setIsLoading(false);
87 | }, 2000);
88 | };
89 |
90 | const handleChange = (event) => {
91 | // setIsLoading(true);
92 | hideAlert();
93 | setFile(event.target.files);
94 | // setTimeout(() => {
95 | // setIsLoading(false);
96 | // }, 2000);
97 | };
98 |
99 | const handleUpload = async () => {
100 | setIsLoading(true);
101 |
102 | let Approvers_Mail = document.getElementsByTagName("input");
103 | let Arraylength = Approvers_Mail.length;
104 | ApproversList = [];
105 | for (let index = 1; index < Arraylength; index++) {
106 | ApproversList.push(Approvers_Mail[index].value);
107 | }
108 |
109 | if (!isValidInput(ApproversList)) {
110 | setError("Please Enter the Valid Mail!");
111 | } else if (!file) {
112 | setError("Please choose a file first!");
113 | } else {
114 | await upload(file, Username, ApproversList, RequestName).then(() => {
115 | clear_field();
116 | });
117 | }
118 |
119 | setTimeout(() => {
120 | setIsLoading(false);
121 | }, 3000);
122 | };
123 |
124 | const clear_field = () => {
125 | setIsLoading(true);
126 |
127 | let inputs = document.getElementsByTagName("input");
128 | for (let index = 0; index < inputs.length; index++) {
129 | inputs[index].value = "";
130 | }
131 |
132 | setTimeout(() => {
133 | setIsLoading(false);
134 | }, 2000);
135 | };
136 |
137 | const hideAlert = () => {
138 | setError("");
139 | };
140 |
141 | return (
142 |
143 | {isLoading &&
}
144 |
145 |
146 |
147 |
148 | Welcome to Student Document Approval System{" "}
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | Home
157 |
158 |
Welcome {Student_Name()}
159 |
160 |
161 | Logout
162 |
163 |
164 |
165 |
{RequestName}
166 |
167 |
168 |
175 |
176 | Upload
177 |
178 |
179 |
180 |
181 | {ApproverNames &&
182 | ApproverNames.map((Approver, index) => (
183 |
184 |
185 |
189 | {Approver}
190 |
191 |
200 |
201 |
202 | ))}
203 |
204 | {error &&
{error}
}
205 |
209 | Submit
210 |
211 |
212 |
213 |
214 |
215 |
© Copyright {year()} University of Jaffna.
216 |
217 |
218 | );
219 | };
220 |
221 | export default SubmitRequest;
222 |
--------------------------------------------------------------------------------
/src/Components/Popup/Popup.css:
--------------------------------------------------------------------------------
1 | #Popup {
2 | position: absolute;
3 | top: 0;
4 | left: 0;
5 | background-color: rgba(0, 0, 0, 0.5);
6 | width: 100vw;
7 | height: 100vh;
8 | min-height: 100vh;
9 | min-width: 100vw;
10 | display: flex;
11 | justify-content: center;
12 | align-items: center;
13 | }
14 |
15 | #Popup .visible-area {
16 | background-color: aliceblue;
17 | /* height: ; */
18 | /* width: 100%; */
19 | box-shadow: 0px 0px 20px rgb(0, 0, 0);
20 | border-radius: 10px;
21 | padding: 1rem;
22 | }
23 |
--------------------------------------------------------------------------------
/src/Components/Popup/Popup.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { useLocation } from "react-router-dom";
3 | import Loading from "../Pages/Loading";
4 | import "./Popup.css";
5 |
6 | import navigation from "../Auth/Navigation";
7 |
8 | const Popup = () => {
9 | const [isLoading, setIsLoading] = useState(false);
10 | // const navigation = useNavigate();
11 | const location = useLocation();
12 |
13 | const RequestName = location.state.RequestName;
14 |
15 | const Hide_Popup = () => {
16 | setIsLoading(true);
17 |
18 | navigation("/Student-Home/MakeRequest");
19 |
20 | setTimeout(() => {
21 | setIsLoading(false);
22 | }, 1000);
23 | };
24 |
25 | return (
26 |
51 | );
52 | };
53 |
54 | export default Popup;
55 |
--------------------------------------------------------------------------------
/src/Components/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kajamohan-Krishnadasan/Software-Engineering-Project/4a936414046b6bc2a457b879592f270e04b3c449/src/Components/assets/logo.png
--------------------------------------------------------------------------------
/src/Components/general.css:
--------------------------------------------------------------------------------
1 | * {
2 | font-family: "Outfit";
3 | margin: 0;
4 | padding: 0;
5 | box-sizing: border-box;
6 | }
7 |
8 | body {
9 | min-width: 100vw;
10 | min-height: 100vh;
11 | width: 100vw;
12 | height: 100vh;
13 | }
14 |
15 | .main {
16 | background: #fff;
17 | /* background-color: #00ADEE; */
18 | width: calc(100vw - 0.5rem);
19 | height: calc(100vh - 0.5rem);
20 | }
21 | button {
22 | cursor: pointer;
23 | }
24 |
25 | .Background {
26 | min-height: 100vh;
27 | min-height: 100vh;
28 | box-sizing: border-box;
29 |
30 | margin: 0.5rem;
31 | background: #164784;
32 | border-radius: 31px;
33 | }
34 |
35 | .Main-Background {
36 | width: 100%;
37 | height: 100%;
38 | padding: 1rem;
39 | background: #0a223f;
40 |
41 | }
42 |
43 | .Header {
44 | width: 100%;
45 | height: 100%;
46 | display: flex;
47 | align-items: center;
48 | justify-content: space-around;
49 | }
50 |
51 | .Footer {
52 | width: 100%;
53 | height: 2rem;
54 | font-size: 1rem;
55 | line-height: 1.5rem;
56 | display: flex;
57 | justify-content: center;
58 | align-items: center;
59 | color: #fff;
60 | }
61 |
62 | .title {
63 | font-weight: 600;
64 | font-size: 3rem;
65 | text-shadow: 1px 1px 10px #000;
66 | margin: 0.5rem;
67 | color: #fff;
68 | }
69 |
70 | .Logo {
71 | border-radius: 50%;
72 | height: 150px;
73 | margin: 1rem;
74 | }
75 |
76 | .Content-Background {
77 | padding: 0.5rem;
78 | background: #eae7e7;
79 | box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
80 | border-radius: 15px;
81 | display: flex;
82 | flex-direction: column;
83 | }
84 | .welcome-with-Logout-button {
85 | display: flex;
86 | padding: 1rem;
87 | justify-content: space-between;
88 | }
89 |
90 | .Welcome-Name {
91 | font-family: "Outfit";
92 | font-style: normal;
93 | font-weight: 400;
94 | font-size: 2rem;
95 | line-height: 2.5rem;
96 | color: #675b5b;
97 | /* text-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 4px 4px rgba(0, 0, 0, 0.25); */
98 | }
99 |
100 | .logout-button {
101 | background-color: #00adee;
102 |
103 | border: 1px solid #000000;
104 | outline: none;
105 | border: none;
106 | box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
107 | font-weight: 600;
108 | font-size: 1.5rem;
109 | text-align: center;
110 | color: #fff;
111 | border-radius: 20px;
112 | padding: 0.8rem;
113 | }
114 |
115 | .buttons-hover:hover {
116 | /* box-shadow: 0px 0px 10px rgba(6, 13, 55, 0.799); */
117 | filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25))
118 | drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25));
119 | }
120 |
121 | .Status {
122 | display: flex;
123 | width: 40px;
124 | height: 40px;
125 | border-radius: 50%;
126 | }
127 |
128 | .Color-Red {
129 | background: #ff0101;
130 | }
131 |
132 | .Color-Blue {
133 | background: #00adee;
134 | }
135 | .Color-Green {
136 | background: #00ee10;
137 | }
138 |
139 | .buttons-sets-home {
140 | display: flex;
141 | flex-direction: column;
142 | padding: 0.5rem 2rem;
143 | align-items: center;
144 | }
145 |
146 | .buttons-sets-home button {
147 | margin: 0.8rem 1rem;
148 | font-size: 2rem;
149 | padding: 0.5rem 1rem;
150 | width: 500px;
151 | background: #d9d9d9;
152 | border-radius: 20px;
153 | display: flex;
154 | align-items: center;
155 | justify-content: space-between;
156 | }
157 |
--------------------------------------------------------------------------------
/src/Components/users/ApproversPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "../general.css";
3 | import logo from "../assets/logo.png";
4 | import Loading from "../Pages/Loading";
5 | // import { useNavigate } from "react-router-dom";
6 | import navigation from "../Auth/Navigation";
7 |
8 | const AproversPage = () => {
9 | const [isLoading, setIsLoading] = useState(false);
10 | // const navigation = useNavigate();
11 | const year = () => {
12 | let VarDate = new Date().getFullYear();
13 | return VarDate;
14 | };
15 |
16 | useEffect(() => {
17 | if (sessionStorage.getItem("Username") === null) {
18 | navigation("/");
19 | } else {
20 | sessionStorage.setItem("MainHome", sessionStorage.getItem("MainHome"));
21 | }
22 | }, []);
23 |
24 | const Staff_Name = () => {
25 | return sessionStorage.getItem("Username");
26 | };
27 |
28 | const Logout = () => {
29 | setIsLoading(true);
30 |
31 | sessionStorage.clear();
32 | localStorage.clear();
33 | navigation("/");
34 |
35 | setTimeout(() => {
36 | setIsLoading(false);
37 | }, 2000);
38 | };
39 |
40 | const Get_Status = (StatusType) => {
41 | sessionStorage.setItem("StatusType", StatusType);
42 | sessionStorage.setItem("MainHome", "Acc-Staff-Home");
43 | navigation("/Acc-Staff-Home/Status");
44 | };
45 |
46 | return (
47 |
48 | {isLoading &&
}
49 |
50 |
51 |
52 |
53 | Welcome to Student Document Approval System{" "}
54 |
55 |
56 |
57 |
58 |
59 |
Welcome {Staff_Name()}
60 |
61 |
62 | Logout
63 |
64 |
65 |
66 |
67 | Get_Status("New Requests")}
70 | >
71 | New Requests
72 |
73 | Get_Status("Approved Requests")}
76 | >
77 | Approved Requests
78 |
79 | Get_Status("Rejected Requests")}
82 | >
83 | Rejected Requests
84 |
85 |
86 |
87 |
88 |
89 |
© Copyright {year()} University of Jaffna.
90 |
91 |
92 | );
93 | };
94 |
95 | export default AproversPage;
96 |
--------------------------------------------------------------------------------
/src/Components/users/AproversPage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import "../general.css";
3 | import "./AproversPage.css";
4 | import logo from "../assets/logo.png";
5 | // import { useNavigate } from "react-router-dom";
6 | import navigation from "../Auth/Navigation";
7 | import Loading from "../Pages/Loading";
8 |
9 | const AproversPage = () => {
10 | // const navigation = useNavigate();
11 | const [isLoading, setIsLoading] = useState(false);
12 | const year = () => {
13 | let VarDate = new Date().getFullYear();
14 | return VarDate;
15 | };
16 |
17 | const Staff_Name = () => {
18 | return "Staff";
19 | };
20 |
21 | const Logout = () => {
22 | setIsLoading(true);
23 |
24 | sessionStorage.clear();
25 | localStorage.clear();
26 | navigation("/");
27 |
28 | setTimeout(() => {
29 | setIsLoading(false);
30 | }, 2000);
31 | };
32 |
33 | const Get_Status = (StatusType) => {
34 | setIsLoading(true);
35 |
36 | sessionStorage.setItem("StatusType", StatusType);
37 | sessionStorage.setItem("MainHome", "Acc-Staff-Home");
38 | navigation("/StatusRequest");
39 |
40 | setTimeout(() => {
41 | setIsLoading(false);
42 | }, 2000);
43 | };
44 |
45 | return (
46 |
47 | {isLoading &&
}
48 |
49 |
50 |
51 |
52 | Welcome to Student Document Approval System{" "}
53 |
54 |
55 |
56 |
57 |
58 |
59 |
Welcome {Staff_Name()}
60 |
61 |
62 | Logout
63 |
64 |
65 |
66 |
Get_Status("Ongoing Requests")}
69 | >
70 | Ongoing Requests
71 |
72 |
Get_Status("Approved Requests")}
75 | >
76 | Approved Requests
77 |
78 |
Get_Status("Rejected Requests")}
81 | >
82 | Rejected Requests
83 |
84 |
85 |
86 |
87 |
© Copyright {year()} University of Jaffna.
88 |
89 |
90 | );
91 | };
92 |
93 | export default AproversPage;
94 |
--------------------------------------------------------------------------------
/src/Components/users/StaffHomePage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "../general.css";
3 | import logo from "../assets/logo.png";
4 | import Loading from "../Pages/Loading";
5 | // import { useNavigate } from "react-router-dom";
6 | import navigation from "../Auth/Navigation";
7 |
8 | const StaffHomePage = () => {
9 | const [isLoading, setIsLoading] = useState(false);
10 | // const navigation = useNavigate();
11 | const year = () => {
12 | let VarDate = new Date().getFullYear();
13 | return VarDate;
14 | };
15 |
16 | const Staff_Name = () => {
17 | return sessionStorage.getItem("Username");
18 | };
19 |
20 | useEffect(() => {
21 | if (sessionStorage.getItem("Username") === null) {
22 | navigation("/");
23 | } else {
24 | sessionStorage.setItem("MainHome", sessionStorage.getItem("MainHome"));
25 | }
26 | }, []);
27 |
28 | const Logout = () => {
29 | setIsLoading(true);
30 | sessionStorage.clear();
31 | localStorage.clear();
32 | navigation("/");
33 |
34 | setTimeout(() => {
35 | setIsLoading(false);
36 | }, 2000);
37 | };
38 |
39 | const set_Flow = () => {
40 | setIsLoading(true);
41 | navigation("/Non-Acc-Staff-Home/SetWorkFlow");
42 |
43 | setTimeout(() => {
44 | setIsLoading(false);
45 | }, 2000);
46 | };
47 |
48 | const Get_Status = (StatusType) => {
49 | sessionStorage.setItem("StatusType", StatusType);
50 | sessionStorage.setItem("MainHome", "Non-Acc-Staff-Home");
51 | navigation("/Non-Acc-Staff-Home/Status");
52 | };
53 |
54 | return (
55 |
56 | {isLoading &&
}
57 |
58 |
59 |
60 |
61 | Welcome to Student Document Approval System{" "}
62 |
63 |
64 |
65 |
66 |
67 |
68 |
Welcome {Staff_Name()}
69 |
70 |
71 | Logout
72 |
73 |
74 |
75 |
76 |
77 | Create Document Flow Path
78 |
79 | Get_Status("New Requests")}
82 | >
83 | New Requests
84 |
85 | Get_Status("Approved Requests")}
88 | >
89 | Approved Requests
90 |
91 | Get_Status("Rejected Requests")}
94 | >
95 | Rejected Requests
96 |
97 |
98 |
99 |
100 |
101 |
© Copyright {year()} University of Jaffna.
102 |
103 |
104 | );
105 | };
106 |
107 | export default StaffHomePage;
108 |
--------------------------------------------------------------------------------
/src/Components/users/StudentHomePage.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "../general.css";
3 | import logo from "../assets/logo.png";
4 | import Loading from "../Pages/Loading";
5 | // import { useNavigate } from "react-router-dom";
6 | import navigation from "../Auth/Navigation";
7 |
8 | const StudentHomePage = () => {
9 | const [isLoading, setIsLoading] = useState(false);
10 | // const navigation = useNavigate();
11 |
12 | const year = () => {
13 | let VarDate = new Date().getFullYear();
14 | return VarDate;
15 | };
16 |
17 | useEffect(() => {
18 | if (sessionStorage.getItem("Username") === null) {
19 | navigation("/");
20 | } else {
21 | sessionStorage.setItem("MainHome",sessionStorage.getItem("MainHome"));
22 | }
23 | }, []);
24 |
25 | const Student_Name = () => {
26 | return sessionStorage.getItem("Username");
27 | };
28 |
29 | const Logout = () => {
30 | setIsLoading(true);
31 |
32 | sessionStorage.clear();
33 | localStorage.clear();
34 | navigation("/");
35 |
36 | setTimeout(() => {
37 | setIsLoading(false);
38 | }, 2000);
39 | };
40 |
41 | const make_a_request = () => {
42 | setIsLoading(true);
43 |
44 | navigation("/Student-Home/MakeRequest");
45 |
46 | setTimeout(() => {
47 | setIsLoading(false);
48 | }, 2000);
49 | };
50 |
51 | const Get_Status = (StatusType) => {
52 | sessionStorage.setItem("StatusType", StatusType);
53 | sessionStorage.setItem("MainHome", "Student-Home");
54 | navigation("/StatusRequest");
55 | };
56 |
57 | return (
58 |
59 | {isLoading &&
}
60 |
61 |
62 |
63 |
64 | Welcome to Student Document Approval System{" "}
65 |
66 |
67 |
68 |
69 |
70 |
Welcome {Student_Name()}
71 |
72 |
73 | Logout
74 |
75 |
76 |
77 |
78 |
79 | Make a Request
80 |
81 |
82 | Get_Status("Ongoing Requests")}
85 | >
86 | Ongoing Requests
87 |
88 |
89 | Get_Status("Approved Requests")}
92 | >
93 | Approved Requests
94 |
95 |
96 | Get_Status("Rejected Requests")}
99 | >
100 | Rejected Requests
101 |
102 |
103 |
104 |
105 |
106 |
© Copyright {year()} University of Jaffna.
107 |
108 |
109 | );
110 | };
111 |
112 | export default StudentHomePage;
113 |
--------------------------------------------------------------------------------
/src/Firebase/firebase.js:
--------------------------------------------------------------------------------
1 | // import * as firebase from "firebase/app"
2 | import { initializeApp } from "firebase/app";
3 | import { getAuth } from "firebase/auth";
4 | import { getStorage } from "firebase/storage";
5 | import { getFirestore } from "firebase/firestore";
6 |
7 | // Your web app's Firebase configuration
8 | // Kajamohan
9 | // gs://student-document-approval-uoj.appspot.com
10 | const firebaseConfig = {
11 | apiKey: "AIzaSyAqmMkHQHROCG3IhHfMfLaVlewbqIN0dzw",
12 | authDomain: "student-document-approval-uoj.firebaseapp.com",
13 | databaseURL:
14 | "https://student-document-approval-uoj-default-rtdb.firebaseio.com",
15 | projectId: "student-document-approval-uoj",
16 | storageBucket: "student-document-approval-uoj.appspot.com",
17 | appId: "1:440037393399:web:0052a2bdadd6a5e49924f2",
18 | messagingSenderId: "440037393399",
19 | };
20 |
21 | // Initialize Firebase
22 | const app = initializeApp(firebaseConfig);
23 | const auth = getAuth(app);
24 | const storage = getStorage(app);
25 | const db = getFirestore(app);
26 |
27 | // const uid = auth.currentUser?.uid;
28 |
29 | export { db, auth, app, storage };
30 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 |
2 | .root{
3 | --font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
4 |
5 | --gradient-text : linear-gradient(89deg, #00BCD4 0%, #00BCD4 12%, #EE82EE 56%, #EE82EE 72%, #EE82EE 92%);
6 |
7 |
8 | --color-bg : #040c18;
9 | --color-footer : #031b34;
10 | --color-text : #81afdd;
11 | --color-subtext : #ff8a71;
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 | import "bootstrap/dist/css/bootstrap.min.css";
5 | import "bootstrap/dist/css/bootstrap.css";
6 |
7 | const rootElement = ReactDOM.createRoot(document.getElementById("root"));
8 |
9 | rootElement.render(
10 |
11 |
12 |
13 | );
14 |
--------------------------------------------------------------------------------