Skip to content

A MERN stack web application through which individuals can attend pre-recorded courses online.

License

Notifications You must be signed in to change notification settings

Abdullah204/Agiles

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

License

Canadian Chamber Of Commerce

landing page

Table of Contents

Project Description

Title

Canadian Chamber Of Commerce

Course

Advanced Computer Lab (CSEN 704), Winter 2022

Theme

The theme of the project, is to create a complete Online Learning System. An Online Learning System is a web application through which individuals can attend pre-recorded courses online. Existing web applications include but are not limited to Coursera, Udemy, LinkedIn Learning, Great Learning and Udacity.

Overview

This project followed the Agile Methodology; meaning it was splited into Sprints, with each Sprint lasting a set amount of time and a fully functioning version of the project with the specified System Requirements should be submitted and evaluated.

Objectives

  • Learn how to properly use the Agile Methodology to plan out a project and develop the software.
  • Learn the process of following a given set of System Requirements to develop a software.
  • Learn to research and master the use of the MERN Stack.
  • Learn how to work together as a team on GitHub.

Motivation

The project is done as a group for a german university course (Advanced Computer lab) and This project is done as a simulation to real company working flow where all team members contribuite together for a final project. which motivated us to put our efforts on a project where we can learn new technologies along side with implementing them on a real application .We make an online courses website to encourage people to develop their skills and make this process easy by learning from home.

Code Styles

The project is formatted using prettier also The project follows the MVC design pattern ,MVC is a software architectural pattern commonly used for developing user interfaces that divide the related program logic into three interconnected elements. This is done to separate internal representations of information from the ways information is presented to and accepted from the user , So the Files in the backend was divided into the M (models) where the schema of the models exist which represent the core of the database , the C (controller) where the functions needed for the routes exists and the V (views) the view in MERN stack is represented by the react frontend server. Also the routes in our project was abstracted from the controller function as shown in API References

Tools and Frameworks

MERN_STACK

What is the MERN Stack?

MERN stands for MongoDB, Express, React, Node, after the four key technologies that make up the stack.

  • MongoDB - document database
  • Express(.js) - Node.js web framework
  • React(.js) - a client-side JavaScript framework
  • Node(.js) - the premier JavaScript web server

Express and Node make up the middle (application) tier. Express.js is a server-side web framework, and Node.js the popular and powerful JavaScript server platform. Regardless of which variant you choose, ME(RVA)N is the ideal approach to working with JavaScript and JSON, all the way through.

How does the MERN stack work?

The MERN architecture allows you to easily construct a 3-tier architecture (frontend, backend, database) entirely using JavaScript and JSON.

MERN_ARCH

- React.js Front End

The top tier of the MERN stack is React.js, the declarative JavaScript framework for creating dynamic client-side applications in HTML. React lets you build up complex interfaces through simple Components, connect them to data on your backend server, and render them as HTML.

React’s strong suit is handling stateful, data-driven interfaces with minimal code and minimal pain, and it has all the bells and whistles you’d expect from a modern web framework: great support for forms, error handling, events, lists, and more.

- Express.js and Node.js Server Tier

The next level down is the Express.js server-side framework, running inside a Node.js server. Express.js bills itself as a “fast, unopinionated, minimalist web framework for Node.js,” and that is indeed exactly what it is. Express.js has powerful models for URL routing (matching an incoming URL with a server function), and handling HTTP requests and responses.

By making XML HTTP Requests (XHRs) or GETs or POSTs from your React.js front-end, you can connect to Express.js functions that power your application. Those functions in turn use MongoDB’s Node.js drivers, either via callbacks for using Promises, to access and update data in your MongoDB database.

- MongoDB Database Tier

If your application stores any data (user profiles, content, comments, uploads, events, etc.), then you’re going to want a database that’s just as easy to work with as React, Express, and Node.

That’s where MongoDB comes in: JSON documents created in your React.js front end can be sent to the Express.js server, where they can be processed and (assuming they’re valid) stored directly in MongoDB for later retrieval. Again, if you’re building in the cloud, you’ll want to look at Atlas. If you’re looking to set up your own MERN stack, read on!

Build Status

  • The project currently under development and there are some styling problems to be fixed
  • jest tests to be added

Code Examples

const signUp = async (req, res) => {
  const { username, email, password, firstname, lastname } = req.body;
  if (!username || !password || !email || !password || !firstname || !lastname)
    return res.status(400).json({ msg: "bad request" });
  const userTrainee = await IndividualTrainee.findOne({ username: username });
  const userInstructor = await Instructor.findOne({ username: username });
  if (userTrainee || userInstructor) {
    return res.status(409).json({ msg: "username already exists" });
  } else {
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(password, salt);
    const newUser = new IndividualTrainee({
      username: username,
      password: hashedPassword,
      state: false,
      email: email,
      firstname: firstname,
      lastname: lastname,
    });
    try {
      const user = await IndividualTrainee.create(newUser);
      res.status(200).json({ msg: "signup successeded" });
    } catch (error) {
      res.status(400).json({ error: error.message });
    }
  }
};
          <section className={style["left"]}>
            <h1>Checkout</h1>
            <section className={style["payment-method"]}>
              <h2>Payment method</h2>
              <div className={style["payment-method-container"]}>
                <ListGroup>
                  <ListGroup.Item className={style["listGroup"]}>
                    <input
                      type="radio"
                      id="creditCard"
                      name="wallet"
                      defaultChecked={true}
                      onChange={() => setSelected("creditcard")}
                      className={style["radio"]}
                    ></input>
                    <CreditCardIcon />
                    <label className={style["header"]}>Credit/Debit Card</label>
                  </ListGroup.Item>
                  <ListGroup.Item className={style["listGroup"]}>
                    <input
                      type="radio"
                      id="wallet"
                      name="wallet"
                      onChange={() => setSelected("wallet")}
                      defaultChecked={false}
                      className={style["radio"]}
                    ></input>
                    <DataSaverOffIcon />
                    <label className={style["header"]}> Wallet</label>
                    {wallet < price - (price * discount) / 100 && (
                      <label className={style["error"]}>
                        sorry you don't have enough amount
                      </label>
                    )}
                    {wallet >= price - (price * discount) / 100 && (
                      <label className={style["success"]}>
                        current amount : {wallet.toFixed(2)} USD
                      </label>
                    )}
                  </ListGroup.Item>
                </ListGroup>
              </div>
            </section>
          </section>
const isAuthTrainee = async(req,res)=>{
    const token = req.cookies['jwt'];
    if (!token) return res.status(401).json({msg:"Unauthorized"});
     jwt.verify(
       token,
       process.env.ACCESS_TOKEN_SECRET_ITRAINEE,
       (err, decoded) => {
         if (err) return res.status(401).json({msg:"Unauthorized"});
         else{res.status(200).json({msg:"Authorized"});}
       }
     );
 }

Features

We have four main users in our website:

Features common for all users except guest:

  • Log in using his email and password.

log in

  • Log out from the website

image

Administrator

  • Add another admin to the website.

add admin

  • Add corporate trainee to the website.

add corporate trainee

  • Add instructor to the website.

Add instructor

  • View the reports and solve it.

solve problems

  • View the courses enroll requests and all the details of the request

Enroll request

  • View refund requests and approved them or not

refund requests

  • Add promotions to any course in the website and specify the percent of discount and the end time of the discount

add promotions

Guest

  • Sign Up for the webiste

image

Corporate Trainee

  • request access to a specific course they do not have access to

image

Instructor

  • view the ratings and reviews on all his/her courses courseReviews

  • view and accept the contract which includes all the rights to the posted videos and materials as well as the % taken by the company on each video per --- registered trainee terms

  • view all the titles of the courses given by him/her

image

  • filter the courses given by him/her based on a subject or price

image

  • search for a course given by him/her based on course title or subject or instructor

image

  • view the amount of money owed per month

image

  • create a new course and fill in all its details inclding title, subtitles, price and short summary about the entire course createCourse

  • upload a video link from YouTube under each subtitle and enter a short description of the video upload video

  • upload a video link from YouTube as a preview to the course upload preview

  • create a multiple choice exam with 4 choices per question

image

  • set the answers (not visible for the trainee) for multiple choice exercises

image

  • view his/her rating and reviews as an instructor
  • edit his/her mini biography or email

image

image

- define a promotion for the course (% discount) and for how long

image

Individual Trainee

  • view the amount available in their wallet from refunded courses 1
  • enter their credit card details to pay for a course they want to register for
  • pay for a course 2
  • request a refund only if less than 50% of the course has been attended 4

Individual Trainee & Corporate Trainee

  • open all the items inside a course he/she is registered for including videos and excercises 5 05
  • rate an instructor 6
  • rate a course 7
  • solve a multiple choice exercise by choosing the correct answer 8
  • submit the answers to the exercise after completing it sumbitExam
  • view his/her grade from the exercise
  • view the questions with the correct solution to view the incorrect answers 10
  • watch a video from a course he/she is registered for 11
  • see his/her progress in the course of how much of the course has been completed so far 12
  • receive a certificate as a PDF after completing the course via email 13
  • download the certificate as a PDF from the website certificate
  • download the notes as a PDF
  • write notes while watching the video 14
  • see a list of all the courses he/she is enrolled in on their profile 15

Guest & instructor & individual trainee

  • view and accept the website/ company refund/ payment policy while signing up 16
  • view the price of each course 17
  • filter the courses based on price (price can be FREE) 18
  • choose a course from the results and view (but not open) its details including course subtitles, excercises , total hours of each subtitle, total hours of the course and price (including % discount if applicable) according to the country selected 19 019

Guest & instructor & individual trainee & corporate trainee

  • select their country

image

  • filter the courses based on a subject and/or rating

image

  • search for a course based on course title or subject or instructor

image

  • view a preview video of the course and the course outline before registering for it

image

  • view the most viewed/ most popular courses

image

  • view all the titles of the courses available including the total hours of the course and course rating

image

instructor & individual trainee & corporate trainee

  • receive an email to change a forgotten password mail verify

  • change his/her password

image

  • report a problem with a course. The problem can be "technical", "financial" or "other"

image

  • see all previously repoted problems and their statuses reportedProblems

  • follow up on an unresolved problem follow

API References

Our APIs is divided into four APIs :

Guest Router

Route : (/course)

GET Courses

  • Route : /listCourses
  • Request type : get

GET Specefic course

  • Route : /listCourses/:id
  • Request type : get
  • Request Header : {id:'courseId}

GET most popular courses

  • Route : /mostpopular
  • Request type : get

Search for a course

  • Route : /listCourses/search
  • Request type : get
  • Request query : {search:'search fields}

Instructor Router

Route : (/instructor)

Create Course

  • Route : /addCourse
  • Request type : post
  • Request Body : { title: 'Full Mern Stack ', price: '180', description: 'MERN is one of several variations of the MEAN stack (MongoDB Express Angular Node),with React.js', subejct: 'programming', language: 'English', imgUrl: '[!imageLink]', coursePreviewUrl :[!CoursePreviewLink], subtitles :[Array(subtitle)] }

Create Exam

  • Route : /setExam /setFinalExam
  • Request type : post
  • Request Body : { subtitleId: 'mongoose.type.objectId()', courseId: 'mongoose.type.objectId()', questions: [Array(questions)] }

Report problem

  • Route : /reportProblem
  • Request type : post
  • Request Body : { reportType: 'technical', problemTitle 'Video Quality', courseId: 'mongoose.type.objectId()', description: 'The video quality is very low' }

viewReportedProblems

  • Route : /viewReportedProblems
  • Request type : get
  • Request Header : is handled using the middleWare of authentication session which contains logged user token

Own Courses

  • Route : /listCourseTitles
  • Request type : get
  • Request Header : {courseId: 'mongoose.type.objectId()'}

View profit

  • Route : /profit
  • Request type : get
  • Request Header : is handled using the middleWare of authentication session which contains logged user token

View questions on courses

  • Route : /getQuestions
  • Request type : get
  • Request Header : {courseId :'mongoose.type.objectId()'}

reply for a question

  • Route : /addReply
  • Request type : patch
  • Request Body : { questionId: 'mongoose.type.objectId()', reply :'you can use typeScript' }

update Subtitles

  • Route : /updateSubtitle
  • Request type : patch
  • Request Body : { courseId:'mongoose.type.objectId()', subId'mongoose.type.objectId()':, linkDesc:'What is MernStack', linkUrl:'[videoUrl]', allowed:true}

delete Subtitles

  • Route : /deletSubtitle
  • Request type : delete
  • Request Body : { courseId:'mongoose.type.objectId()', subId:'mongoose.type.objectId()', linkId:'mongoose.type.objectId()}

Trainee Router

Route : (/individualtrainee)

Register for a course by using credit/debit card

  • Route : /create-checkout-session
  • Request type : post
  • Request Body : { courseId: 'mongoose.type.objectId()', }

Register for a course by using wallet

  • Route : /payWithWallet
  • Request type : post
  • Request Body : { courseId: 'mongoose.type.objectId()', }

Request access for a course in case of corporate

  • Route : /requestAccess
  • Request type : post
  • Request Body : { courseId: 'mongoose.type.objectId()', }

rate course

  • Route : /setRating
  • Request type : post
  • Request Body : { courseId: 'mongoose.type.objectId()', rating : 5, review : 'wonderfull course'}

rate instructor

  • Route : /setRating
  • Request type : post
  • Request Body : { instructor: 'mongoose.type.objectId()', rating : 5, review : 'wonderfull course'}

delet instructor rating

  • Route : /setRating
  • Request type : post
  • Request Body : { instructorId: 'mongoose.type.objectId()'}

Report problem

  • Route : /reportProblem
  • Request type : post
  • Request Body : { reportType: 'technical', problemTitle 'Video Quality', courseId: 'mongoose.type.objectId()', description: 'The video quality is very low' }

Request refund

  • Route : /requestRefund
  • Request type : post
  • Request body : {courseId : 'mongoose.type.objectId()',reason : 'I did not find the course intersting'}

write notes

  • Route : /addNotes
  • Request type : post
  • Request body : {subId :'mongoose.type.objectId()' , note : "need to install express"}

solve exam

  • Route : /submitExam
  • Request type : post
  • Request body : {subId :'mongoose.type.objectId()' ,answers :'ArrayOfAnswers(mcq)'}

View inprogress courses

Route : /inprogress

  • Request type : get
  • Request Header : is handled using the middleWare of authentication session which contains logged user token

View specific inprogress course

Route : /inprogress/:id

  • Request type : get
  • Request Header : is handled using the middleWare of authentication session which contains logged user token
  • Request params : {courseId: 'mongoose.type.objectId()'}

delete course rating

  • Route : /deleteCourseRating
  • Request type : delete
  • Request Body : { courseId: 'mongoose.type.objectId()'}

viewReportedProblems

  • Route : /viewReportedProblems
  • Request type : get
  • Request Header : is handled using the middleWare of authentication session which contains logged user token

change password

  • Route : /changePassword
  • Request type : patch
  • Request body : {password :'ahmed$1484' , email : 'ahmed@gmail.com'}

forogot password

  • Route : /forgotpassword
  • Request type : patch
  • Request body : {email : 'ahmed@gmail.com'}

Admin Router

Route : (/admin)

Add Admin

  • Route : /addAdmin
  • Request type : post
  • Request Body : { username: 'Omar', password: '123' }

Add promotions

  • Route : /addPromotionMulti
  • Request type : post
  • Request Body : { idArr: ['6361b2deef7816eb1d9eb915','6361b484c27988acb69dfb50'], promo: "25", enddate: "20/1/2023" }

Add Corporate Trainee

  • Route : /addCorporate
  • Request type : post
  • Request Body : { firstname: "yehia", lastname: "eldib", username: "eldib", password: "pass%#$@123#4", email: "yehia@gmail.com", gender: "male" }

Add Instructor

  • Route : /addInstructor
  • Request type : post
  • Request Body : { firstname: "yehia", lastname: "eldib", username: "eldib", password: "pass%#$@123#4", email: "yehia@gmail.com", gender: "male" }

View Report

  • Route : /viewReports
  • Request type : get

View enroll requests

  • Route : /accessRequests
  • Request type : get

View refund requests

  • Route : /refundRequests
  • Request type : get

Authentication Router

Route : (/login)

  • Request type : post
  • Request Body : {username :'ahned' , password : 'Ahmed@123'}

Route : (/signUp)

  • Request type : post
  • Request Body : {username :'ahned' , password : 'Ahmed@123' , email : 'ahmed@gmail.com' , firstname:'ahmed' , lastname:'mohmaed'}

Route : (/logOut)

  • Request type : post -Request header : is handled using the middleWare of authentication session which contains logged user token

Testing

The api reoutes were tested using postman , Postman is an application used for API testing. It is an HTTP client that tests HTTP requests, utilizing a graphical user interface, through which we obtain different types of responses that need to be subsequently validated. Postman offers many endpoint interaction methods. The following are some of the most used, including their functions:

  • GET: Obtain information
  • POST: Add information
  • PUT: Replace information
  • PATCH: Update certain information
  • DELETE: Delete information

And we tested the behaviour of our routes and if they produce the correct status code and response according to our project flow .

Contributing

Anyone who would like to contribute in the project please send me an E-mail on hossamelfarr@gmail.com

Credits

Contributers Github Account
Yehea Eldib yehea eldib
Hossam El Far hossam elfar
Ahmed Azooz ahmed azooz
Adham Haggag adham hagag
Abdullah Fouad abdullah fouad

Our references :

Installation

you can install the project using git clone 'https://github.com/Advanced-Computer-Lab-2022/Agiles.git' then run npm install to download all the needed packages using npm install : packages :

  • node js
  • express js
  • mongoose
  • react
  • bcrypt
  • cookie-parser
  • dotenv
  • jsonwebtoken
  • nodemon
  • stripe
  • nodemailer
  • axios
  • bootstrap
  • @mui/icons-material

After cloning the project or downloading the ZIP folder open the project using the integrated terminal or by using the CMD then run the frontend / backend servers

  • cd backend nodemon app to run the backend server on port :8000
  • cd frontend npm start to run the frontend server on port :3000

How to use

You can use our website as one of four main users (Admin , instructor , Itrainee , corporate trainee), you can sign up for an account from the sign up page and login to the website as a trainnee or if you are an instructor the company will create an account for you in its own then you can login and change your password and use our features

Licence

This project is licenced under Apache Licence 2.0

About

A MERN stack web application through which individuals can attend pre-recorded courses online.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 91.2%
  • CSS 8.7%
  • HTML 0.1%