- Project Description
- Motivation
- Code Styles
- Tools and Frameworks
- Build Status
- Code Examples
- Features
- API References
- Testing
- Contributing
- Credits
- Installation
- How to use
- Licence
Canadian Chamber Of Commerce
Advanced Computer Lab (CSEN 704), Winter 2022
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.
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.
- 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.
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.
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
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.
The MERN architecture allows you to easily construct a 3-tier architecture (frontend, backend, database) entirely using JavaScript and JSON.
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.
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.
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!
- The project currently under development and there are some styling problems to be fixed
- jest tests to be added
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"});}
}
);
}
We have four main users in our website:
- Log in using his email and password.
- Log out from the website
- Add another admin to the website.
- Add corporate trainee to the website.
- Add instructor to the website.
- View the reports and solve it.
- View the courses enroll requests and all the details of the request
- View refund requests and approved them or not
- Add promotions to any course in the website and specify the percent of discount and the end time of the discount
- Sign Up for the webiste
- request access to a specific course they do not have access to
-
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
-
view all the titles of the courses given by him/her
- filter the courses given by him/her based on a subject or price
- search for a course given by him/her based on course title or subject or instructor
- view the amount of money owed per month
-
create a new course and fill in all its details inclding title, subtitles, price and short summary about the entire course
-
upload a video link from YouTube under each subtitle and enter a short description of the video
-
create a multiple choice exam with 4 choices per question
- set the answers (not visible for the trainee) for multiple choice exercises
- view his/her rating and reviews as an instructor
- edit his/her mini biography or email
- view the amount available in their wallet from refunded courses
- enter their credit card details to pay for a course they want to register for
- pay for a course
- request a refund only if less than 50% of the course has been attended
- open all the items inside a course he/she is registered for including videos and excercises
- rate an instructor
- rate a course
- solve a multiple choice exercise by choosing the correct answer
- submit the answers to the exercise after completing it
- view his/her grade from the exercise
- view the questions with the correct solution to view the incorrect answers
- watch a video from a course he/she is registered for
- see his/her progress in the course of how much of the course has been completed so far
- receive a certificate as a PDF after completing the course via email
- download the certificate as a PDF from the website
- download the notes as a PDF
- write notes while watching the video
- see a list of all the courses he/she is enrolled in on their profile
- view and accept the website/ company refund/ payment policy while signing up
- view the price of each course
- filter the courses based on price (price can be FREE)
- 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
- select their country
- filter the courses based on a subject and/or rating
- search for a course based on course title or subject or instructor
- view a preview video of the course and the course outline before registering for it
- view the most viewed/ most popular courses
- view all the titles of the courses available including the total hours of the course and course rating
- report a problem with a course. The problem can be "technical", "financial" or "other"
Our APIs is divided into four APIs :
- Route :
/listCourses
- Request type :
get
- Route :
/listCourses/:id
- Request type :
get
- Request Header : {
id:'courseId
}
- Route :
/mostpopular
- Request type :
get
- Route :
/listCourses/search
- Request type :
get
- Request query : {
search:'search fields
}
- 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)] }
- Route :
/setExam
/setFinalExam
- Request type :
post
- Request Body :
{ subtitleId: 'mongoose.type.objectId()', courseId: 'mongoose.type.objectId()', questions: [Array(questions)] }
- Route :
/reportProblem
- Request type :
post
- Request Body :
{ reportType: 'technical', problemTitle 'Video Quality', courseId: 'mongoose.type.objectId()', description: 'The video quality is very low' }
- Route :
/viewReportedProblems
- Request type :
get
- Request Header :
is handled using the middleWare of authentication session which contains logged user token
- Route :
/listCourseTitles
- Request type :
get
- Request Header :
{courseId: 'mongoose.type.objectId()'}
- Route :
/profit
- Request type :
get
- Request Header :
is handled using the middleWare of authentication session which contains logged user token
- Route :
/getQuestions
- Request type :
get
- Request Header :
{courseId :'mongoose.type.objectId()'}
- Route :
/addReply
- Request type :
patch
- Request Body :
{ questionId: 'mongoose.type.objectId()', reply :'you can use typeScript' }
- Route :
/updateSubtitle
- Request type :
patch
- Request Body :
{ courseId:'mongoose.type.objectId()', subId'mongoose.type.objectId()':, linkDesc:'What is MernStack', linkUrl:'[videoUrl]', allowed:true}
- Route :
/deletSubtitle
- Request type :
delete
- Request Body :
{ courseId:'mongoose.type.objectId()', subId:'mongoose.type.objectId()', linkId:'mongoose.type.objectId()}
- Route :
/create-checkout-session
- Request type :
post
- Request Body :
{ courseId: 'mongoose.type.objectId()', }
- Route :
/payWithWallet
- Request type :
post
- Request Body :
{ courseId: 'mongoose.type.objectId()', }
- Route :
/requestAccess
- Request type :
post
- Request Body :
{ courseId: 'mongoose.type.objectId()', }
- Route :
/setRating
- Request type :
post
- Request Body :
{ courseId: 'mongoose.type.objectId()', rating : 5, review : 'wonderfull course'}
- Route :
/setRating
- Request type :
post
- Request Body :
{ instructor: 'mongoose.type.objectId()', rating : 5, review : 'wonderfull course'}
- Route :
/setRating
- Request type :
post
- Request Body :
{ instructorId: 'mongoose.type.objectId()'}
- Route :
/reportProblem
- Request type :
post
- Request Body :
{ reportType: 'technical', problemTitle 'Video Quality', courseId: 'mongoose.type.objectId()', description: 'The video quality is very low' }
- Route :
/requestRefund
- Request type :
post
- Request body :
{courseId : 'mongoose.type.objectId()',reason : 'I did not find the course intersting'}
- Route :
/addNotes
- Request type :
post
- Request body :
{subId :'mongoose.type.objectId()' , note : "need to install express"}
- Route :
/submitExam
- Request type :
post
- Request body :
{subId :'mongoose.type.objectId()' ,answers :'ArrayOfAnswers(mcq)'}
Route : /inprogress
- Request type :
get
- Request Header :
is handled using the middleWare of authentication session which contains logged user token
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()'}
- Route :
/deleteCourseRating
- Request type :
delete
- Request Body :
{ courseId: 'mongoose.type.objectId()'}
- Route :
/viewReportedProblems
- Request type :
get
- Request Header :
is handled using the middleWare of authentication session which contains logged user token
- Route :
/changePassword
- Request type :
patch
- Request body :
{password :'ahmed$1484' , email : '[email protected]'}
- Route :
/forgotpassword
- Request type :
patch
- Request body :
{email : '[email protected]'}
- Route :
/addAdmin
- Request type :
post
- Request Body :
{ username: 'Omar', password: '123' }
- Route :
/addPromotionMulti
- Request type :
post
- Request Body :
{ idArr: ['6361b2deef7816eb1d9eb915','6361b484c27988acb69dfb50'], promo: "25", enddate: "20/1/2023" }
- Route :
/addCorporate
- Request type :
post
- Request Body :
{ firstname: "yehia", lastname: "eldib", username: "eldib", password: "pass%#$@123#4", email: "[email protected]", gender: "male" }
- Route :
/addInstructor
- Request type :
post
- Request Body :
{ firstname: "yehia", lastname: "eldib", username: "eldib", password: "pass%#$@123#4", email: "[email protected]", gender: "male" }
- Route :
/viewReports
- Request type :
get
- Route :
/accessRequests
- Request type :
get
- Route :
/refundRequests
- Request type :
get
- Request type :
post
- Request Body :
{username :'ahned' , password : 'Ahmed@123'}
- Request type :
post
- Request Body :
{username :'ahned' , password : 'Ahmed@123' , email : '[email protected]' , firstname:'ahmed' , lastname:'mohmaed'}
- Request type :
post
-Request header :is handled using the middleWare of authentication session which contains logged user token
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 .
Anyone who would like to contribute in the project please send me an E-mail on [email protected]
Contributers | Github Account |
---|---|
Yehea Eldib | yehea eldib |
Hossam El Far | hossam elfar |
Ahmed Azooz | ahmed azooz |
Adham Haggag | adham hagag |
Abdullah Fouad | abdullah fouad |
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 :8000cd frontend
npm start
to run the frontend server on port :3000
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
This project is licenced under Apache Licence 2.0