20 | }
--------------------------------------------------------------------------------
/frontend/src/components/messages/inbox/Messaging.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Switch, Route } from "react-router-dom";
3 | import Sidebar from "./Sidebar";
4 | import Message from "./MessageContainer";
5 | import DefaultView from "./DefaultView";
6 |
7 | function Messaging() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | );
19 | }
20 |
21 | export default Messaging;
22 |
--------------------------------------------------------------------------------
/frontend/src/components/settings/Settings.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Logout from "./Logout";
3 | import ChangePassword from "./ChangePassword";
4 | import { useSelector, useDispatch } from "react-redux";
5 | import { selectUser, logout } from "../../store/slices/userSlice";
6 |
7 | function SettingsPage() {
8 | const user = useSelector(selectUser);
9 | const dispatch = useDispatch();
10 |
11 | return (
12 |
13 |
Account Settings
14 |
15 |
16 |
17 | );
18 | }
19 |
20 | export default SettingsPage;
21 |
--------------------------------------------------------------------------------
/frontend/src/Loading.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Backdrop from "@material-ui/core/Backdrop";
3 | import CircularProgress from "@material-ui/core/CircularProgress";
4 | import { makeStyles } from "@material-ui/core/styles";
5 |
6 | const useStyles = makeStyles((theme) => ({
7 | backdrop: {
8 | zIndex: theme.zIndex.drawer + 1,
9 | color: "#fff",
10 | },
11 | }));
12 |
13 | export default function SimpleBackdrop() {
14 | const classes = useStyles();
15 |
16 | return (
17 |
18 |
19 |
20 |
21 |
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/backend/models/AttendenceModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const AttendanceSchema = new Schema(
6 | {
7 | classID: {
8 | type: String,
9 | required: true,
10 | },
11 | role: {
12 | type: String,
13 | },
14 | user: String,
15 | users: {
16 | type: [
17 | {
18 | userID: String,
19 | name: String,
20 | surname: String,
21 | status: Boolean,
22 | },
23 | ],
24 | default: [],
25 | },
26 | },
27 | { timestamps: true }
28 | );
29 |
30 | module.exports = mongoose.model("attendance", AttendanceSchema);
31 |
--------------------------------------------------------------------------------
/backend/models/FilesModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const FilesSchema = new Schema(
6 | {
7 | topic: {
8 | type: String,
9 | },
10 | date: {
11 | type: Date,
12 | default: Date.now,
13 | },
14 | notes: {
15 | type: String,
16 | },
17 | courseID: {
18 | type: String,
19 | },
20 | classID: {
21 | type: String,
22 | },
23 | senderID: {
24 | type: String,
25 | },
26 | file: {
27 | type: String,
28 | },
29 | },
30 | { timestamps: true }
31 | );
32 |
33 | module.exports = mongoose.model("notes", FilesSchema);
34 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/students/campuses/AddCampus.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import CampusForm from './CampusForm';
3 |
4 |
5 | function AddCampus({name, location , setname, setlocation, onSubmit, loading}) {
6 | return (
7 |
8 |
Add Campus
9 |
17 |
18 | )
19 | }
20 |
21 | export default AddCampus
22 |
--------------------------------------------------------------------------------
/backend/models/CalenderModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const CalendarSchema = new Schema(
6 | {
7 | title: {
8 | type: String,
9 | required: true,
10 | },
11 | resource: {
12 | type: String,
13 | },
14 | description: {
15 | type: String,
16 | },
17 | start: {
18 | type: Date,
19 | },
20 | end: {
21 | type: Date,
22 | },
23 | allDay: {
24 | type: Boolean,
25 | },
26 | day: {
27 | type: Date,
28 | default: Date.now,
29 | },
30 | },
31 | { timestamps: true }
32 | );
33 |
34 | module.exports = mongoose.model("calendar", CalendarSchema);
35 |
--------------------------------------------------------------------------------
/backend/config/mongodb.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("mongoose");
2 | const dotenv = require("dotenv");
3 |
4 | //LOCAL_DB_CONNECT -localhost database
5 | //DB_CONNECT -online database
6 | dotenv.config();
7 | const connection_url = process.env.LOCAL_DB_CONNECT;
8 |
9 | mongoose.connect(connection_url, {
10 | useCreateIndex: true,
11 | useNewUrlParser: true,
12 | useUnifiedTopology: true,
13 | useFindAndModify: false,
14 | });
15 |
16 | mongoose.connection.once("open", () => {
17 | console.log("db connnected localhost db");
18 | // gfs = new mongoose.mongo.GridFSBucket(connect.db, {
19 | // bucketName: "uploads"
20 | // })
21 | });
22 |
23 | //export default mongoose;
24 | module.exports = mongoose;
25 |
--------------------------------------------------------------------------------
/backend/models/NextofKinModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const NextofKinchema = new Schema(
6 | {
7 | name: {
8 | type: String,
9 | },
10 | surname: {
11 | type: String,
12 | },
13 | address: {
14 | type: String,
15 | },
16 | telephone: {
17 | type: String,
18 | },
19 | occupation: {
20 | type: String,
21 | },
22 | relationship: {
23 | String,
24 | },
25 | gender: {
26 | type: String,
27 | },
28 | email: {
29 | type: String,
30 | },
31 | },
32 | { timestamps: true }
33 | );
34 |
35 | module.exports = mongoose.model("nextofkins", NextofKinchema);
36 |
--------------------------------------------------------------------------------
/backend/models/CorrespondanceModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const CorrespondanceSchema = new Schema(
6 | {
7 | address: {
8 | type: String,
9 | required: true,
10 | },
11 | salutation: {
12 | type: String,
13 | },
14 | subject: {
15 | type: String,
16 | required: true,
17 | },
18 | body: {
19 | type: String,
20 | },
21 | closing: {
22 | type: String,
23 | },
24 | signature: {},
25 | date: {
26 | type: Date,
27 | default: Date.now,
28 | },
29 | },
30 | { timestamps: true }
31 | );
32 |
33 | module.exports = mongoose.model("correspondance", CorrespondanceSchema);
34 |
--------------------------------------------------------------------------------
/frontend/src/TeachersComponents/message/Chat.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Switch, Route } from "react-router-dom";
3 | import Sidebar from "../../components/messages/inbox/Sidebar";
4 | import Message from "../../components/messages/inbox/MessageContainer";
5 | import DefaultView from "../../components/messages/inbox/DefaultView";
6 |
7 | function Messaging() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | );
19 | }
20 |
21 | export default Messaging;
22 |
--------------------------------------------------------------------------------
/frontend/src/store/slices/appSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | export const appSlice = createSlice({
4 | name: "app",
5 | initialState: {
6 | sidebarShow: "responsive",
7 | showLoading: false,
8 | },
9 | reducers: {
10 | set: (state, action) => {
11 | state.sidebarShow = action.payload;
12 | },
13 | setLoading: (state, action) => {
14 | console.log(action.payload);
15 | state.showLoading = action.payload;
16 | },
17 | },
18 | });
19 |
20 | export const { set, setLoading } = appSlice.actions;
21 | export const selectSidebarShow = (state) => state.app.sidebarShow;
22 | export const selectShowLoading = (state) => state.app.showLoading;
23 |
24 | export default appSlice.reducer;
25 |
--------------------------------------------------------------------------------
/backend/models/SchoolModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const SchoolSchema = new Schema(
6 | {
7 | name: {
8 | type: String,
9 | },
10 | fullName: {
11 | type: String,
12 | },
13 | motto: {
14 | type: String,
15 | },
16 | role: {
17 | type: String,
18 | },
19 | userID: {
20 | type: String,
21 | },
22 | resetPassowrdToken: String,
23 | resetPasswordExpires: Date,
24 | logo: String,
25 | address: String,
26 | photoUrl: String,
27 | email: String,
28 | telephone: String,
29 | password: String,
30 | },
31 | { timestamps: true }
32 | );
33 |
34 | module.exports = mongoose.model("accounts", SchoolSchema);
35 |
--------------------------------------------------------------------------------
/backend/models/NonBillModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const NonBillSchema = new Schema(
6 | {
7 | student: {
8 | type: String,
9 | },
10 | term: {
11 | type: String,
12 | },
13 | year: {
14 | type: String,
15 | },
16 | amount: {
17 | type: String,
18 | },
19 | remarks: {
20 | type: String,
21 | },
22 | paymentType: {
23 | type: String,
24 | },
25 | bank: {
26 | type: String,
27 | },
28 | cheque: {
29 | type: String,
30 | },
31 | date: {
32 | type: String,
33 | },
34 | },
35 | { timestamps: true }
36 | );
37 |
38 | module.exports = mongoose.model("nonbillpayment", NonBillSchema);
39 |
--------------------------------------------------------------------------------
/backend/models/SSNITModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const SBASchema = new Schema(
6 | {
7 | year: {
8 | type: String,
9 | },
10 | month: {
11 | type: String,
12 | },
13 | percentage: {
14 | type: Number,
15 | },
16 | teachers: {
17 | type: [
18 | {
19 | userID: String,
20 | name: String,
21 | SSNITNumber: String,
22 | position: String,
23 | salary: Number,
24 | contribution: Number,
25 | grade: String,
26 | interpretation: String,
27 | },
28 | ],
29 | },
30 | },
31 | { timestamps: true }
32 | );
33 |
34 | module.exports = mongoose.model("ssnit", SBASchema);
35 |
--------------------------------------------------------------------------------
/backend/routes/Uploads.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const { cloudinary } = require("../middlewares/cloudinary");
3 |
4 | const route = express.Router();
5 |
6 | route.post("/", async (req, res) => {
7 | try {
8 | let timeStamp = new Date();
9 | timeStamp = timeStamp.toJSON();
10 |
11 | // Set folder for uploads
12 | let day = timeStamp.substring(0, 10);
13 |
14 | let promise = await cloudinary.v2.uploader.upload(req.body.dataUrl, {
15 | public_id: `${day}/files-${timeStamp}`,
16 | tags: "files", // tag
17 | });
18 | console.log("finish loading", promise);
19 | return res.json(promise);
20 | } catch (err) {
21 | console.log("err", err);
22 | res.send({ error: err });
23 | }
24 | });
25 |
26 | module.exports = route;
27 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/Profile/FinanceCard.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link } from "react-router-dom";
3 | import DescriptionIcon from "@material-ui/icons/Description";
4 |
5 | function FinanceCard({ route, name, title }) {
6 | return (
7 |
8 |
9 |
10 | {title && (
11 |
12 |
{title}
13 |
14 | )}
15 | {name}
16 |
17 |
18 |
19 |
20 |
21 | );
22 | }
23 |
24 | export default FinanceCard;
25 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/Profile/Profile.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import ProfileInfo from "./ProfileInfo";
3 | import ProfileTabs from "./ProfileTabs";
4 | import axios from "../../store/axios";
5 | import { useSelector } from "react-redux";
6 | import { selectUser } from "../../store/slices/userSlice";
7 |
8 | function Profile() {
9 | const [admin, setadmin] = useState({});
10 | const user = useSelector(selectUser);
11 |
12 | useEffect(() => {
13 | axios.get(`/school`).then((res) => {
14 | setadmin(res.data);
15 | });
16 | }, [user]);
17 |
18 | return (
19 |
23 | );
24 | }
25 |
26 | export default Profile;
27 |
--------------------------------------------------------------------------------
/frontend/src/components/tables/ExcelExport.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactExport from "react-export-excel";
3 | import moment from "moment";
4 |
5 | const ExcelFile = ReactExport.ExcelFile;
6 | const ExcelSheet = ReactExport.ExcelFile.ExcelSheet;
7 | const ExcelColumn = ReactExport.ExcelFile.ExcelColumn;
8 |
9 | function ExcelExport({ data, btn, name, columns }) {
10 | return (
11 | {btn || "Download"}}
13 | >
14 |
15 | {columns.map((col) => (
16 |
17 | ))}
18 |
19 |
20 | );
21 | }
22 |
23 | export default ExcelExport;
24 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/Profile/SummaryCard.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Card from "@material-ui/core/Card";
3 |
4 | function SummaryCard({ name, percentage, value }) {
5 | return (
6 |
7 |
8 |
9 |
10 |
{name}
11 |
12 |
{percentage &&
%
}
13 |
14 |
15 |
{value}
16 | {percentage}
17 |
18 |
19 |
20 | );
21 | }
22 |
23 | export default SummaryCard;
24 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/messages/Chat.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Switch, Route } from "react-router-dom";
3 | import Sidebar from "../../components/messages/inbox/Sidebar";
4 | import Message from "../../components/messages/inbox/MessageContainer";
5 | import DefaultView from "../../components/messages/inbox/DefaultView";
6 |
7 | function Messaging() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | );
21 | }
22 |
23 | export default Messaging;
24 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/messages/Chat.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Switch, Route } from "react-router-dom";
3 | import Sidebar from "../../components/messages/inbox/Sidebar";
4 | import Message from "../../components/messages/inbox/MessageContainer";
5 | import DefaultView from "../../components/messages/inbox/DefaultView";
6 |
7 | function Messaging() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | );
21 | }
22 |
23 | export default Messaging;
24 |
--------------------------------------------------------------------------------
/frontend/src/components/settings/Logout.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useHistory } from "react-router-dom";
3 |
4 | function Logout({ dispatch, loggout, user }) {
5 | const history = useHistory();
6 |
7 | const handleDelete = () => {
8 | dispatch(loggout());
9 | localStorage.clear();
10 | history.push("/login");
11 | };
12 |
13 | return (
14 |
15 |
16 |
17 | You are logged-in as {user?.id}- {user?.name}{" "}
18 | {user?.lastName ? user?.lastName : ""}
19 |
20 |
23 |
24 |
25 | );
26 | }
27 |
28 | export default Logout;
29 |
--------------------------------------------------------------------------------
/backend/models/PaymentPlanModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const PaymentSchema = new Schema(
6 | {
7 | name: {
8 | type: String,
9 | },
10 | plans: {
11 | type: [
12 | {
13 | name: String,
14 | plan: String,
15 | description: String,
16 | price: String,
17 | },
18 | ],
19 | },
20 | services: {
21 | type: [
22 | {
23 | name: String,
24 | plan1: String,
25 | plan2: String,
26 | plan3: String,
27 | },
28 | ],
29 | },
30 | dataID: {
31 | type: String,
32 | default: "paymentPlan",
33 | },
34 | },
35 | { timestamps: true }
36 | );
37 |
38 | module.exports = mongoose.model("canteenpayplan", PaymentSchema);
39 |
--------------------------------------------------------------------------------
/backend/models/StoreSalesModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const StoreSalesSchema = new Schema(
6 | {
7 | name: {
8 | type: String,
9 | },
10 | totalCost: {
11 | type: Number,
12 | },
13 | amountPaid: {
14 | type: Number,
15 | },
16 | seller: {
17 | type: String,
18 | },
19 | items: {
20 | type: [
21 | {
22 | name: {
23 | type: String,
24 | },
25 | qty: {
26 | type: Number,
27 | },
28 | rate: {
29 | type: Number,
30 | },
31 | amount: {
32 | type: Number,
33 | },
34 | },
35 | ],
36 | },
37 | },
38 | { timestamps: true }
39 | );
40 |
41 | module.exports = mongoose.model("storesales", StoreSalesSchema);
42 |
--------------------------------------------------------------------------------
/backend/models/StaffPayModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const BankingSchema = new Schema(
6 | {
7 | useID: {
8 | type: String,
9 | required: true,
10 | },
11 | basicSalary: {
12 | type: String,
13 | },
14 | bank: {
15 | type: String,
16 | },
17 | employeeSSF: {
18 | type: String,
19 | },
20 | transactions: {
21 | type: [
22 | {
23 | date: {
24 | type: Date,
25 | default: Date.now,
26 | },
27 | allowance: String,
28 | grossIncome: String,
29 | deductions: String,
30 | tax: String,
31 | netSalary: String,
32 | },
33 | ],
34 | },
35 | },
36 | { timestamps: true }
37 | );
38 |
39 | module.exports = mongoose.model("staffpay", BankingSchema);
40 |
--------------------------------------------------------------------------------
/frontend/src/store/slices/userSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from '@reduxjs/toolkit';
2 |
3 | export const userSlice = createSlice({
4 | name: 'user',
5 | initialState: {
6 | user: null
7 | },
8 | reducers: {
9 | loggin: (state, action )=> {
10 | state.user = action.payload;
11 | },
12 | logout: state => {
13 | console.log(state);
14 | state.user = null;
15 | },
16 | update: (state, action) => {
17 | state.user = Object.assign({}, state.user, action.payload);
18 | }
19 | },
20 | });
21 |
22 |
23 | export const { loggin, logout, update } = userSlice.actions;
24 |
25 | export const selectUser = state => state.user.user;
26 |
27 |
28 | export const handleSignout = () => dispatch => {
29 | console.log('signed out')
30 | localStorage.clear();
31 | dispatch(logout());
32 | }
33 | export default userSlice.reducer;
34 |
--------------------------------------------------------------------------------
/backend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "backend",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "start": "node server.js",
8 | "dev": "nodemon start"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@hapi/joi": "^17.1.1",
14 | "bcrypt": "^5.0.0",
15 | "cloudinary": "^1.25.2",
16 | "cors": "^2.8.5",
17 | "crypto-js": "^4.0.0",
18 | "datauri": "^3.0.0",
19 | "dotenv": "^8.2.0",
20 | "express": "^4.17.1",
21 | "express-pino-logger": "^6.0.0",
22 | "method-override": "^3.0.0",
23 | "moment": "^2.29.1",
24 | "mongoose": "^5.11.13",
25 | "multer": "^1.4.2",
26 | "multer-gridfs-storage": "^4.2.0",
27 | "nodemailer": "^6.5.0",
28 | "nodemon": "^2.0.7",
29 | "pusher": "^4.0.2",
30 | "twilio": "^3.58.0",
31 | "uuid": "^8.3.2"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/frontend/src/TeachersComponents/attendance/Attendance.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import AttendanceTable from "../../components/tables/AttendanceTable";
3 | import axios from "../../store/axios";
4 | import { useSelector } from "react-redux";
5 | import { selectUser } from "../../store/slices/userSlice";
6 |
7 | function Attendance() {
8 | const [attendanceData, setattendanceData] = useState([]);
9 | const user = useSelector(selectUser);
10 |
11 | useEffect(() => {
12 | axios.get(`/attendance/user/${user?.userID}`).then((res) => {
13 | console.log(res);
14 | setattendanceData(res.data);
15 | });
16 | }, [user]);
17 |
18 | return (
19 |
20 |
Attendance List
21 |
22 |
23 | );
24 | }
25 |
26 | export default Attendance;
27 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/attendence/AttendancePage.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import AttendanceTable from "../../components/tables/AttendanceTable";
3 | import axios from "../../store/axios";
4 | import { useSelector } from "react-redux";
5 | import { selectUser } from "../../store/slices/userSlice";
6 |
7 | function Attendance() {
8 | const [attendanceData, setattendanceData] = useState([]);
9 | const user = useSelector(selectUser);
10 |
11 | useEffect(() => {
12 | axios.get(`/attendance/user/${user?.userID}`).then((res) => {
13 | console.log(res);
14 | setattendanceData(res.data);
15 | });
16 | }, [user]);
17 |
18 | return (
19 |
20 |
Attendance List
21 |
22 |
23 | );
24 | }
25 |
26 | export default Attendance;
27 |
--------------------------------------------------------------------------------
/backend/models/CoursesModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const CourserSchema = new Schema(
6 | {
7 | date: {
8 | type: Date,
9 | default: Date.now,
10 | },
11 | name: {
12 | type: String,
13 | required: true,
14 | },
15 | code: {
16 | type: String,
17 | required: true,
18 | },
19 | classID: {
20 | type: String,
21 | },
22 | classes: {
23 | type: [
24 | {
25 | teacher: String,
26 | class: String,
27 | _id: String,
28 | },
29 | ],
30 | },
31 | department: {
32 | type: String,
33 | },
34 | type: {
35 | type: String,
36 | },
37 | teacher: {
38 | type: String,
39 | },
40 | default: [],
41 | },
42 | { timestamps: true }
43 | );
44 |
45 | module.exports = mongoose.model("courses", CourserSchema);
46 |
--------------------------------------------------------------------------------
/frontend/src/index.js:
--------------------------------------------------------------------------------
1 | import "react-app-polyfill/ie11"; // For IE 11 support
2 | import "react-app-polyfill/stable";
3 | import "core-js";
4 | import "./polyfill";
5 | import React from "react";
6 | import ReactDOM from "react-dom";
7 | import App from "./App";
8 | import * as serviceWorker from "./serviceWorker";
9 | import { icons } from "./assets/icons";
10 | import { Provider } from "react-redux";
11 | import { initFunc } from "./store/apiCall";
12 | import store from "./store/index";
13 | initFunc();
14 | React.icons = icons;
15 |
16 | ReactDOM.render(
17 |
18 |
19 | ,
20 | document.getElementById("root")
21 | );
22 |
23 | // If you want your app to work offline and load faster, you can change
24 | // unregister() to register() below. Note this comes with some pitfalls.
25 | // Learn more about service workers: http://bit.ly/CRA-PWA
26 | //serviceWorker.unregister();
27 | serviceWorker.register();
28 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/canteen/CanteenNav.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {NavLink} from 'react-router-dom'
3 |
4 | function CanteenNav() {
5 | return (
6 |
7 | Add Canteen Member
8 | All Members
9 | Payments Plan
10 | Make Payment
11 | All Payments
12 |
13 |
14 | )
15 | }
16 |
17 | export default CanteenNav
18 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/staff/Attendence.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AttendanceTable from '../shared/AttendanceTable'
3 | import SearchAttendance from './SearchAttendance';
4 |
5 | function Attendence() {
6 |
7 |
8 | const attendanceData = [
9 | { studentID: "BK2021",name:'Frozen', lastname:'yoghurt'},
10 | { studentID: "BK2021",name:'Frozen', lastname:'yoghurt'},
11 | { studentID: "BK2021",name:'Frozen', lastname:'yoghurt'},
12 | { studentID: "BK2021",name:'Frozen', lastname:'yoghurt'},
13 | { studentID: "BK2021",name:'Frozen', lastname:'yoghurt'},
14 | { studentID: "BK2021",name:'Frozen', lastname:'yoghurt'},
15 | { studentID: "BK2021",name:'Frozen', lastname:'yoghurt'},
16 | ];
17 | return (
18 |
22 | )
23 | }
24 |
25 | export default Attendence
26 |
--------------------------------------------------------------------------------
/frontend/src/TeachersComponents/academics/AllClasses.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import axios from "../../store/axios";
3 | import { useSelector } from "react-redux";
4 | import ClassCard from "./ClassCard";
5 | import { selectUser } from "../../store/slices/userSlice";
6 |
7 | function AllClasses() {
8 | const user = useSelector(selectUser);
9 | const [classes, setclasses] = useState([]);
10 |
11 | useEffect(() => {
12 | const getData = async () => {
13 | let classesData = await axios.get(`/classes/teacher/${user?.userID}`);
14 | setclasses(classesData.data.docs);
15 | };
16 | getData();
17 | }, [user]);
18 |
19 | return (
20 |
21 |
22 | {classes?.length > 0 ? (
23 | classes?.map((e) => )
24 | ) : (
25 |
26 | )}
27 |
28 |
29 | );
30 | }
31 |
32 | export default AllClasses;
33 |
--------------------------------------------------------------------------------
/backend/models/CanteenModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 | const { Schema } = mongoose;
3 |
4 | const CanteenSchema = new Schema(
5 | {
6 | name: {
7 | type: String,
8 | required: true,
9 | },
10 | classID: {
11 | type: String,
12 | },
13 | memberID: {
14 | type: String,
15 | },
16 | userID: {
17 | type: String,
18 | required: true,
19 | },
20 | role: {
21 | type: String,
22 | },
23 | paymentMethod: {
24 | type: String,
25 | },
26 | payments: {
27 | type: [
28 | {
29 | date: {
30 | type: Date,
31 | default: Date.now,
32 | },
33 | receipt: String,
34 | amount: String,
35 | covers: String,
36 | },
37 | ],
38 | },
39 | date: {
40 | type: Date,
41 | default: Date.now,
42 | },
43 | },
44 | { timestamps: true }
45 | );
46 |
47 | module.exports = mongoose.model("canteen", CanteenSchema);
48 |
--------------------------------------------------------------------------------
/frontend/src/assets/icons/sygnet.js:
--------------------------------------------------------------------------------
1 | export const sygnet = ['160 160', `
2 | coreui logo
3 |
4 |
5 |
6 |
7 |
8 |
9 | `]
10 |
--------------------------------------------------------------------------------
/backend/models/ClassesModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const ClassesSchema = new Schema(
6 | {
7 | name: {
8 | type: String,
9 | required: true,
10 | },
11 | teacherID: {
12 | type: String,
13 | },
14 | classCode: {
15 | type: String,
16 | required: true,
17 | },
18 | campusID: {
19 | type: String,
20 | },
21 | division: {
22 | type: String,
23 | },
24 | academic: {
25 | type: String,
26 | },
27 | group: {
28 | type: String,
29 | },
30 | prefect: {
31 | type: String,
32 | },
33 | sba: {
34 | type: Boolean,
35 | },
36 | sbaStaff: {
37 | type: String,
38 | },
39 | date: {
40 | type: Date,
41 | default: Date.now,
42 | },
43 | past: {
44 | type: Boolean,
45 | default: false,
46 | },
47 | },
48 | { timestamps: true }
49 | );
50 |
51 | module.exports = mongoose.model("classes", ClassesSchema);
52 |
--------------------------------------------------------------------------------
/frontend/src/polyfill.js:
--------------------------------------------------------------------------------
1 |
2 | (function () {
3 |
4 | if ( typeof window.CustomEvent === "function" ) return false
5 |
6 | function CustomEvent ( event, params ) {
7 | params = params || { bubbles: false, cancelable: false, detail: undefined }
8 | var evt = document.createEvent( 'CustomEvent' )
9 | evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail )
10 | return evt
11 | }
12 |
13 | CustomEvent.prototype = window.Event.prototype
14 |
15 | window.CustomEvent = CustomEvent
16 | })()
17 |
18 | if (!Element.prototype.matches) {
19 | Element.prototype.matches =
20 | Element.prototype.msMatchesSelector ||
21 | Element.prototype.webkitMatchesSelector;
22 | }
23 |
24 | if (!Element.prototype.closest) {
25 | Element.prototype.closest = function(s) {
26 | var el = this;
27 |
28 | do {
29 | if (Element.prototype.matches.call(el, s)) return el;
30 | el = el.parentElement || el.parentNode;
31 | } while (el !== null && el.nodeType === 1);
32 | return null;
33 | };
34 | }
35 |
--------------------------------------------------------------------------------
/frontend/src/AppLoading.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Backdrop from '@material-ui/core/Backdrop';
3 | import CircularProgress from '@material-ui/core/CircularProgress';
4 | import Button from '@material-ui/core/Button';
5 | import { makeStyles } from '@material-ui/core/styles';
6 |
7 | const useStyles = makeStyles((theme) => ({
8 | backdrop: {
9 | zIndex: theme.zIndex.drawer + 1,
10 | color: '#fff',
11 | },
12 | }));
13 |
14 | export default function SimpleBackdrop() {
15 | const classes = useStyles();
16 | const [open, setOpen] = React.useState(false);
17 | const handleClose = () => {
18 | setOpen(false);
19 | };
20 | const handleToggle = () => {
21 | setOpen(!open);
22 | };
23 |
24 | return (
25 |
26 |
29 |
30 |
31 |
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/students/section/AddSection.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function AddDormitories({ name, setname, loading, onSubmit }) {
4 | return (
5 |
31 | );
32 | }
33 |
34 | export default AddDormitories;
35 |
--------------------------------------------------------------------------------
/frontend/src/components/userInfoTabs/ContactInfo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function ContactInfo({user}) {
4 | return (
5 |
6 |
7 |
Telephone Number:
8 |
{user?.telephone || "N/A"}
9 |
10 |
11 |
Mobile Number:
12 |
{user?.mobilenumber || "N/A"}
13 |
14 |
15 |
Area of Residence:
16 |
{user?.physicalAddress || "N/A"}
17 |
18 |
19 |
Postal Address
20 |
{user?.postalAddress || "N/A"}
21 |
22 |
23 | )
24 | }
25 |
26 | export default ContactInfo
27 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/students/dormitories/AddDormitories.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | function AddDormitories({ name, setname, loading, onSubmit }) {
4 | return (
5 |
6 |
Add Dormitory
7 |
30 |
31 | );
32 | }
33 |
34 | export default AddDormitories;
35 |
--------------------------------------------------------------------------------
/frontend/src/components/dashboard/Card.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Link } from "react-router-dom";
3 | import CountUp from "react-countup";
4 |
5 | function Card({ icon, title, value, link, isPercentage, text, message }) {
6 | const colors = ["#2ad7c5", "#ffa201", "#f939a1"];
7 |
8 | let bgColor = colors[Math.floor(Math.random() * colors.length)];
9 |
10 | return (
11 |
12 |
13 |
14 | {icon}
15 |
16 |
17 |
{title}
18 |
19 |
20 | {text ? value : }
21 |
22 | {isPercentage && "%"}
23 |
24 |
25 |
{message ? message : ""}
26 |
27 |
28 |
29 | );
30 | }
31 |
32 | export default Card;
33 |
--------------------------------------------------------------------------------
/backend/models/SBAModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const SBASchema = new Schema(
6 | {
7 | class: {
8 | type: String,
9 | required: true,
10 | },
11 | course: {
12 | type: String,
13 | },
14 | academicYear: {
15 | type: String,
16 | },
17 | term: {
18 | type: String,
19 | },
20 | exam: {
21 | type: Number,
22 | },
23 | examPercentage: {
24 | type: Number,
25 | },
26 | classWork: {
27 | type: Number,
28 | },
29 | classWorkPercentage: {
30 | type: Number,
31 | },
32 | students: {
33 | type: [
34 | {
35 | userID: String,
36 | name: String,
37 | position: String,
38 | examPercentage: Number,
39 | exam: Number,
40 | classWork: Number,
41 | classWorkPercentage: Number,
42 | total: Number,
43 | },
44 | ],
45 | },
46 | },
47 | { timestamps: true }
48 | );
49 |
50 | module.exports = mongoose.model("sba", SBASchema);
51 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/staff/SearchForm.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function Search() {
4 | return (
5 |
28 | )
29 | }
30 |
31 | export default Search
32 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/shared/ProfilePicture.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import IconButton from "@material-ui/core/IconButton";
3 | import PhotoCamera from "@material-ui/icons/PhotoCamera";
4 | import Avatar from "@material-ui/core/Avatar";
5 | import { getImgSrc } from "../../utils";
6 |
7 | function Profile({ profileimg, setprofileUrl, profileUrl }) {
8 | return (
9 |
10 |
Profile Photo
11 |
18 |
27 |
28 |
33 |
34 | );
35 | }
36 |
37 | export default Profile;
38 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/students/upGrade/Upgrade.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | selectClasses,
4 | selectDormitories,
5 | selectCampuses,
6 | } from "../../../store/slices/schoolSlice";
7 | import { useSelector } from "react-redux";
8 | import PromotingStudent from "./PromotingStudent";
9 | import PromotingClass from "./PromotingClass";
10 | import PromotingDormitories from "./PromotingDormitories";
11 | import PromotingCampus from "./PromotingCampus";
12 | import PromotingPast from "./PromotingPast";
13 |
14 | function Upgrade() {
15 | const classes = useSelector(selectClasses);
16 | const dormitories = useSelector(selectDormitories);
17 | const campuses = useSelector(selectCampuses);
18 |
19 | return (
20 |
21 |
Students Promotions
22 |
23 |
24 |
25 |
26 |
27 |
28 | );
29 | }
30 |
31 | export default Upgrade;
32 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/classes/CalendarPage.js:
--------------------------------------------------------------------------------
1 | import React, {useState, useEffect} from 'react';
2 | import TableList from '../../AdminComponents/shared/ListTable';
3 | import axios from '../../store/axios'
4 |
5 |
6 | const tableHeader = [
7 | {id: "resourse", name: "Type"},
8 | {id: "title", name: "Event"},
9 | {id: "start", name: "Starts"},
10 | {id: "end", name: "Ends"},
11 |
12 | ]
13 |
14 | function ExamsPage() {
15 | const [loading, setloading] = useState(false);
16 | const [events, setevents] = useState([]);
17 |
18 | useEffect(() => {
19 | setloading(true)
20 | axios.get('/calendar')
21 | .then(res => {
22 | setloading(false)
23 | setevents(res.data)
24 | })
25 |
26 | }, [])
27 |
28 | return (
29 |
30 |
Upcoming School Events
31 |
36 |
37 | )
38 | }
39 |
40 | export default ExamsPage
41 |
--------------------------------------------------------------------------------
/frontend/src/TeachersComponents/academics/ClassCard.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import ImportContactsIcon from "@material-ui/icons/ImportContacts";
3 | import { Link } from "react-router-dom";
4 | import axios from "../../store/axios";
5 |
6 | function ClassCard({ id }) {
7 | const [coursName, setcoursName] = useState([]);
8 |
9 | useEffect(() => {
10 | axios.get(`/classes/${id}`).then((res) => {
11 | setcoursName(res.data.docs);
12 | });
13 | }, [id]);
14 |
15 | return (
16 |
17 |
18 | {id ? (
19 |
20 |
21 |
{coursName?.name}
22 |
{id}
23 |
24 | ) : (
25 |
26 |
27 |
Classes
28 | No classes yet
29 |
30 | )}
31 |
32 |
33 | );
34 | }
35 |
36 | export default ClassCard;
37 |
--------------------------------------------------------------------------------
/frontend/src/components/courses/ClassCard.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import ImportContactsIcon from "@material-ui/icons/ImportContacts";
3 | import { Link } from "react-router-dom";
4 | import axios from "../../store/axios";
5 |
6 | function ClassCard({ id, classID }) {
7 | const [coursName, setcoursName] = useState([]);
8 |
9 | useEffect(() => {
10 | axios.get(`/courses/courseCode/${id}`).then((res) => {
11 | setcoursName(res.data.docs);
12 | });
13 | }, [id]);
14 |
15 | console.log(id);
16 | return (
17 |
18 |
19 | {id ? (
20 |
21 |
22 |
{coursName?.name}
23 |
{classID}
24 |
25 | ) : (
26 |
27 |
28 |
Courses
29 | No course yet
30 |
31 | )}
32 |
33 |
34 | );
35 | }
36 |
37 | export default ClassCard;
38 |
--------------------------------------------------------------------------------
/backend/models/BankingModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const BankingSchema = new Schema(
6 | {
7 | bankName: {
8 | type: String,
9 | required: true,
10 | },
11 | accountNumber: {
12 | type: String,
13 | },
14 | accountName: {
15 | type: String,
16 | },
17 | transactions: {
18 | type: Array,
19 | // type: [
20 | // {
21 | // date: {
22 | // type: Date,
23 | // default: Date.now,
24 | // },
25 | // description: String,
26 | // payee: String,
27 | // transactionNumber: String,
28 | // credit: String,
29 | // debit: String,
30 | // type: String,
31 | // bankAcc: String,
32 | // issuedDate: {
33 | // type: Date,
34 | // default: Date.now,
35 | // },
36 | // },
37 | // ],
38 | },
39 | date: {
40 | type: Date,
41 | default: Date.now,
42 | },
43 | },
44 | { timestamps: true },
45 | { typeKey: "$type" }
46 | );
47 |
48 | module.exports = mongoose.model("banking", BankingSchema);
49 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/Profile/ProfileInfo.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { getImgSrc } from "../../utils";
3 |
4 | function ProfileInfo({ admin }) {
5 | return (
6 |
7 |
8 |
})
9 |
10 |
11 |
{admin?.fullName}
12 | {admin?.motto}
13 |
14 |
15 |
16 |
Email
17 |
18 | {admin?.email || "not set"}{" "}
19 |
20 |
21 |
22 |
Telephone
23 |
24 | {" "}
25 | {admin?.telephone || "not set"}
26 |
27 |
28 |
29 |
Address
30 |
31 | {admin?.address || "not set"}{" "}
32 |
33 |
34 |
35 |
36 | );
37 | }
38 |
39 | export default ProfileInfo;
40 |
--------------------------------------------------------------------------------
/frontend/src/components/userInfoTabs/UserInfo.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {Avatar} from '@material-ui/core'
3 | import {Link} from 'react-router-dom'
4 | import {getCapitalize, getIntial, getImgSrc} from '../../utils'
5 | import {useSelector} from 'react-redux';
6 | import {selectUser} from '../../store/slices/userSlice'
7 |
8 |
9 |
10 | function StudentInfo({id, name, surname, middleName, role , route, photoUrl}) {
11 | const user = useSelector(selectUser)
12 | return (
13 |
14 |
15 |
{getCapitalize(name || "")} {middleName && getIntial(middleName)} {getCapitalize(surname || "")}
16 |
{id}
17 |
{role}
18 | {user?.role === "admin" &&
19 |
22 | Edit
23 |
24 | }
25 |
26 |
27 | )
28 | }
29 |
30 | export default StudentInfo
31 |
--------------------------------------------------------------------------------
/backend/models/ChatModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const ChatSchema = new Schema(
6 | {
7 | userID: {
8 | type: String,
9 | },
10 | message: {
11 | type: String,
12 | },
13 | date: {
14 | type: Date,
15 | default: Date.now,
16 | },
17 | parent: {
18 | type: String,
19 | },
20 | isViewed: {
21 | type: Boolean,
22 | default: false,
23 | },
24 | sender: {
25 | type: String,
26 | },
27 | requestor_id: {
28 | type: String,
29 | },
30 | acceptor_id: {
31 | type: String,
32 | },
33 | messages: {
34 | type: [
35 | {
36 | senderID: String,
37 | message: String,
38 | channelID: String,
39 | role: String,
40 | isViewed: {
41 | type: Boolean,
42 | default: false,
43 | },
44 | date: {
45 | type: Date,
46 | default: Date.now,
47 | },
48 | },
49 | ],
50 | default: [],
51 | },
52 | },
53 | { timestamps: true }
54 | );
55 |
56 | module.exports = mongoose.model("chats", ChatSchema);
57 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/finances/DuePayments.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { Link } from "react-router-dom";
3 | import ArrowForwardIosIcon from "@material-ui/icons/ArrowForwardIos";
4 | import TableList from "../../AdminComponents/shared/ListTable";
5 | import { currentCurrency } from "../../utils";
6 |
7 | const tableHeader = [
8 | { id: "due", name: "Due Date" },
9 | { id: "payment", name: "payments" },
10 | { id: "amount", name: `Amount (${currentCurrency()})` },
11 | ];
12 |
13 | function DuePayments() {
14 | const [payments, setpayments] = useState([]);
15 | const [loading, setloading] = useState(false);
16 |
17 | return (
18 |
19 |
20 |
21 | Back
{" "}
22 |
23 |
24 |
25 |
Due Payments
26 |
32 |
33 |
34 | );
35 | }
36 |
37 | export default DuePayments;
38 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/classes/CoursesPage.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import ClassCard from "../../components/courses/ClassCard";
3 | import { selectUser } from "../../store/slices/userSlice";
4 | import { useSelector } from "react-redux";
5 | import axios from "../../store/axios";
6 |
7 | function CoursesPage() {
8 | const [courses, setcourses] = useState([]);
9 | const user = useSelector(selectUser);
10 |
11 | useEffect(() => {
12 | const getdata = async () => {
13 | let data = await axios.get(`/students/student/${user?.userID}`);
14 | let classID = data.data.student?.classID;
15 | await axios.get(`/courses/class/${classID}`).then((res) => {
16 | if (res.data.success) {
17 | setcourses(res.data.docs);
18 | }
19 | });
20 | };
21 | getdata();
22 | }, [user]);
23 |
24 | return (
25 |
26 |
My Courses
27 |
28 | {courses.length > 0 ? (
29 | courses.map((e) => )
30 | ) : (
31 |
32 | )}
33 |
34 |
35 | );
36 | }
37 |
38 | export default CoursesPage;
39 |
--------------------------------------------------------------------------------
/backend/models/NonTeacherModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const NonTeacherSchema = new Schema(
6 | {
7 | name: {
8 | type: String,
9 | required: true,
10 | },
11 | surname: {
12 | type: String,
13 | required: true,
14 | },
15 | email: {
16 | type: String,
17 | },
18 | address: {
19 | type: String,
20 | },
21 | class: {
22 | type: String,
23 | },
24 | role: {
25 | type: String,
26 | default: "nonteacher",
27 | },
28 | telephone: {
29 | type: String,
30 | },
31 | position: {
32 | type: String,
33 | required: true,
34 | },
35 | password: {
36 | type: String,
37 | required: true,
38 | },
39 | nextofKin_ID: {
40 | type: String,
41 | },
42 | gender: {
43 | type: String,
44 | required: true,
45 | },
46 | profileUrl: String,
47 | userID: {
48 | type: String,
49 | },
50 | date: {
51 | type: Date,
52 | default: Date.now,
53 | },
54 | },
55 | { timestamps: true }
56 | );
57 |
58 | module.exports = mongoose.model("nonTeachers", NonTeacherSchema, "accounts");
59 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/classes/Classes.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import { selectUser } from "../../store/slices/userSlice";
3 | import { useSelector } from "react-redux";
4 | import axios from "../../store/axios";
5 | import Loading from "../../Loading";
6 | import ClassDetails from "../../components/class/ClassDetails";
7 |
8 | function Classes() {
9 | const user = useSelector(selectUser);
10 | const [classID, setclassID] = useState(null);
11 | const [loading, setloading] = useState(false);
12 |
13 | useEffect(() => {
14 | const getData = async () => {
15 | setloading(true);
16 | let student = await axios.get(`/user/${user?.userID}`);
17 |
18 | let classData = student?.data?.user;
19 | console.log(classData?.classID);
20 | setclassID(classData?.classID);
21 | setloading(false);
22 | };
23 | getData();
24 | }, [user]);
25 |
26 | return (
27 |
28 | {loading &&
}
29 |
30 | {classID ? (
31 |
32 | ) : (
33 |
No Class Details yet
34 | )}
35 |
36 |
37 | );
38 | }
39 |
40 | export default Classes;
41 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/classes/ClassCard.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import ImportContactsIcon from "@material-ui/icons/ImportContacts";
3 | import { Link } from "react-router-dom";
4 | import { selectUser } from "../../store/slices/userSlice";
5 | import { useSelector } from "react-redux";
6 | import axios from "../../store/axios";
7 |
8 | function ClassCard({ id }) {
9 | const [courses, setcourses] = useState([]);
10 | const user = useSelector(selectUser);
11 |
12 | useEffect(() => {
13 | axios.get(`/students/student/${user?.userID}`).then((res) => {
14 | setcourses(res.data.docs);
15 | });
16 | }, [user]);
17 |
18 | return (
19 |
20 |
21 | {id ? (
22 |
23 |
24 |
Course Name
25 |
id
26 |
27 | ) : (
28 |
29 |
30 |
Courses
31 | No course yet
32 |
33 | )}
34 |
35 |
36 | );
37 | }
38 |
39 | export default ClassCard;
40 |
--------------------------------------------------------------------------------
/frontend/src/containers/TheContent.js:
--------------------------------------------------------------------------------
1 | import React, { Suspense } from 'react'
2 | import {
3 | Route,
4 | Switch
5 | } from 'react-router-dom'
6 | import { CContainer, CFade } from '@coreui/react'
7 |
8 | // routes config
9 | //import routes from '../routes'
10 |
11 | const loading = (
12 |
15 | )
16 |
17 | const TheContent = ({routes, path}) => {
18 | return (
19 |
20 |
21 |
22 |
23 | {routes.map((route, idx) => {
24 | return route.component && (
25 | (
31 |
32 |
33 |
34 | )}
35 | />
36 | )
37 | })}
38 |
39 |
40 |
41 |
42 | )
43 | }
44 |
45 | export default React.memo(TheContent)
46 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/dashboard/RecentActivity.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import axios from "../../store/axios";
3 | import { timeStamp } from "../../utils";
4 |
5 | function RecentActivity() {
6 | const [activities, setactivities] = useState([]);
7 |
8 | useEffect(() => {
9 | axios.get("/activitylog").then((res) => setactivities(res.data));
10 | }, []);
11 |
12 | return (
13 |
14 |
Recent Activities
15 |
16 | {activities.length > 0 ? (
17 | activities.map((e) => (
18 |
19 |
20 |
21 | {e?.user}
22 |
23 |
24 |
25 | {timeStamp(e.createdAt)}
26 |
27 |
28 |
29 |
{e?.activity}
30 |
31 |
32 | ))
33 | ) : (
34 |
No activities yet
35 | )}
36 |
37 |
38 | );
39 | }
40 |
41 | export default RecentActivity;
42 |
--------------------------------------------------------------------------------
/backend/models/TransactionsModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const TransactionSchema = new Schema(
6 | {
7 | amount: {
8 | type: String,
9 | required: true,
10 | },
11 | category: {
12 | type: String,
13 | },
14 | type: {
15 | type: String,
16 | },
17 | paymentMethod: {
18 | type: String,
19 | },
20 | chequeNumber: {
21 | type: String,
22 | },
23 | bank: {
24 | type: String,
25 | },
26 | description: String,
27 | month: String,
28 | year: String,
29 | term: String,
30 | pay: {
31 | type: {
32 | accountNumber: String,
33 | bank: String,
34 | userID: String,
35 | position: String,
36 | month: String,
37 | year: String,
38 | salary: String,
39 | },
40 | },
41 | fees: {
42 | type: {
43 | userID: String,
44 | term: String,
45 | academicYear: String,
46 | applyTo: {
47 | all: Boolean,
48 | tuition: Boolean,
49 | examination: Boolean,
50 | },
51 | },
52 | },
53 | date: {
54 | type: Date,
55 | default: Date.now,
56 | },
57 | },
58 | { timestamps: true }
59 | );
60 |
61 | module.exports = mongoose.model("transactions", TransactionSchema);
62 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/academics/classGroups/AddClassGroup.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useForm } from "react-hook-form";
3 |
4 | export default function AddClassGroup({ name, setname, onSubmit, loading }) {
5 | const { register, handleSubmit, errors } = useForm();
6 |
7 | return (
8 |
39 | );
40 | }
41 |
--------------------------------------------------------------------------------
/frontend/src/scss/_students.scss:
--------------------------------------------------------------------------------
1 | .student__info {
2 | display: flex;
3 | flex-direction: column;
4 | align-items: center;
5 | justify-content: center;
6 |
7 | .avatar {
8 | font-size: 3em;
9 | font-weight: 800;
10 | height: 80px;
11 | width: 80px;
12 | }
13 | }
14 |
15 | .classCard {
16 | background-color: #fff !important;
17 | border-radius: 5px;
18 | padding: 10px;
19 | text-align: center;
20 |
21 | a {
22 | color: $darkBlue !important;
23 | &:hover {
24 | color: $orange !important;
25 | }
26 | }
27 |
28 | &:hover {
29 | transform: scale(1.009);
30 | }
31 |
32 | .icon {
33 | width: 80px !important;
34 | height: 80px !important;
35 | }
36 | }
37 |
38 | .selectBox {
39 | position: relative;
40 | }
41 | .showcheckboxes {
42 | display: block;
43 | border: 1px #dadada solid;
44 | }
45 |
46 | .profileContainer {
47 | position: relative;
48 | .profileIcon {
49 | position: absolute;
50 | color: $darkBlue;
51 | top: 20%;
52 | left: 50%;
53 | transform: translate(-50%);
54 | display: none;
55 | }
56 | }
57 |
58 | .profileContainer:hover .profileIcon {
59 | display: block;
60 | }
61 |
62 | .students__container {
63 | border: 1px solid #ccc;
64 | width: 100%;
65 |
66 | li {
67 | border-bottom: 1px solid #ccc;
68 | padding: 10px 0;
69 | cursor: pointer;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/Profile/StaffTabs.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Card from "./SummaryCard";
3 |
4 | function StaffTabs({ count }) {
5 | return (
6 |
7 |
Staff Overview
8 |
9 |
Staffs
10 |
11 |
19 |
27 |
28 |
29 |
30 |
31 |
32 |
36 |
40 |
41 |
42 | );
43 | }
44 |
45 | export default StaffTabs;
46 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/dashboard/StaffPopulation.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ComplexDonut from "react-svg-donuts/dist/complex";
3 | import "react-svg-donuts/dist/index.css";
4 |
5 | function Population({ maleStudents, femaleStudents }) {
6 | return (
7 |
8 |
Staff
9 |
10 |
26 |
27 |
28 |
29 |
30 |
Female Staff
31 |
32 | {femaleStudents || 0}
33 |
34 |
35 |
36 |
37 |
Male Staff
38 |
39 | {maleStudents || 0}
40 |
41 |
42 |
43 |
44 | );
45 | }
46 |
47 | export default Population;
48 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/dashboard/SchoolPopulation.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ComplexDonut from "react-svg-donuts/dist/complex";
3 | import "react-svg-donuts/dist/index.css";
4 |
5 | function Population({ maleStudents, femaleStudents }) {
6 | return (
7 |
8 |
Students
9 |
10 |
26 |
27 |
28 |
29 |
30 |
Female Students
31 |
32 | {femaleStudents || 0}
33 |
34 |
35 |
36 |
37 |
Male Students
38 |
39 | {maleStudents || 0}
40 |
41 |
42 |
43 |
44 | );
45 | }
46 |
47 | export default Population;
48 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/shared/HandleDelete.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Button from '@material-ui/core/Button';
3 | import Dialog from '@material-ui/core/Dialog';
4 | import DialogActions from '@material-ui/core/DialogActions';
5 | import DialogContent from '@material-ui/core/DialogContent';
6 | import DialogTitle from '@material-ui/core/DialogTitle';
7 | import axios from '../../store/axios'
8 |
9 |
10 | export default function AlertDialog({id, open, setOpen}) {
11 | // const [open, setOpen] = React.useState(false);
12 |
13 | const handleClose = () => {
14 | setOpen(false);
15 | };
16 |
17 | const handleDelete = () => {
18 | axios.delete(`/user/delete/${id}`).then(res => {
19 |
20 | })
21 | }
22 |
23 | return (
24 |
25 |
43 |
44 | );
45 | }
46 |
--------------------------------------------------------------------------------
/frontend/src/containers/TheSidebar.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useSelector, useDispatch } from "react-redux";
3 | import {
4 | CCreateElement,
5 | CSidebar,
6 | CSidebarBrand,
7 | CSidebarNav,
8 | CSidebarNavDivider,
9 | CSidebarNavTitle,
10 | CSidebarMinimizer,
11 | CSidebarNavDropdown,
12 | CSidebarNavItem,
13 | } from "@coreui/react";
14 | import { selectSidebarShow, set } from "../store/slices/appSlice";
15 | import logo from "../assets/icons/logo.png";
16 |
17 | const TheSidebar = ({ navs }) => {
18 | const dispatch = useDispatch();
19 | const show = useSelector(selectSidebarShow);
20 |
21 | return (
22 | dispatch(set(val))}
26 | >
27 |
28 |
34 |
35 |
36 |
45 |
46 |
47 |
48 | );
49 | };
50 |
51 | export default React.memo(TheSidebar);
52 |
--------------------------------------------------------------------------------
/frontend/src/pages/page404/Page404.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | CButton,
4 | CCol,
5 | CContainer,
6 | CInput,
7 | CInputGroup,
8 | CInputGroupPrepend,
9 | CInputGroupAppend,
10 | CInputGroupText,
11 | CRow
12 | } from '@coreui/react'
13 | import CIcon from '@coreui/icons-react'
14 |
15 | const Page404 = () => {
16 | return (
17 |
18 |
19 |
20 |
21 |
22 |
404
23 |
Oops! You{'\''}re lost.
24 |
The page you are looking for was not found.
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Search
35 |
36 |
37 |
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default Page404
45 |
--------------------------------------------------------------------------------
/frontend/src/components/dashboard/SchoolCalender.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Calendar, momentLocalizer } from "react-big-calendar";
3 | import moment from "moment";
4 | import "react-big-calendar/lib/css/react-big-calendar.css";
5 | import axios from "../../store/axios";
6 | import { Link } from "react-router-dom";
7 | import { useSelector } from "react-redux";
8 | import { selectUser } from "../../store/slices/userSlice";
9 |
10 | const localizer = momentLocalizer(moment);
11 |
12 | function SchoolCalender() {
13 | const [events, setevents] = useState([]);
14 | const user = useSelector(selectUser);
15 |
16 | useEffect(() => {
17 | axios.get("/calendar").then((res) => {
18 | setevents(res.data);
19 | });
20 | }, []);
21 |
22 | return (
23 |
24 |
25 |
School Event Calender
26 |
27 | {user?.role === "admin" && (
28 |
29 | Add New Event
30 |
31 | )}
32 |
33 |
34 |
35 |
42 |
43 | );
44 | }
45 |
46 | export default SchoolCalender;
47 |
--------------------------------------------------------------------------------
/frontend/src/pages/page500/Page500.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | CButton,
4 | CCol,
5 | CContainer,
6 | CInput,
7 | CInputGroup,
8 | CInputGroupAppend,
9 | CInputGroupPrepend,
10 | CInputGroupText,
11 | CRow
12 | } from '@coreui/react'
13 | import CIcon from '@coreui/icons-react'
14 |
15 | const Page500 = () => {
16 | return (
17 |
18 |
19 |
20 |
21 |
22 | 500
23 | Houston, we have a problem!
24 | The page you are looking for is temporarily unavailable.
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Search
35 |
36 |
37 |
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default Page500
45 |
--------------------------------------------------------------------------------
/backend/models/FeesModel.js:
--------------------------------------------------------------------------------
1 | const mongoose = require("../config/mongodb");
2 |
3 | const { Schema } = mongoose;
4 |
5 | const FeesSchema = new Schema(
6 | {
7 | name: {
8 | type: String,
9 | },
10 | code: {
11 | type: String,
12 | },
13 | term: String,
14 | year: String,
15 | day: {
16 | type: {
17 | name: {
18 | type: String,
19 | default: "day",
20 | },
21 | tution: String,
22 | facility: String,
23 | maintenance: String,
24 | exam: String,
25 | },
26 | },
27 | freshDay: {
28 | type: {
29 | name: {
30 | type: String,
31 | default: "freshDay",
32 | },
33 | tution: String,
34 | facility: String,
35 | maintenance: String,
36 | exam: String,
37 | },
38 | },
39 | border: {
40 | type: {
41 | name: {
42 | type: String,
43 | default: "border",
44 | },
45 | tution: String,
46 | facility: String,
47 | maintenance: String,
48 | exam: String,
49 | },
50 | },
51 | freshBorder: {
52 | type: {
53 | name: {
54 | type: String,
55 | default: "freshBorder",
56 | },
57 | tution: String,
58 | facility: String,
59 | maintenance: String,
60 | exam: String,
61 | },
62 | },
63 | },
64 | { timestamps: true }
65 | );
66 |
67 | module.exports = mongoose.model("fees", FeesSchema);
68 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/Profile/FinancialTabs.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Card from "./FinanceCard";
3 |
4 | function FinancialTabs() {
5 | return (
6 |
7 |
Financial Reports
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
30 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | );
45 | }
46 |
47 | export default FinancialTabs;
48 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/staff/PayrowPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ListTable from '../shared/ListTable';
3 | import Payrow from './SearchPayrow'
4 |
5 | function PayrowPage() {
6 | const data = [
7 | {id: "123", name: "Rudo Mapfumba", role: "Teacher", bank: "Bank of China", accNum: "21294040392043205050", salary: "2500", status: "Paid"},
8 | {id: "124", name: "Rudo Mapfumba", role: "Teacher", bank: "Bank of China", accNum: "21294040392043205050", salary: "2500", status: "Paid"},
9 | {id: "125", name: "Rudo Mapfumba", role: "Teacher", bank: "Bank of China", accNum: "21294040392043205050", salary: "2500", status: "Paid"},
10 | {id: "126", name: "Rudo Mapfumba", role: "Teacher", bank: "Bank of China", accNum: "21294040392043205050", salary: "2500", status: "Paid"},
11 | {id: "127", name: "Rudo Mapfumba", role: "Teacher", bank: "Bank of China", accNum: "21294040392043205050", salary: "2500", status: "Paid"}
12 | ];
13 | const tableHeadings = [
14 | {id: "id", name: "Staff ID"},
15 | {id: "name", name: "Name"},
16 | {id: "role", name: "Staff Type"},
17 | {id: "bank", name: "Bank"},
18 | {id: "accNum", name: "Account Number"},
19 | {id: "salary", name: "Salary"},
20 | {id: "status", name: "Status"},
21 |
22 | ];
23 |
24 | return (
25 |
29 | )
30 | }
31 |
32 | export default PayrowPage
33 |
--------------------------------------------------------------------------------
/backend/middlewares/multer.js:
--------------------------------------------------------------------------------
1 | const multer = require("multer");
2 | const path = require("path");
3 | const { v4 } = require("uuid");
4 | const fs = require("fs/promises");
5 |
6 | const UPLOAD_DIRECTORY = "./consumerPhotos";
7 |
8 | const checkIfDirectoryExists = async () => {
9 | try {
10 | await fs.stat(UPLOAD_DIRECTORY);
11 | } catch (err) {
12 | if (err.code === "ENOENT") {
13 | await fs.mkdir(UPLOAD_DIRECTORY);
14 | }
15 | }
16 | };
17 |
18 | const storage = multer.diskStorage({
19 | async destination(req, file, callback) {
20 | //console.log(file)
21 | try {
22 | await checkIfDirectoryExists();
23 | // console.log(file, "multer file")
24 | callback(null, UPLOAD_DIRECTORY);
25 | } catch (err) {
26 | callback(err);
27 | }
28 | },
29 |
30 | async filename(req, file, callback) {
31 | const fileExtension = path.extname(file.originalname);
32 | const fileName = `${v4()}${fileExtension}`;
33 | // console.log(fileName, "filename")
34 | callback(null, fileName);
35 | },
36 | });
37 |
38 | const uploader = multer({
39 | storage: storage,
40 | limits: { fileSize: 2000000 },
41 | });
42 |
43 | const getUploadedFiles = async () => {
44 | return await fs.readdir(UPLOAD_DIRECTORY);
45 | };
46 |
47 | const findUploadedFile = async (fileName) => {
48 | const info = await fs.stat(path.resolve(UPLOAD_DIRECTORY, fileName));
49 | console.log({ info });
50 | return info;
51 | };
52 |
53 | module.exports = {
54 | findUploadedFile,
55 | getUploadedFiles,
56 | uploader,
57 | UPLOAD_DIRECTORY,
58 | };
59 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/finance/setfees/DeleteFeesModal.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Button from '@material-ui/core/Button';
3 | import Dialog from '@material-ui/core/Dialog';
4 | import DialogActions from '@material-ui/core/DialogActions';
5 | import DialogContent from '@material-ui/core/DialogContent';
6 | import DialogContentText from '@material-ui/core/DialogContentText';
7 |
8 |
9 | function DeleteFeesModal({ open , setOpen, handleDelete, loading}) {
10 |
11 | const handleClose = () => {
12 | setOpen(false);
13 | };
14 |
15 | return (
16 |
37 | )
38 | }
39 |
40 | export default DeleteFeesModal
41 |
--------------------------------------------------------------------------------
/frontend/src/TeachersComponents/academics/AllCourses.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import ClassCard from "../../components/courses/ClassCard";
3 | import { selectUser } from "../../store/slices/userSlice";
4 | import { useSelector } from "react-redux";
5 | import axios from "../../store/axios";
6 |
7 | function AllCourses() {
8 | const [courses, setcourses] = useState([]);
9 | const user = useSelector(selectUser);
10 |
11 | useEffect(() => {
12 | axios.get(`/courses/teacher/${user?.id}`).then((res) => {
13 | console.log(res);
14 | if (res.data.success) {
15 | //let classesArr = []
16 | let classes = res.data?.docs.map((e) => {
17 | let classesArr = [];
18 | e.classes.map((i) => {
19 | if (i.teacher === user?.id) {
20 | classesArr.push({
21 | class: i.class,
22 | teacher: i.teacher,
23 | course: e.code,
24 | });
25 | }
26 | });
27 | return classesArr;
28 | });
29 | console.log(classes.flat());
30 | setcourses(classes.flat());
31 | }
32 | });
33 | }, [user]);
34 |
35 | return (
36 |
37 |
My Tutorial Courses
38 |
39 | {courses?.length > 0 ? (
40 | courses?.map((e, i) => (
41 |
42 | ))
43 | ) : (
44 |
45 | )}
46 |
47 |
48 | );
49 | }
50 |
51 | export default AllCourses;
52 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/academics/combinedReports/CombinedReports.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Search from "./Search";
3 | import Table from "./Table";
4 | import axios from "../../../store/axios";
5 | import { errorAlert } from "../../../utils";
6 |
7 | function CombinedReports() {
8 | const [data, setdata] = useState([]);
9 | const [term, setterm] = useState("");
10 | const [year, setyear] = useState("");
11 | const [classID, setclass] = useState("");
12 | const [loading, setloading] = useState(false);
13 | const [show, setshow] = useState(false);
14 |
15 | const handleSearch = (e) => {
16 | setshow(false);
17 | e.preventDefault();
18 | setloading(true);
19 | if (classID === "" || term === "" || year === "") {
20 | setloading(false);
21 | return errorAlert("Please select all fields");
22 | }
23 | axios.get(`/sba/class/${classID}/${year}/${term}`).then((result) => {
24 | setloading(false);
25 | console.log(result);
26 | setdata(result.data.docs);
27 | setshow(true);
28 | });
29 | };
30 |
31 | return (
32 |
33 |
Combined Reports
34 |
35 |
45 |
46 | {show &&
}
47 |
48 | );
49 | }
50 |
51 | export default CombinedReports;
52 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/academics/progressReports/ProgressReports.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Search from "./Search";
3 | import Table from "./Table";
4 | import axios from "../../../store/axios";
5 | import { errorAlert } from "../../../utils";
6 |
7 | function ProgressReports() {
8 | const [data, setdata] = useState([]);
9 | const [classID, setclassID] = useState("");
10 | const [term, setterm] = useState("");
11 | const [academicYear, setacademicYear] = useState("");
12 | const [loading, setloading] = useState(false);
13 |
14 | const handleSearch = (e) => {
15 | e.preventDefault();
16 | setloading(true);
17 | if (classID === "" || term === "" || academicYear === "") {
18 | setloading(false);
19 | return errorAlert("Please select all fields");
20 | }
21 | axios.get(`/students/class/${classID}`).then((res) => {
22 | setloading(false);
23 | if (res.data.error) {
24 | return errorAlert(res.data.error);
25 | }
26 | setdata(res.data.users);
27 | });
28 | };
29 |
30 | return (
31 |
32 |
Progress Reports
33 |
34 |
44 |
45 | {data.length > 0 &&
}
46 |
47 | );
48 | }
49 |
50 | export default ProgressReports;
51 |
--------------------------------------------------------------------------------
/frontend/src/components/userInfoTabs/StudentDetails.js:
--------------------------------------------------------------------------------
1 | import React, {useEffect, useState} from 'react';
2 | import StudentInfo from './UserInfo';
3 | import StudentTabs from './StudentTabs';
4 | import axios from '../../../store/axios';
5 | import { useParams} from 'react-router-dom'
6 | import {errorAlert} from '../../utils'
7 |
8 | function StudentDetails() {
9 | const [details, setdetails] = useState(null);
10 |
11 | const {id} =useParams()
12 |
13 | useEffect(() => {
14 | axios.get(`/students/student/${id}`).then(res => {
15 | if(res.data.error){
16 | errorAlert(res.data.error)
17 | return 0
18 | }
19 | setdetails(res.data.student)
20 | })
21 |
22 | }, [id])
23 |
24 |
25 |
26 | return (
27 |
28 |
Student Details
29 |
30 | {details ? <>
31 |
32 |
38 |
39 |
40 |
41 |
42 | > :
Student not found
}
43 |
44 |
45 | )
46 | }
47 |
48 | export default StudentDetails
49 |
--------------------------------------------------------------------------------
/frontend/src/TeachersComponents/dashboard/Profile.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Link } from "react-router-dom";
3 | import InfoTabs from "../../components/userInfoTabs/StaffTabs";
4 | import Profile from "../../components/profile/UpdateProfile";
5 | import { useSelector } from "react-redux";
6 | import { selectUser } from "../../store/slices/userSlice";
7 | import { getCapitalize, getIntial } from "../../utils";
8 | import axios from "../../store/axios";
9 |
10 | function ProfilePage() {
11 | const user = useSelector(selectUser);
12 | const [userDetails, setuserDetails] = useState({});
13 |
14 | useEffect(() => {
15 | axios.get(`/teachers/${user?.userID}`).then((res) => {
16 | setuserDetails(res.data.teacher);
17 | });
18 | }, [user]);
19 |
20 | return (
21 |
22 |
About Me
23 |
24 |
27 |
28 |
29 | {getCapitalize(user?.name)} {getIntial(user?.middleName || "")}{" "}
30 | {getCapitalize(user?.lastName)}
31 |
32 |
{user?.id}
33 |
Role
34 |
35 | Edit
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | );
44 | }
45 |
46 | export default ProfilePage;
47 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/profile/ProfilePage.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Link } from "react-router-dom";
3 | import InfoTabs from "../../components/userInfoTabs/StudentTabs";
4 | import Profile from "../../components/profile/UpdateProfile";
5 | import { useSelector } from "react-redux";
6 | import { selectUser } from "../../store/slices/userSlice";
7 | import { getCapitalize, getIntial } from "../../utils";
8 | import axios from "../../store/axios";
9 |
10 | function ProfilePage() {
11 | const user = useSelector(selectUser);
12 | const [userDetails, setuserDetails] = useState({});
13 |
14 | useEffect(() => {
15 | axios.get(`/students/student/${user?.userID}`).then((res) => {
16 | console.log(res.data);
17 | setuserDetails(res.data.student);
18 | });
19 | }, [user]);
20 |
21 | return (
22 |
23 |
About Me
24 |
25 |
28 |
29 |
30 | {getCapitalize(user?.name)} {getIntial(user?.middleName || "")}{" "}
31 | {getCapitalize(user?.lastName)}
32 |
33 |
{user?.id}
34 |
Role
35 |
36 | Edit
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | );
45 | }
46 |
47 | export default ProfilePage;
48 |
--------------------------------------------------------------------------------
/frontend/src/scss/_admin.scss:
--------------------------------------------------------------------------------
1 | .dashboard__card {
2 | background-color: $white;
3 | padding: 20px;
4 | display: flex;
5 | margin-bottom: 30px;
6 | align-items: center;
7 | color: $black !important;
8 | //justify-content: space-between;
9 |
10 | .card__digits {
11 | font-weight: 800;
12 | font-size: 1.7em;
13 | }
14 | .card__details {
15 | margin-left: 10px;
16 | }
17 | h5 {
18 | opacity: 0.4;
19 | }
20 | .card__icon {
21 | background-color: lightblue;
22 | border-radius: 50%;
23 | padding: 20px;
24 | }
25 | &:hover {
26 | transform: scale(1.02);
27 | }
28 | }
29 |
30 | .activities__container {
31 | height: 500px;
32 | overflow-y: scroll;
33 |
34 | &::-webkit-scrollbar {
35 | display: hidden;
36 | }
37 | }
38 | .dashboard__attendance {
39 | height: 50vh;
40 | }
41 | .notices {
42 | max-height: 500;
43 | min-height: 100%;
44 | overflow: scroll;
45 |
46 | &::-webkit-scrollbar {
47 | display: none;
48 | }
49 |
50 | .notice {
51 | padding: 20px;
52 |
53 | .chip__date {
54 | background-color: $darkBlue;
55 | color: $white !important;
56 | }
57 | }
58 | }
59 |
60 | .attendances {
61 | .color__box {
62 | width: 100px;
63 | height: 20px;
64 | }
65 | .male__color {
66 | background: #051f3e !important;
67 | }
68 | .female__color {
69 | background-color: #ffa201;
70 | }
71 | }
72 |
73 | .fees {
74 | font-size: 1em;
75 |
76 | .icon {
77 | width: 0.8em;
78 | height: 0.8em;
79 | color: red;
80 | font-weight: 800;
81 | }
82 | }
83 |
84 | .form__sender {
85 | padding: 0 !important;
86 |
87 | .header {
88 | background-color: $darkBlue;
89 | padding: 10px;
90 | color: #ccc;
91 | margin-bottom: 10px;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/frontend/src/TeachersComponents/message/Broadcast.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import SendForm from "../../components/messages/SendToForm";
3 | import { useSelector } from "react-redux";
4 | import { selectUser } from "../../store/slices/userSlice";
5 | import axios from "../../store/axios";
6 | import { errorAlert, successAlert } from "../../utils";
7 |
8 | function MessageAdmin() {
9 | const [message, setmessage] = useState("");
10 | const [recipient, setrecipient] = useState("admin");
11 | const user = useSelector(selectUser);
12 |
13 | const recipientOptions = [
14 | {
15 | id: "admin",
16 | name: "admin",
17 | },
18 | ];
19 |
20 | const onSend = (e) => {
21 | e.preventDefault();
22 | if (message && recipient) {
23 | axios
24 | .post(`/chats`, {
25 | message,
26 | sender: user?.userID,
27 | userID: recipient,
28 | })
29 | .then((res) => {
30 | if (res.data.error) {
31 | errorAlert(res.data.error);
32 | return 0;
33 | }
34 | successAlert("message send");
35 | setmessage("");
36 | });
37 | }
38 | };
39 |
40 | const searchOptions = () => {
41 | return recipientOptions.map((option) => (
42 |
45 | ));
46 | };
47 |
48 | return (
49 |
50 |
60 |
61 | );
62 | }
63 |
64 | export default MessageAdmin;
65 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/staff/SearchPayrow.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function SearchPayrow() {
4 | return (
5 |
44 | )
45 | }
46 |
47 | export default SearchPayrow
48 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/classes/CoursePage.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import { useParams } from "react-router-dom";
3 | import axios from "../../store/axios";
4 |
5 | function Course() {
6 | const [courseDetails, setcourseDetails] = useState({});
7 | const [isClass, setisClass] = useState(null);
8 | const { id } = useParams();
9 |
10 | useEffect(() => {
11 | axios.get(`/course/courseCode/${id}`).then((response) => {
12 | if (response.data.success) {
13 | setcourseDetails(response.data.docs);
14 | } else {
15 | setisClass(false);
16 | console.log("ERROR", response.data);
17 | }
18 | });
19 | }, [id]);
20 |
21 | return (
22 |
23 |
24 |
Course Details
25 | {isClass ? (
26 | <>
27 |
28 |
Course
29 |
{courseDetails?.name || "N/A"}
30 |
31 |
32 |
Code
33 |
{courseDetails?.code || "N/A"}
34 |
35 |
36 |
Course Department
37 |
{courseDetails?.type || "N/A"}
38 |
39 |
40 |
Course Teacher
41 |
{courseDetails?.teacher || "N/A"}
42 |
43 | >
44 | ) : (
45 |
No Class Details yet
46 | )}
47 |
48 |
49 | );
50 | }
51 |
52 | export default Course;
53 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/students/pastStudents/ViewOptions.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import IconButton from "@material-ui/core/IconButton";
3 | import Menu from "@material-ui/core/Menu";
4 | import MenuItem from "@material-ui/core/MenuItem";
5 | import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
6 | import { useSelector } from "react-redux";
7 | import { selectUser } from "../../../store/slices/userSlice";
8 |
9 | export default function SimpleMenu({
10 | id,
11 | route,
12 | history,
13 | handleDelete,
14 | handleWithdraw,
15 | }) {
16 | const [anchorEl, setAnchorEl] = React.useState(null);
17 | const user = useSelector(selectUser);
18 |
19 | const handleClick = (event) => {
20 | setAnchorEl(event.currentTarget);
21 | };
22 |
23 | const handleClose = () => {
24 | setAnchorEl(null);
25 | };
26 |
27 | return (
28 |
29 |
34 |
35 |
36 |
66 |
67 | );
68 | }
69 |
--------------------------------------------------------------------------------
/frontend/src/components/dashboard/NoticeBoard.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import Notice from "./Notice";
3 | import axios from "../../store/axios";
4 | import { Link } from "react-router-dom";
5 | import { getTrimString } from "../../utils";
6 |
7 | function NoticeBoard({ user }) {
8 | const [notices, setnotices] = useState([]);
9 |
10 | useEffect(() => {
11 | axios.get("/notification").then((res) => {
12 | setnotices(res.data);
13 | });
14 | }, []);
15 |
16 | let max = 5;
17 | let length = notices.length;
18 |
19 | return (
20 |
21 |
22 |
23 |
Notice Board
24 |
25 |
26 | {user === "admin" && (
27 |
28 | {" "}
29 | Add New Notice
30 |
31 | )}
32 |
33 |
34 |
35 | {notices.length > 0 ? (
36 | <>
37 | {notices.slice(0, max).map((notice) => (
38 |
39 |
47 |
48 |
49 | ))}{" "}
50 | {length > 5 && (
51 |
View More
52 | )}
53 | >
54 | ) : (
55 |
No Notice yet
56 | )}
57 |
58 | );
59 | }
60 |
61 | export default NoticeBoard;
62 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/finance/banking/Banking.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import ListTable from "../../shared/ListTable";
3 | import { useHistory, Link } from "react-router-dom";
4 | import axios from "../../../store/axios";
5 | import { errorAlert, successAlert } from "../../../utils";
6 |
7 | function Banking() {
8 | const history = useHistory();
9 | const [loading, setloading] = useState(false);
10 | const [banks, setbanks] = useState([]);
11 |
12 | useEffect(() => {
13 | axios.get("/banking").then((res) => {
14 | setbanks(res.data);
15 | });
16 | }, []);
17 |
18 | const tableHeadings = [
19 | { id: "bankName", name: "Bank" },
20 | { id: "accountName", name: "Account Name" },
21 | { id: "accountNumber", name: "Account Number" },
22 | { id: "balance", name: "Balance" },
23 | ];
24 |
25 | const handleEdit = (id) => {
26 | history.push(`/finance/banking/transaction/${id}`);
27 | };
28 |
29 | const handleDelete = (id) => {
30 | const ans = window.confirm(
31 | "are you sure you want to delete banking details"
32 | );
33 | if (ans) {
34 | //delete
35 | axios.delete(`/banking/delete/${id}`).then((res) => {
36 | if (res.data.error) {
37 | errorAlert(res.data.error);
38 | return 0;
39 | }
40 | successAlert("Deleted");
41 | setbanks(banks.filter((e) => e._id !== id));
42 | });
43 | }
44 | };
45 |
46 | return (
47 |
48 |
49 | Add New Bank
50 |
51 |
Banking Details
52 |
59 |
60 | );
61 | }
62 |
63 | export default Banking;
64 |
--------------------------------------------------------------------------------
/frontend/src/TeachersComponents/message/MessageAdmin.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import SendForm from "../../components/messages/SendToForm";
3 | import { useSelector } from "react-redux";
4 | import { selectUser } from "../../store/slices/userSlice";
5 | import axios from "../../store/axios";
6 | import { errorAlert, successAlert } from "../../utils";
7 |
8 | function MessageAdmin() {
9 | const [message, setmessage] = useState("");
10 | const [recipient, setrecipient] = useState("");
11 | const recipientOptions = [{ id: "admin", name: "admin" }];
12 | const user = useSelector(selectUser);
13 | const [loading, setloading] = useState("");
14 |
15 | const onSend = (e) => {
16 | e.preventDefault();
17 | if (message && recipient) {
18 | setloading(true);
19 | axios
20 | .post(`/chats/user`, {
21 | message,
22 | userID: recipient,
23 | sender: user?.userID,
24 | })
25 | .then((res) => {
26 | setloading(false);
27 | if (res.data.error) {
28 | errorAlert(res.data.error);
29 | return 0;
30 | }
31 | successAlert("message send");
32 | setmessage("");
33 | });
34 | }
35 | };
36 |
37 | const searchOptions = () => {
38 | return recipientOptions.map((option) => (
39 |
43 | ));
44 | };
45 |
46 | return (
47 |
48 |
60 |
61 | );
62 | }
63 |
64 | export default MessageAdmin;
65 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/attendance/StaffAttendance/StaffAttendanceRegister.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import Table from "../../shared/RegisterAttendance";
3 | import axios from "../../../store/axios";
4 | import { errorAlert } from "../../../utils";
5 | import moment from "moment";
6 |
7 | function RegisterAttendance() {
8 | const [loading, setloading] = useState(false);
9 | const [staff, setstaff] = useState([]);
10 |
11 | useEffect(() => {
12 | axios.get(`/teachers`).then((res) => {
13 | let data = res.data.map((sta) => {
14 | return {
15 | userID: sta.userID,
16 | name: sta.name,
17 | surname: sta.surname,
18 | status: false,
19 | };
20 | });
21 | setstaff(data);
22 | });
23 | }, []);
24 |
25 | const handleRegisterAttendance = () => {
26 | setloading(true);
27 | axios
28 | .post("/attendance/register", {
29 | users: staff,
30 | classID: "staff",
31 | role: "staff",
32 | })
33 | .then((res) => {
34 | setloading(false);
35 | console.log(res);
36 | if (res.data.error) {
37 | errorAlert(res.data.error);
38 | return 0;
39 | }
40 | })
41 | .catch((err) => {
42 | console.log(err);
43 | setloading(false);
44 | errorAlert("Sorry something when wrong");
45 | });
46 | };
47 |
48 | return (
49 |
50 |
Staff Attendance Register
51 |
52 |
53 | {moment().format("dddd D MMMM YYYY")}
54 |
55 |
56 |
63 |
64 | );
65 | }
66 |
67 | export default RegisterAttendance;
68 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/canteen/Members.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import ListTable from "../shared/ListTable";
3 | import axios from "../../store/axios";
4 | import { useHistory } from "react-router-dom";
5 | import CanteenNav from "./CanteenNav";
6 | import { errorAlert } from "../../utils";
7 |
8 | function Members() {
9 | const [data, setdata] = useState([]);
10 | const [loading, setloading] = useState(false);
11 | const history = useHistory();
12 |
13 | const tableHeader = [
14 | { id: "memberID", name: " Member ID" },
15 | { id: "userID", name: "School ID" },
16 | { id: "name", name: "Name" },
17 | { id: "role", name: "Type" },
18 | { id: "paymentMethod", name: "Payment Method" },
19 | ];
20 |
21 | useEffect(() => {
22 | axios.get("/canteen").then((res) => {
23 | setdata(res.data);
24 | });
25 | }, []);
26 |
27 | const handleEdit = (id) => {
28 | history.push(`/canteen/members/edit/${id}`);
29 | };
30 |
31 | const handleDelete = (id) => {
32 | let ans = window.confirm("Are you sure you want to delete");
33 | if (ans) {
34 | setloading(true);
35 | axios
36 | .delete(`/canteen/delete/${id}`)
37 | .then(() => {
38 | setloading(false);
39 | setdata(data.filter((res) => res.memberID !== id));
40 | })
41 | .catch((err) => {
42 | console.log(err);
43 | errorAlert("something went wrong");
44 | setloading(false);
45 | });
46 | }
47 | };
48 |
49 | return (
50 |
51 |
52 |
53 |
54 |
Canteen Members
55 |
63 |
64 | );
65 | }
66 |
67 | export default Members;
68 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/Profile/StudentsTabs.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Card from "./SummaryCard";
3 |
4 | function StudentsTabs({ count }) {
5 | return (
6 |
7 |
Students Overview
8 |
9 |
Students
10 |
11 |
19 |
27 |
28 |
29 |
30 |
31 |
Admissions
32 |
33 |
37 |
41 |
42 |
43 |
44 |
45 |
49 |
53 |
57 |
58 |
59 | );
60 | }
61 |
62 | export default StudentsTabs;
63 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/attendance/StaffAttendance/EditStaffAttendance.js:
--------------------------------------------------------------------------------
1 | import React, {useState , useEffect} from 'react'
2 | import Table from '../../shared/RegisterAttendance';
3 | import axios from '../../../store/axios';
4 | import {errorAlert} from '../../../utils';
5 | import {useParams} from 'react-router-dom'
6 |
7 |
8 |
9 | function RegisterAttendance() {
10 | const [loading, setloading] = useState(false);
11 | const { id } = useParams()
12 | const [staff, setstaff] = useState([])
13 |
14 |
15 | useEffect(() => {
16 | if(id){
17 | axios.get(`/attendance/attendance/${id}`).then(res => {
18 | console.log(res)
19 | setstaff(res.data.users)
20 | })
21 | }
22 | }, [id])
23 |
24 |
25 | const handleRegisterAttendance = () => {
26 | setloading(true)
27 | axios.put(`/attendance/update/${id}`, {users: staff}).then(res => {
28 | setloading(false)
29 | if(res.data.error){
30 | errorAlert(res.data.error);
31 | return 0
32 | }
33 | }).catch(err => {
34 | console.log(err);
35 | setloading(false)
36 | errorAlert("Sorry something when wrong");
37 | })
38 | };
39 |
40 | const handleResetAttendance = () => {
41 | axios.get(`/attendance/attendance/${id}`).then(res => {
42 | console.log(res)
43 | setstaff(res.data.users)
44 | })
45 | };
46 |
47 |
48 | return (
49 |
50 |
51 | Edit Staff Attendance
52 |
53 |
61 |
62 | )
63 | }
64 |
65 | export default RegisterAttendance
66 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/finance/banking/AddBank.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import BankForm from './BankForm';
3 | import axios from '../../../store/axios';
4 | import {errorAlert, successAlert} from '../../../utils';
5 | import {Link} from 'react-router-dom';
6 | import ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos';
7 |
8 |
9 | function AddBank() {
10 | const [name, setname] = useState("");
11 | const [bank, setbank] = useState("");
12 | const [number, setnumber] = useState("");
13 | const [loading, setloading] = useState(false)
14 |
15 |
16 | const handleAdd = () => {
17 | setloading(true)
18 | axios.post('/banking/create', {
19 | bankName: bank,
20 | accountName: name,
21 | accountNumber: number
22 | }).then(res => {
23 | setloading(false)
24 | if(res.data.error){
25 | errorAlert(res.data.error);
26 | return 0;
27 | }
28 | successAlert("successfully created.");
29 | setname("");
30 | setbank("");
31 | setnumber("");
32 | }).catch(err => {
33 | setloading(false);
34 | errorAlert("something went wrong");
35 | })
36 | }
37 |
38 | return (
39 |
40 |
41 |
42 | Back to Banks List
43 |
44 |
45 |
46 |
Add new Bank
47 |
57 |
58 |
59 | )
60 | }
61 |
62 | export default AddBank
63 |
--------------------------------------------------------------------------------
/frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | School Dashboard
18 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/backend/routes/DivisionRoutes.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const DivisionModel = require("../models/DivisionModel");
3 | const { stringtoLowerCase } = require("../middlewares/utils");
4 | const route = express.Router();
5 |
6 | route.get("/", async (req, res) => {
7 | const data = await DivisionModel.find().sort({
8 | createdAt: "desc",
9 | });
10 | res.json(data);
11 | });
12 |
13 | //create
14 | route.post("/create", async (req, res) => {
15 | let body = req.body;
16 |
17 | let code = stringtoLowerCase(body.name);
18 |
19 | const departExist = await DivisionModel.findOne({
20 | code: code,
21 | });
22 | if (departExist) {
23 | return res.json({ success: false, error: "Department already exist" });
24 | }
25 |
26 | DivisionModel.create({
27 | ...body,
28 | code: code,
29 | })
30 | .then((doc) => {
31 | console.log(doc);
32 | res.json({ success: true, doc });
33 | })
34 | .catch((err) => {
35 | console.log(err);
36 | res.json({ success: false, message: "failed" });
37 | });
38 | });
39 |
40 | //edit
41 | route.put("/update/:id", (req, res) => {
42 | if (!req.params.id) {
43 | return res.status(400).send("Missing URL parameter: username");
44 | }
45 | DivisionModel.findOneAndUpdate(
46 | {
47 | _id: req.params.id,
48 | },
49 | req.body,
50 | {
51 | new: true,
52 | }
53 | )
54 | .then((doc) => {
55 | console.log(doc);
56 | if (!doc) {
57 | return res.json({ success: false, error: "doex not exists" });
58 | }
59 | return res.json({ success: true, doc });
60 | })
61 | .catch((err) => {
62 | res.json({ success: false, message: err });
63 | });
64 | });
65 |
66 | //delete
67 | route.delete("/delete/:id", (req, res) => {
68 | DivisionModel.findOneAndRemove({
69 | _id: req.params.id,
70 | })
71 | .then((doc) => {
72 | res.json(doc);
73 | })
74 | .catch((err) => {
75 | res.status(500).json(err);
76 | });
77 | });
78 |
79 | module.exports = route;
80 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/attendance/StudentAttendance/EditAttendance.js:
--------------------------------------------------------------------------------
1 | import React, {useState , useEffect} from 'react'
2 | import Table from '../../shared/RegisterAttendance';
3 | import axios from '../../../store/axios';
4 | import {errorAlert} from '../../../utils';
5 | import {useParams} from 'react-router-dom'
6 |
7 |
8 |
9 | function RegisterAttendance() {
10 | const [loading, setloading] = useState(false);
11 | const {classID, id } = useParams()
12 | const [students, setstudents] = useState([])
13 |
14 |
15 | useEffect(() => {
16 | if(id){
17 | axios.get(`/attendance/attendance/${id}`).then(res => {
18 | console.log(res)
19 | setstudents(res.data.users)
20 | })
21 | }
22 | }, [id])
23 |
24 |
25 | const handleRegisterAttendance = () => {
26 | setloading(true)
27 | axios.put(`/attendance/update/${id}`, {users: students}).then(res => {
28 | setloading(false)
29 | if(res.data.error){
30 | errorAlert(res.data.error);
31 | return 0
32 | }
33 | }).catch(err => {
34 | console.log(err);
35 | setloading(false)
36 | errorAlert("Sorry something when wrong");
37 | })
38 | }
39 |
40 | const handleResetAttendance = () => {
41 | axios.get(`/attendance/students/${id}`).then(res => {
42 | console.log(res)
43 | setstudents(res.data.users)
44 | })
45 | }
46 |
47 |
48 | return (
49 |
50 |
51 | Edit {classID} Attendance
52 |
53 | {classID &&
54 |
}
61 |
62 | )
63 | }
64 |
65 | export default RegisterAttendance
66 |
--------------------------------------------------------------------------------
/frontend/src/components/userInfoTabs/EmploymentTab.js:
--------------------------------------------------------------------------------
1 | import moment from "moment";
2 | import React, { useState, useEffect } from "react";
3 | import axios from "../../store/axios";
4 |
5 | function EmploymentTab({ user }) {
6 | const [campus, setcampus] = useState("");
7 |
8 | useEffect(() => {
9 | if (user?.campusID) {
10 | axios.get(`/campuses/${user?.campusID}`).then((res) => {
11 | setcampus(res.data.docs.name);
12 | });
13 | }
14 | }, [user]);
15 |
16 | return (
17 |
18 |
19 |
Position Role:
20 |
{user?.position || "N/A"}
21 |
22 |
23 |
Department:
24 |
{user?.department || "N/A"}
25 |
26 |
27 |
Campus:
28 |
{campus || "N/A"}
29 |
30 |
31 |
Employment Date
32 |
33 | {moment(user?.employmentDate).format("DD MMMM YYYY") || "N/A"}{" "}
34 |
35 |
36 |
37 |
Qualification:
38 |
{user?.qualifications || "N/A"}
39 |
40 |
41 |
Years of Experience:
42 |
{user?.years || "N/A"}
43 |
44 |
45 |
Bank:
46 |
{user?.bank || "N/A"}
47 |
48 |
49 |
Account Number:
50 |
{user?.accountNumber || "N/A"}
51 |
52 |
53 | );
54 | }
55 |
56 | export default EmploymentTab;
57 |
--------------------------------------------------------------------------------
/frontend/src/components/dashboard/Notice.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import moment from "moment";
3 | import Chip from "@material-ui/core/Chip";
4 | import { IconButton } from "@material-ui/core";
5 | import OpenInNewIcon from "@material-ui/icons/OpenInNew";
6 | import Edit from "./EditNotice";
7 |
8 | function Notice({
9 | description,
10 | createdBy,
11 | date,
12 | title,
13 | createdAt,
14 | isEdit,
15 | id,
16 | open,
17 | setOpen,
18 | editData,
19 | handleDelete,
20 | }) {
21 | const colors = ["#2ad7c5", "#ffa201", "#f939a1"];
22 |
23 | const handleOpenEdit = () => {
24 | setOpen(true);
25 | editData?.setdate(date);
26 | editData?.settitle(title);
27 | editData?.setcreatedby(createdBy);
28 | editData?.setdescription(description);
29 | editData?.seteditID(id);
30 | };
31 |
32 | let bgColor = colors[Math.floor(Math.random() * colors.length)];
33 |
34 | return (
35 |
36 |
37 |
38 | {title}
39 |
40 |
45 |
46 | {description}
47 |
48 |
49 |
50 | {createdBy} /{" "}
51 | {moment(createdAt).fromNow()}
52 |
53 |
54 |
55 | {isEdit && (
56 | <>
57 |
58 | handleOpenEdit()}>
59 |
60 |
61 |
62 |
68 | >
69 | )}
70 |
71 | );
72 | }
73 |
74 | export default Notice;
75 |
--------------------------------------------------------------------------------
/backend/routes/YeargroupRoutes.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const YearGroupModel = require("../models/YearGroupModel");
3 | const { stringtoLowerCase } = require("../middlewares/utils");
4 | const route = express.Router();
5 |
6 | route.get("/", async (req, res) => {
7 | const data = await YearGroupModel.find().sort({
8 | createdAt: "desc",
9 | });
10 | res.json(data);
11 | });
12 |
13 | //create
14 | route.post("/create", async (req, res) => {
15 | let body = req.body;
16 |
17 | let code = stringtoLowerCase(body.name);
18 |
19 | const departExist = await YearGroupModel.findOne({
20 | code: code,
21 | year: body.year,
22 | });
23 | if (departExist) {
24 | return res.json({ success: false, error: "Year Group already exist" });
25 | }
26 |
27 | YearGroupModel.create({
28 | ...body,
29 | code: code,
30 | })
31 | .then((doc) => {
32 | console.log(doc);
33 | res.json({ success: true, doc });
34 | })
35 | .catch((err) => {
36 | console.log(err);
37 | res.json({ success: false, message: "failed" });
38 | });
39 | });
40 |
41 | //edit
42 | route.put("/update/:id", (req, res) => {
43 | if (!req.params.id) {
44 | return res.status(400).send("Missing URL parameter: username");
45 | }
46 | YearGroupModel.findOneAndUpdate(
47 | {
48 | _id: req.params.id,
49 | },
50 | req.body,
51 | {
52 | new: true,
53 | }
54 | )
55 | .then((doc) => {
56 | console.log(doc);
57 | if (!doc) {
58 | return res.json({ success: false, error: "does not exists" });
59 | }
60 | return res.json({ success: true, doc });
61 | })
62 | .catch((err) => {
63 | res.json({ success: false, message: err });
64 | });
65 | });
66 |
67 | //delete
68 | route.delete("/delete/:id", (req, res) => {
69 | YearGroupModel.findOneAndRemove({
70 | _id: req.params.id,
71 | })
72 | .then((doc) => {
73 | res.json(doc);
74 | })
75 | .catch((err) => {
76 | res.status(500).json(err);
77 | });
78 | });
79 |
80 | module.exports = route;
81 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/shared/ViewOptions.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import IconButton from "@material-ui/core/IconButton";
3 | import Menu from "@material-ui/core/Menu";
4 | import MenuItem from "@material-ui/core/MenuItem";
5 | import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
6 | import { useSelector } from "react-redux";
7 | import { selectUser } from "../../store/slices/userSlice";
8 |
9 | export default function SimpleMenu({
10 | id,
11 | route,
12 | history,
13 | isWithdraw,
14 | handleDelete,
15 | handleWithdraw,
16 | }) {
17 | const [anchorEl, setAnchorEl] = React.useState(null);
18 | const user = useSelector(selectUser);
19 |
20 | const handleClick = (event) => {
21 | setAnchorEl(event.currentTarget);
22 | };
23 |
24 | const handleClose = () => {
25 | setAnchorEl(null);
26 | };
27 |
28 | return (
29 |
30 |
35 |
36 |
37 |
71 |
72 | );
73 | }
74 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/staff/StaffDetails.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import Info from "../../components/userInfoTabs/UserInfo";
3 | import StaffTabs from "../../components/userInfoTabs/StaffTabs";
4 | import axios from "../../store/axios";
5 | import { errorAlert } from "../../utils";
6 | import { useParams, useHistory } from "react-router-dom";
7 |
8 | function StaffDetails() {
9 | const [details, setdetails] = useState({});
10 | const { id } = useParams();
11 | const [loading, setloading] = useState(false);
12 | const history = useHistory();
13 |
14 | useEffect(() => {
15 | setloading(true);
16 | axios
17 | .get(`/teachers/${id}`)
18 | .then((res) => {
19 | setloading(false);
20 | if (res.data.error) {
21 | history.push("/staff");
22 | // errorAlert(res.data.error);
23 | return 0;
24 | }
25 | setdetails(res.data.teacher);
26 | })
27 | .catch((err) => {
28 | console.log(err);
29 | setloading(false);
30 | });
31 | }, [id, history]);
32 |
33 | console.log(details);
34 |
35 | return (
36 |
37 | {!loading && (
38 | <>
39 |
Staff Details
40 | {!details ? (
41 |
Staff Member not found
42 | ) : (
43 |
44 |
45 |
54 |
55 |
56 |
57 |
58 |
59 | )}
60 | >
61 | )}
62 |
63 | );
64 | }
65 |
66 | export default StaffDetails;
67 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/dashboard/Attendance.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | //import { Chart } from "react-chartjs-2";
3 | import { Bar } from "@reactchartjs/react-chart.js";
4 | import moment from "moment";
5 | import axios from "../../store/axios";
6 |
7 | const date = new Date();
8 | const month = date.getMonth();
9 | var year = date.getFullYear();
10 | var day = date.getDate();
11 | var weekday = date.getDay();
12 | var start = new Date(year, month, day - weekday);
13 | var end = moment(start).add(7, "day").format("dddd D MMMM YYYY");
14 |
15 | function AttendanceTabs() {
16 | const [dates, setdates] = useState([]);
17 | const [datas, setdatas] = useState([]);
18 |
19 | useEffect(() => {
20 | let arr = [];
21 | let d = [];
22 | for (var i = 0; i < 7; i++) {
23 | arr.push(moment(start).add(i, "day").format("dd"));
24 | d.push(Math.floor(Math.random() * Math.floor(100)));
25 | }
26 | setdates(arr);
27 | //setdatas(d);
28 | }, []);
29 |
30 | useEffect(() => {
31 | let d = moment(start).format("DD-MM-YYYY");
32 | console.log(d);
33 | axios.get(`/count/attendance/week/${d}`).then((res) => {
34 | setdatas(res.data.map((e) => e.value));
35 | });
36 | }, []);
37 |
38 | const data = {
39 | labels: dates,
40 | datasets: [
41 | {
42 | label: "Attendance",
43 | data: datas,
44 | backgroundColor: "#051f3e",
45 | borderColor: "#051f3e",
46 | borderWidth: 1,
47 | },
48 | ],
49 | };
50 |
51 | const options = {
52 | scales: {
53 | yAxes: [
54 | {
55 | ticks: {
56 | beginAtZero: true,
57 | },
58 | },
59 | ],
60 | },
61 | };
62 |
63 | return (
64 |
65 |
66 | Attendance Report from {moment(start).format(" D MMMM YYYY")} to{" "}
67 | {moment(end).format(" D MMMM YYYY")}
68 |
69 |
70 |
71 | );
72 | }
73 |
74 | export default AttendanceTabs;
75 |
--------------------------------------------------------------------------------
/frontend/src/StudentComponents/messages/MessageAdmin.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import SendForm from "../../components/messages/SendToForm";
3 | import { useSelector } from "react-redux";
4 | import { selectUser } from "../../store/slices/userSlice";
5 | import axios from "../../store/axios";
6 | import { errorAlert, successAlert } from "../../utils";
7 |
8 | function MessageAdmin() {
9 | const [message, setmessage] = useState("");
10 | const [recipient, setrecipient] = useState("admin");
11 | const user = useSelector(selectUser);
12 | const [loading, setloading] = useState(false);
13 |
14 | const recipientOptions = [
15 | {
16 | id: "admin",
17 | name: "admin",
18 | },
19 | ];
20 |
21 | const onSend = (e) => {
22 | e.preventDefault();
23 | if (message && recipient) {
24 | setloading(true);
25 | axios
26 | .post(`/chats/user`, {
27 | message,
28 | sender: user?.id,
29 | userID: recipient,
30 | telephone: "",
31 | })
32 | .then((res) => {
33 | console.log(res);
34 | setloading(false);
35 | if (res.data.error) {
36 | errorAlert(res.data.error);
37 | return 0;
38 | }
39 | successAlert("message send");
40 | setmessage("");
41 | })
42 | .catch((err) => {
43 | console.log(err);
44 | setloading(false);
45 | });
46 | }
47 | };
48 |
49 | const searchOptions = () => {
50 | return recipientOptions.map((option) => (
51 |
54 | ));
55 | };
56 |
57 | return (
58 |
59 |
70 |
71 | );
72 | }
73 |
74 | export default MessageAdmin;
75 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/finance/expenditure/ViewPayment.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import ListTable from "../../shared/ListTable";
3 | import { Link } from "react-router-dom";
4 | import axios from "../../../store/axios";
5 | import { getTrimString, errorAlert, currentCurrency } from "../../../utils";
6 |
7 | const tableHeader = [
8 | { id: "date", name: "Date" },
9 | { id: "category", name: "Category" },
10 | { id: "type", name: "Type" },
11 | { id: "description", name: "Description" },
12 | { id: "amount", name: `Amount (${currentCurrency()})` },
13 | { id: "paymentMethod", name: "Payment Type" },
14 | ];
15 |
16 | function ViewPayment() {
17 | const [expenditures, setexpenditures] = useState([]);
18 |
19 | useEffect(() => {
20 | axios.get("/transactions").then((res) => {
21 | let data = res.data.map((e) => {
22 | return {
23 | ...e,
24 | description: getTrimString(e.description, 50),
25 | };
26 | });
27 | setexpenditures(data);
28 | });
29 | }, []);
30 |
31 | const handleEdit = (id) => {};
32 |
33 | const handleDelete = (id) => {
34 | axios.delete(`/transactions/delete/${id}`).then((res) => {
35 | if (res.data.error) {
36 | errorAlert(res.data.error);
37 | }
38 | setexpenditures(expenditures.filter((e) => e._id !== id));
39 | });
40 | };
41 |
42 | return (
43 |
44 |
Transactions
45 |
46 |
47 | Record An Income
48 |
49 |
50 | Make a Payment
51 |
52 |
53 |
54 |
61 |
62 |
63 | );
64 | }
65 |
66 | export default ViewPayment;
67 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/academics/yearGroups/AddYearGroup.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useForm } from "react-hook-form";
3 | import { getYearsList } from "../../../utils";
4 |
5 | export default function AddClassGroup({
6 | name,
7 | setname,
8 | onSubmit,
9 | loading,
10 | year,
11 | setyear,
12 | }) {
13 | const { register, handleSubmit, errors } = useForm();
14 | const yearOptions = getYearsList(10);
15 | return (
16 |
67 | );
68 | }
69 |
--------------------------------------------------------------------------------
/frontend/src/AdminComponents/staff/SearchAttendance.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function SearchAttendance() {
4 | return (
5 |
41 | )
42 | }
43 |
44 | export default SearchAttendance
45 |
--------------------------------------------------------------------------------
/backend/routes/DepartmentRoutes.js:
--------------------------------------------------------------------------------
1 | const express = require("express");
2 | const DepartmentsModel = require("../models/DepartmentsModel");
3 | const { stringtoLowerCase } = require("../middlewares/utils");
4 | const route = express.Router();
5 |
6 | route.get("/", async (req, res) => {
7 | const data = await DepartmentsModel.find().sort({
8 | createdAt: "desc",
9 | });
10 | res.json(data);
11 | });
12 |
13 | //create
14 | route.post("/create", async (req, res) => {
15 | let body = req.body;
16 |
17 | let code = stringtoLowerCase(body.name);
18 |
19 | const departExist = await DepartmentsModel.findOne({
20 | code: code,
21 | });
22 | if (departExist) {
23 | return res.json({ success: false, error: "Department already exist" });
24 | }
25 |
26 | DepartmentsModel.create({
27 | ...body,
28 | code: code,
29 | })
30 | .then((doc) => {
31 | console.log(doc);
32 | res.json({ success: true, doc });
33 | })
34 | .catch((err) => {
35 | console.log(err);
36 | res.json({ success: false, message: "failed" });
37 | });
38 | });
39 |
40 | //edit
41 | route.put("/update/:id", (req, res) => {
42 | if (!req.params.id) {
43 | return res.status(400).send("Missing URL parameter: username");
44 | }
45 | DepartmentsModel.findOneAndUpdate(
46 | {
47 | _id: req.params.id,
48 | },
49 | req.body,
50 | {
51 | new: true,
52 | }
53 | )
54 | .then((doc) => {
55 | console.log(doc);
56 | if (!doc) {
57 | return res.json({ success: false, error: "doex not exists" });
58 | }
59 | return res.json({ success: true, doc });
60 | })
61 | .catch((err) => {
62 | res.json({ success: false, message: err });
63 | });
64 | });
65 |
66 | //delete
67 | route.delete("/delete/:id", (req, res) => {
68 | if (!req.params.id) {
69 | return res.status(400).send("Missing URL parameter: username");
70 | }
71 | DepartmentsModel.findOneAndRemove({
72 | _id: req.params.id,
73 | })
74 | .then((doc) => {
75 | res.json(doc);
76 | })
77 | .catch((err) => {
78 | res.status(500).json(err);
79 | });
80 | });
81 |
82 | module.exports = route;
83 |
--------------------------------------------------------------------------------