The project itself aims to be a valuable resource for people looking to improve their skills and knowledge. It provides a convenient and accessible way for people to learn new things and achieve their goals through online courses and exercises. By offering the opportunity to practice and apply what they have learned, the project helps students not only learn new information, but also test their understanding and retain it for longer periods of time. The project strives to be the best it can be and continues to work towards this goal.
- The project is currently in development.
- Unit tests will be added.
- Camel Case in variable names used
You can then run Prettier on your code by using the prettier command in your terminal. For example:
prettier --write "src/**/*.js"
Advanced Computer Lab (CSEN 704/ DMET 706), Winter 2022
Our project is an online learning platform that allows both individual and corporate trainees to enroll in a variety of courses and track their progress as they work towards earning a certificate of completion. The platform features a range of courses taught by experienced instructors who have created engaging lectures and quizzes to help students master the material. In addition to providing a convenient and flexible way for learners to gain new skills and knowledge, the platform also offers tools for instructors to manage their courses and for admins to track and address any issues that may arise, such as requests for refunds or reports of problems. Whether you're looking to advance your career, learn a new hobby, or simply expand your horizons, our platform is a great resource for anyone looking to learn and grow.
Our project was developed using the Agile Methodology, which involves breaking the project into shorter time periods called "Sprints." Each Sprint has a specific set of goals, and at the end of each Sprint, a fully functional version of the project is delivered and evaluated based on the specified system requirements. This approach allows for a more flexible and responsive development process, as it allows for ongoing adjustments and improvements to be made based on feedback and changing needs.
- Gain an understanding of how to effectively utilize the Agile Methodology for project planning and software development
- 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.
- React
- Redux
- Node.js
- Express
- MongoDB
- Mongoose
- Joi
- Material-UI
- Stripe
- Git
- Github Actions
- NodeMailer
- Postman
- VSCode
- JWT
Feature | 🔰 Status |
---|---|
Authentiation | ✔️ |
Authorization | ✔️ |
User Roles | ✔️ |
Payments | ✔️ |
User Email Notifications | ✔️ |
User Password Reset | ✔️ |
REST API | ✔️ |
Validation using JOI | ✔️ |
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
In order to run this project locally, simply fork and clone the repository or download as zip and unzip on your machine.
- Open the project in your prefered code editor.
- Go to terminal -> New terminal (If you are using VS code)
- Split your terminal into two (run the client on one terminal and the server on the other terminal)
In order to use ES6 MODULE
in node js.
> cd server
> find `package.json`
> below `main` enter a new key-value pair called `type = module`
In the first terminal
> git clone https://github.com/Advanced-Computer-Lab-2022/Asyad-El-Code.git
> cd Asyad-El-Code/
> cd server & npm i & cd..
> cd client & npm i
Backend
cd server && npm start
Frontend
cd client && npm start
Add this keys to .env file to run project
PORT
MONGO_URI
TOKEN_KEY
HOST
USER
PASS
SERVICE
STRIPE_PRIVATE_KEY
export const RatingAndReviewPopup = ({
ratingOpen,
handleCancelRating,
handleSubmit,
}) => {
const dispatch = useDispatch();
const [ratingValue, setRatingValue] = useState(0);
const [review, setReview] = useState("");
//update RatingOpen to false when cancel button is clicked
const handleCancel = () => {
handleCancelRating();
};
const handleClick = () => {
handleSubmit(ratingValue, review);
};
return (
<>
<Dialog open={ratingOpen}>
<DialogTitle>Add a rating and review for the course</DialogTitle>
<DialogContent>
<DialogContentText>Add a rating from 1 to 5</DialogContentText>
<Rating
name="simple-controlled-rating"
value={ratingValue}
onChange={(event, newValue) => {
setRatingValue(newValue);
}}
/>
<DialogContentText>Add a review</DialogContentText>
<TextField
id="outlined-multiline-static"
label="Review"
multiline
rows={4}
defaultValue=""
variant="outlined"
onChange={(e) => setReview(e.target.value)}
/>
</DialogContent>
<DialogActions>
<Button variant="outlined" color="primary" onClick={handleClick}>
Submit
</Button>
<Button variant="outlined" color="primary" onClick={handleCancel}>
Cancel
</Button>
</DialogActions>
</Dialog>
</>
);
export const updateRating = async (req, res) => {
try {
const id = mongoose.Types.ObjectId(req.params.id);
const { rating } = req.body;
const instructor = await Instructor.findById(id);
if (!instructor) return res.status(404).send("instructor not found");
const updatedInstructor = await Instructor.findByIdAndUpdate(
id,
{ rating: rating },
{ new: true }
);
res.status(200).send(updatedInstructor);
} catch (error) {
res.status(400).send(error.message);
}
};
POST /signup
Headers | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token is added. |
Body | Type | Description |
---|---|---|
firstName |
string |
Required. firstName of trainee |
lastName |
string |
Required. lastName of the trainee |
email |
string |
Required. email of trainee |
password |
string |
Required. password of trainee |
gender |
string |
Required. gender of the trainee |
Response
{
"result":{"firstName":"Roberto",
"lastName":"joseph",
"gender":"Male",
"password":"hashedPassword",
"_id":"63b19f456422dcc9bbca8c35",
"courses":[],
"grades":[],
"notes":[],
},
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
"type":"indivdualTrainee"
}
POST /signin
Headers | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token is added. |
Body | Type | Description |
---|---|---|
email |
string |
Required. email of trainee |
password |
string |
Required. password of the trainee |
Response
{
"result": {
"firstName":"Roberto",
"lastName":"Joseph",
"email":"robertojoseph@gmail.com",
"password":"hashedPassword",
"gender":"Male"
},
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJz
dWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
"type":"individualTrainee"
}
POST /sendemail
Body | Type | Description |
---|---|---|
email |
string |
Required. user email. |
{"email":"robertojoseph@gmail.com"}
POST /confirmPassword/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. user id. |
Body | Type | Description |
---|---|---|
password |
string |
Required. user new password. |
Response
{
"message":"success"
}
GET /filterInstructorCourses
Query | Type | Description |
---|---|---|
id |
string |
Required. id of instructor |
subject |
string |
Required. course subject |
price |
string |
Required. price of course |
rating |
string |
Required. rating of course |
Code Example 💻
export const filterInstructorCourses = async (req, res) => {
try {
const { id, subject, price, rating } = req.query;
const subjectArray = subject.split(/[,]+/);
const priceArray = price.split(/[,]+/);
const ratingArray = rating.split(/[,]+/);
const courses = await Course.aggregate([
{ $match: { "instructor.instructorId": mongoose.Types.ObjectId(id) } },
{ $match: { subject: { $in: subjectArray } } },
{ $match: { rating: { $lte: parseInt(ratingArray[1]) } } },
{ $match: { rating: { $gte: parseInt(ratingArray[0]) } } },
{
$addFields: {
discountedPrice: {
$cond: [
{
$and: [
{ $lte: ["$promotion.startDate", new Date(Date.now())] },
{ $gte: ["$promotion.endDate", new Date(Date.now())] },
],
},
{
$multiply: [
"$price",
{ $subtract: [1, "$promotion.discount"] },
],
},
"$price",
],
},
},
},
{ $match: { discountedPrice: { $lte: parseInt(priceArray[1]) } } },
{ $match: { discountedPrice: { $gte: parseInt(priceArray[0]) } } },
]);
if (!courses) {
res.status(404).send("Cannot find Courses for this instructor");
}
res.status(200).send(courses);
} catch (err) {
res.status(401).send(err);
}
};
Response
{
"courses":[]
}
POST /createInstructor
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. role should be admin. |
Body | Type | Description |
---|---|---|
userName |
string |
Required. username of instructor |
firstName |
string |
Required. firstname of instructor |
lastName |
string |
Required. lastname of instructor |
email |
string |
Required. email of instructor |
gender |
string |
Required. gender of instructor |
passsword |
string |
Required. password of instructor |
country |
string |
Required. country of instructor |
phoneNumber |
string |
Required. phoneNumber of instructor |
about |
string |
Required. biography of instructor |
dateOfBirth |
string |
Required. date of birth of instructor |
Response
{
"userName": "robertoJoseph",
"firstName": "roberto",
"lastName": "joseph",
"email": "instructor10@gmail.com",
"gender": "Male",
"password": "pass123",
"country": "egypt",
"dateOfBirth": "20/08/2001",
"wallet": "0",
"phoneNumber: "010xxxxxxx",
"about": "firstInstructor",
}
GET /instructor
Response
{
"instructors":[]
}
GET /viewTitles/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Instructor id. |
Response
{
"courses":[]
}
POST /addNewCourse
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of the instructor |
Body | Type | Description |
---|---|---|
title |
string |
Required. title of course |
summary |
string |
Required. summary of the course |
subject |
string |
Required. subject of the course |
previewVideo |
string |
Required. preview video of the course |
outline |
array |
Required. outline of the course |
exercises |
array |
Required. exercises of the course |
price |
number |
Required. price of the course |
releaseDate |
string |
Required. releasedate of the course |
language |
string |
Required. language of the course |
image |
string |
Required. image of the course |
duration |
number |
Required. duration of the course |
Parameter | Type | Description |
---|---|---|
id |
string |
Required. instructor id |
Response
{
"title":"course1",
"summary":"This is a nodeJs course",
"price":"500",
"rating":"0",
"previewVideo":"youtube video url",
"outline":{
[
"outline":"Section 1",
"totalHours":"30",
"subtitles":[
{
"subtitle":"lecture1",
"minutes":"13",
"videoUrl":"youtube video url"
}
],
"exercises":[
{
"question":"question1",
"answers":[
{
"answer":"answer1",
"correct":"true",
}
]
}
]
]
},
"price":500,
"instructorId":{ "instructorId":"id", "name": "roberto" },
"ratings":[],
"reviews":[],
"numberOfEnrolledStudents":0,
}
PATCH /updateInformation/:id
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of the instructor |
Parameter | Type | Description |
---|---|---|
id |
string |
Required. instructor id |
Body | Type | Description |
---|---|---|
firstName |
string |
Required. first name of the insttrucor |
lastName |
string |
Required. last name of the instructor |
country |
string |
Required. country of the instructor |
phoneNumber |
string |
Required. phone number of the instrcutor |
Response
{
"firstName":"jannah"
"lastName":"gabr",
"lastName":"gabr",
"biography":"I teach math",
"phoneNumber":"01092022xxxx",
}
POST /addReview
Query | Type | Description |
---|---|---|
instructorId |
string |
Required. id of the instructor |
individualTraineeId |
string |
Required. id of the trainee |
coorporateTraineeId |
string |
Required. id of the trainee |
review |
string |
Required. review on instrcutor |
Response
{
"userName": "robertoJoseph",
"firstName": "roberto",
"lastName": "joseph",
"email": "instructor10@gmail.com",
"gender": "Male",
"password": "pass123",
"country": "egypt",
"dateOfBirth": "20/08/2001",
"wallet": "0",
"phoneNumber": "010xxxxxxx",
"about": "firstInstructor",
"reviews":[
"individualTraineeId":"5f7b11be78b93e73d92366f9",
"review":"el ragel da meya el meya",
]
}
POST /updateRating/:id
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of the instructor |
Query | Type | Description |
---|---|---|
id |
string |
Required. id of the instructor |
Body | Type | Description |
---|---|---|
rating |
number |
Required. rating on the instructor |
Response
{
"userName": "robertoJoseph",
"firstName": "roberto",
"lastName": "joseph",
"email": "instructor10@gmail.com",
"gender": "Male",
"password": "pass123",
"country": "egypt",
"dateOfBirth": "20/08/2001",
"wallet": "0",
"phoneNumber: "010xxxxxxx",
"about": "firstInstructor",
"rating":[
"individualTraineeId":"5f7b11be78b93e73d92366f9",
"rating":5,
]
}
POST /definePromotion
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of the instructor |
Param | Type | Description |
---|---|---|
id |
string |
Required. id of the instructor |
Body | Type | Description |
---|---|---|
rating |
number |
Required. rating on the instructor |
Response
{
"userName": "robertoJoseph",
"firstName": "roberto",
"lastName": "joseph",
"email": "instructor10@gmail.com",
"gender": "Male",
"password": "pass123",
"country": "egypt",
"dateOfBirth": "20/08/2001",
"wallet": "0",
"phoneNumber": "010xxxxxxx",
"about": "firstInstructor",
"rating":[
"individualTraineeId":"5f7b11be78b93e73d92366f9",
"rating":5,
]
}
GET /getAllInstructorCourses/:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. id of the instructor |
Response
{
"courses":[]
}
GET /getNotes
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of the trainee |
Query | Type | Description |
---|---|---|
userId |
string |
Required. id of trainee |
courseId |
string |
Required. course id |
lectureId |
string |
Required. lecture id |
Response
{
"notes": [
{
"subtitleId":"5f7b11be78b93e73d92366f9",
"note": [{ "value": "nice", time: "33" }],
}
]
}
GET /getPdf
Response
> res,sendFile(`${__dirname}/test.pdf`)
PUT /:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Id of trainee |
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of trainee |
Body | Type | Description |
---|---|---|
firstName |
string |
Required. first name of trainee |
lastName |
string |
Required. last name of trainee |
phoneNumber |
string |
Required. phone number of trainee |
country |
string |
Required. country of trainee |
Response
{
"firstName":"kareem",
"lastName":"khedr",
"phoneNunber":"010222xxxx",
"country":"egypt"
}
POST /enrollInCourse
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of trainee |
Body | Type | Description |
---|---|---|
courseId |
string |
Required. id of course |
Response
{
"instructor":{
"courses":[
"courseId":"5f7b11be78b93e73d92366f9",
"title":"Course Flutter",
"summary":"yes babe",
"duration":"30",
"releaseDate":"20/8/2019",
"summary":"yes man",
]
}
}
POST /addGrade
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of trainee |
Query | Type | Description |
---|---|---|
courseId |
string |
Required. id of course |
score |
number |
Required. grade of trainee |
total |
number |
Required. total grade |
individualTraineeId |
id |
Required. id of trainee |
score |
number |
Required. score from the exercise |
Response
{
"grades": [
{
"score": 30,
"total": 50,
"exerciseId": "5f7b11be78b93e73d92366f9",
},
],
}
POST /addSeenContent
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of trainee |
Query | Type | Description |
---|---|---|
courseId |
string |
Required. id of course |
outlineId |
string |
Required. id of lecture |
individualTraineeId |
string |
Required. id of trainee |
minutes |
number |
Required. id of trainee |
Response
{
"seenContent": [
{
"duration": 30,
"contentId": "5f7b11be78b93e73d92366f9",
},
],
}
POST /addNotes
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of trainee |
Query | Type | Description |
---|---|---|
courseId |
string |
Required. id of course |
lectureId |
string |
Required. id of lecture |
individualTraineeId |
string |
Required. id of trainee |
note |
string |
Required. note of trainee |
playedMinutes |
number |
Required. time of note |
Response
{
"notes": [
{
"subtitleId": "5f7b11be78b93e73d92366f9",
"note": [{ "value": "nice", "time": "33" }],
},
],
}
GET /:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. id of trainee |
```http
GET /getPdf
```
Response
> res,sendFile(`promise.resolve(__dirname)/test.pdf`)
POST /payForCourse
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of trainee |
Query | Type | Description |
---|---|---|
courses |
array |
Required. array of courses to buy |
individualTraineeId |
string |
Required. id of trainee |
instructorId |
string |
Required. the instructorId to gain profit |
Response
{
"session":"checkout_session_id"
}
POST /sendEmail
Header | Type | Description |
---|---|---|
Authorization |
string |
Required. Bearer token of trainee |
Query | Type | Description |
---|---|---|
courseId |
string |
Required. id of course |
userId |
string |
Required. id of trainee |
Response
{
"message":"PDF sent successfully"
}
GET /
Response
{
"individualTrainees":[]
}
Applying Authroization Header to all the routes which checks if the user is admin from his token
GET /
Response
{
"admins":[]
}
GET /refunds
Response
[
{
"individualTraineeId": "5f7b11be78b93e73d92366f9",
"courseId": "5f7b11be78b93e73d92366f9",
"_id": "5f7b11be78b93e73d92366f9",
"refundType": "course",
"refundReason": "reason",
"firstName": "firstName",
"lastName": "lastName",
"courseName": "courseName",
"email":"email",
}
]
POST /
Body | Type | Description |
---|---|---|
userName |
string |
Required. First name of admin |
email |
string |
Required. Email of admin |
password |
string |
Required. Password of admin |
Response
{
"admin": {
"userName": "heidarAdmin",
"email": "admin@gmail.com",
"password": "hashedPassword"",
"_id": "5f7b11be78b93e73d92366f9",
}
}
GET /courseRequests
Response
[
{
"userId": "5f7b11be78b93e73d92366f9",
"courseId": "5f7b11be78b93e73d92366f9",
"_id": "5f7b11be78b93e73d92366f9",
"userName": "user13333",
"request": "I need this course to be added",
"date": "20/10/2020",
"email":"roo@gmail.com",
"courseName":"first course"
}
]
GET /:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. id of admin |
Response
{
"admin": {
"userName": "heidarAdmin",
"email": "admin@gmail.com",
"password": "hashedPassword"",
"_id": "5f7b11be78b93e73d92366f9",
}
}
POST /addInstructor
Body | Type | Description |
---|---|---|
userName |
string |
Required. First name of instructor |
email |
string |
Required. Email of instructor |
password |
string |
Required. Password of instructor |
Response
{
"instructor": {
"userName": "heidarAdmin",
"email": "instructor10@gmail.com"
"password": "hashedPassword"",
"_id": "5f7b11be78b93e73d92366f9",
}
}
POST /addCoorporate
Body | Type | Description |
---|---|---|
userName |
string |
Required. First name of coorporate |
email |
string |
Required. Email of coorporate |
password |
string |
Required. Password of coorporate |
Response
{
"coorporate": {
"userName": "heidarAdmin",
"email": "coor@gmail.com",
"password": "hashedPassword"",
}
}
POST /acceptCourseRequest
Body | Type | Description |
---|---|---|
email |
string |
Required. coorporate email |
courseName |
string |
Required. name of the course |
Response
{
"message": "Course Request Accepted"
}
POST /rejectCourseRequest
Body | Type | Description |
---|---|---|
email |
string |
Required. coorporate email |
courseName |
string |
Required. name of the course |
Response
{
"message": "Course Request Rejected"
}
POST /provideCourse
A table of query
Query | Type | Description |
---|---|---|
id |
string |
Required. id of course |
coorporateId |
string |
Required. id of coorporate |
Response
{
"message": "Course Provided"
}
POST /acceptRefund
Body | Type | Description |
---|---|---|
email |
string |
Required. email of user |
courseName |
string |
Required. name of the course |
Response
{
"message":"Refund request has been accepted and email has been sent to ${email}"
}
POST /rejectRefund
A table of body contain email and courseName
Body | Type | Description |
---|---|---|
email |
string |
Required. email of user |
courseName |
string |
Required. name of the course |
Response
{
"message":"Refund request has been rejected and email has been sent to ${email}"
}
POST /deleteRefundRequest/:id
A table of params contain id of refund request
Parameter | Type | Description |
---|---|---|
id |
string |
Required. id of refund request |
Response
{
"message": "Refund Request Deleted"
}
GET /filter/price
A table of body contains max and min price of the course you wantt o search for
Body | Type | Description |
---|---|---|
max |
number |
Required. max price of course |
min |
number |
Required. min price of course |
Response
{
"courses":[
{
"title": "course1",
"description": "course1 description",
"price": 100,
"image": "image1",
"instructor": {
"instructorId": "5f7b11be78b93e73d92366f9",
"name":"jannah"
},
"duration": 40,
"subject":"computer science",
"rating": 4.5,
"language": "english",
"rating": 4.5,
"outlines":[],
"reviews":[],
"promotion":{
"discount": 10,
"startDate": "2020-10-10",
"endDate": "2020-10-10"
},
"ratings":[],
"numberOfEnrolledStudents": 0,
"releasedDate": "2020-10-10",
}
]
}
GET /course/
A table of parameter
Parameter | Type | Description |
---|---|---|
id |
string |
Required. id of course |
Response
{
"course": {
"title": "course1",
"description": "course1 description",
"price": 100,
"image": "image1",
"instructor": {
"instructorId": "5f7b11be78b93e73d92366f9",
"name":"jannah"
},
"duration": 40,
"subject":"computer science",
"rating": 4.5,
"language": "english",
"rating": 4.5,
"outlines":[],
"reviews":[],
"promotion":{
"discount": 10,
"startDate": "2020-10-10",
"endDate": "2020-10-10"
},
"ratings":[],
"numberOfEnrolledStudents": 0,
"releasedDate": "2020-10-10",
}
}
GET /searchBySubjectAndRating
A table of body consists of rating and subject
Body | Type | Description |
---|---|---|
rating |
number |
Required. rating of course |
subject |
string |
Required. subject of course |
Response
{
"courses":[
{
"title": "course1",
"description": "course1 description",
"price": 100,
"image": "image1",
"instructor": {
"instructorId": "5f7b11be78b93e73d92366f9",
"name":"jannah"
},
"duration": 40,
"subject":"computer science",
"rating": 4.5,
"language": "english",
"rating": 4.5,
"outlines":[],
"reviews":[],
"promotion":{
"discount": 10,
"startDate": "2020-10-10",
"endDate": "2020-10-10"
},
"ratings":[],
"numberOfEnrolledStudents": 0,
"releasedDate": "2020-10-10",
}
]
}
GET /filterAllCourses
Code Example
export const filterAllCourses = async (req, res) => {
try {
const { subject, price, rating } = req.query;
const subjectArray = subject.split(/[,]+/);
const priceArray = price.split(/[,]+/);
const ratingArray = rating.split(/[,]+/);
const c = await Course.aggregate([
{
$match: {
subject: { $in: subjectArray },
},
},
{
$match: {
rating: { $lte: parseInt(ratingArray[1]) },
},
},
{
$match: {
rating: { $gte: parseInt(ratingArray[0]) },
},
},
{
$addFields: {
discountedPrice: {
$cond: [
{
$and: [
{ $lte: ["$promotion.startDate", new Date(Date.now())] },
{ $gte: ["$promotion.endDate", new Date(Date.now())] },
],
},
{
$multiply: [
"$price",
{ $subtract: [1, "$promotion.discount"] },
],
},
"$price",
],
},
},
},
{
$match: {
discountedPrice: { $lte: parseInt(priceArray[1]) },
},
},
{
$match: {
discountedPrice: { $gte: parseInt(priceArray[0]) },
},
},
]);
if (!c) return res.status(200).send({ message: "No course found" });
res.status(200).send(c);
} catch (err) {
res.status(401).send(err);
}
};
Query | Type | Description |
---|---|---|
subject |
string |
Required. subject of course |
price |
string |
Required. price of course |
rating |
string |
Required. rating of course |
Response
{
"courses":[
{
"title": "course1",
"description": "course1 description",
"price": 100,
"image": "image1",
"instructor": {
"instructorId": "5f7b11be78b93e73d92366f9",
"name":"jannah"
},
"duration": 40,
"subject":"computer science",
"rating": 4.5,
"language": "english",
"rating": 4.5,
"outlines":[],
"reviews":[],
"promotion":{
"discount": 10,
"startDate": "2020-10-10",
"endDate": "2020-10-10"
},
"ratings":[],
"numberOfEnrolledStudents": 0,
"releasedDate": "2020-10-10",
}
]
}
POST /addRating
A table of query consists of rating and courseid , traineeId
Query | Type | Description |
---|---|---|
rating |
number |
Required. rating of course |
courseId |
string |
Required. id of course |
traineeId |
string |
Required. id of trainee |
Response
```json
{
"message": "rating added successfully"
}
```
GET /getCoursesWithPromotion
Code example 💻
export const getCoursesWithPromotion = async (req, res) => {
try {
const courses = await Course.aggregate([
{
$addFields: {
discountedPrice: {
$cond: [
{
$and: [
{ $lte: ["$promotion.startDate", new Date(Date.now())] },
{ $gte: ["$promotion.endDate", new Date(Date.now())] },
],
},
{
$multiply: [
"$price",
{ $subtract: [1, "$promotion.discount"] },
],
},
"$price",
],
},
},
},
]);
if (!courses) return res.status(404).send({ message: "Courses not found" });
res.status(200).send(courses);
} catch (error) {
console.log(error);
}
};
Response
{
"courses":[
{
"title": "course1",
"description": "course1 description",
"price": 100,
"image": "image1",
"instructor": {
"instructorId": "5f7b11be78b93e73d92366f9",
"name":"jannah"
},
"duration": 40,
"subject":"computer science",
"rating": 4.5,
"language": "english",
"rating": 4.5,
"outlines":[],
"reviews":[],
"promotion":{
"discount": 10,
"startDate": "2020-10-10",
"endDate": "2020-10-10"
},
"ratings":[],
"numberOfEnrolledStudents": 0,
"releasedDate": "2020-10-10",
}
]
}
POST /requestRefund
A table of body consists of course, type, individualTraineeId, coorporateTraineeId, firstName, lastName, email, refundReason, refundType
Body | Type | Description |
---|---|---|
course |
string |
Required. course of refund |
type |
string |
Required. type of refund |
individualTraineeId |
string |
Required. id of individual trainee |
coorporateTraineeId |
string |
Required. id of coorporate trainee |
firstName |
string |
Required. first name of trainee |
lastName |
string |
Required. last name of trainee |
email |
string |
Required. email of trainee |
refundReason |
string |
Required. reason of refund |
refundType |
string |
Required. type of refund |
Response
{
"message": "refund request sent successfully"
}
GET /getPopularCourses
Code example 💻
try {
const courses = await Course.aggregate([
{
$addFields: {
discountedPrice: {
$cond: [
{
$and: [
{ $lte: ["$promotion.startDate", new Date(Date.now())] },
{ $gte: ["$promotion.endDate", new Date(Date.now())] },
],
},
{
$multiply: [
"$price",
{ $subtract: [1, "$promotion.discount"] },
],
},
"$price",
],
},
},
},
])
.sort({ numberOfTraineesEnrolled: -1 })
.limit(12);
if (!courses) return res.status(404).send({ message: "Courses not found" });
res.status(200).send(courses);
} catch (error) {
console.log(error);
}
};
Response
{
"courses":[
{
"title": "Mern Stack",
"description": "Mern Popular One ",
"price": 100,
"image": "image1",
"instructor": {
"instructorId": "5f7b11be78b93e73d92366f9",
"name":"klllll"
},
"duration": 40,
"subject":"computer science",
"rating": 4.5,
"language": "english",
"rating": 4.5,
"outlines":[],
"reviews":[],
"promotion":{
"discount": 10,
"startDate": "2020-10-10",
"endDate": "2020-10-10"
},
"ratings":[],
"numberOfEnrolledStudents": 15,
"releasedDate": "2020-10-10",
}
]
}
POST /
Body | Type | Description |
---|---|---|
course |
string |
Required. course of refund |
reporterEmail |
string |
Required. email of reporter |
courseId |
string |
Required. id of course |
courseName |
string |
Required. name of course |
type |
string |
Required. type of problem |
details |
string |
Required. details of problem |
Response
{
"reporterEmail": "rro@gmail.com",
"courseId": "5f7b11be78b93e73d92366f9",
"courseName": "Mern Stack",
"type": "money",
"details": "money problem"
}
GET /
Response
{
"reportedProblems": [
{
"reporterEmail": "hm@gmail.com",
"courseId": "5f7b11be78b93e73d92366f9",
"courseName": "Mern Stack",
"type": "money",
"details": "money problem",
"status":"pending",
"date": "2020-10-10",
"response": "",
"date":"2020-10-10"
}
]
}
GET /getReportedProblemByReporterEmail
Response
{
"reporterEmail": "hm@gmail.com",
"courseId": "5f7b11be78b93e73d92366f9",
"courseName": "Mern Stack",
"type": "money",
"details": "money problem",
"status":"pending",
"date": "2020-10-10",
"response": "",
"date":"2020-10-10"
}
PUT /:id
Parameter | Type | Description |
---|---|---|
id |
string |
Required. id of the problem |
A table of body consists of response and status
Body | Type | Description |
---|---|---|
response |
string |
Required. response of the problem |
status |
string |
Required. status of the problem |
Response
{
"reporterEmail": "hm@gmail.com",
"courseId": "5f7b11be78b93e73d92366f9",
"courseName": "Mern Stack",
"type": "money",
"details": "money problem",
"status":"resolved",
"date": "2020-10-10",
"response": "I got you friend",
"date":"2020-10-10"
}
GET /getResolvedProblems
Response
{
"reportedProblems": [
{
"reporterEmail": "hm@gmail.com",
"courseId": "5f7b11be78b93e73d92366f9",
"courseName": "Mern Stack",
"type": "money",
"details": "money problem",
"status":"resolved",
"date": "2020-10-10",
"response": "I got you friend",
"date":"2020-10-10"
}
]
}