An Online Learning web-based system through which individuals can attend and learn pre-recorded courses online. This application was implemented using the MERN stack.
This project was developed for the GUC's CSEN704 Advanced Computer Lab. The lab is a project-based course that aims to teach students:
- Scrum and Agile methodologies
- Software development best practices
- Software development tools and techniques
- Software development process
- Software Testing
- Latest backend and frontend technologies
And since Web Development is a crucial part in our current era, this course gave us the perfect opportunity to explore Node.js, React, CSS and JavaScript all in one go. It also pushed us to challenge ourselves since our main goal from the start was to provide the user with the ultimate online experience.
- All user requirements are met and fulfilled, but more testing is needed to ensure the best service and UX.
- This project is currently a work-in-progress.
- Unit tests will be added in the next roll-out.
- Feedback and error handling is currently in development for a better UI/UX experience.
We used the standardised JavaScript coding style conventions to improve the overall readability and maintainability of our code. Moreover, this gives a uniform appearance to the code and makes it as clean and easy to read as possible. A semicolon is present after each statement. All functions are declared above the code that uses them. We also used naming conventions for local variables. We named the local variables using camelCase lettering starting with small letter.
The architecture for the features is MVC (Model View Controller).
We used camelCase for variables to be more consistent.
Codes are formatted in VS Code using the
Alt + Shift + Fcommand.
- Login page:
- Signup page:
- About page:
- Home page:
- Instructor Lobby:
- Add course:
- Report Page:
- Payment Page for Trainee:
In Back-end
NodeJS
Nodemailer
MongoDB
Mongoose
Express
Bcrypt
Body-parser
Cors
Dotenv
Fs
Html-pdf
Https
Jsonwebtoken
Nodejs-nodemailer-outlook
Nodemon
Passport
Passport-jwt
Randomstring
Validator
In Front-end
ReactJS
Material UI
Axios
Bcrypt
Dateformat
File-saver
Jsonwebtoken
Http
Jspdf
Jwt-decode
The system serves different type of users (Admins, Instructors, Individual Trainees and Corporate Trainees)
As a Guest, you can
View all courses, search and filter courses by price, rating or subject and view their description.
Signup.
Login.
Request forget password email to recover password.
As a Trainee, you can
View all courses.
Search and filter courses by price, rating or subject and view their description.
Purchase courses.
View course videos.
Solve exercises.
Request refund for course.
Solve exam exercises.
Report a problem whether it is technical, financial or other.
Rate courses and instructors.
View their balance.
Add/remove credit cards.
Download a completion certificate when completing a course.
Write course notes and download them.
View all reports and their status.
Edit his email or password.
Follow up on unresolved issue.
View his profile.
As a Corporate Trainee, you can
View all courses.
Search and filter courses by rating or subject and view their description.
Request to access a course.
View course videos.
Solve exercises.
Solve exam exercises.
Report a problem whether it is technical, financial or other.
Rate a courses and instructors.
Write course notes and download them.
Download a completion certificate when completing a course.
View all reports and their status.
Edit his email or password.
Follow up on unresolved issue.
View his profile.
As an Instructor, you can
Create a new course and add all it's information.
Set promotion for a specific course.
View all his/her ratings and reviews.
View all ratings and reviews about his/her courses.
Report a problem whether it is technical, financial or other.
View all reports and their status.
Edit his biography or email or password.
Search and filter courses by price, rating or subject and view their description.
Search and filter his courses by price, rating or subject and view their description.
Follow up on unresolved issue.
View his profile.
Receive a monthly income whenever someone enrolls in one of his/her courses.
As an Admin, you can
Add corporate trainees and set their usernames and passwords.
Add instructors and set their usernames and passwords.
View reported problems and can add comments and set report status.
Grant access to refund requests by trainees.
Grant access to course requests by corporate trainees.
Set promotion for one or more than one course.
Add another admin and set their usernames and passwords.
View follow ups on unresolved issues.
Search and filter courses by price, rating or subject and view their description.
constupdateCertificateState=async(req,res)=>{const{ courseId }=req.body;try{constid=mongoose.Types.ObjectId(req.params.id);constdbResp=awaitTrainee.findOneAndUpdate({"_id": id,'courses.courseId': courseId},{'$set': {'courses.$.receivedCertificate': true}});if(dbResp){res.status(201).json("Successfull update!!");}else{res.status(400).json({message: 'Not able to update'});}}catch(error){res.status(500).json({message: error.message});}}constsendPDF=(toEmail,body)=>{nodeoutlook.sendEmail({auth: {user: process.env.SENDER_EMAIL,pass: process.env.SENDER_PASSWORD},from: process.env.SENDER_EMAIL,to: toEmail,subject: 'Certificate of completion',text: body,attachments: [{filename: 'certificate.pdf',path: '../backend/Controllers/Documents/certificate.pdf',contentType: 'application/pdf'}],onError: (e)=>console.log(e),onSuccess: (i)=>console.log(i)});};exportconstAddProfile=(form,setShow,setMessage)=>dispatch=>{axios.post("/api/profiles",form).then(res=>{setShow(true)setMessage("User added with success")dispatch({type: ERRORS,payload: {}})setTimeout(()=>{setShow(false)},4000);}).catch(err=>{dispatch({type: ERRORS,payload: err.response.data})});}consthandlePromotion=(e)=>{varupdatedCourseList=[...checkedCourses];letcurrent=courses.filter((item)=>newKeys.some((key)=>item[key].toString().toLowerCase().includes(e.target.value.toString().toLowerCase())));if(e.target.checked){updatedCourseList=[...checkedCourses].concat(current);}else{console.log(updatedCourseList.length);for(leti=0;i<updatedCourseList.length;i++){if(updatedCourseList[i]["_id"]===e.target.value){console.log(updatedCourseList[i]["_id"]+" at "+i);updatedCourseList.splice(i,1);i--;}}}setCheckedCourses(updatedCourseList);};consthandleSubmit=(e)=>{console.log(checkedCard);e.preventDefault();//prevent form submissionif(checkedCard===null){setNoCreditCard("You need to enter select a payment method.");}elseif(checkedCard==="balance"&&!purchased){if(trainee.balance>=course.price){registerCourse();letfinalPrice=course.price*-1;updateBalance(finalPrice);updateInstructorBalance(-1*finalPrice);setPurchased(true);}else{setHtml2(`You dont have enought money in the balance!`);}}elseif(checkedCard!=="balance"&&checkedCard!==null&&!purchased){checkExpiryDate(checkedCard);}else{setHtml("You already bought the course");}};constpostComment=async()=>{constbody={ instructorComment };constresponse=awaitfetch(`/report/instructorpostcomment/${reportId}`,{method: "POST",body: JSON.stringify(body),headers: {"Access-Control-Allow-Origin": "*","Content-Type": "application/json",},});constjson=awaitresponse.json();if(response.ok){window.location.reload();}};constperformIntersection=(arr1,arr2,arr3,arr4)=>{constintersectionResult1=arr1.filter((x)=>arr2.indexOf(x)!==-1);constintersectionResult2=intersectionResult1.filter((x)=>arr3.indexOf(x)!==-1);constintersectionResult3=intersectionResult2.filter((x)=>arr4.indexOf(x)!==-1);if(arr4.length===0){returnintersectionResult2;}else{returnintersectionResult3;}};<BoxclassName="card-border"><BoxclassName='wallet-div'><Buttonvariant="contained" onClick={handleClick}><Walletsx={{marginRight:"2px"}}/>Wallet</Button><p>{balanceHtml}</p></Box><h4>The information of course: {course.courseTitle} </h4><Box><CheckRegistered/></Box><ReactPlayersandbox="allow-presentation" loop={false}className='react-player' url={course.coursePreview}width='20%' height='100%' controls={true}/><Box><strong>Course Subtitles: </strong> {course.subtitles && course.subtitles.map((subtitle) => (
<Box><p>{subtitle.subTitle}</p><p>Description:{subtitle.description}</p><p>Total Hours of the Chapter: {subtitle.hours}</p></Box>
))}</Box><p><strong>Price: </strong>{Math.ceil(course.price * rateVal)}{" "}{currencyVal}</p><p><strong>Instructor of the course: </strong>{instructorName}</p><p><strong>Total Hours of the course: </strong>{course.totalHours} Hours</p><Box><strong>Course Exercises: </strong> {course.courseExercises && course.courseExercises.map((exercise) => (
<Box><p>Question: {exercise.question}</p></Box>
))}</Box></Box>- Open two separate terminals.
- In the first terminal, go to the Backend folder and type the command:
npm icd backend && npm i
- In the second terminal, go to the Frontend folder and type the command:
npm icd frontend && npm i
Admin route:
GET all admins
Description: returns all admins in the database.
URL:
/adminParameters: None
Body: None
Response: Models.Admins
Authorization: Required. Bearer token of the Admin.
GET a specific admin with id
Description: returns a specific admin in the database.
URL:
/admin/:idParameters: Admin's id "id"
Body: None
Response: Models.Admin
Authorization: Required. Bearer token of the Admin.
PATCH a specific admin with id
Description: updates a specific admin in the database.
URL:
/admin/editadmin/:idParameters: Admin's id "id"
Body: { userName, password }
Response: Models.Admin
Authorization: Required. Bearer token of the Admin.
Trainee route:
GET all trainees
Description: returns all trainees in the database.
URL:
/traineeParameters: None
Body: None
Response: Models.Trainees
Authorization: Required. Bearer token of the Admin or Trainee.
GET a specific trainee
Description: returns a specific trainee in the database.
URL:
/trainee/:idParameters: Trainee's id "id"
Body: None
Response: Models.Trainee
Authorization: Required. Bearer token of the Admin or Trainee.
GET a trainee's courses
Description: returns all the registered courses for a specific trainee.
URL:
/trainee/getcourses/:idParameters: Trainee's id "id"
Body: None
Response: Models.Trainee.courses
Authorization: Required. Bearer token of the Trainee.
POST a course registeration
Description: Allow Trainee to register in a course.
URL:
/trainee/register/:idParameters: Trainee's id "id"
Body: { courseId, courseGrade, courseProgress }
Response: { course }
Authorization: Required. Bearer token of the Trainee.
POST to find exercises grade.
Description: Allow Trainee to find his last exercises grade.
URL:
/trainee/findgrade/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { course.exercises.exercisesgrade }
Authorization: Required. Bearer token of the Trainee.
POST to find exam grade.
Description: Allow Trainee to find his exam grade.
URL:
/trainee/findtestgrade/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { course.exercises.examgrade }
Authorization: Required. Bearer token of the Trainee.
POST a new credit-card.
Description: Allow Trainee to add a new credit-card.
URL:
/trainee/addcredit/:idParameters: Trainee's id "id"
Body: { cardName, cardNumber, cardExpiryDate, cardCVV }
Response: { newCreditCard }
Authorization: Required. Bearer token of the Trainee.
POST to check if registered in course.
Description: Find out if a trainee is enrolled in a course or not.
URL:
/trainee/checkregister/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { true } or { false }
Authorization: Required. Bearer token of the Trainee.
POST to change balance.
Description: Update trainee's balance.
URL:
/trainee/updatebalance/:idParameters: Trainee's id "id"
Body: { balanceValue }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Trainee.
POST to change course progress.
Description: Update trainee's course progress.
URL:
/trainee/updateprogress/:idParameters: Trainee's id "id"
Body: { courseId, currentChapter, totalChapters }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Trainee.
POST to find course progress.
Description: Request to find out trainee's current course progress.
URL:
/trainee/courseprogress/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { course.courseProgress }
Authorization: Required. Bearer token of the Trainee.
POST to change exam status.
Description: Update trainee's exam status where he solved it or not.
URL:
/trainee/updateexamstatus/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Trainee.
POST to change exam grade.
Description: Update trainee's exam grade.
URL:
/trainee/updateexamgrade/:idParameters: Trainee's id "id"
Body: { courseId, examGrade}
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Trainee.
POST to change exercises grade.
Description: Update trainee's exercises grade.
URL:
/trainee/updateexercisesgrade/:idParameters: Trainee's id "id"
Body: { courseId, exercisesGrade }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Trainee.
POST to change exercises status.
Description: Update exercises status whether a trainee already solved the exercises or not.
URL:
/trainee/updateexercisesstatus/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Trainee.
POST to refund a course.
Description: Remove a course from a trainee's registered courses and return the money to his balance.
URL:
/trainee/refund/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { { message: "refund done successfully!" } }
Authorization: Required. Bearer token of the Admin or Trainee.
POST to find a specific credit card.
Description: Find a specific credit-card from a trainee's credit-card list.
URL:
/trainee/findcreditcard/:idParameters: Trainee's id "id"
Body: { creditCardId }
Response: { creditCard }
Authorization: Required. Bearer token of the Trainee.
POST to delete a specific credit card.
Description: Delete a specific credit-card from a trainee's credit-card list.
URL:
/trainee/deletecard/:idParameters: Trainee's id "id"
Body: { creditCardId }
Response: { { message: "credit card removed done successfully!" } }
Authorization: Required. Bearer token of the Trainee.
POST a new course note.
Description: Let a trainee add a new note to the list of notes for a course.
URL:
/trainee/postnote/:idParameters: Trainee's id "id"
Body: { courseId, note }
Response: { newNote }
Authorization: Required. Bearer token of the Trainee.
POST to get all course notes.
Description: Let a trainee get all course notes for a specific course.
URL:
/trainee/getnotes/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { notes }
Authorization: Required. Bearer token of the Trainee.
POST to send an email to a trainee with completion certificate.
Description: Send a completion certificate to a trainee's email.
URL:
/trainee/emailpdf/:idParameters: Trainee's id "id"
Body: { email, courseName }
Response: { { message: "sent successfully" } }
Authorization: Required. Bearer token of the Trainee.
POST to find certificate state.
Description: Find the certificate state of trainee whether he recieved his certificate or not in a specific course.
URL:
/trainee/checkcertstate/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { true } or { false }
Authorization: Required. Bearer token of the Trainee.
POST to find exercises status.
Description: Request to find out if a trainee solved exercises or not.
URL:
/trainee/checkexstatus/:idParameters: trainee's id "id"
Body: { courseId }
Response: { true } or { false }
Authorization: Required. Bearer token of the Trainee.
POST to update certificate state.
Description: Update the certificate state of trainee whether he recieved his certificate or not in a specific course.
URL:
/trainee/updatecertstate/:idParameters: Trainee's id "id"
Body: { courseId }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Trainee.
POST to find exam status.
Description: Request to find out if a trainee solved exam or not.
URL:
/trainee/checkstatus/:idParameters: trainee's id "id"
Body: { courseId }
Response: { true } or { false }
Authorization: Required. Bearer token of the Trainee.
POST to create a new certificate.
Description: Create a completion certificate for a specific course for a trainee.
URL:
/trainee/createpdfParameters: None
Body: { name, courseTitle } , NOTE: name here is trainee's name.
Response: { res.pdfDirectory }
Authorization: Required. Bearer token of the Trainee.
GET a course's completion certificate.
Description: Return a completion certificate for a specific course for a trainee.
URL:
/trainee/cert/getpdfParameters: None
Body: None
Response: { success! }
Authorization: Required. Bearer token of the Trainee.
Instructor route :
GET all instructors info
Description: returns all instructors in the database.
URL:
/instructorParameters: None
Body: None
Response: { Models.Instructor }
Authorization: Required. Bearer token of the Instructor, Admin.
GET a specific instructor
Description: returns a specific instructor in the database.
URL:
/instructor/:idParameters: Instructor's id "id"
Body: None
Response: { Models.Instructor }
Authorization: Required. Bearer token of the Instructor, Trainee, Corprate Trainee.
DELETE a specific instructor
Description: delete an instructor from the database.
URL:
/instructor/:idParameters: Instructor's id "id"
Body: None
Response: { Models.Instructor }
Authorization: Required. Bearer token of the Instructor, Admin.
PATCH a specific instructor's info
Description: Update instructor's info in the database.
URL:
/instructor/changeInfo/:idParameters: Instructor's id "id"
Body: { email, bio, password, verified }
Response: { Models.Instructor }
Authorization: Required. Bearer token of the Instructor.
POST an instructor's review
Description: Create new review for an instructor in the database.
URL:
/instructor/review/:idParameters: Id of user doing the review "id"
Body: { iRating, iReview, traineeId, corpTraineeId }
Response: { Models.Instructor.newReview }
Authorization: Required. Bearer token of the Instructor, Trainee, Corprate Trainee.
Course route:
GET all courses
Description: returns all courses in the database.
URL:
/courseParameters: None
Body: None
Response: { Models.Course }
Authorization: None
GET a specific course
Description: returns a specific COurse in the database.
URL:
/course/:idParameters: Course's id "id"
Body: None
Response: { Models.Course }
Authorization: None
GET a single Course's rating
Description: returns the rating of a specific course.
URL:
/course/rating/:idParameters: Course's id "id"
Body: None
Response: { Models.Instructor.courses }
Authorization: None
Get a subset of courses using a subset of ids
Description: returns all the 3 highest viewed courses.
URL:
/course/highest/viewsParameters: None
Body: None
Response: { Models.courses }
Authorization: None
GET All Course Subjects
Description: returns all subjects of the registered courses in the database.
URL:
/course/get/coursesubjectsParameters: None
Body: None
Response: { courseSubjects }
Authorization: None
GET a single Course's rating
Description: Allow Trainee to add a new credit-card.
URL:
/course/rating/:idParameters: Trainee's id "id"
Body: None
Response:
json { "Course Rating is: " + currentOverallRating }Authorization: None
GET max price
Description: return the most expensive course in the database.
URL:
/course/maxParameters: None
Body: None
Response: { Models.course[0].price }
Authorization: None
GET Some courses
Description: return all info of some courses.
URL:
/course/subsetParameters: None
Body: { ids }
Response: { courses }
Authorization: None
POST a new Course
Description: create new course in the database.
URL:
/course/addParameters: None
Body: { courseTitle, subtitles, price, shortSummary, subject, totalHours, instructor, instructorName, courseExercises, exam, coursePreview }
Response:
json { message: "Course added successfully", message: "Course info" + course }Authorization: None
POST a new course's Review
Description: Create new review for a course in the database.
URL:
/course/review/:idParameters: Id of user doing the review "id"
Body: { cRating, cReview, traineeId, corpTraineeId }
Response: { Models.course.newReview }
Authorization: None
POST Course's Promotion
Description: Create a promotion on a course in the database.
URL:
/course/promo/:idParameters: Course's id "id"
Body: { promotionStartDate, promotionEndDate, promotionRate }
Response: { message: "updated successfully!" }
Authorization: None
POST Promo on several courses
Description: Request to add promotions on several courses.
URL:
/course/coursespostpromotionParameters: None
Body: { ids, promotionStartDate, promotionEndDate, promotionRate }
Response: { message: "Promotion Added successfully." }
Authorization: None
DELETE a course's info
Description: Delete a course's info from the database.
URL:
/course/:idParameters: Course's id "id"
Body: { courseId }
Response: { Models.course }
Authorization: None
PATCH a course's info
Description: Update a course's info in the database.
URL:
/course/:idParameters: Course's id "id"
Body: { courseId }
Response: { Models.course }
Authorization: None
PATCH a course's promotion
Description: Update a promotion on a course in the database.
URL:
/course/updatepromo/:idParameters: Course's id "id"
Body: None
Response: { message: "rate updated succesfully", message: "course info" + course }
Authorization: None
PATCH the views for a course
Description: Update the views for a course in the database.
URL:
/course/updateview/:idParameters: Course's id "id"
Body: None
Response: { Models.course }
Authorization: None
Corporate Trainee route:
GET all corporate trainees
Description: returns all corporate trainees in the database.
URL:
/corptraineeParameters: None
Body: None
Response: Models.corpTrainees
Authorization: Required. Bearer token of the Admin or Corporate Trainee.
GET a specific corporate trainee
Description: returns a specific corporate trainee in the database.
URL:
/corptrainee/:idParameters: Corporate Trainee's id "id"
Body: None
Response: Models.corpTrainee
Authorization: Required. Bearer token of the Admin or Corporate Trainee.
GET a corporate trainee's courses
Description: returns all the registered courses for a specific corporate trainee.
URL:
/corptrainee/getcourses/:idParameters: Corporate Trainee's id "id"
Body: None
Response: Models.corpTrainee.courses
Authorization: Required. Bearer token of the Corporate Trainee.
POST a course registeration
Description: Allow corporate trainee to register in a course.
URL:
/corptrainee/register/:idParameters: corporate trainee's id "id"
Body: { courseId, courseGrade, courseProgress }
Response: { course }
Authorization: Required. Bearer token of the Admin or Corporate Trainee.
POST to find exercises grade.
Description: Allow Corporate trainee to find his last exercises grade.
URL:
/corptrainee/findgrade/:idParameters: Corporate trainee's id "id"
Body: { courseId }
Response: { course.exercises.exercisesgrade }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to find exam grade.
Description: Allow Corporate Trainee to find his exam grade.
URL:
/corptrainee/findtestgrade/:idParameters: Corporate trainee's id "id"
Body: { courseId }
Response: { course.exercises.examgrade }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to check if corporate trainee has access to a specific course.
Description: Find out if a corporate trainee has access to a specific course or not.
URL:
/corptrainee/checkaccess/:idParameters: corporate trainee's id "id"
Body: { courseId }
Response: { true } or { false }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to change course progress.
Description: Update corporate trainee's course progress.
URL:
/corptrainee/updateprogress/:idParameters: corporate trainee's id "id"
Body: { courseId, currentChapter, totalChapters }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to find course progress.
Description: Request to find out corporate trainee's current course progress.
URL:
/corptrainee/courseprogress/:idParameters: corporate trainee's id "id"
Body: { courseId }
Response: { course.courseProgress }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to find exercises status.
Description: Request to find out if a corporate trainee solved exercises or not.
URL:
/corptrainee/checkexstatus/:idParameters: corporate trainee's id "id"
Body: { courseId }
Response: { true } or { false }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to find exam status.
Description: Request to find out if a corporate trainee solved exam or not.
URL:
/corptrainee/checkstatus/:idParameters: corporate trainee's id "id"
Body: { courseId }
Response: { true } or { false }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to change exam status.
Description: Update corporate trainee's exam status where he solved it or not.
URL:
/corptrainee/updateexamstatus/:idParameters: corporate trainee's id "id"
Body: { courseId }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to change exam grade.
Description: Update corporate trainee's exam grade.
URL:
/corptrainee/updateexamgrade/:idParameters: corporate trainee's id "id"
Body: { courseId, examGrade}
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to change exercises grade.
Description: Update corporate trainee's exercises grade.
URL:
/corptrainee/updateexercisesgrade/:idParameters: corporate trainee's id "id"
Body: { courseId, exercisesGrade }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to change exercises status.
Description: Update exercises status whether a corporate trainee already solved the exercises or not.
URL:
/corptrainee/updateexercisesstatus/:idParameters: corporate trainee's id "id"
Body: { courseId }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Corporate Trainee.
POST a new course note.
Description: Let a corporate trainee add a new note to the list of notes for a course.
URL:
/corptrainee/postnote/:idParameters: corporate trainee's id "id"
Body: { courseId, note }
Response: { newNote }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to get all course notes.
Description: Let a corporate trainee get all course notes for a specific course.
URL:
/corptrainee/getnotes/:idParameters: corporate trainee's id "id"
Body: { courseId }
Response: { notes }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to send an email to a corporate trainee with completion certificate.
Description: Send a completion certificate to a corporate trainee's email.
URL:
/corptrainee/emailpdf/:idParameters: corporate trainee's id "id"
Body: { email, courseName }
Response: { { message: "sent successfully" } }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to find certificate state.
Description: Find the certificate state of corporate trainee whether he recieved his certificate or not in a specific course.
URL:
/corptrainee/checkcertstate/:idParameters: corporate trainee's id "id"
Body: { courseId }
Response: { true } or { false }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to update certificate state.
Description: Update the certificate state of corporate trainee whether he recieved his certificate or not in a specific course.
URL:
/corptrainee/updatecertstate/:idParameters: corporate trainee's id "id"
Body: { courseId }
Response: { "Successfull update!!" }
Authorization: Required. Bearer token of the Corporate Trainee.
POST to create a new certificate.
Description: Create a completion certificate for a specific course for a corporate trainee.
URL:
/corptrainee/createpdfParameters: None
Body: { name, courseTitle } , NOTE: name here is trainee's name.
Response: { res.pdfDirectory }
Authorization: Required. Bearer token of the Corporate Trainee.
GET a course's completion certificate.
Description: Return a completion certificate for a specific course for a corporate trainee.
URL:
/corptrainee/cert/getpdfParameters: None
Body: None
Response: { success! }
Authorization: Required. Bearer token of the Corporate Trainee.
Guest route:
POST a signup.
Description: Create a new trainee in the database with the hashed password and his information.
URL:
/guest/signupParameters: None
Body: {userName, firstName, lastName, email, gender, role, password, confirm}
Response: { success }
Authorization: None.
POST a Login.
Description: Login in the website as a trainee or instructor or admin or corporate trainee.
URL:
/guest/loginParameters: None
Body: { userName, password }
Response: { success }
Authorization: None.
POST a new Admin.
Description: Create a new admin.
URL:
/guest/create/adminParameters: None
Body: { firstName, lastName,userName,email,role,gender,password,confirm }
Response: { success }
Authorization: None.
POST a new instructor.
Description: Create a new instructor.
URL:
/guest/create/instructorParameters: None
Body: { firstName, lastName,userName,country,phoneNumber,address,email,role,gender,bio,password,confirm }
Response: { success }
Authorization: None.
POST a new corporate trainee.
Description: Create a new corporate trainee.
URL:
/guest/create/corptraineeParameters: None
Body: { firstName, lastName,userName,country,phoneNumber,address,email,role,gender,password,confirm }
Response: { success }
Authorization: None.
POST a forget password request.
Description: Send an email to a user's email to change password.
URL:
/guest/forgotpasswordParameters: None
Body: { email }
Response: { success }
Authorization: None.
POST a new password.
Description: Change the password to a new password for any type of user.
URL:
/guest/changepasswordParameters: None
Body: { id,password }
Response: { success }
Authorization: None.
Report route:
GET a specific report.
Description: Find a specific report using a report ID.
URL:
/report/request/:idParameters: report's id "id"
Body: None
Response: { Models.report }
Authorization: None.
GET refund reports.
Description: GET all refund reports.
URL:
/report/requests/refundParameters: None
Body: None
Response: { Models.refundReports }
Authorization: None.
GET access reports.
Description: GET all access reports.
URL:
/report/requests/accessParameters: None
Body: None
Response: { Models.accessReports }
Authorization: None.
GET reported course problems for a corporate trainee.
Description: GET all reported course problems for a corporate trainee.
URL:
/report/request/getcoursereportscorp/:idParameters: corporate trainee's id "id"
Body: None
Response: { Models.reportedProblems }
Authorization: None.
GET reported course problems for an instructor.
Description: GET all reported course problems for an instructor.
URL:
/report/request/getcoursereportsinst/:idParameters: instructor's id "id"
Body: None
Response: { Models.reportedProblems }
Authorization: None.
GET reported course problems for a trainee.
Description: GET all reported course problems for a trainee.
URL:
/report/request/getcoursereportstrainee/:idParameters: trainee's id "id"
Body: None
Response: { Models.reportedProblems }
Authorization: None.
GET unresolved reports for corporate trainee.
Description: GET all unresolved reports for a specific corporate trainee.
URL:
/report/request/getcorptraineeunresolved/:idParameters: corporate trainee's id "id"
Body: None
Response: { Models.unresolvedReports }
Authorization: None.
GET resolved reports for corporate trainee.
Description: GET all resolved reports for a specific corporate trainee.
URL:
/report/request/getcorptraineeresolved/:idParameters: corporate trainee's id "id"
Body: None
Response: { Models.resolvedReports }
Authorization: None.
GET unresolved reports for trainee.
Description: GET all unresolved reports for a specific trainee.
URL:
/report/request/gettraineeunresolved/:idParameters: trainee's id "id"
Body: None
Response: { Models.unresolvedReports }
Authorization: None.
GET resolved reports for trainee.
Description: GET all resolved reports for a specific trainee.
URL:
/report/request/gettraineeresolved/:idParameters: trainee's id "id"
Body: None
Response: { Models.resolvedReports }
Authorization: None.
GET unresolved reports for instructor.
Description: GET all unresolved reports for a specific instructor.
URL:
/report/request/getinstructorunresolved/:idParameters: instructor's id "id"
Body: None
Response: { Models.unresolvedReports }
Authorization: None.
GET resolved reports for instructor.
Description: GET all resolved reports for a specific instructor.
URL:
/report/request/getinstructorresolved/:idParameters: instructor's id "id"
Body: None
Response: { Models.resolvedReports }
Authorization: None.
GET all reports.
Description: GET all reports whether resolved or unresolved.
URL:
/report/requests/allproblemsParameters: None.
Body: None
Response: { Models.reports }
Authorization: None.
PATCH a specific report.
Description: Find and update a specific report.
URL:
/report/request/updaterequest/:idParameters: report's id "id".
Body: { courseProgress, refundAmount, requestType, reportStatus, adminComment}
Response: { Models.report }
Authorization: None.
DELETE a specific report.
Description: Find and delete a specific report.
URL:
/report/request/deleterequest/:idParameters: report's id "id".
Body: None
Response: { Models.report }
Authorization: None.
POST a new report.
Description: Create a new report with all necessary fields.
URL:
/report/request/postrequestParameters: None
Body: { traineeId, corpTraineeId, instructorId, courseId, courseProgress, refundAmount, requestType, reportStatus, adminComment }
Response: { Models.report._id }
Authorization: None.
POST a new comment as a trainee.
Description: Add a new comment to the list of comments in a specific problem by a trainee.
URL:
/report/request/traineepostcomment/:idParameters: report's id "id"
Body: { traineeComment }
Response: { newComment }
Authorization: None.
POST a new comment as a corporate trainee.
Description: Add a new comment to the list of comments in a specific problem by a corporate trainee.
URL:
/report/request/corptraineepostcomment/:idParameters: report's id "id"
Body: { corpTraineeComment }
Response: { newComment }
Authorization: None.
POST a new comment as a instructor.
Description: Add a new comment to the list of comments in a specific problem by a instructor.
URL:
/report/request/instructorpostcomment/:idParameters: report's id "id"
Body: { instructorComment }
Response: { newComment }
Authorization: None.
Testing was done using jest. To run the tests, run the following command:
> npm run testAlso, tests can be done using Postman on any route.
To run backend
cd backend && node App.jsTo run frontend
cd frontend && npm run start*The backend server and frontend will be running on the specified ports in your .env file.
Any contributions to our code is welcomed. You can always improve the frontend for a better UX.
- Our team "RADS" did a tremendous work in order to fullfill this project on time. Special thanks to our Scrum Master, Ahmed Khaled @Ahmed Khaled, for being always there for support and for managing our team smoothly:
- Khaled Ayman @Khaled Ayman
- Ali Elserafy @Ali Serafy
- Hassan Haridy @Hassan Haridy
- Misk Mohamed @Misk Abdullah
- Links that helped us alot:
MIT License
Copyright (c) [2023] [Ahmed Khaled]
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

