├── .eslintcache
├── .gitignore
├── .vscode
└── settings.json
├── Procfile
├── README.md
├── frontend
├── .eslintcache
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src
│ ├── App.js
│ ├── actions
│ ├── attendanceActions.jsx
│ ├── studentActions.jsx
│ └── userActions.jsx
│ ├── components
│ ├── analysisComponent.jsx
│ ├── attendanceTable.jsx
│ ├── attendanceTableComponent.jsx
│ ├── footer.jsx
│ ├── formContainer.jsx
│ ├── header.jsx
│ ├── loader.jsx
│ ├── message.jsx
│ ├── paginate.jsx
│ ├── rating.jsx
│ ├── searchBox.jsx
│ └── student.jsx
│ ├── constants
│ ├── attendanceConstant.jsx
│ ├── studentConstant.jsx
│ └── userConstants.jsx
│ ├── css
│ ├── bootstrap.min.css
│ └── index.css
│ ├── index.js
│ ├── reducers
│ ├── attendanceReducer.jsx
│ ├── studentsReducer.jsx
│ └── userReducers.jsx
│ ├── reportWebVitals.js
│ ├── screens
│ ├── Authentication Screens
│ │ ├── LoginView.jsx
│ │ └── RegisterView.jsx
│ ├── addStudentView.jsx
│ ├── analysisView.jsx
│ ├── attendanceView.jsx
│ ├── homeView.jsx
│ ├── profileView.jsx
│ ├── studentDetailsView.jsx
│ ├── studentTableView.jsx
│ ├── userEditView.jsx
│ └── userListView.jsx
│ └── store.jsx
├── package-lock.json
├── package.json
└── server
├── config
└── mongoDBConfig.js
├── controllers
├── attendanceController.js
├── studentController.js
└── userController.js
├── data
└── students.js
├── index.js
├── middleware
├── authMiddleware.js
└── errorMiddleware.js
├── models
├── attendance.js
├── student.js
└── user.js
├── routes
├── attendanceRoutes.js
├── studentRoutes.js
└── userRoutes.js
├── seeder.js
└── utils
└── generateToken.js
/.eslintcache:
--------------------------------------------------------------------------------
1 | [{"/home/shashi/Projects/React Projects/hostel-app/src/reportWebVitals.js":"1","/home/shashi/Projects/React Projects/hostel-app/src/components/header.jsx":"2","/home/shashi/Projects/React Projects/hostel-app/src/reducers/orphanageReducer.jsx":"3","/home/shashi/Projects/React Projects/hostel-app/src/components/orphanage.jsx":"4","/home/shashi/Projects/React Projects/hostel-app/src/constants/orphanageConstant.jsx":"5","/home/shashi/Projects/React Projects/hostel-app/src/App.js":"6","/home/shashi/Projects/React Projects/hostel-app/src/screens/orphangeDetailsView.jsx":"7","/home/shashi/Projects/React Projects/hostel-app/src/screens/homeView.jsx":"8","/home/shashi/Projects/React Projects/hostel-app/src/components/searchBox.jsx":"9","/home/shashi/Projects/React Projects/hostel-app/src/screens/addStudentView.jsx":"10","/home/shashi/Projects/React Projects/hostel-app/src/screens/analysisView.jsx":"11","/home/shashi/Projects/React Projects/hostel-app/src/actions/orphanageActions.jsx":"12","/home/shashi/Projects/React Projects/hostel-app/src/screens/editOrphanageDetails.jsx":"13"},{"size":362,"mtime":1611587355656,"results":"14","hashOfConfig":"15"},{"size":1420,"mtime":1611588899653,"results":"16","hashOfConfig":"15"},{"size":2572,"mtime":1611587355656,"results":"17","hashOfConfig":"15"},{"size":1015,"mtime":1611587355656,"results":"18","hashOfConfig":"15"},{"size":1091,"mtime":1611587355656,"results":"19","hashOfConfig":"15"},{"size":1181,"mtime":1611590345616,"results":"20","hashOfConfig":"15"},{"size":3630,"mtime":1611587679636,"results":"21","hashOfConfig":"15"},{"size":1240,"mtime":1611588079853,"results":"22","hashOfConfig":"15"},{"size":783,"mtime":1611588125620,"results":"23","hashOfConfig":"15"},{"size":4986,"mtime":1611590107133,"results":"24","hashOfConfig":"15"},{"size":1222,"mtime":1611591364130,"results":"25","hashOfConfig":"15"},{"size":4092,"mtime":1611587355653,"results":"26","hashOfConfig":"15"},{"size":4936,"mtime":1611587355656,"results":"27","hashOfConfig":"15"},{"filePath":"28","messages":"29","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"30"},"cbixyl",{"filePath":"31","messages":"32","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"33","usedDeprecatedRules":"30"},{"filePath":"34","messages":"35","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"36","messages":"37","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"38","messages":"39","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"40","messages":"41","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"42","messages":"43","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"44","usedDeprecatedRules":"45"},{"filePath":"46","messages":"47","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"30"},{"filePath":"48","messages":"49","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"45"},{"filePath":"50","messages":"51","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"52","messages":"53","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"54","usedDeprecatedRules":"30"},{"filePath":"55","messages":"56","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"57","messages":"58","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/home/shashi/Projects/React Projects/hostel-app/src/reportWebVitals.js",[],["59","60"],"/home/shashi/Projects/React Projects/hostel-app/src/components/header.jsx",["61","62"],"import React from 'react'\nimport { Container, Nav, Navbar, NavDropdown } from 'react-bootstrap'\nimport { Route } from 'react-router-dom'\nimport { LinkContainer } from 'react-router-bootstrap'\nimport SearchBox from './searchBox'\n\nconst Header = () => {\n return (\n \n \n \n \n NSD Solutions\n \n \n \n } />\n\n \n \n \n \n \n )\n}\n\nexport default Header\n","/home/shashi/Projects/React Projects/hostel-app/src/reducers/orphanageReducer.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/src/components/orphanage.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/src/constants/orphanageConstant.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/src/App.js",[],"/home/shashi/Projects/React Projects/hostel-app/src/screens/orphangeDetailsView.jsx",["63"],"import React, { useEffect } from 'react'\nimport { useDispatch, useSelector } from 'react-redux'\n\nimport {\n getorphanageDetails,\n deleteOrphanage,\n} from '../actions/orphanageActions'\nimport { Row, Col, Image, ListGroup, Card, Button } from 'react-bootstrap'\nimport { Link } from 'react-router-dom'\nimport Rating from '../components/rating'\nimport Loading from '../components/loader.jsx'\nimport Message from '../components/message.jsx'\nimport { ORPHANAGE_DELETE_RESET } from '../constants/orphanageConstant'\n\nconst OrphanageDetailsView = ({ history, match }) => {\n const orphanageId = match.params.id\n const dispatch = useDispatch()\n const orphanageDetails = useSelector((state) => state.orphanageDetails)\n const { loading, error, orphanage } = orphanageDetails\n const orphanageDelete = useSelector((state) => state.orphanageDelete)\n const {\n loading: loadingDelete,\n error: errorDelete,\n success,\n } = orphanageDelete\n useEffect(() => {\n if (success) {\n dispatch({ type: ORPHANAGE_DELETE_RESET })\n history.push('/')\n }\n console.log(JSON.stringify(orphanage))\n if (orphanageId !== orphanage._id) {\n dispatch(getorphanageDetails(orphanageId))\n }\n }, [dispatch, match, success])\n\n const pushToEdit = () => {\n history.push(`/orphanage/${orphanage._id}/edit`)\n }\n\n const deleteOrphanag = () => {\n dispatch(deleteOrphanage(orphanageId))\n }\n\n \n\n \n\n return (\n <>\n \n Go Back\n \n {loadingDelete && }\n {errorDelete && {errorDelete}}\n {loading ? (\n \n ) : error ? (\n {error}\n ) : (\n \n \n \n \n \n \n \n {orphanage.name}
\n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n Contact:\n \n {orphanage.contact}\n \n
\n \n \n \n Address:\n \n {orphanage.city},{orphanage.state}\n \n
\n \n \n \n \n \n \n \n \n
\n )}\n >\n )\n}\n\nexport default OrphanageDetailsView\n",["64","65"],"/home/shashi/Projects/React Projects/hostel-app/src/screens/homeView.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/src/components/searchBox.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/src/screens/addStudentView.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/src/screens/analysisView.jsx",["66"],"import React, { useState, useEffect } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { Row, Col, Table } from \"react-bootstrap\";\nimport DatePicker from \"react-datepicker\";\nimport \"react-datepicker/dist/react-datepicker.css\";\n\nconst AnalysisView = () => {\n const [startDate, setStartDate] = useState(new Date());\n\n return (\n <>\n \n Go Back\n \n
\n \n \n Analysis for
\n \n {startDate.toISOString().toString().substring(0, 10)}\n \n \n \n setStartDate(date)}\n />\n \n
\n \n \n \n Name | \n Contact No | \n Room No | \n Block No | \n Category | \n Attendance | \n
\n \n
\n \n >\n );\n};\n\nexport default AnalysisView;\n","/home/shashi/Projects/React Projects/hostel-app/src/actions/orphanageActions.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/src/screens/editOrphanageDetails.jsx",[],{"ruleId":"67","replacedBy":"68"},{"ruleId":"69","replacedBy":"70"},{"ruleId":"71","severity":1,"message":"72","line":3,"column":10,"nodeType":"73","messageId":"74","endLine":3,"endColumn":15},{"ruleId":"71","severity":1,"message":"75","line":5,"column":8,"nodeType":"73","messageId":"74","endLine":5,"endColumn":17},{"ruleId":"76","severity":1,"message":"77","line":35,"column":6,"nodeType":"78","endLine":35,"endColumn":32,"suggestions":"79"},{"ruleId":"67","replacedBy":"80"},{"ruleId":"69","replacedBy":"81"},{"ruleId":"71","severity":1,"message":"82","line":1,"column":27,"nodeType":"73","messageId":"74","endLine":1,"endColumn":36},"no-native-reassign",["83"],"no-negated-in-lhs",["84"],"no-unused-vars","'Route' is defined but never used.","Identifier","unusedVar","'SearchBox' is defined but never used.","react-hooks/exhaustive-deps","React Hook useEffect has missing dependencies: 'history', 'orphanage', and 'orphanageId'. Either include them or remove the dependency array.","ArrayExpression",["85"],["83"],["84"],"'useEffect' is defined but never used.","no-global-assign","no-unsafe-negation",{"desc":"86","fix":"87"},"Update the dependencies array to be: [dispatch, history, match, orphanage, orphanageId, success]",{"range":"88","text":"89"},[1198,1224],"[dispatch, history, match, orphanage, orphanageId, success]"]
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | node_modules/
6 |
7 | /.pnp
8 | .pnp.js
9 |
10 | # testing
11 | /coverage
12 |
13 | # production
14 | /frontend/build
15 | /frontend/node_modules
16 |
17 | # misc
18 | .DS_Store
19 | .env
20 | .env.local
21 | .env.development.local
22 | .env.test.local
23 | .env.production.local
24 |
25 | npm-debug.log*
26 | yarn-debug.log*
27 | yarn-error.log*
28 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cmake.configureOnOpen": true
3 | }
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: node server/index.js
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hostel Management Application
2 |
3 | Created using MERN Stack with Redux
4 |
5 | ## Installation
6 |
7 | ```
8 | npm install
9 | cd frontend && npm install
10 | ```
11 |
12 | ### Configure .env file
13 |
14 | ```
15 | NODE_ENV = development/production
16 | PORT = 5000
17 | MONGO_URI= Mongo Uri
18 | JWT_SECRET= JWT Key
19 | ```
20 |
21 | ## Features
22 |
23 | - [x] Register/Login Screens
24 | - [x] Student Details
25 | - [x] Add Student
26 | - [x] Edit/Delete Student Details
27 | - [x] Update Student Where abouts
28 | - [x] Can take Attendance Daily
29 | - [x] Dispaly Attendance Details
30 | - [x] Download Csv file of attendance
31 | - [x] Delete Attendance of previous n days
32 | - [x] Control User List
33 | - [x] Edit User Admin Status
34 | - [x] Data Controlled by only Admins
35 |
36 | ## Contributing
37 |
38 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
39 |
40 | Please make sure to update tests as appropriate.
41 |
--------------------------------------------------------------------------------
/frontend/.eslintcache:
--------------------------------------------------------------------------------
1 | [{"/home/shashi/Projects/React Projects/hostel-app/frontend/src/App.js":"1","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/homeView.jsx":"2","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/addStudentView.jsx":"3","/home/shashi/Projects/React Projects/hostel-app/frontend/src/index.js":"4","/home/shashi/Projects/React Projects/hostel-app/frontend/src/store.jsx":"5","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/header.jsx":"6","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/message.jsx":"7","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/rating.jsx":"8","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/searchBox.jsx":"9","/home/shashi/Projects/React Projects/hostel-app/frontend/src/reducers/studentsReducer.jsx":"10","/home/shashi/Projects/React Projects/hostel-app/frontend/src/constants/studentConstant.jsx":"11","/home/shashi/Projects/React Projects/hostel-app/frontend/src/actions/studentActions.jsx":"12","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/student.jsx":"13","/home/shashi/Projects/React Projects/hostel-app/frontend/src/actions/userActions.jsx":"14","/home/shashi/Projects/React Projects/hostel-app/frontend/src/reducers/userReducers.jsx":"15","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/Authentication Screens/LoginView.jsx":"16","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/formContainer.jsx":"17","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/Authentication Screens/RegisterView.jsx":"18","/home/shashi/Projects/React Projects/hostel-app/frontend/src/constants/userConstants.jsx":"19","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/analysisView.jsx":"20","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/loader.jsx":"21","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/footer.jsx":"22","/home/shashi/Projects/React Projects/hostel-app/frontend/src/reportWebVitals.js":"23","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/paginate.jsx":"24","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/studentDetailsView.jsx":"25","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/studentTableView.jsx":"26","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/attendanceView.jsx":"27","/home/shashi/Projects/React Projects/hostel-app/frontend/src/reducers/attendanceReducer.jsx":"28","/home/shashi/Projects/React Projects/hostel-app/frontend/src/actions/attendanceActions.jsx":"29","/home/shashi/Projects/React Projects/hostel-app/frontend/src/constants/attendanceConstant.jsx":"30","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/analysisComponent.jsx":"31","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/attendanceTable.jsx":"32","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/attendanceTableComponent.jsx":"33","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/profileView.jsx":"34","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/userListView.jsx":"35","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/userEditView.jsx":"36"},{"size":2000,"mtime":1612457509687,"results":"37","hashOfConfig":"38"},{"size":2760,"mtime":1612458544737,"results":"39","hashOfConfig":"38"},{"size":7160,"mtime":1612266721633,"results":"40","hashOfConfig":"38"},{"size":595,"mtime":1611587355656,"results":"41","hashOfConfig":"38"},{"size":1760,"mtime":1612540038213,"results":"42","hashOfConfig":"38"},{"size":2509,"mtime":1612455514013,"results":"43","hashOfConfig":"38"},{"size":236,"mtime":1611587355656,"results":"44","hashOfConfig":"38"},{"size":1670,"mtime":1611587355656,"results":"45","hashOfConfig":"38"},{"size":783,"mtime":1611588125620,"results":"46","hashOfConfig":"38"},{"size":3180,"mtime":1612338704456,"results":"47","hashOfConfig":"38"},{"size":1297,"mtime":1612276158097,"results":"48","hashOfConfig":"38"},{"size":4652,"mtime":1612511277820,"results":"49","hashOfConfig":"38"},{"size":861,"mtime":1612458074420,"results":"50","hashOfConfig":"38"},{"size":6593,"mtime":1612243543269,"results":"51","hashOfConfig":"38"},{"size":3520,"mtime":1612243170023,"results":"52","hashOfConfig":"38"},{"size":2146,"mtime":1612242755929,"results":"53","hashOfConfig":"38"},{"size":331,"mtime":1611587355653,"results":"54","hashOfConfig":"38"},{"size":3149,"mtime":1612243440719,"results":"55","hashOfConfig":"38"},{"size":1502,"mtime":1612242844223,"results":"56","hashOfConfig":"38"},{"size":3733,"mtime":1612540523853,"results":"57","hashOfConfig":"38"},{"size":386,"mtime":1611587355656,"results":"58","hashOfConfig":"38"},{"size":280,"mtime":1611587355653,"results":"59","hashOfConfig":"38"},{"size":362,"mtime":1611587355656,"results":"60","hashOfConfig":"38"},{"size":743,"mtime":1612503930076,"results":"61","hashOfConfig":"38"},{"size":5749,"mtime":1612511177533,"results":"62","hashOfConfig":"38"},{"size":2402,"mtime":1612440885763,"results":"63","hashOfConfig":"38"},{"size":1116,"mtime":1612453105207,"results":"64","hashOfConfig":"38"},{"size":1789,"mtime":1612540078413,"results":"65","hashOfConfig":"38"},{"size":2462,"mtime":1612540492013,"results":"66","hashOfConfig":"38"},{"size":859,"mtime":1612539882713,"results":"67","hashOfConfig":"38"},{"size":2641,"mtime":1612539718740,"results":"68","hashOfConfig":"38"},{"size":2085,"mtime":1612454468233,"results":"69","hashOfConfig":"38"},{"size":3361,"mtime":1612453607120,"results":"70","hashOfConfig":"38"},{"size":3635,"mtime":1612455338080,"results":"71","hashOfConfig":"38"},{"size":2730,"mtime":1612457423720,"results":"72","hashOfConfig":"38"},{"size":3182,"mtime":1612457679380,"results":"73","hashOfConfig":"38"},{"filePath":"74","messages":"75","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},"cy2yr9",{"filePath":"77","messages":"78","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"79","usedDeprecatedRules":"76"},{"filePath":"80","messages":"81","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"82"},{"filePath":"83","messages":"84","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"85"},{"filePath":"86","messages":"87","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"88","messages":"89","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"82"},{"filePath":"90","messages":"91","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"92"},{"filePath":"93","messages":"94","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"95"},{"filePath":"96","messages":"97","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"98"},{"filePath":"99","messages":"100","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"101"},{"filePath":"102","messages":"103","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"104","messages":"105","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"106","messages":"107","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"101"},{"filePath":"108","messages":"109","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"110","messages":"111","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"101"},{"filePath":"112","messages":"113","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"95"},{"filePath":"114","messages":"115","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"101"},{"filePath":"116","messages":"117","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"82"},{"filePath":"118","messages":"119","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"101"},{"filePath":"120","messages":"121","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"122"},{"filePath":"123","messages":"124","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"95"},{"filePath":"125","messages":"126","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"101"},{"filePath":"127","messages":"128","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"101"},{"filePath":"129","messages":"130","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"101"},{"filePath":"131","messages":"132","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"133","usedDeprecatedRules":"101"},{"filePath":"134","messages":"135","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"136","usedDeprecatedRules":"82"},{"filePath":"137","messages":"138","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"76"},{"filePath":"139","messages":"140","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"141","messages":"142","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"143","messages":"144","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"145","messages":"146","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"147","messages":"148","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"149","usedDeprecatedRules":"82"},{"filePath":"150","messages":"151","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"152"},{"filePath":"153","messages":"154","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"95"},{"filePath":"155","messages":"156","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"157","messages":"158","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"101"},"/home/shashi/Projects/React Projects/hostel-app/frontend/src/App.js",[],["159","160"],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/homeView.jsx",["161"],"import React, { useEffect, useState } from \"react\";\nimport { useDispatch, useSelector } from \"react-redux\";\nimport Student from \"../components/student\";\nimport Loading from \"../components/loader.jsx\";\nimport Message from \"../components/message.jsx\";\nimport { listStudents } from \"../actions/studentActions\";\nimport Paginate from \"../components/paginate\";\nimport {\n Row,\n Col,\n ButtonGroup,\n ToggleButton,\n Container,\n} from \"react-bootstrap\";\nimport StudentsTableView from \"./studentTableView\";\n\nconst HomeView = ({ match, history }) => {\n const [isGrid, setIsGrid] = useState(true);\n const keyword = match.params.keyword;\n\n const pageNumber = match.params.pageNumber || 1;\n const userLogin = useSelector((state) => state.userLogin);\n const { loading: userLoading, userInfo } = userLogin;\n\n const dispatch = useDispatch();\n\n const studentsList = useSelector((state) => state.studentsList);\n const { loading, error, students, page, pages } = studentsList;\n\n useEffect(() => {\n if (!userLoading && !userInfo) {\n history.push(\"/login\");\n }\n dispatch(listStudents(keyword, pageNumber));\n }, [keyword, pageNumber]);\n\n return (\n <>\n <>\n \n \n \n \n \n {[\"Grid\", \"Table\"].map((type) => (\n \n setIsGrid(e.target.value === \"Grid\" ? true : false)\n }\n >\n {type === \"Grid\" ? <> Grid> : <> Table >}\n \n ))}\n \n \n \n
\n \n >\n\n Students
\n {loading ? (\n \n ) : error ? (\n {error}\n ) : isGrid ? (\n <>\n \n {students.map((student) => (\n \n \n \n ))}\n
\n \n >\n ) : (\n <>\n \n >\n )}\n >\n );\n};\n\nexport default HomeView;\n","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/addStudentView.jsx",[],["162","163"],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/index.js",[],["164","165"],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/store.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/header.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/message.jsx",[],["166","167"],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/rating.jsx",[],["168","169"],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/searchBox.jsx",[],["170","171"],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/reducers/studentsReducer.jsx",[],["172","173"],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/constants/studentConstant.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/actions/studentActions.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/student.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/actions/userActions.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/reducers/userReducers.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/Authentication Screens/LoginView.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/formContainer.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/Authentication Screens/RegisterView.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/constants/userConstants.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/analysisView.jsx",["174","175"],"import React, { useState, useEffect } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { Row, Col, Button, Modal, Form } from \"react-bootstrap\";\nimport DatePicker from \"react-datepicker\";\nimport { useDispatch, useSelector } from \"react-redux\";\nimport \"react-datepicker/dist/react-datepicker.css\";\nimport {\n deleteAttendanceByDate,\n getAnalysisByDate,\n} from \"../actions/attendanceActions\";\nimport AnalysisComponent from \"../components/analysisComponent\";\nimport Loading from \"../components/loader\";\nimport Message from \"../components/message\";\n\nconst AnalysisView = () => {\n const dispatch = useDispatch();\n const [modal, setModal] = useState(false);\n const [days, setDays] = useState(0);\n const [idList, setIdList] = useState([]);\n const [startDate, setStartDate] = useState(new Date());\n const attendanceAnalysis = useSelector((state) => state.attendanceAnalysis);\n const { attendance } = attendanceAnalysis;\n const attendanceDelete = useSelector((state) => state.attendanceDelete);\n const {\n loading: loadingDelete,\n success: successDelete,\n error: errorDelete,\n } = attendanceDelete;\n useEffect(() => {\n if (attendance) {\n var temp = idList;\n Object.entries(attendance.details).map((at) => {\n temp.push(at[0]);\n });\n\n setIdList(temp);\n } else {\n dispatch(getAnalysisByDate(startDate.toString().substring(0, 15)));\n }\n }, [attendance, dispatch]);\n\n const changeDate = (date) => {\n dispatch(getAnalysisByDate(date.toString().substring(0, 15)));\n setStartDate(date);\n };\n const showModal = () => {\n setModal(true);\n };\n const closeModal = () => {\n setModal(false);\n };\n\n const startDelete = () => {\n setModal(false);\n dispatch(deleteAttendanceByDate(days));\n };\n\n return (\n <>\n \n \n Go Back\n \n \n \n
\n
\n {loadingDelete && }\n {errorDelete && {errorDelete}}\n {successDelete && Attendance Deleted}\n\n \n \n \n Analysis for
\n \n {startDate.toISOString().toString().substring(0, 10)}\n \n \n \n changeDate(date)}\n />\n \n
\n \n \n Enter Number of days before to delete\n \n \n \n Enter no of days\n setDays(e.target.value)}\n >\n \n \n \n \n \n \n \n \n {}\n \n >\n );\n};\n\nexport default AnalysisView;\n","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/loader.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/footer.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/reportWebVitals.js",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/paginate.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/studentDetailsView.jsx",["176"],"import React, { useState, useEffect } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { useDispatch, useSelector } from \"react-redux\";\nimport {\n Row,\n Col,\n Image,\n ListGroup,\n Card,\n Button,\n Form,\n} from \"react-bootstrap\";\nimport Loading from \"../components/loader\";\nimport Message from \"../components/message\";\nimport {\n getStudentDetails,\n updateStudent,\n deleteStudent,\n} from \"../actions/studentActions\";\nimport { STUDENT_UPDATE_RESET } from \"../constants/studentConstant\";\nconst StudentDetailsView = ({ match, history }) => {\n const [status, setStatus] = useState(\"\");\n const dispatch = useDispatch();\n const studentDetails = useSelector((state) => state.studentDetails);\n const { loading, error, student } = studentDetails;\n const studentUpdate = useSelector((state) => state.studentUpdate);\n const {\n loading: loadingUpdate,\n error: errorUpdate,\n success: successUpdate,\n } = studentUpdate;\n const studentDelete = useSelector((state) => state.studentDelete);\n const {\n loading: loadingDelete,\n error: errorDelete,\n success: successDelete,\n } = studentDelete;\n\n useEffect(() => {\n if (successDelete) {\n history.push(\"/\");\n }\n if (successUpdate) {\n dispatch({ type: STUDENT_UPDATE_RESET });\n }\n if (!student || !student._id || student._id !== match.params.id) {\n dispatch(getStudentDetails(match.params.id));\n }\n if (student && student._id && !status) {\n setStatus(student.status);\n }\n }, [dispatch, match, successUpdate, successDelete]);\n\n const navigateToEdit = () => {\n history.push({\n pathname: `/student/edit/${student._id}`,\n state: { studentProps: student },\n });\n };\n const updateStatus = () => {\n student.status = status;\n dispatch(updateStudent(student));\n };\n\n const deleteStuden = () => {\n if (window.confirm(\"Are you sure\")) {\n dispatch(deleteStudent(student._id));\n }\n };\n return (\n <>\n \n Go Back\n \n {loading || loadingUpdate || loadingDelete ? (\n \n ) : error ? (\n {error}\n ) : (\n <>\n {errorUpdate && {errorUpdate}}\n {errorDelete && {errorDelete}}\n {student && (\n \n \n \n \n \n \n \n {student.name}
\n \n \n Phone No:{student.contact}\n \n \n Father Contact:{student.fatherContact}\n \n \n City:{student.city}\n \n \n Address:{student.address}\n \n \n \n \n \n \n \n \n Room No:\n {student.roomNo}\n
\n \n \n \n Block No:\n {student.blockNo}\n
\n \n \n \n Status:\n \n setStatus(e.target.value)}\n >\n {[\"Hostel\", \"Outside\", \"Home\"].map((x) => (\n \n ))}\n \n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n \n
\n )}\n >\n )}\n >\n );\n};\n\nexport default StudentDetailsView;\n","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/studentTableView.jsx",["177"],"import React, { useEffect } from \"react\";\nimport { Table } from \"react-bootstrap\";\nimport { useDispatch, useSelector } from \"react-redux\";\nimport Message from \"../components/message\";\nimport Loader from \"../components/loader\";\nimport Paginate from \"../components/paginate\";\nimport { listStudents } from \"../actions/studentActions\";\nimport { Link } from \"react-router-dom\";\n\nconst StudentsTableView = ({ keyword, pageNumber }) => {\n const dispatch = useDispatch();\n\n const studentsList = useSelector((state) => state.studentsList);\n const { loading, error, students, page, pages } = studentsList;\n useEffect(() => {\n if (!students) {\n dispatch(listStudents(keyword, pageNumber));\n }\n }, [dispatch, keyword, pageNumber]);\n return (\n <>\n {loading ? (\n \n ) : error ? (\n {error}\n ) : (\n <>\n \n \n \n Stream | \n NAME | \n STATUS | \n CONTACT | \n ROOM NO | \n CITY | \n
\n \n \n {students.map((student) => (\n \n {student.category} | \n \n {student.name}\n | \n \n \n {student.status}\n \n | \n \n {student.contact}\n | \n {student.roomNo} | \n {student.city} | \n
\n ))}\n \n
\n \n >\n )}\n >\n );\n};\n\nexport default StudentsTableView;\n","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/attendanceView.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/reducers/attendanceReducer.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/actions/attendanceActions.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/constants/attendanceConstant.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/analysisComponent.jsx",["178"],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/attendanceTable.jsx",["179","180","181"],"import React, { useEffect, useState } from \"react\";\nimport { useSelector, useDispatch } from \"react-redux\";\nimport Loading from \"./loader\";\nimport Message from \"./message\";\nimport AttendanceTableComponent from \"./attendanceTableComponent\";\n\nconst AttendanceTable = ({ roomNo }) => {\n const dispatch = useDispatch();\n const [attendanceMap, setAttendanceMap] = useState({});\n\n const getStudentsByRoomNo = useSelector((state) => state.getStudentsByRoomNo);\n const { loading, error, students, attendance } = getStudentsByRoomNo;\n const attendanceDataEnter = useSelector((state) => state.attendanceDataEnter);\n const {\n loading: loadingAttendance,\n error: errorAttendance,\n } = attendanceDataEnter;\n useEffect(() => {\n if (students) {\n arrangeTable();\n }\n }, [dispatch, attendance, attendanceMap, students]);\n\n const arrangeTable = () => {\n if (attendance) {\n var tempMap = attendanceMap;\n students.map((student) => {\n if (attendance.data[student._id]) {\n tempMap[student._id] = attendance.data[student._id];\n } else {\n tempMap[student._id] = \"Hostel\";\n }\n });\n setAttendanceMap(attendanceMap);\n } else {\n students.map((student) => {\n var temp = attendanceMap;\n temp[student._id] = \"Hostel\";\n setAttendanceMap(temp);\n });\n }\n var temp = attendanceMap;\n setAttendanceMap(temp);\n };\n\n return (\n <>\n {error && {error}}\n {loading || loadingAttendance ? (\n \n ) : (\n <>\n {errorAttendance && (\n {errorAttendance}\n )}\n {students && (\n <>\n \n >\n )}\n >\n )}\n >\n );\n};\n\nexport default AttendanceTable;\n","/home/shashi/Projects/React Projects/hostel-app/frontend/src/components/attendanceTableComponent.jsx",["182"],"import React, { useEffect } from \"react\";\nimport { Table, Form, Button } from \"react-bootstrap\";\nimport { useDispatch } from \"react-redux\";\nimport { postAttendance } from \"../actions/attendanceActions\";\nimport { Link } from \"react-router-dom\";\nconst AttendanceTableComponent = ({\n students,\n attendanceMap,\n setAttendanceMap,\n attendance,\n roomNo,\n}) => {\n const dispatch = useDispatch();\n useEffect(() => {}, [dispatch, attendanceMap]);\n const updateAttendance = () => {\n if (attendance) {\n if (!attendance.roomNo.includes(roomNo)) {\n attendance.roomNo.push(roomNo);\n }\n }\n const roomData = attendance ? attendance.roomNo : roomNo;\n const dataData = attendanceMap;\n const detailsData = attendance ? attendance.details : {};\n students.map((student) => {\n detailsData[student._id] = {\n name: student.name,\n contact: student.contact,\n roomNo: student.roomNo,\n };\n });\n\n dispatch(\n postAttendance({\n roomNo: roomData,\n details: detailsData,\n data: dataData,\n })\n );\n };\n return (\n <>\n \n \n \n NAME | \n Attendance | \n STATUS | \n CONTACT | \n CITY | \n
\n \n \n {students &&\n students.map((student) => (\n <>\n \n \n {student.name}\n | \n \n \n {\n var tempMap = attendanceMap;\n tempMap[student._id] = e.target.value;\n setAttendanceMap(tempMap);\n }}\n >\n \n \n \n \n \n \n | \n \n \n {student.status}\n \n | \n \n {student.contact}\n | \n {student.city} | \n
\n >\n ))}\n \n
\n \n >\n );\n};\n\nexport default AttendanceTableComponent;\n","/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/profileView.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/userListView.jsx",[],"/home/shashi/Projects/React Projects/hostel-app/frontend/src/screens/userEditView.jsx",[],{"ruleId":"183","replacedBy":"184"},{"ruleId":"185","replacedBy":"186"},{"ruleId":"187","severity":1,"message":"188","line":35,"column":6,"nodeType":"189","endLine":35,"endColumn":27,"suggestions":"190"},{"ruleId":"183","replacedBy":"191"},{"ruleId":"185","replacedBy":"192"},{"ruleId":"183","replacedBy":"193"},{"ruleId":"185","replacedBy":"194"},{"ruleId":"183","replacedBy":"195"},{"ruleId":"185","replacedBy":"196"},{"ruleId":"183","replacedBy":"197"},{"ruleId":"185","replacedBy":"198"},{"ruleId":"183","replacedBy":"199"},{"ruleId":"185","replacedBy":"200"},{"ruleId":"183","replacedBy":"201"},{"ruleId":"185","replacedBy":"202"},{"ruleId":"203","severity":1,"message":"204","line":32,"column":51,"nodeType":"205","messageId":"206","endLine":32,"endColumn":53},{"ruleId":"187","severity":1,"message":"207","line":40,"column":6,"nodeType":"189","endLine":40,"endColumn":28,"suggestions":"208"},{"ruleId":"187","severity":1,"message":"209","line":52,"column":6,"nodeType":"189","endLine":52,"endColumn":53,"suggestions":"210"},{"ruleId":"187","severity":1,"message":"211","line":19,"column":6,"nodeType":"189","endLine":19,"endColumn":37,"suggestions":"212"},{"ruleId":"203","severity":1,"message":"204","line":22,"column":56,"nodeType":"205","messageId":"206","endLine":22,"endColumn":58},{"ruleId":"187","severity":1,"message":"213","line":22,"column":6,"nodeType":"189","endLine":22,"endColumn":53,"suggestions":"214"},{"ruleId":"203","severity":1,"message":"204","line":27,"column":30,"nodeType":"205","messageId":"206","endLine":27,"endColumn":32},{"ruleId":"203","severity":1,"message":"204","line":36,"column":30,"nodeType":"205","messageId":"206","endLine":36,"endColumn":32},{"ruleId":"203","severity":1,"message":"204","line":24,"column":28,"nodeType":"205","messageId":"206","endLine":24,"endColumn":30},"no-native-reassign",["215"],"no-negated-in-lhs",["216"],"react-hooks/exhaustive-deps","React Hook useEffect has missing dependencies: 'dispatch', 'history', 'userInfo', and 'userLoading'. Either include them or remove the dependency array.","ArrayExpression",["217"],["215"],["216"],["215"],["216"],["215"],["216"],["215"],["216"],["215"],["216"],["215"],["216"],"array-callback-return","Array.prototype.map() expects a return value from arrow function.","ArrowFunctionExpression","expectedInside","React Hook useEffect has missing dependencies: 'idList' and 'startDate'. Either include them or remove the dependency array.",["218"],"React Hook useEffect has missing dependencies: 'history', 'status', and 'student'. Either include them or remove the dependency array.",["219"],"React Hook useEffect has a missing dependency: 'students'. Either include it or remove the dependency array.",["220"],"React Hook useEffect has a missing dependency: 'arrangeTable'. Either include it or remove the dependency array.",["221"],"no-global-assign","no-unsafe-negation",{"desc":"222","fix":"223"},{"desc":"224","fix":"225"},{"desc":"226","fix":"227"},{"desc":"228","fix":"229"},{"desc":"230","fix":"231"},"Update the dependencies array to be: [dispatch, history, keyword, pageNumber, userInfo, userLoading]",{"range":"232","text":"233"},"Update the dependencies array to be: [attendance, dispatch, idList, startDate]",{"range":"234","text":"235"},"Update the dependencies array to be: [dispatch, match, successUpdate, successDelete, student, status, history]",{"range":"236","text":"237"},"Update the dependencies array to be: [dispatch, keyword, pageNumber, students]",{"range":"238","text":"239"},"Update the dependencies array to be: [dispatch, attendance, attendanceMap, students, arrangeTable]",{"range":"240","text":"241"},[1116,1137],"[dispatch, history, keyword, pageNumber, userInfo, userLoading]",[1402,1424],"[attendance, dispatch, idList, startDate]",[1494,1541],"[dispatch, match, successUpdate, successDelete, student, status, history]",[702,733],"[dispatch, keyword, pageNumber, students]",[780,827],"[dispatch, attendance, attendanceMap, students, arrangeTable]"]
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hostel-app",
3 | "version": "0.1.0",
4 | "proxy": "http://127.0.0.1:5000",
5 | "private": true,
6 | "dependencies": {
7 | "@testing-library/jest-dom": "^5.11.4",
8 | "@testing-library/react": "^11.1.0",
9 | "@testing-library/user-event": "^12.1.10",
10 | "axios": "^0.21.1",
11 | "react": "^17.0.1",
12 | "react-bootstrap": "^1.4.3",
13 | "react-csv": "^2.0.3",
14 | "react-datepicker": "^3.4.1",
15 | "react-dom": "^17.0.1",
16 | "react-redux": "^7.2.2",
17 | "react-router-bootstrap": "^0.25.0",
18 | "react-router-dom": "^5.2.0",
19 | "react-scripts": "4.0.1",
20 | "redux": "^4.0.5",
21 | "redux-devtools-extension": "^2.13.8",
22 | "redux-thunk": "^2.3.0",
23 | "web-vitals": "^0.2.4"
24 | },
25 | "scripts": {
26 | "start": "react-scripts start",
27 | "build": "react-scripts build",
28 | "test": "react-scripts test",
29 | "eject": "react-scripts eject"
30 | },
31 | "eslintConfig": {
32 | "extends": [
33 | "react-app",
34 | "react-app/jest"
35 | ]
36 | },
37 | "browserslist": {
38 | "production": [
39 | ">0.2%",
40 | "not dead",
41 | "not op_mini all"
42 | ],
43 | "development": [
44 | "last 1 chrome version",
45 | "last 1 firefox version",
46 | "last 1 safari version"
47 | ]
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/frontend/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shashiben/Hostel-Management/030f7684a3cc9c4a62a204ab2d6046413632f866/frontend/public/favicon.ico
--------------------------------------------------------------------------------
/frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
23 |
24 |
33 | React App
34 |
35 |
36 |
37 |
38 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/frontend/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shashiben/Hostel-Management/030f7684a3cc9c4a62a204ab2d6046413632f866/frontend/public/logo192.png
--------------------------------------------------------------------------------
/frontend/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shashiben/Hostel-Management/030f7684a3cc9c4a62a204ab2d6046413632f866/frontend/public/logo512.png
--------------------------------------------------------------------------------
/frontend/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/frontend/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/frontend/src/App.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import HomeView from "../src/screens/homeView";
3 | import { BrowserRouter as Router, Route } from "react-router-dom";
4 | import { Container } from "react-bootstrap";
5 | import Header from "./components/header";
6 | import Footer from "./components/footer";
7 | import AddStudentView from "./screens/addStudentView";
8 | import AnalysisView from "./screens/analysisView";
9 | import LoginView from "./screens/Authentication Screens/LoginView";
10 | import RegisterView from "./screens/Authentication Screens/RegisterView";
11 | import StudentDetailsView from "./screens/studentDetailsView";
12 | import AttendanceView from "./screens/attendanceView";
13 | import ProfileView from "./screens/profileView";
14 | import UserListView from "./screens/userListView";
15 | import UserEditView from "./screens/userEditView";
16 |
17 | const App = () => {
18 | return (
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
40 |
41 |
42 |
43 |
44 |
45 | );
46 | };
47 |
48 | export default App;
49 |
--------------------------------------------------------------------------------
/frontend/src/actions/attendanceActions.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | ATTENDANCE_DATA_ENTER_FAIL,
3 | ATTENDANCE_DATA_ENTER_REQUEST,
4 | ATTENDANCE_DATA_ENTER_SUCCESS,
5 | ATTENDANCE_ANALYSIS_FAIL,
6 | ATTENDANCE_ANALYSIS_REQUEST,
7 | ATTENDANCE_ANALYSIS_SUCCESS,
8 | ATTENDANCE_DELETE_REQUEST,
9 | ATTENDANCE_DELETE_SUCCESS,
10 | ATTENDANCE_DELETE_FAIL,
11 | } from "../constants/attendanceConstant";
12 | import axios from "axios";
13 |
14 | export const postAttendance = (attendance) => async (dispatch, getState) => {
15 | try {
16 | dispatch({ type: ATTENDANCE_DATA_ENTER_REQUEST });
17 | const {
18 | userLogin: { userInfo },
19 | } = getState();
20 | const config = {
21 | headers: {
22 | Authorization: `Bearer ${userInfo.token}`,
23 | },
24 | };
25 |
26 | const { data } = await axios.post(`/attendance/`, attendance, config);
27 | dispatch({
28 | type: ATTENDANCE_DATA_ENTER_SUCCESS,
29 | payload: data,
30 | });
31 | } catch (error) {
32 | dispatch({
33 | type: ATTENDANCE_DATA_ENTER_FAIL,
34 | payload:
35 | error.response && error.response.data.message
36 | ? error.response.data.message
37 | : error.message,
38 | });
39 | }
40 | };
41 |
42 | export const getAnalysisByDate = (date) => async (dispatch, getState) => {
43 | try {
44 | dispatch({ type: ATTENDANCE_ANALYSIS_REQUEST });
45 | const {
46 | userLogin: { userInfo },
47 | } = getState();
48 | const config = {
49 | headers: {
50 | Authorization: `Bearer ${userInfo.token}`,
51 | },
52 | };
53 | const { data } = await axios.post(
54 | `/attendance/getAnalysis`,
55 | { date: date },
56 | config
57 | );
58 |
59 | dispatch({
60 | type: ATTENDANCE_ANALYSIS_SUCCESS,
61 | payload: data,
62 | });
63 | } catch (error) {
64 | dispatch({
65 | type: ATTENDANCE_ANALYSIS_FAIL,
66 | payload:
67 | error.response && error.response.data.message
68 | ? error.response.data.message
69 | : error.message,
70 | });
71 | }
72 | };
73 |
74 | export const deleteAttendanceByDate = (days) => async (dispatch, getState) => {
75 | try {
76 | dispatch({ type: ATTENDANCE_DELETE_REQUEST });
77 | const {
78 | userLogin: { userInfo },
79 | } = getState();
80 | const config = {
81 | headers: {
82 | Authorization: `Bearer ${userInfo.token}`,
83 | },
84 | };
85 | const { data } = await axios.delete(`/attendance/${days}`, config);
86 |
87 | dispatch({
88 | type: ATTENDANCE_DELETE_SUCCESS,
89 | payload: data,
90 | });
91 | } catch (error) {
92 | dispatch({
93 | type: ATTENDANCE_DELETE_FAIL,
94 | payload:
95 | error.response && error.response.data.message
96 | ? error.response.data.message
97 | : error.message,
98 | });
99 | }
100 | };
101 |
--------------------------------------------------------------------------------
/frontend/src/actions/studentActions.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | STUDENT_LIST_REQUEST,
3 | STUDENT_LIST_SUCCESS,
4 | STUDENT_LIST_ERROR,
5 | STUDENT_ADD_ERROR,
6 | STUDENT_ADD_REQUEST,
7 | STUDENT_ADD_SUCCESS,
8 | STUDENT_DELETE_ERROR,
9 | STUDENT_DELETE_REQUEST,
10 | STUDENT_DELETE_SUCCESS,
11 | STUDENT_UPDATE_ERROR,
12 | STUDENT_UPDATE_REQUEST,
13 | STUDENT_UPDATE_SUCCESS,
14 | STUDENT_DETAILS_REQUEST,
15 | STUDENT_DETAILS_SUCCESS,
16 | STUDENT_DETAILS_ERROR,
17 | STUDENT_ROOM_NO_REQUEST,
18 | STUDENT_ROOM_NO_SUCCESS,
19 | STUDENT_ROOM_NO_ERROR,
20 | } from "../constants/studentConstant";
21 | import axios from "axios";
22 |
23 | export const listStudents = (keyword = "", pageNumber = "") => async (
24 | dispatch,
25 | getState
26 | ) => {
27 | try {
28 | dispatch({ type: STUDENT_LIST_REQUEST });
29 | const {
30 | userLogin: { userInfo },
31 | } = getState();
32 | const config = {
33 | headers: {
34 | Authorization: `Bearer ${userInfo.token}`,
35 | },
36 | };
37 |
38 | const { data } = await axios.get(
39 | `/student/all?keyword=${keyword}&pageNumber=${pageNumber}`,
40 | config
41 | );
42 | dispatch({
43 | type: STUDENT_LIST_SUCCESS,
44 | payload: data,
45 | });
46 | } catch (error) {
47 | dispatch({
48 | type: STUDENT_LIST_ERROR,
49 | payload:
50 | error.response && error.response.data.message
51 | ? error.response.data.message
52 | : error.message,
53 | });
54 | }
55 | };
56 |
57 | export const addStudent = (student) => async (dispatch, getState) => {
58 | try {
59 | dispatch({ type: STUDENT_ADD_REQUEST });
60 | const {
61 | userLogin: { userInfo },
62 | } = getState();
63 | const config = {
64 | headers: {
65 | Authorization: `Bearer ${userInfo.token}`,
66 | },
67 | };
68 |
69 | const { data } = await axios.post(`/student/addStudent`, student, config);
70 |
71 | dispatch({
72 | type: STUDENT_ADD_SUCCESS,
73 | payload: data,
74 | });
75 | } catch (error) {
76 | dispatch({
77 | type: STUDENT_ADD_ERROR,
78 | payload:
79 | error.response && error.response.data.message
80 | ? error.response.data.message
81 | : error.message,
82 | });
83 | }
84 | };
85 |
86 | export const getStudentDetails = (id) => async (dispatch, getState) => {
87 | try {
88 | dispatch({ type: STUDENT_DETAILS_REQUEST });
89 | const {
90 | userLogin: { userInfo },
91 | } = getState();
92 | const config = {
93 | headers: {
94 | Authorization: `Bearer ${userInfo.token}`,
95 | },
96 | };
97 |
98 | const { data } = await axios.get(`/student/${id}`, config);
99 |
100 | dispatch({
101 | type: STUDENT_DETAILS_SUCCESS,
102 | payload: data,
103 | });
104 | } catch (error) {
105 | dispatch({
106 | type: STUDENT_DETAILS_ERROR,
107 | payload:
108 | error.response && error.response.data.message
109 | ? error.response.data.message
110 | : error.message,
111 | });
112 | }
113 | };
114 |
115 | export const updateStudent = (student) => async (dispatch, getState) => {
116 | try {
117 | dispatch({ type: STUDENT_UPDATE_REQUEST });
118 | const {
119 | userLogin: { userInfo },
120 | } = getState();
121 | const config = {
122 | headers: {
123 | Authorization: `Bearer ${userInfo.token}`,
124 | },
125 | };
126 | const { data } = await axios.put(
127 | `/student/${student._id}`,
128 | student,
129 | config
130 | );
131 |
132 | dispatch({
133 | type: STUDENT_UPDATE_SUCCESS,
134 | payload: data,
135 | });
136 | } catch (error) {
137 | dispatch({
138 | type: STUDENT_UPDATE_ERROR,
139 | payload:
140 | error.response && error.response.data.message
141 | ? error.response.data.message
142 | : error.message,
143 | });
144 | }
145 | };
146 |
147 | export const deleteStudent = (id) => async (dispatch, getState) => {
148 | try {
149 | dispatch({ type: STUDENT_DELETE_REQUEST });
150 | const {
151 | userLogin: { userInfo },
152 | } = getState();
153 | const config = {
154 | headers: {
155 | Authorization: `Bearer ${userInfo.token}`,
156 | },
157 | };
158 |
159 | const { data } = await axios.delete(`/student/${id}`, config);
160 |
161 | dispatch({
162 | type: STUDENT_DELETE_SUCCESS,
163 | payload: data,
164 | });
165 | } catch (error) {
166 | dispatch({
167 | type: STUDENT_DELETE_ERROR,
168 | payload:
169 | error.response && error.response.data.message
170 | ? error.response.data.message
171 | : error.message,
172 | });
173 | }
174 | };
175 |
176 | export const getStudentsByRoomNo = (roomNo) => async (dispatch, getState) => {
177 | try {
178 | dispatch({ type: STUDENT_ROOM_NO_REQUEST });
179 | const {
180 | userLogin: { userInfo },
181 | } = getState();
182 | const config = {
183 | headers: {
184 | Authorization: `Bearer ${userInfo.token}`,
185 | },
186 | };
187 |
188 | const { data } = await axios.get(`/student/room/${roomNo}`, config);
189 | dispatch({
190 | type: STUDENT_ROOM_NO_SUCCESS,
191 | payload: data,
192 | });
193 | } catch (error) {
194 | dispatch({
195 | type: STUDENT_ROOM_NO_ERROR,
196 | payload:
197 | error.response && error.response.data.message
198 | ? error.response.data.message
199 | : error.message,
200 | });
201 | }
202 | };
203 |
--------------------------------------------------------------------------------
/frontend/src/actions/userActions.jsx:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import {
3 | USER_DETAILS_FAIL,
4 | USER_DETAILS_REQUEST,
5 | USER_DETAILS_SUCCESS,
6 | USER_LOGIN_FAIL,
7 | USER_LOGIN_REQUEST,
8 | USER_LOGIN_SUCCESS,
9 | USER_LOGOUT,
10 | USER_REGISTER_FAIL,
11 | USER_REGISTER_REQUEST,
12 | USER_REGISTER_SUCCESS,
13 | USER_UPDATE_PROFILE_FAIL,
14 | USER_UPDATE_PROFILE_REQUEST,
15 | USER_UPDATE_PROFILE_SUCCESS,
16 | USER_DETAILS_RESET,
17 | USER_LIST_FAIL,
18 | USER_LIST_SUCCESS,
19 | USER_LIST_REQUEST,
20 | USER_LIST_RESET,
21 | USER_DELETE_REQUEST,
22 | USER_DELETE_SUCCESS,
23 | USER_DELETE_FAIL,
24 | USER_UPDATE_FAIL,
25 | USER_UPDATE_SUCCESS,
26 | USER_UPDATE_REQUEST,
27 | } from "../constants/userConstants";
28 |
29 | export const login = (email, password) => async (dispatch) => {
30 | try {
31 | dispatch({
32 | type: USER_LOGIN_REQUEST,
33 | });
34 |
35 | const config = {
36 | headers: {
37 | "Content-Type": "application/json",
38 | },
39 | };
40 |
41 | const { data } = await axios.post(
42 | "/users/login",
43 | { email, password },
44 | config
45 | );
46 |
47 | dispatch({
48 | type: USER_LOGIN_SUCCESS,
49 | payload: data,
50 | });
51 |
52 | localStorage.setItem("userInfo", JSON.stringify(data));
53 | } catch (error) {
54 | dispatch({
55 | type: USER_LOGIN_FAIL,
56 | payload:
57 | error.response && error.response.data.message
58 | ? error.response.data.message
59 | : error.message,
60 | });
61 | }
62 | };
63 |
64 | export const logout = () => (dispatch) => {
65 | localStorage.removeItem("userInfo");
66 | dispatch({ type: USER_LOGOUT });
67 | dispatch({ type: USER_DETAILS_RESET });
68 | dispatch({ type: USER_LIST_RESET });
69 | document.location.href = "/login";
70 | };
71 |
72 | export const register = (name, email, password) => async (dispatch) => {
73 | try {
74 | dispatch({
75 | type: USER_REGISTER_REQUEST,
76 | });
77 |
78 | const config = {
79 | headers: {
80 | "Content-Type": "application/json",
81 | },
82 | };
83 |
84 | const { data } = await axios.post(
85 | "/users",
86 | { name, email, password },
87 | config
88 | );
89 |
90 | dispatch({
91 | type: USER_REGISTER_SUCCESS,
92 | payload: data,
93 | });
94 |
95 | dispatch({
96 | type: USER_LOGIN_SUCCESS,
97 | payload: data,
98 | });
99 |
100 | localStorage.setItem("userInfo", JSON.stringify(data));
101 | } catch (error) {
102 | dispatch({
103 | type: USER_REGISTER_FAIL,
104 | payload:
105 | error.response && error.response.data.message
106 | ? error.response.data.message
107 | : error.message,
108 | });
109 | }
110 | };
111 |
112 | export const getUserDetails = (id) => async (dispatch, getState) => {
113 | try {
114 | dispatch({
115 | type: USER_DETAILS_REQUEST,
116 | });
117 |
118 | const {
119 | userLogin: { userInfo },
120 | } = getState();
121 |
122 | const config = {
123 | headers: {
124 | Authorization: `Bearer ${userInfo.token}`,
125 | },
126 | };
127 |
128 | const { data } = await axios.get(`/users/${id}`, config);
129 |
130 | dispatch({
131 | type: USER_DETAILS_SUCCESS,
132 | payload: data,
133 | });
134 | } catch (error) {
135 | const message =
136 | error.response && error.response.data.message
137 | ? error.response.data.message
138 | : error.message;
139 | if (message === "Not authorized, token failed") {
140 | dispatch(logout());
141 | }
142 | dispatch({
143 | type: USER_DETAILS_FAIL,
144 | payload: message,
145 | });
146 | }
147 | };
148 |
149 | export const updateUserProfile = (user) => async (dispatch, getState) => {
150 | try {
151 | dispatch({
152 | type: USER_UPDATE_PROFILE_REQUEST,
153 | });
154 |
155 | const {
156 | userLogin: { userInfo },
157 | } = getState();
158 |
159 | const config = {
160 | headers: {
161 | "Content-Type": "application/json",
162 | Authorization: `Bearer ${userInfo.token}`,
163 | },
164 | };
165 |
166 | const { data } = await axios.put(`/users/profile`, user, config);
167 |
168 | dispatch({
169 | type: USER_UPDATE_PROFILE_SUCCESS,
170 | payload: data,
171 | });
172 | dispatch({
173 | type: USER_LOGIN_SUCCESS,
174 | payload: data,
175 | });
176 | localStorage.setItem("userInfo", JSON.stringify(data));
177 | } catch (error) {
178 | const message =
179 | error.response && error.response.data.message
180 | ? error.response.data.message
181 | : error.message;
182 | if (message === "Not authorized, token failed") {
183 | dispatch(logout());
184 | }
185 | dispatch({
186 | type: USER_UPDATE_PROFILE_FAIL,
187 | payload: message,
188 | });
189 | }
190 | };
191 |
192 | export const listUsers = () => async (dispatch, getState) => {
193 | try {
194 | dispatch({
195 | type: USER_LIST_REQUEST,
196 | });
197 |
198 | const {
199 | userLogin: { userInfo },
200 | } = getState();
201 |
202 | const config = {
203 | headers: {
204 | Authorization: `Bearer ${userInfo.token}`,
205 | },
206 | };
207 |
208 | const { data } = await axios.get(`/users`, config);
209 |
210 | dispatch({
211 | type: USER_LIST_SUCCESS,
212 | payload: data,
213 | });
214 | } catch (error) {
215 | const message =
216 | error.response && error.response.data.message
217 | ? error.response.data.message
218 | : error.message;
219 | if (message === "Not authorized, token failed") {
220 | dispatch(logout());
221 | }
222 | dispatch({
223 | type: USER_LIST_FAIL,
224 | payload: message,
225 | });
226 | }
227 | };
228 |
229 | export const deleteUser = (id) => async (dispatch, getState) => {
230 | try {
231 | dispatch({
232 | type: USER_DELETE_REQUEST,
233 | });
234 |
235 | const {
236 | userLogin: { userInfo },
237 | } = getState();
238 |
239 | const config = {
240 | headers: {
241 | Authorization: `Bearer ${userInfo.token}`,
242 | },
243 | };
244 |
245 | await axios.delete(`/users/${id}`, config);
246 |
247 | dispatch({ type: USER_DELETE_SUCCESS });
248 | } catch (error) {
249 | const message =
250 | error.response && error.response.data.message
251 | ? error.response.data.message
252 | : error.message;
253 | if (message === "Not authorized, token failed") {
254 | dispatch(logout());
255 | }
256 | dispatch({
257 | type: USER_DELETE_FAIL,
258 | payload: message,
259 | });
260 | }
261 | };
262 |
263 | export const updateUser = (user) => async (dispatch, getState) => {
264 | try {
265 | dispatch({
266 | type: USER_UPDATE_REQUEST,
267 | });
268 |
269 | const {
270 | userLogin: { userInfo },
271 | } = getState();
272 |
273 | const config = {
274 | headers: {
275 | "Content-Type": "application/json",
276 | Authorization: `Bearer ${userInfo.token}`,
277 | },
278 | };
279 |
280 | const { data } = await axios.put(`/users/${user._id}`, user, config);
281 |
282 | dispatch({ type: USER_UPDATE_SUCCESS });
283 |
284 | dispatch({ type: USER_DETAILS_SUCCESS, payload: data });
285 |
286 | dispatch({ type: USER_DETAILS_RESET });
287 | } catch (error) {
288 | const message =
289 | error.response && error.response.data.message
290 | ? error.response.data.message
291 | : error.message;
292 | if (message === "Not authorized, token failed") {
293 | dispatch(logout());
294 | }
295 | dispatch({
296 | type: USER_UPDATE_FAIL,
297 | payload: message,
298 | });
299 | }
300 | };
301 |
--------------------------------------------------------------------------------
/frontend/src/components/analysisComponent.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import { Table } from "react-bootstrap";
3 | import { useSelector } from "react-redux";
4 | import Loading from "./loader";
5 | import Message from "./message";
6 | import { CSVLink } from "react-csv";
7 |
8 | const AnalysisComponent = () => {
9 | const attendanceAnalysis = useSelector((state) => state.attendanceAnalysis);
10 | const { loading, error, attendance } = attendanceAnalysis;
11 | const [data, setData] = useState([]);
12 | const [headers, setHeaders] = useState([]);
13 | useEffect(() => {
14 | if (attendance) {
15 | setHeaders([
16 | { label: "Name", key: "name" },
17 | { label: "Contact", key: "contact" },
18 | { label: "Room No", key: "roomNo" },
19 | { label: "Status", key: "attendance" },
20 | ]);
21 | var csvMapList = [];
22 | Object.entries(attendance.details).map((student) => {
23 | var csvMap = {};
24 | csvMap["name"] = student[1].name;
25 | csvMap["contact"] = student[1].contact;
26 | csvMap["roomNo"] = student[1].roomNo;
27 | csvMap["attendance"] = attendance.data[student[0]];
28 | csvMapList.push(csvMap);
29 | });
30 |
31 | setData(csvMapList);
32 | }
33 | }, [attendance]);
34 | return (
35 | <>
36 | {error && {error}}
37 | {loading ? (
38 |
39 | ) : (
40 | <>
41 | {attendance && (
42 | <>
43 |
44 |
45 |
46 | Name |
47 | Contact No |
48 | Room No |
49 | Attendance |
50 |
51 |
52 |
53 | {attendance &&
54 | Object.entries(attendance.details).map((student) => {
55 | return (
56 |
57 | {student[1].name} |
58 | {student[1].contact} |
59 | {student[1].roomNo} |
60 | {attendance.data[student[0]]} |
61 |
62 | );
63 | })}
64 |
65 |
66 |
74 | Download
75 |
76 | >
77 | )}
78 | >
79 | )}
80 | >
81 | );
82 | };
83 |
84 | export default AnalysisComponent;
85 |
--------------------------------------------------------------------------------
/frontend/src/components/attendanceTable.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import { useSelector, useDispatch } from "react-redux";
3 | import Loading from "./loader";
4 | import Message from "./message";
5 | import AttendanceTableComponent from "./attendanceTableComponent";
6 |
7 | const AttendanceTable = ({ roomNo }) => {
8 | const dispatch = useDispatch();
9 | const [attendanceMap, setAttendanceMap] = useState({});
10 |
11 | const getStudentsByRoomNo = useSelector((state) => state.getStudentsByRoomNo);
12 | const { loading, error, students, attendance } = getStudentsByRoomNo;
13 | const attendanceDataEnter = useSelector((state) => state.attendanceDataEnter);
14 | const {
15 | loading: loadingAttendance,
16 | error: errorAttendance,
17 | } = attendanceDataEnter;
18 | useEffect(() => {
19 | if (students) {
20 | arrangeTable();
21 | }
22 | }, [dispatch, attendance, attendanceMap, students]);
23 |
24 | const arrangeTable = () => {
25 | if (attendance) {
26 | var tempMap = attendanceMap;
27 | students.map((student) => {
28 | if (attendance.data[student._id]) {
29 | tempMap[student._id] = attendance.data[student._id];
30 | } else {
31 | tempMap[student._id] = "Hostel";
32 | }
33 | });
34 | setAttendanceMap(attendanceMap);
35 | } else {
36 | students.map((student) => {
37 | var temp = attendanceMap;
38 | temp[student._id] = "Hostel";
39 | setAttendanceMap(temp);
40 | });
41 | }
42 | var temp = attendanceMap;
43 | setAttendanceMap(temp);
44 | };
45 |
46 | return (
47 | <>
48 | {error && {error}}
49 | {loading || loadingAttendance ? (
50 |
51 | ) : (
52 | <>
53 | {errorAttendance && (
54 | {errorAttendance}
55 | )}
56 | {students && (
57 | <>
58 |
65 | >
66 | )}
67 | >
68 | )}
69 | >
70 | );
71 | };
72 |
73 | export default AttendanceTable;
74 |
--------------------------------------------------------------------------------
/frontend/src/components/attendanceTableComponent.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from "react";
2 | import { Table, Form, Button } from "react-bootstrap";
3 | import { useDispatch } from "react-redux";
4 | import { postAttendance } from "../actions/attendanceActions";
5 | import { Link } from "react-router-dom";
6 | const AttendanceTableComponent = ({
7 | students,
8 | attendanceMap,
9 | setAttendanceMap,
10 | attendance,
11 | roomNo,
12 | }) => {
13 | const dispatch = useDispatch();
14 | useEffect(() => {}, [dispatch, attendanceMap]);
15 | const updateAttendance = () => {
16 | if (attendance) {
17 | if (!attendance.roomNo.includes(roomNo)) {
18 | attendance.roomNo.push(roomNo);
19 | }
20 | }
21 | const roomData = attendance ? attendance.roomNo : roomNo;
22 | const dataData = attendanceMap;
23 | const detailsData = attendance ? attendance.details : {};
24 | students.map((student) => {
25 | detailsData[student._id] = {
26 | name: student.name,
27 | contact: student.contact,
28 | roomNo: student.roomNo,
29 | };
30 | });
31 |
32 | dispatch(
33 | postAttendance({
34 | roomNo: roomData,
35 | details: detailsData,
36 | data: dataData,
37 | })
38 | );
39 | };
40 | return (
41 | <>
42 |
43 |
44 |
45 | NAME |
46 | Attendance |
47 | STATUS |
48 | CONTACT |
49 | CITY |
50 |
51 |
52 |
53 | {students &&
54 | students.map((student) => (
55 | <>
56 |
57 |
58 | {student.name}
59 | |
60 |
61 |
63 | {
68 | var tempMap = attendanceMap;
69 | tempMap[student._id] = e.target.value;
70 | setAttendanceMap(tempMap);
71 | }}
72 | >
73 |
74 |
75 |
76 |
77 |
78 |
79 | |
80 |
81 |
91 | {student.status}
92 |
93 | |
94 |
95 | {student.contact}
96 | |
97 | {student.city} |
98 |
99 | >
100 | ))}
101 |
102 |
103 |
106 | >
107 | );
108 | };
109 |
110 | export default AttendanceTableComponent;
111 |
--------------------------------------------------------------------------------
/frontend/src/components/footer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Container, Row, Col } from 'react-bootstrap'
3 |
4 | const Footer = () => {
5 | return (
6 |
7 |
8 | Copyright ©NSD Solutions
9 |
10 |
11 | )
12 | }
13 |
14 | export default Footer
15 |
--------------------------------------------------------------------------------
/frontend/src/components/formContainer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Col, Container, Row } from 'react-bootstrap'
3 |
4 | const FormContainer = ({ children }) => {
5 | return (
6 |
7 |
8 |
9 | {children}
10 |
11 |
12 |
13 | )
14 | }
15 |
16 | export default FormContainer
17 |
--------------------------------------------------------------------------------
/frontend/src/components/header.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Container, Nav, Navbar, NavDropdown } from "react-bootstrap";
3 | import { Route } from "react-router-dom";
4 | import { LinkContainer } from "react-router-bootstrap";
5 | import SearchBox from "./searchBox";
6 | import { useDispatch, useSelector } from "react-redux";
7 | import { logout } from "../actions/userActions";
8 |
9 | const Header = ({ history }) => {
10 | const dispatch = useDispatch();
11 | const userLogin = useSelector((state) => state.userLogin);
12 | const { userInfo } = userLogin;
13 |
14 | const logoutHandler = () => {
15 | dispatch(logout());
16 | history.push("/login");
17 | };
18 | return (
19 |
20 |
21 |
22 |
23 | NSD Solutions
24 |
25 |
26 |
27 | } />
28 |
62 |
63 |
64 |
65 |
66 | );
67 | };
68 |
69 | export default Header;
70 |
--------------------------------------------------------------------------------
/frontend/src/components/loader.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Spinner } from 'react-bootstrap'
3 |
4 | const Loading = () => {
5 | return (
6 |
16 | Loading...
17 |
18 | )
19 | }
20 |
21 | export default Loading
22 |
--------------------------------------------------------------------------------
/frontend/src/components/message.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Alert } from 'react-bootstrap'
3 | const Message = ({ variant, children }) => {
4 | return {children}
5 | }
6 | Message.defaultProps = {
7 | variant: 'info',
8 | }
9 |
10 | export default Message
11 |
--------------------------------------------------------------------------------
/frontend/src/components/paginate.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Pagination } from "react-bootstrap";
3 | import { LinkContainer } from "react-router-bootstrap";
4 |
5 | const Paginate = ({ pages, page, isAdmin = false, keyword = "" }) => {
6 | return (
7 | pages > 1 && (
8 |
9 | {[...Array(pages).keys()].map((x) => (
10 |
20 | {x + 1}
21 |
22 | ))}
23 |
24 | )
25 | );
26 | };
27 |
28 | export default Paginate;
29 |
--------------------------------------------------------------------------------
/frontend/src/components/rating.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | const Rating = ({ value, text, color }) => {
5 | return (
6 |
7 |
8 | = 1
12 | ? 'fas fa-star'
13 | : value >= 0.5
14 | ? 'fas fa-star-half-alt'
15 | : 'far fa-star'
16 | }
17 | >
18 |
19 |
20 | = 2
24 | ? 'fas fa-star'
25 | : value >= 1.5
26 | ? 'fas fa-star-half-alt'
27 | : 'far fa-star'
28 | }
29 | >
30 |
31 |
32 | = 3
36 | ? 'fas fa-star'
37 | : value >= 2.5
38 | ? 'fas fa-star-half-alt'
39 | : 'far fa-star'
40 | }
41 | >
42 |
43 |
44 | = 4
48 | ? 'fas fa-star'
49 | : value >= 3.5
50 | ? 'fas fa-star-half-alt'
51 | : 'far fa-star'
52 | }
53 | >
54 |
55 |
56 | = 5
60 | ? 'fas fa-star'
61 | : value >= 4.5
62 | ? 'fas fa-star-half-alt'
63 | : 'far fa-star'
64 | }
65 | >
66 |
67 | {text && text}
68 |
69 | )
70 | }
71 |
72 | Rating.defaultProps = {
73 | color: '#f8e825',
74 | }
75 |
76 | Rating.propTypes = {
77 | text: PropTypes.string,
78 | color: PropTypes.string,
79 | }
80 |
81 | export default Rating
82 |
--------------------------------------------------------------------------------
/frontend/src/components/searchBox.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import { Form, Button } from 'react-bootstrap'
3 |
4 | const SearchBox = ({history}) => {
5 | const [keyword, setKeyword] = useState('')
6 | const submitHandler = (e) => {
7 | e.preventDefault ()
8 | if(keyword.trim()){
9 | history.push(`/search/${keyword}`)
10 | }else{
11 | history.push(`/`)
12 | }
13 | }
14 | return (
15 | setKeyword(e.target.value)}
23 | >
24 |
27 |
28 | )
29 | }
30 |
31 | export default SearchBox
32 |
--------------------------------------------------------------------------------
/frontend/src/components/student.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Card, Col, Row, Image } from "react-bootstrap";
3 | import { Link } from "react-router-dom";
4 | const Student = ({ stuentDetails: student }) => {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | {student.name}
14 |
15 |
16 |
17 |
18 | Room No: {student.roomNo}
19 |
20 |
21 | Stream: {student.category}
22 |
23 |
24 | Contact:
25 | {student.contact}
26 |
27 |
28 |
29 | );
30 | };
31 |
32 | export default Student;
33 |
--------------------------------------------------------------------------------
/frontend/src/constants/attendanceConstant.jsx:
--------------------------------------------------------------------------------
1 | export const ATTENDANCE_DATA_ENTER_REQUEST = "ATTENDANCE_DATA_ENTER_REQUEST";
2 | export const ATTENDANCE_DATA_ENTER_SUCCESS = "ATTENDANCE_DATA_ENTER_SUCCESS";
3 | export const ATTENDANCE_DATA_ENTER_FAIL = "ATTENDANCE_DATA_ENTER_FAIL";
4 | export const ATTENDANCE_DATA_ENTER_RESET = "ATTENDANCE_DATA_ENTER_RESET";
5 |
6 | export const ATTENDANCE_ANALYSIS_REQUEST = "ATTENDANCE_ANALYSIS_REQUEST";
7 | export const ATTENDANCE_ANALYSIS_SUCCESS = "ATTENDANCE_ANALYSIS_SUCCESS";
8 | export const ATTENDANCE_ANALYSIS_FAIL = "ATTENDANCE_ANALYSIS_FAIL";
9 | export const ATTENDANCE_ANALYSIS_RESET = "ATTENDANCE_ANALYSIS_RESET";
10 |
11 | export const ATTENDANCE_DELETE_REQUEST = "ATTENDANCE_DELETE_REQUEST";
12 | export const ATTENDANCE_DELETE_SUCCESS = "ATTENDANCE_DELETE_SUCCESS";
13 | export const ATTENDANCE_DELETE_FAIL = "ATTENDANCE_DELETE_FAIL";
14 | export const ATTENDANCE_DELETE_RESET = "ATTENDANCE_DELETE_RESET";
--------------------------------------------------------------------------------
/frontend/src/constants/studentConstant.jsx:
--------------------------------------------------------------------------------
1 | export const STUDENT_LIST_REQUEST = "STUDENT_LIST_REQUEST";
2 | export const STUDENT_LIST_SUCCESS = "STUDENT_LIST_SUCCESS";
3 | export const STUDENT_LIST_ERROR = "STUDENT_LIST_ERROR";
4 |
5 | export const STUDENT_ADD_REQUEST = "STUDENT_ADD_REQUEST";
6 | export const STUDENT_ADD_SUCCESS = "STUDENT_ADD_SUCCESS";
7 | export const STUDENT_ADD_ERROR = "STUDENT_ADD_ERROR";
8 |
9 | export const STUDENT_DETAILS_REQUEST = "STUDENT_DETAILS_REQUEST";
10 | export const STUDENT_DETAILS_SUCCESS = "STUDENT_DETAILS_SUCCESS";
11 | export const STUDENT_DETAILS_ERROR = "STUDENT_DETAILS_ERROR";
12 |
13 | export const STUDENT_UPDATE_REQUEST = "STUDENT_UPDATE_REQUEST";
14 | export const STUDENT_UPDATE_SUCCESS = "STUDENT_UPDATE_SUCCESS";
15 | export const STUDENT_UPDATE_ERROR = "STUDENT_UPDATE_ERROR";
16 | export const STUDENT_UPDATE_RESET = "STUDENT_UPDATE_RESET";
17 |
18 | export const STUDENT_DELETE_REQUEST = "STUDENT_DELETE_REQUEST";
19 | export const STUDENT_DELETE_SUCCESS = "STUDENT_DELETE_SUCCESS";
20 | export const STUDENT_DELETE_ERROR = "STUDENT_DELETE_ERROR";
21 | export const STUDENT_DELETE_RESET = "STUDENT_DELETE_RESET";
22 |
23 | export const STUDENT_ROOM_NO_REQUEST = "STUDENT_ROOM_NO_REQUEST";
24 | export const STUDENT_ROOM_NO_SUCCESS = "STUDENT_ROOM_NO_SUCCESS";
25 | export const STUDENT_ROOM_NO_ERROR = "STUDENT_ROOM_NO_ERROR";
26 | export const STUDENT_ROOM_NO_RESET = "STUDENT_ROOM_NO_RESET";
27 |
--------------------------------------------------------------------------------
/frontend/src/constants/userConstants.jsx:
--------------------------------------------------------------------------------
1 | export const USER_LOGIN_REQUEST = "USER_LOGIN_REQUEST";
2 | export const USER_LOGIN_SUCCESS = "USER_LOGIN_SUCCESS";
3 | export const USER_LOGIN_FAIL = "USER_LOGIN_FAIL";
4 | export const USER_LOGOUT = "USER_LOGOUT";
5 |
6 | export const USER_REGISTER_REQUEST = "USER_REGISTER_REQUEST";
7 | export const USER_REGISTER_SUCCESS = "USER_REGISTER_SUCCESS";
8 | export const USER_REGISTER_FAIL = "USER_REGISTER_FAIL";
9 |
10 | export const USER_DETAILS_REQUEST = "USER_DETAILS_REQUEST";
11 | export const USER_DETAILS_SUCCESS = "USER_DETAILS_SUCCESS";
12 | export const USER_DETAILS_FAIL = "USER_DETAILS_FAIL";
13 | export const USER_DETAILS_RESET = "USER_DETAILS_RESET";
14 |
15 | export const USER_UPDATE_PROFILE_REQUEST = "USER_UPDATE_PROFILE_REQUEST";
16 | export const USER_UPDATE_PROFILE_SUCCESS = "USER_UPDATE_PROFILE_SUCCESS";
17 | export const USER_UPDATE_PROFILE_FAIL = "USER_UPDATE_PROFILE_FAIL";
18 | export const USER_UPDATE_PROFILE_RESET = "USER_UPDATE_PROFILE_RESET";
19 |
20 | export const USER_LIST_REQUEST = "USER_LIST_REQUEST";
21 | export const USER_LIST_SUCCESS = "USER_LIST_SUCCESS";
22 | export const USER_LIST_FAIL = "USER_LIST_FAIL";
23 | export const USER_LIST_RESET = "USER_LIST_RESET";
24 |
25 | export const USER_DELETE_REQUEST = "USER_DELETE_REQUEST";
26 | export const USER_DELETE_SUCCESS = "USER_DELETE_SUCCESS";
27 | export const USER_DELETE_FAIL = "USER_DELETE_FAIL";
28 |
29 | export const USER_UPDATE_REQUEST = "USER_UPDATE_REQUEST";
30 | export const USER_UPDATE_SUCCESS = "USER_UPDATE_SUCCESS";
31 | export const USER_UPDATE_FAIL = "USER_UPDATE_FAIL";
32 | export const USER_UPDATE_RESET = "USER_UPDATE_RESET";
33 |
--------------------------------------------------------------------------------
/frontend/src/css/index.css:
--------------------------------------------------------------------------------
1 | main {
2 | min-height: 80vh;
3 | }
4 | .rating span {
5 | margin: 0.1rem;
6 | }
7 | h3 {
8 | padding: 1rem 0;
9 | }
10 | h1 {
11 | font-size: 1.8rem;
12 | padding: 1rem 0;
13 | }
14 | h2 {
15 | font-size: 1.4rem;
16 | padding: 0.5rem 0;
17 | }
18 |
--------------------------------------------------------------------------------
/frontend/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import './css/index.css'
4 | import { Provider } from 'react-redux'
5 | import store from './store'
6 | import App from './App'
7 | import reportWebVitals from './reportWebVitals'
8 | import './css/bootstrap.min.css'
9 |
10 | ReactDOM.render(
11 |
12 |
13 | ,
14 | document.getElementById('root')
15 | )
16 |
17 | // If you want to start measuring performance in your app, pass a function
18 | // to log results (for example: reportWebVitals(console.log))
19 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
20 | reportWebVitals()
21 |
--------------------------------------------------------------------------------
/frontend/src/reducers/attendanceReducer.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | ATTENDANCE_DATA_ENTER_FAIL,
3 | ATTENDANCE_DATA_ENTER_REQUEST,
4 | ATTENDANCE_DATA_ENTER_RESET,
5 | ATTENDANCE_DATA_ENTER_SUCCESS,
6 | ATTENDANCE_ANALYSIS_FAIL,
7 | ATTENDANCE_ANALYSIS_REQUEST,
8 | ATTENDANCE_ANALYSIS_RESET,
9 | ATTENDANCE_ANALYSIS_SUCCESS,
10 | ATTENDANCE_DELETE_REQUEST,
11 | ATTENDANCE_DELETE_SUCCESS,
12 | ATTENDANCE_DELETE_FAIL,
13 | } from "../constants/attendanceConstant";
14 |
15 | export const attendanceDataEnterReducer = (state = {}, action) => {
16 | switch (action.type) {
17 | case ATTENDANCE_DATA_ENTER_REQUEST:
18 | return { ...state, loading: true };
19 | case ATTENDANCE_DATA_ENTER_SUCCESS:
20 | return {
21 | loading: false,
22 | attendance: action.payload,
23 | };
24 | case ATTENDANCE_DATA_ENTER_FAIL:
25 | return { loading: false, error: action.payload };
26 | case ATTENDANCE_DATA_ENTER_RESET:
27 | return {};
28 |
29 | default:
30 | return state;
31 | }
32 | };
33 |
34 | export const attendanceAnalysisReducer = (state = {}, action) => {
35 | switch (action.type) {
36 | case ATTENDANCE_ANALYSIS_REQUEST:
37 | return { loading: true };
38 | case ATTENDANCE_ANALYSIS_SUCCESS:
39 | return {
40 | loading: false,
41 | attendance: action.payload,
42 | };
43 | case ATTENDANCE_ANALYSIS_FAIL:
44 | return { loading: false, error: action.payload };
45 | case ATTENDANCE_ANALYSIS_RESET:
46 | return {};
47 |
48 | default:
49 | return state;
50 | }
51 | };
52 |
53 | export const deleteAttendanceReducer = (state = {}, action) => {
54 | switch (action.type) {
55 | case ATTENDANCE_DELETE_REQUEST:
56 | return { loading: true };
57 | case ATTENDANCE_DELETE_SUCCESS:
58 | return {
59 | loading: false,
60 | success: true,
61 | };
62 | case ATTENDANCE_DELETE_FAIL:
63 | return { loading: false, error: action.payload };
64 | case ATTENDANCE_ANALYSIS_RESET:
65 | return {};
66 |
67 | default:
68 | return state;
69 | }
70 | };
71 |
--------------------------------------------------------------------------------
/frontend/src/reducers/studentsReducer.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | STUDENT_LIST_REQUEST,
3 | STUDENT_LIST_SUCCESS,
4 | STUDENT_LIST_ERROR,
5 | STUDENT_ADD_ERROR,
6 | STUDENT_ADD_REQUEST,
7 | STUDENT_ADD_SUCCESS,
8 | STUDENT_UPDATE_ERROR,
9 | STUDENT_UPDATE_REQUEST,
10 | STUDENT_UPDATE_SUCCESS,
11 | STUDENT_UPDATE_RESET,
12 | STUDENT_DELETE_ERROR,
13 | STUDENT_DELETE_REQUEST,
14 | STUDENT_DELETE_SUCCESS,
15 | STUDENT_DELETE_RESET,
16 | STUDENT_DETAILS_REQUEST,
17 | STUDENT_DETAILS_SUCCESS,
18 | STUDENT_DETAILS_ERROR,
19 | STUDENT_ROOM_NO_REQUEST,
20 | STUDENT_ROOM_NO_SUCCESS,
21 | STUDENT_ROOM_NO_ERROR,
22 | STUDENT_ROOM_NO_RESET,
23 | } from "../constants/studentConstant";
24 |
25 | export const studentListReducer = (state = { students: [] }, action) => {
26 | switch (action.type) {
27 | case STUDENT_LIST_REQUEST:
28 | return { ...state, loading: true };
29 | case STUDENT_LIST_SUCCESS:
30 | return {
31 | loading: false,
32 | students: action.payload.students,
33 | pages: action.payload.pages,
34 | page: action.payload.page,
35 | };
36 | case STUDENT_LIST_ERROR:
37 | return { loading: false, error: action.payload };
38 |
39 | default:
40 | return state;
41 | }
42 | };
43 |
44 | export const studentAddReducer = (state = { students: {} }, action) => {
45 | switch (action.type) {
46 | case STUDENT_ADD_REQUEST:
47 | return { ...state, loading: true };
48 | case STUDENT_ADD_SUCCESS:
49 | return { loading: false, success: true };
50 | case STUDENT_ADD_ERROR:
51 | return { loading: false, error: action.payload };
52 |
53 | default:
54 | return state;
55 | }
56 | };
57 |
58 | export const studentDetailsReducer = (state = {}, action) => {
59 | switch (action.type) {
60 | case STUDENT_DETAILS_REQUEST:
61 | return { ...state, loading: true };
62 | case STUDENT_DETAILS_SUCCESS:
63 | return { loading: false, student: action.payload };
64 | case STUDENT_DETAILS_ERROR:
65 | return { loading: false, error: action.payload };
66 |
67 | default:
68 | return state;
69 | }
70 | };
71 |
72 | export const studentUpdateReducer = (state = {}, action) => {
73 | switch (action.type) {
74 | case STUDENT_UPDATE_REQUEST:
75 | return { ...state, loading: true };
76 | case STUDENT_UPDATE_SUCCESS:
77 | return { loading: false, success: true };
78 | case STUDENT_UPDATE_ERROR:
79 | return { loading: false, error: action.payload };
80 | case STUDENT_UPDATE_RESET:
81 | return {};
82 |
83 | default:
84 | return state;
85 | }
86 | };
87 |
88 | export const studentDeleteReducer = (state = {}, action) => {
89 | switch (action.type) {
90 | case STUDENT_DELETE_REQUEST:
91 | return { ...state, loading: true };
92 | case STUDENT_DELETE_SUCCESS:
93 | return { loading: false, success: true };
94 | case STUDENT_DELETE_ERROR:
95 | return { loading: false, error: action.payload };
96 | case STUDENT_DELETE_RESET:
97 | return {};
98 |
99 | default:
100 | return state;
101 | }
102 | };
103 | export const getStudentsByRoomNoReducer = (state = {}, action) => {
104 | switch (action.type) {
105 | case STUDENT_ROOM_NO_REQUEST:
106 | return { ...state, loading: true };
107 | case STUDENT_ROOM_NO_SUCCESS:
108 | return {
109 | loading: false,
110 | students: action.payload.students,
111 | attendance: action.payload.attendance,
112 | };
113 | case STUDENT_ROOM_NO_ERROR:
114 | return { loading: false, error: action.payload };
115 | case STUDENT_ROOM_NO_RESET:
116 | return {};
117 |
118 | default:
119 | return state;
120 | }
121 | };
122 |
--------------------------------------------------------------------------------
/frontend/src/reducers/userReducers.jsx:
--------------------------------------------------------------------------------
1 | import {
2 | USER_DETAILS_FAIL,
3 | USER_DETAILS_REQUEST,
4 | USER_DETAILS_RESET,
5 | USER_DETAILS_SUCCESS,
6 | USER_LIST_REQUEST,
7 | USER_LIST_SUCCESS,
8 | USER_LIST_FAIL,
9 | USER_LIST_RESET,
10 | USER_LOGIN_FAIL,
11 | USER_LOGIN_REQUEST,
12 | USER_LOGIN_SUCCESS,
13 | USER_LOGOUT,
14 | USER_REGISTER_FAIL,
15 | USER_REGISTER_REQUEST,
16 | USER_REGISTER_SUCCESS,
17 | USER_UPDATE_PROFILE_FAIL,
18 | USER_UPDATE_PROFILE_REQUEST,
19 | USER_UPDATE_PROFILE_SUCCESS,
20 | USER_DELETE_REQUEST,
21 | USER_DELETE_SUCCESS,
22 | USER_DELETE_FAIL,
23 | USER_UPDATE_RESET,
24 | USER_UPDATE_REQUEST,
25 | USER_UPDATE_SUCCESS,
26 | USER_UPDATE_FAIL,
27 | USER_UPDATE_PROFILE_RESET,
28 | } from "../constants/userConstants";
29 |
30 | export const userLoginReducer = (state = {}, action) => {
31 | switch (action.type) {
32 | case USER_LOGIN_REQUEST:
33 | return { loading: true };
34 | case USER_LOGIN_SUCCESS:
35 | return { loading: false, userInfo: action.payload };
36 | case USER_LOGIN_FAIL:
37 | return { loading: false, error: action.payload };
38 | case USER_LOGOUT:
39 | return {};
40 | default:
41 | return state;
42 | }
43 | };
44 |
45 | export const userRegisterReducer = (state = {}, action) => {
46 | switch (action.type) {
47 | case USER_REGISTER_REQUEST:
48 | return { loading: true };
49 | case USER_REGISTER_SUCCESS:
50 | return { loading: false, userInfo: action.payload };
51 | case USER_REGISTER_FAIL:
52 | return { loading: false, error: action.payload };
53 | case USER_LOGOUT:
54 | return {};
55 | default:
56 | return state;
57 | }
58 | };
59 |
60 | export const userDetailsReducer = (state = { user: {} }, action) => {
61 | switch (action.type) {
62 | case USER_DETAILS_REQUEST:
63 | return { ...state, loading: true };
64 | case USER_DETAILS_SUCCESS:
65 | return { loading: false, user: action.payload };
66 | case USER_DETAILS_FAIL:
67 | return { loading: false, error: action.payload };
68 | case USER_DETAILS_RESET:
69 | return { user: {} };
70 | default:
71 | return state;
72 | }
73 | };
74 |
75 | export const userUpdateProfileReducer = (state = {}, action) => {
76 | switch (action.type) {
77 | case USER_UPDATE_PROFILE_REQUEST:
78 | return { loading: true };
79 | case USER_UPDATE_PROFILE_SUCCESS:
80 | return { loading: false, success: true, userInfo: action.payload };
81 | case USER_UPDATE_PROFILE_FAIL:
82 | return { loading: false, error: action.payload };
83 | case USER_UPDATE_PROFILE_RESET:
84 | return {};
85 | default:
86 | return state;
87 | }
88 | };
89 |
90 | export const userListReducer = (state = { users: [] }, action) => {
91 | switch (action.type) {
92 | case USER_LIST_REQUEST:
93 | return { loading: true };
94 | case USER_LIST_SUCCESS:
95 | return { loading: false, users: action.payload };
96 | case USER_LIST_FAIL:
97 | return { loading: false, error: action.payload };
98 | case USER_LIST_RESET:
99 | return { users: [] };
100 | default:
101 | return state;
102 | }
103 | };
104 |
105 | export const userDeleteReducer = (state = {}, action) => {
106 | switch (action.type) {
107 | case USER_DELETE_REQUEST:
108 | return { loading: true };
109 | case USER_DELETE_SUCCESS:
110 | return { loading: false, success: true };
111 | case USER_DELETE_FAIL:
112 | return { loading: false, error: action.payload };
113 | default:
114 | return state;
115 | }
116 | };
117 |
118 | export const userUpdateReducer = (state = { user: {} }, action) => {
119 | switch (action.type) {
120 | case USER_UPDATE_REQUEST:
121 | return { loading: true };
122 | case USER_UPDATE_SUCCESS:
123 | return { loading: false, success: true };
124 | case USER_UPDATE_FAIL:
125 | return { loading: false, error: action.payload };
126 | case USER_UPDATE_RESET:
127 | return {
128 | user: {},
129 | };
130 | default:
131 | return state;
132 | }
133 | };
134 |
--------------------------------------------------------------------------------
/frontend/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/frontend/src/screens/Authentication Screens/LoginView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react'
2 | import { Link } from 'react-router-dom'
3 | import { Form, Button, Row, Col } from 'react-bootstrap'
4 | import { useDispatch, useSelector } from 'react-redux'
5 | import Message from '../../components/message'
6 | import Loader from '../../components/loader'
7 | import FormContainer from '../../components/formContainer'
8 | import { login } from '../../actions/userActions'
9 |
10 | const LoginView = ({ location, history }) => {
11 | const [email, setEmail] = useState('')
12 | const [password, setPassword] = useState('')
13 |
14 | const dispatch = useDispatch()
15 |
16 | const userLogin = useSelector((state) => state.userLogin)
17 | const { loading, error, userInfo } = userLogin
18 |
19 | const redirect = location.search ? location.search.split('=')[1] : '/'
20 |
21 | useEffect(() => {
22 | if (userInfo) {
23 | history.push(redirect)
24 | }
25 | }, [history, userInfo, redirect])
26 |
27 | const submitHandler = (e) => {
28 | e.preventDefault()
29 | dispatch(login(email, password))
30 | }
31 |
32 | return (
33 |
34 | Sign In
35 | {error && {error}}
36 | {loading && }
37 |
39 | Email Address
40 | setEmail(e.target.value)}
45 | >
46 |
47 |
48 |
49 | Password
50 | setPassword(e.target.value)}
55 | >
56 |
57 |
58 |
61 |
62 |
63 |
64 |
65 | New Customer?{' '}
66 |
67 | Register
68 |
69 |
70 |
71 |
72 | )
73 | }
74 |
75 | export default LoginView
76 |
--------------------------------------------------------------------------------
/frontend/src/screens/Authentication Screens/RegisterView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Link } from "react-router-dom";
3 | import { Form, Button, Row, Col } from "react-bootstrap";
4 | import { useDispatch, useSelector } from "react-redux";
5 | import Message from "../../components/message";
6 | import Loader from "../../components/loader";
7 | import FormContainer from "../../components/formContainer";
8 | import { register } from "../../actions/userActions";
9 |
10 | const RegisterView = ({ location, history }) => {
11 | const [name, setName] = useState("");
12 | const [email, setEmail] = useState("");
13 | const [password, setPassword] = useState("");
14 | const [confirmPassword, setConfirmPassword] = useState("");
15 | const [message, setMessage] = useState(null);
16 |
17 | const dispatch = useDispatch();
18 |
19 | const userRegister = useSelector((state) => state.userRegister);
20 | const { loading, error, userInfo } = userRegister;
21 |
22 | const redirect = location.search ? location.search.split("=")[1] : "/";
23 |
24 | useEffect(() => {
25 | if (userInfo) {
26 | history.push(redirect);
27 | }
28 | }, [history, userInfo, redirect]);
29 |
30 | const submitHandler = (e) => {
31 | e.preventDefault();
32 | if (password !== confirmPassword) {
33 | setMessage("Passwords do not match");
34 | } else {
35 | dispatch(register(name, email, password));
36 | }
37 | };
38 |
39 | return (
40 |
41 | Sign Up
42 | {message && {message}}
43 | {error && {error}}
44 | {loading && }
45 |
47 | Name
48 | setName(e.target.value)}
53 | >
54 |
55 |
56 |
57 | Email Address
58 | setEmail(e.target.value)}
63 | >
64 |
65 |
66 |
67 | Password
68 | setPassword(e.target.value)}
73 | >
74 |
75 |
76 |
77 | Confirm Password
78 | setConfirmPassword(e.target.value)}
83 | >
84 |
85 |
86 |
89 |
90 |
91 |
92 |
93 | Have an Account?{" "}
94 |
95 | Login
96 |
97 |
98 |
99 |
100 | );
101 | };
102 |
103 | export default RegisterView;
104 |
--------------------------------------------------------------------------------
/frontend/src/screens/addStudentView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Button, Form } from "react-bootstrap";
3 | import { Link, useHistory } from "react-router-dom";
4 | import FormContainer from "../components/formContainer";
5 | import { useDispatch, useSelector } from "react-redux";
6 | import { addStudent, updateStudent } from "../actions/studentActions";
7 | import Loading from "../components/loader.jsx";
8 | import Message from "../components/message.jsx";
9 | import { STUDENT_UPDATE_RESET } from "../constants/studentConstant";
10 | import Loader from "../components/loader";
11 |
12 | const AddStudentView = () => {
13 | const history = useHistory();
14 | const [isEdit, setIsEdit] = useState(false);
15 | const [name, setName] = useState("");
16 | const [address, setAddress] = useState("");
17 | const [category, setCategory] = useState("");
18 | const [city, setCity] = useState("");
19 | const [contact, setContact] = useState("");
20 | const [fatherContact, setFatherContact] = useState("");
21 | const [image, setImage] = useState("");
22 | const [roomNo, setRoomNo] = useState("");
23 | const [blockNo, setBlockNo] = useState("");
24 | const [status, setStatus] = useState("Hostel");
25 |
26 | const dispatch = useDispatch();
27 | const studentAdd = useSelector((state) => state.studentAdd);
28 | const { loading, error, success } = studentAdd;
29 | const studentUpdate = useSelector((state) => state.studentUpdate);
30 | const {
31 | loading: loadingUpdate,
32 | error: errorUpdate,
33 | success: successUpdate,
34 | } = studentUpdate;
35 |
36 | useEffect(() => {
37 | if (successUpdate) {
38 | dispatch({ type: STUDENT_UPDATE_RESET });
39 | history.push("/");
40 | }
41 | if (history.location.state && history.location.state.studentProps) {
42 | setIsEdit(true);
43 | const student = history.location.state.studentProps;
44 | setName(student.name);
45 | setAddress(student.address);
46 | setCategory(student.category);
47 | setCity(student.city);
48 | setContact(student.contact);
49 | setFatherContact(student.fatherContact);
50 | setImage(student.image);
51 | setRoomNo(student.roomNo);
52 | setBlockNo(student.blockNo);
53 | setStatus(student.status);
54 | }
55 | if (success) {
56 | history.push("/");
57 | }
58 | }, [dispatch, history, success, successUpdate]);
59 |
60 | const submitHandler = () => {
61 | if (isEdit === true) {
62 | const _id = history.location.state.studentProps._id;
63 | dispatch(
64 | updateStudent({
65 | _id,
66 | name,
67 | address,
68 | category,
69 | city,
70 | contact,
71 | fatherContact,
72 | image,
73 | roomNo,
74 | blockNo,
75 | status,
76 | })
77 | );
78 | } else {
79 | dispatch(
80 | addStudent({
81 | name,
82 | address,
83 | category,
84 | city,
85 | contact,
86 | fatherContact,
87 | image,
88 | roomNo,
89 | blockNo,
90 | status,
91 | })
92 | );
93 | }
94 | };
95 |
96 | return (
97 | <>
98 |
99 | Go Back
100 |
101 |
102 | {loading || loadingUpdate ? (
103 |
104 | ) : (
105 | <>
106 | {errorUpdate && {errorUpdate}}
107 |
108 | {isEdit ? "Edit Student" : "Add Student"}
109 | {loading && }
110 | {error && {error}}
111 |
112 |
113 | Name
114 | setName(e.target.value)}
119 | >
120 |
121 |
122 | Status
123 | setStatus(e.target.value)}
127 | >
128 | {["Hostel", "Outside", "Home"].map((x) => (
129 |
132 | ))}
133 |
134 |
135 |
136 | Address
137 | setAddress(e.target.value)}
142 | >
143 |
144 |
145 | City
146 | setCity(e.target.value)}
151 | >
152 |
153 |
154 | Contact
155 | setContact(e.target.value)}
160 | >
161 |
162 |
163 | Father Contact
164 | setFatherContact(e.target.value)}
169 | >
170 |
171 |
172 | Room No
173 | setRoomNo(e.target.value)}
178 | >
179 |
180 |
181 | Block Number
182 | setBlockNo(e.target.value)}
187 | >
188 |
189 |
190 | Image Url
191 | setImage(e.target.value)}
196 | >
197 |
198 |
199 | Category
200 | setCategory(e.target.value)}
205 | >
206 |
207 |
210 |
211 | >
212 | )}
213 | >
214 | );
215 | };
216 |
217 | export default AddStudentView;
218 |
--------------------------------------------------------------------------------
/frontend/src/screens/analysisView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Link } from "react-router-dom";
3 | import { Row, Col, Button, Modal, Form } from "react-bootstrap";
4 | import DatePicker from "react-datepicker";
5 | import { useDispatch, useSelector } from "react-redux";
6 | import "react-datepicker/dist/react-datepicker.css";
7 | import {
8 | deleteAttendanceByDate,
9 | getAnalysisByDate,
10 | } from "../actions/attendanceActions";
11 | import AnalysisComponent from "../components/analysisComponent";
12 | import Loading from "../components/loader";
13 | import Message from "../components/message";
14 |
15 | const AnalysisView = () => {
16 | const dispatch = useDispatch();
17 | const [modal, setModal] = useState(false);
18 | const [days, setDays] = useState(0);
19 | const [idList, setIdList] = useState([]);
20 | const [startDate, setStartDate] = useState(new Date());
21 | const attendanceAnalysis = useSelector((state) => state.attendanceAnalysis);
22 | const { attendance } = attendanceAnalysis;
23 | const attendanceDelete = useSelector((state) => state.attendanceDelete);
24 | const {
25 | loading: loadingDelete,
26 | success: successDelete,
27 | error: errorDelete,
28 | } = attendanceDelete;
29 | useEffect(() => {
30 | if (attendance) {
31 | var temp = idList;
32 | Object.entries(attendance.details).map((at) => {
33 | temp.push(at[0]);
34 | });
35 |
36 | setIdList(temp);
37 | } else {
38 | dispatch(getAnalysisByDate(startDate.toString().substring(0, 15)));
39 | }
40 | }, [attendance, dispatch]);
41 |
42 | const changeDate = (date) => {
43 | dispatch(getAnalysisByDate(date.toString().substring(0, 15)));
44 | setStartDate(date);
45 | };
46 | const showModal = () => {
47 | setModal(true);
48 | };
49 | const closeModal = () => {
50 | setModal(false);
51 | };
52 |
53 | const startDelete = () => {
54 | setModal(false);
55 | dispatch(deleteAttendanceByDate(days));
56 | };
57 |
58 | return (
59 | <>
60 |
61 |
62 | Go Back
63 |
64 |
65 |
68 |
69 |
70 | {loadingDelete && }
71 | {errorDelete && {errorDelete}}
72 | {successDelete && Attendance Deleted}
73 |
74 |
75 |
76 |
77 | Analysis for
78 |
79 | {startDate.toISOString().toString().substring(0, 10)}
80 |
81 |
82 |
83 | changeDate(date)}
86 | />
87 |
88 |
89 |
90 |
91 | Enter Number of days before to delete
92 |
93 |
94 |
96 | Enter no of days
97 | setDays(e.target.value)}
102 | >
103 |
104 |
105 |
106 |
107 |
110 |
113 |
114 |
115 | {}
116 |
117 | >
118 | );
119 | };
120 |
121 | export default AnalysisView;
122 |
--------------------------------------------------------------------------------
/frontend/src/screens/attendanceView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Form, Button } from "react-bootstrap";
3 | import { useDispatch } from "react-redux";
4 | import { getStudentsByRoomNo as action } from "../actions/studentActions";
5 | import AttendanceTable from "../components/attendanceTable";
6 |
7 | const AttendanceView = () => {
8 | const [roomNo, setRoomNo] = useState("");
9 | const dispatch = useDispatch();
10 | useEffect(() => {}, [dispatch]);
11 | const submitHandler = (e) => {
12 | e.preventDefault();
13 | dispatch(action(roomNo));
14 | };
15 |
16 | const changeRoomNo = (e) => {
17 | setRoomNo(e.target.value);
18 | };
19 | return (
20 | <>
21 | Take Attendance
22 | changeRoomNo(e)}
30 | >
31 |
34 |
35 |
36 | >
37 | );
38 | };
39 |
40 | export default AttendanceView;
41 |
--------------------------------------------------------------------------------
/frontend/src/screens/homeView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import { useDispatch, useSelector } from "react-redux";
3 | import Student from "../components/student";
4 | import Loading from "../components/loader.jsx";
5 | import Message from "../components/message.jsx";
6 | import { listStudents } from "../actions/studentActions";
7 | import Paginate from "../components/paginate";
8 | import {
9 | Row,
10 | Col,
11 | ButtonGroup,
12 | ToggleButton,
13 | Container,
14 | } from "react-bootstrap";
15 | import StudentsTableView from "./studentTableView";
16 |
17 | const HomeView = ({ match, history }) => {
18 | const [isGrid, setIsGrid] = useState(true);
19 | const keyword = match.params.keyword;
20 |
21 | const pageNumber = match.params.pageNumber || 1;
22 | const userLogin = useSelector((state) => state.userLogin);
23 | const { loading: userLoading, userInfo } = userLogin;
24 |
25 | const dispatch = useDispatch();
26 |
27 | const studentsList = useSelector((state) => state.studentsList);
28 | const { loading, error, students, page, pages } = studentsList;
29 |
30 | useEffect(() => {
31 | if (!userLoading && !userInfo) {
32 | history.push("/login");
33 | }
34 | dispatch(listStudents(keyword, pageNumber));
35 | }, [keyword, pageNumber]);
36 |
37 | return (
38 | <>
39 | <>
40 |
41 |
42 |
43 |
44 |
45 | {["Grid", "Table"].map((type) => (
46 |
54 | setIsGrid(e.target.value === "Grid" ? true : false)
55 | }
56 | >
57 | {type === "Grid" ? <> Grid> : <> Table >}
58 |
59 | ))}
60 |
61 |
62 |
63 |
64 |
65 | >
66 |
67 | Students
68 | {loading ? (
69 |
70 | ) : error ? (
71 | {error}
72 | ) : isGrid ? (
73 | <>
74 |
75 | {students.map((student) => (
76 |
77 |
78 |
79 | ))}
80 |
81 |
86 | >
87 | ) : (
88 | <>
89 |
90 | >
91 | )}
92 | >
93 | );
94 | };
95 |
96 | export default HomeView;
97 |
--------------------------------------------------------------------------------
/frontend/src/screens/profileView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Form, Button, Row, Col } from "react-bootstrap";
3 | import { useDispatch, useSelector } from "react-redux";
4 | import Message from "../components/message";
5 | import Loader from "../components/loader";
6 | import { getUserDetails, updateUserProfile } from "../actions/userActions";
7 | import { USER_UPDATE_PROFILE_RESET } from "../constants/userConstants";
8 |
9 | const ProfileView = ({ history }) => {
10 | const [name, setName] = useState("");
11 | const [email, setEmail] = useState("");
12 | const [password, setPassword] = useState("");
13 | const [confirmPassword, setConfirmPassword] = useState("");
14 | const [message, setMessage] = useState(null);
15 |
16 | const dispatch = useDispatch();
17 |
18 | const userDetails = useSelector((state) => state.userDetails);
19 | const { loading, error, user } = userDetails;
20 |
21 | const userLogin = useSelector((state) => state.userLogin);
22 | const { userInfo } = userLogin;
23 |
24 | const userUpdateProfile = useSelector((state) => state.userUpdateProfile);
25 | const { success } = userUpdateProfile;
26 | useEffect(() => {
27 | if (!userInfo) {
28 | history.push("/login");
29 | } else {
30 | if (!user || !user.name || success) {
31 | dispatch({ type: USER_UPDATE_PROFILE_RESET });
32 | dispatch(getUserDetails("profile"));
33 | } else {
34 | setName(user.name);
35 | setEmail(user.email);
36 | }
37 | }
38 | }, [dispatch, history, userInfo, user, success]);
39 |
40 | const submitHandler = (e) => {
41 | e.preventDefault();
42 | if (password !== confirmPassword) {
43 | setMessage("Passwords do not match");
44 | } else {
45 | dispatch(updateUserProfile({ id: user._id, name, email, password }));
46 | }
47 | };
48 |
49 | return (
50 |
51 |
52 | Profile
53 | {message && {message}}
54 |
55 | {success && Profile Updated}
56 | {loading ? (
57 |
58 | ) : error ? (
59 | {error}
60 | ) : (
61 |
63 | Name
64 | setName(e.target.value)}
69 | >
70 |
71 |
72 |
73 | Email Address
74 | setEmail(e.target.value)}
79 | >
80 |
81 |
82 |
83 | Password
84 | setPassword(e.target.value)}
89 | >
90 |
91 |
92 |
93 | Confirm Password
94 | setConfirmPassword(e.target.value)}
99 | >
100 |
101 |
102 |
105 |
106 | )}
107 |
108 |
109 |
110 | );
111 | };
112 |
113 | export default ProfileView;
114 |
--------------------------------------------------------------------------------
/frontend/src/screens/studentDetailsView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Link } from "react-router-dom";
3 | import { useDispatch, useSelector } from "react-redux";
4 | import {
5 | Row,
6 | Col,
7 | Image,
8 | ListGroup,
9 | Card,
10 | Button,
11 | Form,
12 | } from "react-bootstrap";
13 | import Loading from "../components/loader";
14 | import Message from "../components/message";
15 | import {
16 | getStudentDetails,
17 | updateStudent,
18 | deleteStudent,
19 | } from "../actions/studentActions";
20 | import { STUDENT_UPDATE_RESET } from "../constants/studentConstant";
21 | const StudentDetailsView = ({ match, history }) => {
22 | const [status, setStatus] = useState("");
23 | const dispatch = useDispatch();
24 | const studentDetails = useSelector((state) => state.studentDetails);
25 | const { loading, error, student } = studentDetails;
26 | const studentUpdate = useSelector((state) => state.studentUpdate);
27 | const {
28 | loading: loadingUpdate,
29 | error: errorUpdate,
30 | success: successUpdate,
31 | } = studentUpdate;
32 | const studentDelete = useSelector((state) => state.studentDelete);
33 | const {
34 | loading: loadingDelete,
35 | error: errorDelete,
36 | success: successDelete,
37 | } = studentDelete;
38 |
39 | useEffect(() => {
40 | if (successDelete) {
41 | history.push("/");
42 | }
43 | if (successUpdate) {
44 | dispatch({ type: STUDENT_UPDATE_RESET });
45 | }
46 | if (!student || !student._id || student._id !== match.params.id) {
47 | dispatch(getStudentDetails(match.params.id));
48 | }
49 | if (student && student._id && !status) {
50 | setStatus(student.status);
51 | }
52 | }, [dispatch, match, successUpdate, successDelete]);
53 |
54 | const navigateToEdit = () => {
55 | history.push({
56 | pathname: `/student/edit/${student._id}`,
57 | state: { studentProps: student },
58 | });
59 | };
60 | const updateStatus = () => {
61 | student.status = status;
62 | dispatch(updateStudent(student));
63 | };
64 |
65 | const deleteStuden = () => {
66 | if (window.confirm("Are you sure")) {
67 | dispatch(deleteStudent(student._id));
68 | }
69 | };
70 | return (
71 | <>
72 |
73 | Go Back
74 |
75 | {loading || loadingUpdate || loadingDelete ? (
76 |
77 | ) : error ? (
78 | {error}
79 | ) : (
80 | <>
81 | {errorUpdate && {errorUpdate}}
82 | {errorDelete && {errorDelete}}
83 | {student && (
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | {student.name}
92 |
93 |
94 | Phone No:{student.contact}
95 |
96 |
97 | Father Contact:{student.fatherContact}
98 |
99 |
100 | City:{student.city}
101 |
102 |
103 | Address:{student.address}
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 | Room No:
113 | {student.roomNo}
114 |
115 |
116 |
117 |
118 | Block No:
119 | {student.blockNo}
120 |
121 |
122 |
123 |
124 | Status:
125 |
126 | setStatus(e.target.value)}
131 | >
132 | {["Hostel", "Outside", "Home"].map((x) => (
133 |
136 | ))}
137 |
138 |
139 |
140 |
141 |
142 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
160 |
161 |
162 |
165 |
166 |
167 |
168 |
169 |
170 | )}
171 | >
172 | )}
173 | >
174 | );
175 | };
176 |
177 | export default StudentDetailsView;
178 |
--------------------------------------------------------------------------------
/frontend/src/screens/studentTableView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from "react";
2 | import { Table } from "react-bootstrap";
3 | import { useDispatch, useSelector } from "react-redux";
4 | import Message from "../components/message";
5 | import Loader from "../components/loader";
6 | import Paginate from "../components/paginate";
7 | import { listStudents } from "../actions/studentActions";
8 | import { Link } from "react-router-dom";
9 |
10 | const StudentsTableView = ({ keyword, pageNumber }) => {
11 | const dispatch = useDispatch();
12 |
13 | const studentsList = useSelector((state) => state.studentsList);
14 | const { loading, error, students, page, pages } = studentsList;
15 | useEffect(() => {
16 | if (!students) {
17 | dispatch(listStudents(keyword, pageNumber));
18 | }
19 | }, [dispatch, keyword, pageNumber]);
20 | return (
21 | <>
22 | {loading ? (
23 |
24 | ) : error ? (
25 | {error}
26 | ) : (
27 | <>
28 |
29 |
30 |
31 | Stream |
32 | NAME |
33 | STATUS |
34 | CONTACT |
35 | ROOM NO |
36 | CITY |
37 |
38 |
39 |
40 | {students.map((student) => (
41 |
42 | {student.category} |
43 |
44 | {student.name}
45 | |
46 |
47 |
57 | {student.status}
58 |
59 | |
60 |
61 | {student.contact}
62 | |
63 | {student.roomNo} |
64 | {student.city} |
65 |
66 | ))}
67 |
68 |
69 |
70 | >
71 | )}
72 | >
73 | );
74 | };
75 |
76 | export default StudentsTableView;
77 |
--------------------------------------------------------------------------------
/frontend/src/screens/userEditView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Link } from "react-router-dom";
3 | import { Form, Button } from "react-bootstrap";
4 | import { useDispatch, useSelector } from "react-redux";
5 | import Message from "../components/message";
6 | import Loader from "../components/loader";
7 | import FormContainer from "../components/formContainer";
8 | import { getUserDetails, updateUser } from "../actions/userActions";
9 | import { USER_UPDATE_RESET } from "../constants/userConstants";
10 |
11 | const UserEditView = ({ match, history }) => {
12 | const userId = match.params.userId;
13 |
14 | const [name, setName] = useState("");
15 | const [email, setEmail] = useState("");
16 | const [isAdmin, setIsAdmin] = useState(false);
17 |
18 | const dispatch = useDispatch();
19 |
20 | const userDetails = useSelector((state) => state.userDetails);
21 | const { loading, error, user } = userDetails;
22 |
23 | const userUpdate = useSelector((state) => state.userUpdate);
24 | const {
25 | loading: loadingUpdate,
26 | error: errorUpdate,
27 | success: successUpdate,
28 | } = userUpdate;
29 |
30 | useEffect(() => {
31 | console.log(userId);
32 | if (successUpdate) {
33 | dispatch({ type: USER_UPDATE_RESET });
34 | history.push("/userList");
35 | } else {
36 | if (!user || !user.name || user._id !== userId) {
37 | dispatch(getUserDetails(userId));
38 | } else {
39 | setName(user.name);
40 | setEmail(user.email);
41 | setIsAdmin(user.isAdmin);
42 | }
43 | }
44 | }, [dispatch, history, userId, user, successUpdate]);
45 |
46 | const submitHandler = (e) => {
47 | e.preventDefault();
48 | dispatch(updateUser({ _id: userId, name, email, isAdmin }));
49 | };
50 |
51 | return (
52 | <>
53 |
54 | Go Back
55 |
56 |
57 | Edit User
58 | {loadingUpdate && }
59 | {errorUpdate && {errorUpdate}}
60 | {loading ? (
61 |
62 | ) : error ? (
63 | {error}
64 | ) : (
65 |
67 | Name
68 | setName(e.target.value)}
73 | >
74 |
75 |
76 |
77 | Email Address
78 | setEmail(e.target.value)}
83 | >
84 |
85 |
86 |
87 | setIsAdmin(e.target.checked)}
92 | >
93 |
94 |
95 |
98 |
99 | )}
100 |
101 | >
102 | );
103 | };
104 |
105 | export default UserEditView;
106 |
--------------------------------------------------------------------------------
/frontend/src/screens/userListView.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from "react";
2 | import { LinkContainer } from "react-router-bootstrap";
3 | import { Table, Button } from "react-bootstrap";
4 | import { useDispatch, useSelector } from "react-redux";
5 | import Message from "../components/message";
6 | import Loader from "../components/loader";
7 | import { listUsers, deleteUser } from "../actions/userActions";
8 |
9 | const UserListView = ({ history }) => {
10 | const dispatch = useDispatch();
11 |
12 | const userList = useSelector((state) => state.userList);
13 | const { loading, error, users } = userList;
14 |
15 | const userLogin = useSelector((state) => state.userLogin);
16 | const { userInfo } = userLogin;
17 |
18 | const userDelete = useSelector((state) => state.userDelete);
19 | const { success: successDelete } = userDelete;
20 |
21 | useEffect(() => {
22 | if (userInfo && userInfo.isAdmin) {
23 | dispatch(listUsers());
24 | } else {
25 | history.push("/login");
26 | }
27 | }, [dispatch, history, successDelete, userInfo]);
28 |
29 | const deleteHandler = (id) => {
30 | if (window.confirm("Are you sure")) {
31 | dispatch(deleteUser(id));
32 | }
33 | };
34 |
35 | return (
36 | <>
37 | Users
38 | {loading ? (
39 |
40 | ) : error ? (
41 | {error}
42 | ) : (
43 |
44 |
45 |
46 | ID |
47 | NAME |
48 | EMAIL |
49 | ADMIN |
50 | |
51 |
52 |
53 |
54 | {users.map((user) => (
55 |
56 | {user._id} |
57 | {user.name} |
58 |
59 | {user.email}
60 | |
61 |
62 | {user.isAdmin ? (
63 |
64 | ) : (
65 |
66 | )}
67 | |
68 |
69 |
70 |
73 |
74 |
81 | |
82 |
83 | ))}
84 |
85 |
86 | )}
87 | >
88 | );
89 | };
90 |
91 | export default UserListView;
92 |
--------------------------------------------------------------------------------
/frontend/src/store.jsx:
--------------------------------------------------------------------------------
1 | import { createStore, combineReducers, applyMiddleware } from "redux";
2 | import thunk from "redux-thunk";
3 | import { composeWithDevTools } from "redux-devtools-extension";
4 | import {} from "./actions/studentActions";
5 | import {
6 | studentListReducer,
7 | studentAddReducer,
8 | studentDetailsReducer,
9 | getStudentsByRoomNoReducer,
10 | studentUpdateReducer,
11 | studentDeleteReducer,
12 | } from "./reducers/studentsReducer";
13 | import {
14 | userLoginReducer,
15 | userRegisterReducer,
16 | userDetailsReducer,
17 | userUpdateProfileReducer,
18 | userListReducer,
19 | userDeleteReducer,
20 | userUpdateReducer,
21 | } from "./reducers/userReducers";
22 | import {
23 | attendanceDataEnterReducer,
24 | attendanceAnalysisReducer,
25 | deleteAttendanceReducer,
26 | } from "./reducers/attendanceReducer";
27 |
28 | const reducer = combineReducers({
29 | studentsList: studentListReducer,
30 | studentDetails: studentDetailsReducer,
31 | studentAdd: studentAddReducer,
32 | studentUpdate: studentUpdateReducer,
33 | studentDelete: studentDeleteReducer,
34 | getStudentsByRoomNo: getStudentsByRoomNoReducer,
35 | userLogin: userLoginReducer,
36 | userRegister: userRegisterReducer,
37 | userDetails: userDetailsReducer,
38 | userUpdateProfile: userUpdateProfileReducer,
39 | userList: userListReducer,
40 | userDelete: userDeleteReducer,
41 | userUpdate: userUpdateReducer,
42 | attendanceDataEnter: attendanceDataEnterReducer,
43 | attendanceAnalysis: attendanceAnalysisReducer,
44 | attendanceDelete: deleteAttendanceReducer,
45 | });
46 | const userInfoFromStorage = localStorage.getItem("userInfo")
47 | ? JSON.parse(localStorage.getItem("userInfo"))
48 | : null;
49 |
50 | const initialState = {
51 | userLogin: { userInfo: userInfoFromStorage },
52 | };
53 |
54 | const middleware = [thunk];
55 | const store = createStore(
56 | reducer,
57 | initialState,
58 | composeWithDevTools(applyMiddleware(...middleware))
59 | );
60 |
61 | export default store;
62 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "type": "module",
7 | "engines": {
8 | "npm": "7.4.0",
9 | "node":"15.6.0"
10 | },
11 | "scripts": {
12 | "start": "node server/index.js",
13 | "server": "nodemon server/index.js",
14 | "client": "npm start --prefix frontend",
15 | "dev": "concurrently \"npm run server\" \"npm run client\"",
16 | "test": "echo \"Error: no test specified\" && exit 1",
17 | "heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix frontend && npm run build --prefix frontend"
18 | },
19 | "author": "",
20 | "license": "ISC",
21 | "dependencies": {
22 | "bcryptjs": "^2.4.3",
23 | "colors": "^1.4.0",
24 | "dotenv": "^8.2.0",
25 | "express": "^4.17.1",
26 | "express-async-handler": "^1.1.4",
27 | "jsonwebtoken": "^8.5.1",
28 | "mongoose": "^5.10.6",
29 | "morgan": "^1.10.0",
30 | "multer": "^1.4.2"
31 | },
32 | "devDependencies": {
33 | "concurrently": "^5.3.0",
34 | "nodemon": "^2.0.4"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/server/config/mongoDBConfig.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose";
2 |
3 | const connectDB = async () => {
4 | try {
5 | const conn = await mongoose.connect(process.env.MONGO_URI, {
6 | useUnifiedTopology: true,
7 | useNewUrlParser: true,
8 | useCreateIndex: true,
9 | });
10 |
11 | console.log(`MongoDB Connected: ${conn.connection.host}`);
12 | } catch (error) {
13 | console.error(`Error: ${error.message}`);
14 | process.exit(1);
15 | }
16 | };
17 |
18 | export default connectDB;
19 |
--------------------------------------------------------------------------------
/server/controllers/attendanceController.js:
--------------------------------------------------------------------------------
1 | import asyncHandler from "express-async-handler";
2 | import Attendance from "../models/attendance.js";
3 |
4 | const getAttendanceByRoomNo = asyncHandler(async (req, res) => {
5 | const date = req.body.date || Date().toString().substring(0, 15);
6 | const attendance = await Attendance.findOne({
7 | roomNo: { $in: [req.body.roomNo] },
8 | date: date,
9 | });
10 | if (attendance) {
11 | res.json(attendance);
12 | } else {
13 | res.status(404);
14 | throw new Error(
15 | `You didn't take attendance today for room No:${req.params.roomId}`
16 | );
17 | }
18 | });
19 |
20 | const getAttendance = asyncHandler(async (req, res) => {
21 | const date = req.body.date || Date().toString().substring(0, 15);
22 | const attendance = await Attendance.findOne({
23 | date: date,
24 | });
25 | if (attendance) {
26 | res.json(attendance);
27 | } else {
28 | res.status(404);
29 | throw new Error(`You didn't take attendance ${date}!!`);
30 | }
31 | });
32 |
33 | const enterAttendanceByRoomNo = asyncHandler(async (req, res) => {
34 | const date = req.body.date || Date().toString().substring(0, 15);
35 | const attendance = await Attendance.findOne({
36 | date: date,
37 | });
38 | if (attendance) {
39 | const dataTemp = attendance.data;
40 | const detailsTemp = attendance.details;
41 | for (const [key, value] of Object.entries(req.body.data)) {
42 | dataTemp.set(key, value);
43 | }
44 | for (const [key, value] of Object.entries(req.body.details)) {
45 | detailsTemp.set(key, value);
46 | }
47 | attendance.details = detailsTemp;
48 | attendance.data = dataTemp;
49 |
50 | const updatedAttendance = await attendance.save();
51 | res.json(updatedAttendance);
52 | } else {
53 | const newAttendance = await Attendance.create({
54 | roomNo: [req.body.roomNo],
55 | date: date,
56 | data: req.body.data,
57 | details: req.body.details,
58 | });
59 | res.json(newAttendance);
60 | }
61 | });
62 |
63 | const deleteAttendanceByDays = asyncHandler(async (req, res) => {
64 | const days = req.params.days;
65 | var date = new Date();
66 | var deletionDate = new Date(date.setDate(date.getDate() - days));
67 | await Attendance.deleteMany({
68 | createdAt: { $lt: deletionDate },
69 | });
70 | res.json({ message: `Deleted Attendance for before past ${days} days` });
71 | });
72 |
73 | export {
74 | getAttendanceByRoomNo,
75 | enterAttendanceByRoomNo,
76 | getAttendance,
77 | deleteAttendanceByDays,
78 | };
79 |
--------------------------------------------------------------------------------
/server/controllers/studentController.js:
--------------------------------------------------------------------------------
1 | import asyncHandler from "express-async-handler";
2 | import Student from "../models/student.js";
3 | import Attendance from "../models/attendance.js";
4 |
5 | const addStudent = asyncHandler(async (req, res) => {
6 | const {
7 | name,
8 | address,
9 | category,
10 | city,
11 | contact,
12 | fatherContact,
13 | image,
14 | roomNo,
15 | blockNo,
16 | status,
17 | } = req.body;
18 |
19 | const studentExist = await Student.findOne({ name: name });
20 |
21 | if (studentExist) {
22 | res.status(400);
23 | throw new Error("Student already exists");
24 | }
25 |
26 | const student = await Student.create({
27 | name,
28 | address,
29 | category,
30 | city,
31 | contact,
32 | fatherContact,
33 | image,
34 | roomNo,
35 | blockNo,
36 | status,
37 | });
38 |
39 | if (student) {
40 | res.status(201).json({
41 | _id: student._id,
42 | name: student.name,
43 | address: student.address,
44 | category: student.category,
45 | city: student.city,
46 | contact: student.contact,
47 | fatherContact: student.fatherContact,
48 | image: student.image,
49 | roomNo: student.roomNo,
50 | blockNo: student.blockNo,
51 | status: student.status,
52 | });
53 | } else {
54 | res.status(400);
55 | throw new Error("Invalid Student data");
56 | }
57 | });
58 | const updateStudentProfile = asyncHandler(async (req, res) => {
59 | const student = await Student.findById(req.body._id);
60 |
61 | if (student) {
62 | student.name = req.body.name || student.name;
63 | student.address = req.body.address || student.address;
64 | student.category = req.body.category || student.category;
65 | student.city = req.body.city || student.city;
66 | student.contact = req.body.contact || student.contact;
67 | student.fatherContact = req.body.fatherContact || student.fatherContact;
68 | student.image = req.body.image || student.image;
69 | student.roomNo = req.body.roomNo || student.roomNo;
70 | student.blockNo = req.body.blockNo || student.blockNo;
71 | student.status = req.body.status || student.status;
72 | const updatedStudent = await student.save();
73 |
74 | res.json({
75 | _id: updatedStudent._id,
76 | name: updatedStudent.name,
77 | address: updatedStudent.address,
78 | category: updatedStudent.category,
79 | city: updatedStudent.city,
80 | contact: updatedStudent.contact,
81 | fatherContact: updatedStudent.fatherContact,
82 | image: updatedStudent.image,
83 | roomNo: updatedStudent.roomNo,
84 | blockNo: updatedStudent.blockNo,
85 | status: updatedStudent.status,
86 | });
87 | } else {
88 | res.status(404);
89 | throw new Error("Student not found");
90 | }
91 | });
92 | const getAllStudents = asyncHandler(async (req, res) => {
93 | const pageSize = 15;
94 | const page = Number(req.query.pageNumber) || 1;
95 |
96 | const keyword = req.query.keyword
97 | ? {
98 | name: {
99 | $regex: req.query.keyword,
100 | $options: "i",
101 | },
102 | }
103 | : {};
104 |
105 | const count = await Student.countDocuments({ ...keyword });
106 | const students = await Student.find({ ...keyword })
107 | .limit(pageSize)
108 | .skip(pageSize * (page - 1));
109 | if (students && students.length != 0) {
110 | res.json({ students, page, pages: Math.ceil(count / pageSize) });
111 | } else {
112 | res.status(404);
113 | throw new Error("No Students Found");
114 | }
115 | });
116 |
117 | const deleteStudent = asyncHandler(async (req, res) => {
118 | const student = await Student.findById(req.params.id);
119 |
120 | if (student) {
121 | await student.remove();
122 | res.json({ message: "Student removed" });
123 | } else {
124 | res.status(404);
125 | throw new Error("Student not found");
126 | }
127 | });
128 | const getStudentById = asyncHandler(async (req, res) => {
129 | const student = await Student.findById(req.params.id);
130 | if (student) {
131 | res.json(student);
132 | } else {
133 | res.status(404);
134 | throw new Error("Students not found");
135 | }
136 | });
137 |
138 | const getStudentByRoomNo = asyncHandler(async (req, res) => {
139 | const attendance = await Attendance.findOne({
140 | date: Date().toString().substring(0, 15),
141 | roomNo: { $in: [req.params.roomId] },
142 | });
143 | const students = await Student.find({ roomNo: req.params.roomId });
144 | if (students) {
145 | attendance
146 | ? res.json({ students: students, attendance: attendance })
147 | : res.json({ students: students });
148 | } else {
149 | res.status(404);
150 | throw new Error("Students not found");
151 | }
152 | });
153 |
154 | export {
155 | addStudent,
156 | updateStudentProfile,
157 | getAllStudents,
158 | deleteStudent,
159 | getStudentById,
160 | getStudentByRoomNo,
161 | };
162 |
--------------------------------------------------------------------------------
/server/controllers/userController.js:
--------------------------------------------------------------------------------
1 | import asyncHandler from "express-async-handler";
2 | import generateToken from "../utils/generateToken.js";
3 | import User from "../models/user.js";
4 |
5 | const authUser = asyncHandler(async (req, res) => {
6 | const { email, password } = req.body;
7 |
8 | const user = await User.findOne({ email });
9 |
10 | if (user && (await user.matchPassword(password))) {
11 | res.json({
12 | _id: user._id,
13 | name: user.name,
14 | email: user.email,
15 | isAdmin: user.isAdmin,
16 | token: generateToken(user._id),
17 | });
18 | } else {
19 | res.status(401);
20 | throw new Error("Invalid email or password");
21 | }
22 | });
23 |
24 | const registerUser = asyncHandler(async (req, res) => {
25 | const { name, email, password } = req.body;
26 |
27 | const userExists = await User.findOne({ email });
28 |
29 | if (userExists) {
30 | res.status(400);
31 | throw new Error("User already exists");
32 | }
33 |
34 | const user = await User.create({
35 | name,
36 | email,
37 | password,
38 | });
39 |
40 | if (user) {
41 | const token = generateToken(user._id);
42 | res.status(201).json({
43 | _id: user._id,
44 | name: user.name,
45 | email: user.email,
46 | isAdmin: user.isAdmin,
47 | token: token,
48 | });
49 | } else {
50 | res.status(400);
51 | throw new Error("Invalid user data");
52 | }
53 | });
54 |
55 | const getUserProfile = asyncHandler(async (req, res) => {
56 | const user = await User.findById(req.user._id);
57 |
58 | if (user) {
59 | res.json({
60 | _id: user._id,
61 | name: user.name,
62 | email: user.email,
63 | isAdmin: user.isAdmin,
64 | });
65 | } else {
66 | res.status(404);
67 | throw new Error("User not found");
68 | }
69 | });
70 |
71 | const updateUserProfile = asyncHandler(async (req, res) => {
72 | const user = await User.findById(req.user._id);
73 |
74 | if (user) {
75 | user.name = req.body.name || user.name;
76 | user.email = req.body.email || user.email;
77 | if (req.body.password) {
78 | user.password = req.body.password;
79 | }
80 |
81 | const updatedUser = await user.save();
82 |
83 | res.json({
84 | _id: updatedUser._id,
85 | name: updatedUser.name,
86 | email: updatedUser.email,
87 | isAdmin: updatedUser.isAdmin,
88 | token: generateToken(updatedUser._id),
89 | });
90 | } else {
91 | res.status(404);
92 | throw new Error("User not found");
93 | }
94 | });
95 |
96 | const getUsers = asyncHandler(async (req, res) => {
97 | const users = await User.find({});
98 | res.json(users);
99 | });
100 |
101 | const deleteUser = asyncHandler(async (req, res) => {
102 | const user = await User.findById(req.params.id);
103 |
104 | if (user) {
105 | await user.remove();
106 | res.json({ message: "User removed" });
107 | } else {
108 | res.status(404);
109 | throw new Error("User not found");
110 | }
111 | });
112 |
113 | const getUserById = asyncHandler(async (req, res) => {
114 | const user = await User.findById(req.params.id).select("-password");
115 |
116 | if (user) {
117 | res.json(user);
118 | } else {
119 | res.status(404);
120 | throw new Error("User not found");
121 | }
122 | });
123 |
124 | const updateUser = asyncHandler(async (req, res) => {
125 | const user = await User.findById(req.params.id);
126 |
127 | if (user) {
128 | user.name = req.body.name || user.name;
129 | user.email = req.body.email || user.email;
130 | user.isAdmin = req.body.isAdmin;
131 |
132 | const updatedUser = await user.save();
133 |
134 | res.json({
135 | _id: updatedUser._id,
136 | name: updatedUser.name,
137 | email: updatedUser.email,
138 | isAdmin: updatedUser.isAdmin,
139 | });
140 | } else {
141 | res.status(404);
142 | throw new Error("User not found");
143 | }
144 | });
145 |
146 | export {
147 | authUser,
148 | registerUser,
149 | getUserProfile,
150 | updateUserProfile,
151 | getUsers,
152 | deleteUser,
153 | getUserById,
154 | updateUser,
155 | };
156 |
--------------------------------------------------------------------------------
/server/data/students.js:
--------------------------------------------------------------------------------
1 | const students = [];
2 | export default students;
3 |
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import userRoutes from "./routes/userRoutes.js";
3 | import studentRoutes from "./routes/studentRoutes.js";
4 | import attendanceRoutes from "./routes/attendanceRoutes.js";
5 | import path from "path";
6 | import morgan from "morgan";
7 |
8 | import dotenv from "dotenv";
9 | import connectDB from "./config/mongoDBConfig.js";
10 | import { errorHandler, notFound } from "./middleware/errorMiddleware.js";
11 | dotenv.config();
12 | connectDB();
13 | const app = express();
14 |
15 | if (process.env.NODE_ENV === "development") {
16 | app.use(morgan("dev"));
17 | }
18 | app.use(express.json());
19 | app.use(express.urlencoded({ extended: false }));
20 | app.use("/users", userRoutes);
21 | app.use("/student", studentRoutes);
22 | app.use("/attendance", attendanceRoutes);
23 |
24 | const __dirname = path.resolve();
25 | if (process.env.NODE_ENV === "production") {
26 | app.use(express.static(path.join(__dirname, "/frontend/build")));
27 |
28 | app.get("*", (req, res) =>
29 | res.sendFile(path.resolve(__dirname, "frontend", "build", "index.html"))
30 | );
31 | } else {
32 | app.get("/", (req, res) => {
33 | res.send("API is running....");
34 | });
35 | }
36 | app.use(errorHandler);
37 | app.use(notFound);
38 |
39 | const PORT = process.env.PORT || 5000;
40 |
41 | app.listen(
42 | PORT,
43 | console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`)
44 | );
45 |
--------------------------------------------------------------------------------
/server/middleware/authMiddleware.js:
--------------------------------------------------------------------------------
1 | import jwt from "jsonwebtoken";
2 | import asyncHandler from "express-async-handler";
3 | import User from "../models/user.js";
4 |
5 | const protect = asyncHandler(async (req, res, next) => {
6 | let token;
7 |
8 | if (
9 | req.headers.authorization &&
10 | req.headers.authorization.startsWith("Bearer")
11 | ) {
12 | try {
13 | token = req.headers.authorization.split(" ")[1];
14 |
15 | const decoded = jwt.verify(token, process.env.JWT_SECRET);
16 |
17 | req.user = await User.findById(decoded.id).select("-password");
18 |
19 | next();
20 | } catch (error) {
21 | console.error(error);
22 | res.status(401);
23 | throw new Error("Not authorized, token failed");
24 | }
25 | }
26 |
27 | if (!token) {
28 | res.status(401);
29 | throw new Error("Not authorized, no token");
30 | }
31 | });
32 |
33 | const admin = (req, res, next) => {
34 | if (req.user && req.user.isAdmin) {
35 | next();
36 | } else {
37 | res.status(401);
38 | throw new Error("Not authorized as an admin");
39 | }
40 | };
41 |
42 | export { protect, admin };
43 |
--------------------------------------------------------------------------------
/server/middleware/errorMiddleware.js:
--------------------------------------------------------------------------------
1 | const notFound = (req, res, next) => {
2 | const error = new Error(`Not Found - ${req.originalUrl}`);
3 | res.status(404);
4 | next(error);
5 | };
6 |
7 | const errorHandler = (err, req, res, next) => {
8 | const statusCode = res.statusCode === 200 ? 500 : res.statusCode;
9 | res.status(statusCode);
10 | res.json({
11 | message: err.message,
12 | stack: process.env.NODE_ENV === "production" ? null : err.stack,
13 | });
14 | };
15 |
16 | export { notFound, errorHandler };
17 |
--------------------------------------------------------------------------------
/server/models/attendance.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose";
2 |
3 | const attendanceSchema = mongoose.Schema(
4 | {
5 | roomNo: {
6 | type: Array,
7 | required: true,
8 | },
9 | date: {
10 | type: String,
11 | default: Date().toString().substring(0, 15),
12 | },
13 | data: {
14 | type: Map,
15 | required: true,
16 | default: {},
17 | },
18 | details: {
19 | type: Map,
20 | required: true,
21 | default: {},
22 | },
23 | },
24 | {
25 | timestamps: true,
26 | }
27 | );
28 |
29 | const Attendance = mongoose.model("Attendance", attendanceSchema);
30 |
31 | export default Attendance;
32 |
--------------------------------------------------------------------------------
/server/models/student.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose";
2 |
3 | const studentSchema = mongoose.Schema(
4 | {
5 | name: {
6 | type: String,
7 | required: true,
8 | },
9 | address: {
10 | type: String,
11 | required: true,
12 | },
13 | category: {
14 | type: String,
15 | required: true,
16 | },
17 | city: {
18 | type: String,
19 | required: true,
20 | },
21 | contact: {
22 | type: Number,
23 | required: true,
24 | },
25 | fatherContact: {
26 | type: Number,
27 | required: true,
28 | },
29 | image: {
30 | type: String,
31 | required: true,
32 | },
33 | roomNo: {
34 | type: String,
35 | required: true,
36 | },
37 | blockNo: {
38 | type: String,
39 | required: true,
40 | },
41 | status: {
42 | type: String,
43 | required: true,
44 | },
45 | },
46 | {
47 | timestamps: true,
48 | }
49 | );
50 |
51 | const Student = mongoose.model("Student", studentSchema);
52 |
53 | export default Student;
54 |
--------------------------------------------------------------------------------
/server/models/user.js:
--------------------------------------------------------------------------------
1 | import mongoose from "mongoose";
2 | import bcrypt from "bcryptjs";
3 |
4 | const userSchema = mongoose.Schema(
5 | {
6 | name: {
7 | type: String,
8 | required: true,
9 | },
10 | email: {
11 | type: String,
12 | required: true,
13 | unique: true,
14 | },
15 | password: {
16 | type: String,
17 | required: true,
18 | },
19 | isAdmin: {
20 | type: Boolean,
21 | required: true,
22 | default: false,
23 | },
24 | },
25 | {
26 | timestamps: true,
27 | }
28 | );
29 |
30 | userSchema.methods.matchPassword = async function (enteredPassword) {
31 | return await bcrypt.compare(enteredPassword, this.password);
32 | };
33 |
34 | userSchema.pre("save", async function (next) {
35 | if (!this.isModified("password")) {
36 | next();
37 | }
38 |
39 | const salt = await bcrypt.genSalt(10);
40 | this.password = await bcrypt.hash(this.password, salt);
41 | });
42 |
43 | const User = mongoose.model("User", userSchema);
44 |
45 | export default User;
46 |
--------------------------------------------------------------------------------
/server/routes/attendanceRoutes.js:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import {
3 | deleteAttendanceByDays,
4 | enterAttendanceByRoomNo,
5 | getAttendance,
6 | getAttendanceByRoomNo,
7 | } from "../controllers/attendanceController.js";
8 | import { protect, admin } from "../middleware/authMiddleware.js";
9 | const router = express.Router();
10 | router.route("/:roomId").get(protect, getAttendanceByRoomNo);
11 | router.route("/").post(protect, admin, enterAttendanceByRoomNo);
12 | router.route("/:days").delete(protect, admin, deleteAttendanceByDays);
13 | router.route("/getAnalysis").post(protect, getAttendance);
14 |
15 | export default router;
16 |
--------------------------------------------------------------------------------
/server/routes/studentRoutes.js:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import {
3 | addStudent,
4 | deleteStudent,
5 | getAllStudents,
6 | getStudentById,
7 | updateStudentProfile,
8 | getStudentByRoomNo,
9 | } from "../controllers/studentController.js";
10 | import { protect, admin } from "../middleware/authMiddleware.js";
11 |
12 | const router = express.Router();
13 | router.route("/all").get(protect, getAllStudents);
14 | router.route("/addStudent").post(protect, admin, addStudent);
15 | router
16 | .route("/:id")
17 | .get(protect, getStudentById)
18 | .delete(protect, admin, deleteStudent)
19 | .put(protect, admin, updateStudentProfile);
20 | router.route("/room/:roomId").get(getStudentByRoomNo);
21 | export default router;
22 |
--------------------------------------------------------------------------------
/server/routes/userRoutes.js:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | const router = express.Router();
3 | import {
4 | authUser,
5 | registerUser,
6 | getUserProfile,
7 | updateUserProfile,
8 | getUsers,
9 | deleteUser,
10 | getUserById,
11 | updateUser,
12 | } from "../controllers/userController.js";
13 | import { protect, admin } from "../middleware/authMiddleware.js";
14 |
15 | router.route("/").post(registerUser).get(protect, admin, getUsers);
16 | router.post("/login", authUser);
17 | router
18 | .route("/profile")
19 | .get(protect, getUserProfile)
20 | .put(protect, updateUserProfile);
21 | router
22 | .route("/:id")
23 | .delete(protect, admin, deleteUser)
24 | .get(protect, admin, getUserById)
25 | .put(protect, admin, updateUser);
26 |
27 | export default router;
28 |
--------------------------------------------------------------------------------
/server/seeder.js:
--------------------------------------------------------------------------------
1 | import dotenv from "dotenv";
2 | import students from "./data/students.js";
3 | import Student from "./models/student.js";
4 |
5 | import connectDB from "./config/db.js";
6 |
7 | dotenv.config();
8 |
9 | connectDB();
10 |
11 | const importData = async () => {
12 | try {
13 | await Student.deleteMany();
14 | console.log("Data Imported!");
15 | process.exit();
16 | } catch (error) {
17 | console.error(`${error}`);
18 | process.exit(1);
19 | }
20 | };
21 |
22 | const destroyData = async () => {
23 | try {
24 | await Student.deleteMany();
25 | console.log("Data Destroyed!");
26 | process.exit();
27 | } catch (error) {
28 | console.error(`${error}`);
29 | process.exit(1);
30 | }
31 | };
32 |
33 | if (process.argv[2] === "-d") {
34 | destroyData();
35 | } else {
36 | importData();
37 | }
38 |
--------------------------------------------------------------------------------
/server/utils/generateToken.js:
--------------------------------------------------------------------------------
1 | import jwt from 'jsonwebtoken'
2 |
3 | const generateToken = (id) => {
4 | return jwt.sign({ id }, process.env.JWT_SECRET, {
5 | expiresIn: '30d',
6 | })
7 | }
8 |
9 | export default generateToken
10 |
--------------------------------------------------------------------------------