This project is an online learning system website for the Canadian Chamber of Commerce.
We are students at the German University in Cairo and this project was done as a part of the "Advanced Computer Lab" course. The project contributes 85% to the course's total grade. Not only was the huge effect on our grade our motivation, but we were also very eager to learn the MERN stack development and made sure to provide a more than adequate product.
- If the instructor uploads a wrong format of embed video link it will show up weird things instead of the video
- If the admin grants/denies a request/refund it the buttons will be diabled but the request won't disappear until the page is refreshed
- When the instructor defines a promotion on his course, the new price doesn't appear until the instructor refreshes the page
We have used standardJS code style.
- We used Visual Studio Code as a code editor.
- We used the MERN stack (Mongoose, Express, ReactJS, NodeJS) to develop this project.
- We used MUI components for the ReactJS frontend.
- Made pagination for the explore page (explore page is the one which views all courses)
- We put a lot of work into developing a very satisfying and responsive UX
- We did our best in trying to create a unique and delicate UI
- Created unique home pages for each user
- The pages and buttons are very responsive and they give feedback
The following are some examples of the functions used in the backend in the controllers:
- Viewing all courses
const viewAllCourses = async (req, res) => {
try {
const courses = await Course.find()
if (!courses) {
return res.status(404)
.json({ error: "no courses found" })
}
res.status(200).json(courses)
} catch (error) {
res.status(400).json({ error: "error" })
}
}
- Instructor uploading a preview video embed link
const uploadPreview = async (req, res) => {
const courseid = req.params.courseid
const { videoLink } = req.body
console.log('video embed link : ' + videoLink)
if (!mongoose.Types.ObjectId.isValid(courseid)) {
return res.status(404)
.json({ error: 'no such id' })
}
try {
const course = await Course
.findByIdAndUpdate(courseid,
{ PreviewVideo: videoLink })
if (!course) {
return res.status(404)
.json({ error: 'course not found' })
}
res.status(200).json(videoLink)
} catch (error) {
res.status(400).json({ error: 'error' })
}
}
The following is an example of a frontend return statement. In this particular example it is the component where the instructor defines a promotion for one of his courses.
return (
<Paper
elevation={4} style={{padding:20 ,
width:280,
margin: '16px auto',
maxHeight:'55vh',
borderRadius:'16px'}}
>
<Stack spacing={2}>
<Typography variant="h3">
Define Discount
</Typography>
<TextField
label="Discount Percentage"
type="number" min="0" max="100"
onChange={(e) => setDiscount(e.target.value)}
value={Discount} />
<TextField
label="Discount Expiry Date"
type="date"
onChange={(e) => setEndDate(e.target.value)}
value={EndDate}/>
<Button
variant="contained"
onClick={handleSubmit}>Submit</Button>
{success &&
<Alert severity="success">
{success}
</Alert>}
{Error &&
<Alert severity="error">
{Error}
</Alert>}
</Stack>
</Paper>
)
For developers, we suggest that you install these packages before you start working on this project:
- Install nodejs
- Install Visual Studio Code
- Install nodemon with npm
npm i nodemon
- Install express with npm
npm i express
- Install mongoose with npm
npm i mongoose
- Install react with npm
npm i react
- Install git with npm
npm i git
- Install mui with npm
npm install @mui/material @emotion/react @emotion/styled
- Install mui material icons with npm
npm install @mui/icons-material
GET /api/guest/viewAllCourses
No parameters needed
POST /api/trainee/page/rateCourse
POST /api/corpTrainee/page/rateCourse
Body | Type | Description |
---|---|---|
rating |
int |
The rating on a scale 1-5 |
review |
string |
The review |
courseID |
string |
The id of the course to be rated |
Username |
string |
The Username of the trainee |
POST /api/instructor/uploadpreview/:courseid
Parameter | Type | Description |
---|---|---|
courseid |
string |
Id of item to fetch of the course |
Body | Type | Description |
---|---|---|
videoLink |
string |
Embed link of the video |
POST /api/admin/resolveproblem
Body | Type | Description |
---|---|---|
problemid |
string |
Id of the problem |
- Try inserting an incorrect username or password when logging in
userSchema.statics.Login = async function (Username, Password) {
if (!Username || !Password)
throw Error('Must type username or password')
const user = await this.findOne({ Username })
if (!user)
throw Error('Incorrect username or password')
const validpass = await bcrypt.compare(Password, user.Password)
if (!validpass)
throw Error('incorrect username or password')
return user
}
- Try inserting an email of a wrong format when signing up
userSchema.statics.RegTrainee = async function
(Username, Email, Password, Firstname, Lastname, Gender) {
const Type = 'Trainee'
if (!Email || !Password || !Username)
throw Error('Must type email or password or username')
if (!Validator.isEmail(Email))
throw Error('incorrect email format')
if (!Validator.isStrongPassword(Password))
throw Error('weak pasword')
let useru = await this.findOne({ Username })
if (useru)
throw Error('username already in use')
let usere = await this.findOne({ Email })
if (usere)
throw Error('Email already in use')
const salt = await bcrypt.genSalt(10)
let hash = await bcrypt.hash(Password, salt)
const user = await this.create({ Username, Email, Password: hash, Type })
const trainee = await Trainee.create({ _id: user._id, Firstname: Firstname, Lastname: Lastname, Gender: Gender })
if (!trainee)
await this.delete({ _id: user._id })
return trainee, user
}
There are 5 types of users on the website:
- Guest
- Admin
- Trainee
- Corporate Trainee
- Instructor
The first time you open the website you are automatically a guest.
-
- Click on sign up button on the right of the top bar
- Enter your details and click sign up!
-
You have to be created by an Admin.
-
Click on your icon on the right of the top bar and click Sign out.
- Check out our most popular courses, which you can find at the bottom of the home page
- Search for a course from the search bar on the top bar
- Explore a variety of our courses by clicking on explore on the top bar
-
Explore a variety of our courses by clicking on explore on the top bar
-
Register to a course by following these steps:
- Click on your desired course
- Click on Buy Now button
- Enter your credit card details
-
View and access courses that you bought by clicking on My Courses on the top bar
-
Explore a variety of our courses by clicking on explore on the top bar
-
Register to a course by following these steps:
- Click on your desired course
- Click on Request Access button
- Wait for an admin to respond to your request
-
View and access courses that you have access to by clicking on My Courses on the top bar
- You can add a user, define a promotion, View and respond to course requests, refund requests and reported problems by clicking on its respective button on the top bar
-
Create a course by clicking on Create Course button on the top bar, and then following the steps
-
Define a promotion on one of your courses by following these steps:
- Click on My Courses button on the top bar
- Click on your desired course
- You'll find a box titled "Define a promotion"
- Type in the percentage discount
- Type in the date you would like this promotion to end
- Click on Submit button
Contributions are always welcome!
You can contribute by adding features to the system.
Thanks to MUI which was our main resource developing the frontend
Thanks to all the contributors