Canadian Chamber of Commerce Learning Platform is an online learning and teaching platform meant to allow both students and instructors to be in one simple to use and convenient platform for learning.
As students, we created this project simply because we needed something like it, a place where quality learning can be found with the touch a button. Also as Computer Science students we needed to practice/learn web development, as it is the most popular form of Software development in recent years, so this project was a great entry and got us familiar with the technologies used in that particular field. It is also part of our curriculum CSEN 704.
The project is complete as of January 2023. Unit tests could be added for stress testing.
The project was built with the standard react functional component coding style along with node and express. The client side was divided into page and component folders housing each react component along with the styling. The server side was divided into routes, controllers, and middlewares to serve all the client requests. Prettier was used for formatting all the files. Most of the code was written in camelCase except for react components which were declared using PascalCase. Server routes were written using kebab-case.
Client: React, Axios
Server: Node, Express
Database: MongoDB
- Cross Platform
- Attractive design
- Responsive
- Very streamlined and intuitive
- Efficient and bug free
Server
Our backend is composed of routes that connect to controllers where all the logic is handled.This is an example of one of the routers:
const express = require("express");
const router = express.Router();
const ReviewController = require("../../controllers/ReviewController");
router.get("/my-reviews", ReviewController.getMyReviews);
router.get(
"/my-courses/:id/get-my-reviews",
ReviewController.getTraineeReviews
);
router.post(
"/my-courses/:id/instructors/:id/add-review",
ReviewController.addInstructorReview
);
router.post("/my-courses/:id/add-review", ReviewController.addCourseReview);
router.put(
"/my-courses/:id/instructors/:id/edit-review",
ReviewController.editInstructorReview
);
router.put("/my-courses/:id/edit-review", ReviewController.editCourseReview);
router.delete(
"/my-courses/:id/delete-review",
ReviewController.deleteCourseReview
);
router.delete(
"/my-courses/:id/instructors/:id/delete-review",
ReviewController.deleteInstructorReview
);
module.exports = router;
Here is an example of a controller function:
const getTraineeReviews = async (req, res) => {
const id = req.user.id;
const courseId = req.params.id;
const reviews = {};
const course = await Course.findById(courseId).select({
userReviews: { $elemMatch: { user: id } },
});
const courseInstructors = await Course.findById(courseId).populate(
"instructor"
);
reviews.instructorReview = [];
let i = 0;
for (const instructor of courseInstructors.instructor) {
reviews.instructorReview[i] = instructor.userReviews.find(
(review) => review.user.toString() === id
);
!reviews.instructorReview[i] && (reviews.instructorReview[i] = {});
i++;
}
reviews.courseReview = course.userReviews ? course.userReviews[0] : {};
res.send(reviews);
};
All our routers pass through an authentication middleware for logged in users:
const jwt = require("jsonwebtoken");
const authenticateToken = (req, res, next) => {
if (req.cookies?.jwt && req.cookies?.accessToken) {
const accessToken = req.cookies.accessToken;
const refreshToken = req.cookies.jwt;
let validAccess = false,
validRefresh = false;
let data;
jwt.verify(accessToken, process.env.ACCESS_TOKEN_SECRET, (err, decoded) => {
if (err) {
// Wrong or expired access token
return res.status(401).json({ message: "Unauthorized" });
} else {
validAccess = true;
data = decoded;
}
});
jwt.verify(
refreshToken,
process.env.REFRESH_TOKEN_SECRET,
(err, decoded) => {
if (err) {
// Wrong or expired refresh token
return res
.status(401)
.json({ message: "Unauthorized,expired refresh" });
} else {
validRefresh = true;
}
}
);
if (validAccess && validRefresh) {
req.user = data;
const now = Math.floor(new Date().getTime() / 1000);
const newAccessToken = jwt.sign(
{ ...data, exp: now + 60 * 30 * 4 },
process.env.ACCESS_TOKEN_SECRET
);
res.cookie("accessToken", `${newAccessToken}`);
return next();
} else {
return res
.status(401)
.json({ message: "Unauthorized, some cookies are expired" });
}
} else {
return res
.status(401)
.json({ message: "Unauthorized, some cookies are missing" });
}
};
module.exports = authenticateToken;
Client
The client side is composed of a main router component responsible for resolving user routes to react components. The router works by using a custom PrivateRoute component that redirects unauthorized users to thier respective home pages.
Here is a sample from the router:
{/* Admin */}
<Route
path="/admin/reports"
element={
<PrivateRoute type={"admin"}>
<ReportsPage />
</PrivateRoute>
}
></Route>
{/* Individual */}
<Route
path="/individual-trainee"
element={
<PrivateRoute type={"individual"}>
<TraineeHomePage />
</PrivateRoute>
}
></Route>
This is the PrivateRoute component:
import React from "react";
import { Navigate } from "react-router-dom";
function PrivateRoute({ type, children }) {
if (
localStorage.getItem("type") === type ||
(!localStorage.getItem("type") && type === "guest")
) {
return <> {children} </>;
}
return (
<Navigate
to={
localStorage.getItem("type")
? localStorage.getItem("type") === "individual" ||
localStorage.getItem("type") === "corporate"
? "/" + localStorage.getItem("type") + "-trainee"
: "/" + localStorage.getItem("type")
: "/"
}
/>
);
}
export default PrivateRoute;
Here is an example of a react page:
import app from "../../utils/AxiosConfig.js";
import "./ViewMyCourses.css";
import { useEffect, useState, memo } from "react";
import { useLocation } from "react-router-dom";
import MyFiltersContainer from "../../components/ViewMyCourses/MyFiltersContainer";
import MyCoursesContainer from "../../components/ViewMyCourses/MyCoursesContainer";
import { useSearchParams } from "react-router-dom";
function ViewMyCourses() {
const location = useLocation();
const [courses, setCourses] = useState([]);
const [noCourses, setNoCourses] = useState(false);
const [filter, setFilter] = useState({
searchItem:
location.state?.searchItem !== null &&
location.state?.searchItem !== undefined
? location.state?.searchItem
: null,
});
// eslint-disable-next-line
const [searchParams, setSearchParams] = useSearchParams();
const token = searchParams.get("added");
useEffect(() => {
async function insideEffect() {
//handle somethingggg
if (token != null) {
await app.post("add-course-to-individual", { token }).then((res) => {});
}
setCourses([]);
await app
.get(
localStorage.getItem("type")
? localStorage.getItem("type") === "corporate" ||
localStorage.getItem("type") === "individual"
? "/trainee/my-populated-courses"
: "/" + localStorage.getItem("type") + "/my-populated-courses"
: "/my-populated-courses",
{
headers: {
type: localStorage.getItem("type"),
country: localStorage.getItem("country"),
},
params: { ...filter },
}
)
.then((response) => {
if (response.data.length === 0) setNoCourses(true);
else {
setNoCourses(false);
setCourses(response.data);
}
});
}
insideEffect();
//eslint-disable-next-line
}, [filter]);
return (
<div className="view-courses-wrapper">
{localStorage.getItem("type") === "instructor" && (
<MyFiltersContainer
setFilter={setFilter}
setNoCourses={setNoCourses}
></MyFiltersContainer>
)}
<div className="main-content">
<MyCoursesContainer
courses={courses}
noCourses={noCourses}
></MyCoursesContainer>
</div>
</div>
);
}
export default memo(ViewMyCourses);
Here is the MyCoursesContainer nested within the page:
import { memo } from "react";
import { Spinner } from "loading-animations-react";
import noCourses from "../../assets/ViewCourses/noCourses.svg";
import Pagination from "../../layouts/Pagination/Pagination";
function MyCoursesContainer(props) {
return (
<>
{props.noCourses ? (
<>
<div
style={{
marginBottom: "200px",
width: "100%",
height: "100%",
flexGrow: "1",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}}
>
<img
src={noCourses}
alt="noCourses"
style={{ width: "200px", height: "200px" }}
></img>
<p
style={{ fontSize: "25px", fontWeight: "700", marginTop: "50px" }}
>
You have no courses yet.
</p>
</div>
</>
) : props.courses.length === 0 ? (
<div
style={{
marginBottom: "300px",
width: "100%",
height: "100%",
flexGrow: "1",
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
}}
>
<div style={{ width: "200px", height: "200px" }}>
<Spinner
color1="#96cea8"
color2="#96cea8"
textColor="rgba(0,0,0, 0.5)"
/>
</div>
</div>
) : (
<>
<Pagination items={props.courses} itemsPerPage={12} my={true} />
</>
)}
</>
);
}
export default memo(MyCoursesContainer);
This component employs pagination for a better user experience while also rendering the loading animations while the course data is loading. If no courses are found, an alert is rendered instead.
- Clone the repository
git clone https://github.com/Advanced-Computer-Lab-2022/5AM-club-.git
- Install NPM packages in both client and server
cd 5AM-club-/client
npm install --force
cd ../server
npm install --force
The API routes are divided into 4 groups.
Note: All endpoints were tested using postman to ensure correct response bodies were returned.
Website
This endpoint fetches the contract from the database
GET/contract
Parameters: None.
Accessible by: Instructors
Response
{"content":"This is a contract", "type":"contract"}
This endpoint fetches the terms of service from the database
GET/terms-of-service
Parameters: None.
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors
Response
{"content":"These are the terms of service", "type":"tos"}
User Data
Fetches a user using his id
GET/get-user
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
type |
string |
Required. Specifies the type of user to be fetched. |
Accessible by: Individual Trainees, Corporate Trainees, Instructors, Admins
Response
{"username":"corporate","password":"$2a$08$NZlSVgrj/hjKcWOKuazxB.0vA.777qDpiuPvwt3jotgnhMVEf2YXK","type":"corporate","firstName":"","lastName":"","gender":"","country":"United States","walletMoney":"0","courses":[]}
Fetches all users' data
GET/get-users
Parameter | Type | Description |
---|---|---|
type |
string |
Required. Specifies the type of users to be fetched. |
Accessible by: Individual Trainees, Corporate Trainees, Instructors, Admins
Response
[
{"username":"corporate","password":"$2a$08$NZlSVgrj/hjKcWOKuazxB.0vA.777qDpiuPvwt3jotgnhMVEf2YXK","type":"corporate","firstName":"","lastName":"","gender":"","country":"United States","walletMoney":"0","courses":[]},{"username":"corporate2","password":"$2a$08$Ijewzx9FAKDikvHRWB.Vden4j1OAJAsNpjXf4drMT7DliStn2ggT.","type":"corporate","firstName":"Amr","lastName":"Mohamed","gender":"male","country":"United States","walletMoney":"0","courses":["63b34f81d21f21568822c23a"],"email":"amrmohamedyonis@gmail.com"}]
Fetches the trainee's data associated with a specific course
GET/get-trainee-course
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
courseid |
string |
Required. Specifies the course. |
Accessible by: Individual Trainees, Corporate Trainees
Response
{"courseId":"63b41b88a4407253aa5951ab","traineeId":"63b35175d21f21568822c464","progress":[false],"answers":[["-1","-1","-1","-1"]],"notes":[[]],"lastSection":"0","grades":["0"],"purchasingCost":"999.99","sent":false,"createdAt":"1672748088649","updatedAt":"1672748088649"}
Fetches the instructor of a course
GET/get-course-instructor
Parameter | Type | Description |
---|---|---|
courseid |
string |
Required. Specifies the course. |
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors
Response
{"username":"instructor2","password":"$2a$08$y62vIAnkebL467eUJaSW6OQOeeizU5ZgAiV6U31xdH5tjOkdBTmmC","email":"amr.younis@student.guc.edu.eg","country":"United States","rating":"0","biography":"This is my biography","courses":["63b34f81d21f21568822c23a"],"money_owed":[{"year":"2023","month":"1","amount":"599.98"}],"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"instructor review","rating":"5"}]}
Fetches the type a user using his Id
GET/get-user-type
Parameter | Type | Description |
---|---|---|
userid |
string |
Required. Specifies the user. |
Accessible by: Guests
Response
"Instructor"
Checks if a profile is complete for a user created by the admin
GET/complete-profile
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Corporate Trainees, Instuctors
Response
"true"
Adds an admin user to the database
POST/add-admin
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Admins
Request Body
{"username":"admin","password":"$2a$08$tdURlKJUGvi9QyaTl7q3Yexc6wD.H6JNx4wQhxYxMyObnLZGPaDKy"}
Response
"Admin added successfully!"
Adds an instructor user to the database
POST/add-instructor
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Admins
Request Body
{"username":"instructor","password":"$2a$08$tdURlKJUGvi9QyaTl7q3Yexc6wD.H6JNx4wQhxYxMyObnLZGPaDKy"}
Response
"Instructor added successfully!"
Adds a corporate trainee user to the database
POST/add-corporate-trainee
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Admins
Request Body
{"username":"corporate","password":"Corporate-@2001"}
Response
"Trainee added successfully!"
Adds an individual trainee user to the database
POST/signUp
Parameters: None.
Accessible by: Guests
Request Body
{"username":"admin","password":"Admin-@2001","email":"amrmohamedyonis@gmail.com","gender":"male","firstName":"Amr","lastName":"Mohamed"}
Response
"Trainee added successfully!"
Allow the user to access the main home page
POST/login
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Guests
Request Body
{"username":"admin","password":"Admin-@2001"}
Response
{
"type":"admin",
"username": "admin",
"country":"United States",
}
Logs out a user from the site
GET/logout
Parameters: None.
Accessible by: Individual Trainees, Corporate Trainees, Instructors, Admins
Response
"logging out!!"
Changes the country of a user to the selected country
PUT/set-country
Parameter | Type | Description |
---|---|---|
authorization |
string |
Holds the token for authorization. |
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors, Admins
Request Body
{"country":"egypt"}
Changes the personal information of an instructor in the database
PUT/edit-personal-info
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Instructors
Request Body
{"email":"amrmohamedyonis2@gmail.com","biography":"This is my biography2"}
Response
{"username":"instructor2","password":"$2a$08$y62vIAnkebL467eUJaSW6OQOeeizU5ZgAiV6U31xdH5tjOkdBTmmC","email":"amrmohamedyonis2@gmail.com","country":"United States","rating":"0","biography":"This is my biography2","courses":["63b34f81d21f21568822c23a"],"money_owed":[{"year":"2023","month":"1","amount":"599.98"}],"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"instructor review","rating":"5"}]}
Updates the data of a trainee for a specific course
PUT/edit-trainee-course
Parameter | Type | Description |
---|---|---|
traineeId |
string |
Required. Specifies the trainee. |
courseId |
string |
Required. Specifies the course. |
Accessible by: Individual Trainees, Corporate Trainees.
Request Body
{"progress":[true],"answers":[["-1","-1","-1","-1"]],"notes":[[]],"lastSection":"0","grades":["0"]}
Response
{"courseId":"63b41b88a4407253aa5951ab","63b35175d21f21568822c464","progress":[true],"answers":[["-1","-1","-1","-1"]],"notes":[[]],"lastSection":"0","grades":["0"],"purchasingCost":"999.99","sent":false,"createdAt":"1672748088649","updatedAt":"1672748088649"}
Sends an email to a user to change his/her password
PUT/change-password-email
Parameter | Type | Description |
---|---|---|
email |
string |
Required. The user's email. |
Accessible by: Individual Trainees, Coporate Trainees, Instructors
Response
"email sent"
Submits a report from a user
POST/report-problem
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Individual Trainees, Coporate Trainees, Instructors
Request Body
{
"courseName":"Test Course",
"problemType":"technical",
"problem":"This is a problem"}
Response
"Problem reported successfully!"
Fetches all the submitted problems by a user
GET/view-problems
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Individual Trainees, Corporate Trainees, Instructors
Response
[{"userId":"63b35175d21f21568822c464","username":"individual","courseName":"Test Course","problemType":"financial","problem":"This is a problem 2","status":"unseen","comments":[],"createdAt":"1672696255786","updatedAt":"1672696255786"}]
Adds a follow up to the report
PUT/follow-up
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Specifies the report. |
Accessible by: Individual Trainees, Corporate Trainees, Instructors
Request Body
{"description":"Follow up",
"createdAt":"2023-01-03T12:00:00.947Z"}
Response
"comment added successfully"
Sets the problem status
PUT/set-problem-status
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Specifies the report. |
Accessible by: Admins
Request Body
{"status":"resolved"}
Response
["userId":"63b41653a4407253aa594b8e","username":"hadwa.hassan","courseName":"Test Course","problemType":"technical","problem":"can't refund","status":"resolved","comments":[{"description":"Follow up","createdAt":"2023-01-03T12:00:00.947Z"}],"createdAt":"1672747084528","updatedAt":"1672747227527"},{"userId":"63b34ec7d21f21568822c219","username":"instructor2","courseName":"Test Course","problemType":"technical","problem":"This is a problem","status":"unseen","comments":[],"createdAt":"1672695695111","updatedAt":"1672695695111"}]
Sends a certificate to the trainees by email upon finishing a course
PUT/send-certificate
Parameter | Type | Description |
---|---|---|
courseId |
string |
Required. Specifies the course. |
traineeId |
string |
Required. Specifies the trainee. |
Accessible by: Individual Trainees, Corporate Trainees
Response
"email sent"
Changes the password for a user
PUT/change-password
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Individual Trainees, Corporate Trainees, Instructors
Request Body
{"password":"new password"}
Response
"Password changed successfully"
Changes the password of a user that forgot the old password
PUT/change-forgotten-password
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Specifies the user. |
type |
string |
Required. Specifies the type of the user. |
Accessible by: Guests
Request Body
{"password":"new password"}
Response
"Password changed successfully"
Fetches the amount of money in the wallet of the trainee
GET/wallet-money
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Individual Trainees
Response
"2000"
Pays for a course
POST/pay
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Individual Trainees
Request Body
{"courseId":"63b34f81d21f21568822c23a","coursePrice":"1300","courseName":"Test Course"}
Response
{"url":"http://localhost:3000/individual-trainee/my-courses?added=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0cmFpbmVlSWQiOiI2M2IzNTE3NWQyMWYyMTU2ODgyMmM0NjQiLCJjb3Vyc2VJZCI6IjYzYjM0ZjgxZDIxZjIxNTY4ODIyYzIzYSIsInBhaWRGcm9tV2FsbGV0IjotOTk5Ljk5LCJpYXQiOjE2NzMwMzY0MjcsImV4cCI6MTY3NDMzMjQyN30.bN5dWSOvprZEbWep-Cb0VdvhXl5PVBP3lEj5jwHEK4c"}
Requests a refund
PUT/refund
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Individual Trainees
Request Body
{"courseId":"63b34f81d21f21568822c23a"}
Response
"refunded successfully"
Adds a course to an individual trainee
POST/add-course-to-individual
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Individual Trainees
Request Body
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0cmFpbmVlSWQiOiI2M2IzNTE3NWQyMWYyMTU2ODgyMmM0NjQiLCJjb3Vyc2VJZCI6IjYzYjM0ZjgxZDIxZjIxNTY4ODIyYzIzYSIsInBhaWRGcm9tV2FsbGV0IjotOTk5Ljk5LCJpYXQiOjE2NzMwMzY0MjcsImV4cCI6MTY3NDMzMjQyN30.bN5dWSOvprZEbWep-Cb0VdvhXl5PVBP3lEj5jwHEK4c"}
Response
"bought successfully"
Updates a user's profile
PUT/update-profile
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Corporate Trainees, Instructors
Request Body
{"password":"new password","email":"amrmohamedyoniss@gmail.com","firstName":"Amr","lastName":"Mohamed"}
Response
{"username":"corporate2","password":"$2a$08$Ijewzx9FAKDikvHRWB.Vden4j1OAJAsNpjXf4drMT7DliStn2ggT.","type":"corporate","firstName":"Amr","lastName":"Mohamed","gender":"male","country":"United States","walletMoney":"0","courses":["63b34f81d21f21568822c23a"],"email":"amrmohamedyoniss@gmail.com"}
Updates a user's profile
PUT/update-profile
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Corporate Trainees, Instructors
Request Body
{"password":"new password","email":"amrmohamedyoniss@gmail.com","firstName":"Amr","lastName":"Mohamed"}
Response
{"username":"corporate2","password":"$2a$08$Ijewzx9FAKDikvHRWB.Vden4j1OAJAsNpjXf4drMT7DliStn2ggT.","type":"corporate","firstName":"Amr","lastName":"Mohamed","gender":"male","country":"United States","walletMoney":"0","courses":["63b34f81d21f21568822c23a"],"email":"amrmohamedyoniss@gmail.com"}
Reviews
Fetches the reviews of an instructor
GET/my-reviews
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Instructors
Response
[{
"user":"63b41b22a4407253aa59501d",
"review":"instructor review",
"rating":"5",
}]
Fetches a trainee's reviews for a specific course and its instructors
GET/my-courses/${id}/get-my-reviews
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
id |
string |
Required. Specifies the course |
Accessible by: Individual Trainees, Corporate Trainees
Response
[{"user":"63b41b22a4407253aa59501d",
"review":"instructor review",
"rating":"5"}]
Adds a review and rating for one of the instructors
POST/my-courses/${id}/instructors/${id}/add-review
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
id |
string |
Required. Specifies the Instructor |
Accessible by: Individual Trainees, Corporate Trainees
Request Body
{
"review": "Great Great job",
"rating": "5",
}
Response
"Review added successfully"
Adds a review and rating for an owned course
POST/my-courses/${id}/add-review
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
id |
string |
Required. Specifies the course |
Accessible by: Individual Trainees, Corporate Trainees
Request Body
{
"review": "Average course",
"rating": "2",
}
Response
"Review added successfully"
Edits a review and rating for one of the instructors
PUT/my-courses/${id}/instructors/${id}/edit-review
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
id |
string |
Required. Specifies the instructor |
Accessible by: Individual Trainees, Corporate Trainees
Request Body
{
"review": " not useful",
"rating": "5",
}
Response
"Review edited successfully"
Edits a review and rating for an owned course
PUT/my-courses/${id}/edit-review
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
id |
string |
Required. Specifies the course |
Accessible by: Individual Trainees, Corporate Trainees
Request Body
{
"review": " Above-average course",
"rating": "4",
}
Response
"Review edited successfully"
Deletes a review and rating for an owned course
DELETE/my-courses/${id}/delete-review
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
id |
string |
Required. Specifies the course |
Accessible by: Corporate Trainees, Individual Trainees
Response
"Review deleted successfully"
Deletes a review and rating for one of the instructors
DELETE/my-courses/${id}/instructors/${id}/delete-review
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
id |
string |
Required. Specifies the instructor |
Accessible by: Corporate Trainees, Individual Trainees
Response
"Review deleted successfully"
Courses
Fetches the user's courses
GET/my-courses
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Corporate Trainees, Instructors
Request Body
{"password":"new password","email":"amrmohamedyoniss@gmail.com","firstName":"Amr","lastName":"Mohamed"}
Response
{"username":"corporate2","password":"$2a$08$Ijewzx9FAKDikvHRWB.Vden4j1OAJAsNpjXf4drMT7DliStn2ggT.","type":"corporate","firstName":"Amr","lastName":"Mohamed","gender":"male","country":"United States","walletMoney":"0","courses":["63b34f81d21f21568822c23a"],"email":"amrmohamedyoniss@gmail.com"}
Fetches all published courses
GET/courses
Parameter | Type | Description |
---|---|---|
min |
string |
Required. Specifies the minimum course price. |
max |
string |
Required. Specifies the maximum course price. |
subject |
string |
Required. Specifies the subjects of the course. |
rating |
string |
Required. Specifies the minimum rating of the course. |
searchItem |
string |
Required. Specifies the search query used to search for the course.. |
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors
Response
[{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":["63b35175d21f21568822c464","63b34ed7d21f21568822c21c","63b41653a4407253aa594b8e","63b41922a4407253aa594dfd","63b41b22a4407253aa59501d"],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}]
Fetches the data of owned courses with any data associated with it (like instructors data, owners data ...etc)
GET/my-populated-courses
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
min |
string |
Required. Specifies the minimum course price. |
max |
string |
Required. Specifies the maximum course price. |
subject |
string |
Required. Specifies the subjects of the course. |
rating |
string |
Required. Specifies the minimum rating of the course. |
searchItem |
string |
Required. Specifies the search query used to search for the course.. |
Accessible by: Individual Trainees, Corporate Trainees, Instructors
Response
[{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":[object],"owners":[object,object,object,object,object],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}]
Fetches the data of all courses with any data associated with it (like instructors data, owners data ...etc)
GET/populated-courses
Parameter | Type | Description |
---|---|---|
min |
string |
Required. Specifies the minimum course price. |
max |
string |
Required. Specifies the maximum course price. |
subject |
string |
Required. Specifies the subjects of the course. |
rating |
string |
Required. Specifies the minimum rating of the course. |
searchItem |
string |
Required. Specifies the search query used to search for the course.. |
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors
Response
[{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":[object],"owners":[object,object,object,object,object],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}]
Fetches the maximum and minimum price of owned courses
GET/my-courses/my-course-max-min
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
min |
string |
Required. Specifies the minimum course price. |
max |
string |
Required. Specifies the maximum course price. |
subject |
string |
Required. Specifies the subjects of the course. |
rating |
string |
Required. Specifies the minimum rating of the course. |
searchItem |
string |
Required. Specifies the search query used to search for the course.. |
Accessible by: Individual Trainees, Corporate Trainees, Instructors
Response
{"min":"200","max":"500"}
Fetches the maximum and minimum price of all courses
GET/courses/course-max-min
Parameter | Type | Description |
---|---|---|
min |
string |
Required. Specifies the minimum course price. |
max |
string |
Required. Specifies the maximum course price. |
subject |
string |
Required. Specifies the subjects of the course. |
rating |
string |
Required. Specifies the minimum rating of the course. |
searchItem |
string |
Required. Specifies the search query used to search for the course.. |
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors
Response
{"min":"100","max":"550"}
Fetches the subjects of owned courses
GET/courses/my-course-subjects
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
min |
string |
Required. Specifies the minimum course price. |
max |
string |
Required. Specifies the maximum course price. |
subject |
string |
Required. Specifies the subjects of the course. |
rating |
string |
Required. Specifies the minimum rating of the course. |
searchItem |
string |
Required. Specifies the search query used to search for the course.. |
Accessible by: Individual Trainees, Corporate Trainees, Instructors
Response
["subject 1","test subject"]
Fetches the subjects of all courses
GET/courses/course-subjects
Parameter | Type | Description |
---|---|---|
min |
string |
Required. Specifies the minimum course price. |
max |
string |
Required. Specifies the maximum course price. |
subject |
string |
Required. Specifies the subjects of the course. |
rating |
string |
Required. Specifies the minimum rating of the course. |
searchItem |
string |
Required. Specifies the search query used to search for the course.. |
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors
Response
["subject 1","test subject","sub","sub2"]
Increment the number of views for a course
PUT/my-courses/increment-views${id}
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Specifies the course. |
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors
Response
[{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":[object],"owners":[object,object,object,object,object],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}]
Fetches a specific course
GET/courses/${courseId}
Parameter | Type | Description |
---|---|---|
min |
string |
Required. Specifies the minimum course price. |
max |
string |
Required. Specifies the maximum course price. |
subject |
string |
Required. Specifies the subjects of the course. |
rating |
string |
Required. Specifies the minimum rating of the course. |
searchItem |
string |
Required. Specifies the search query used to search for the course.. |
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":["63b35175d21f21568822c464","63b34ed7d21f21568822c21c","63b41653a4407253aa594b8e","63b41922a4407253aa594dfd","63b41b22a4407253aa59501d"],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}
Fetches a specific course with any data associated with it (like instructors data, owners data ...etc)
GET/populated-courses/${courseId}
Parameter | Type | Description |
---|---|---|
min |
string |
Required. Specifies the minimum course price. |
max |
string |
Required. Specifies the maximum course price. |
subject |
string |
Required. Specifies the subjects of the course. |
rating |
string |
Required. Specifies the minimum rating of the course. |
searchItem |
string |
Required. Specifies the search query used to search for the course.. |
Accessible by: Guests, Individual Trainees, Corporate Trainees, Instructors
Response
[{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":[object],"owners":[object,object,object,object,object],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}]
Adds a corporate course request
PUT/courses/${courseId}/course-request
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
courseId |
string |
Required. Specifies the course. |
Accessible by: Corporate Trainees
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":["63b35175d21f21568822c464","63b34ed7d21f21568822c21c","63b41653a4407253aa594b8e","63b41922a4407253aa594dfd","63b41b22a4407253aa59501d"],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}
Accepts a corporate course request
PUT/courses/${courseId}/accept-course-request
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
courseId |
string |
Required. Specifies the course. |
traineeId |
string |
Required. Specifies the trainee. |
Accessible by: Admins
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":["63b35175d21f21568822c464","63b34ed7d21f21568822c21c","63b41653a4407253aa594b8e","63b41922a4407253aa594dfd","63b41b22a4407253aa59501d"],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}
Rejects a corporate course request
PUT/courses/${courseId}/reject-course-request
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
courseId |
string |
Required. Specifies the course. |
traineeId |
string |
Required. Specifies the trainee. |
Accessible by: Admins
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":["63b35175d21f21568822c464","63b34ed7d21f21568822c21c","63b41653a4407253aa594b8e","63b41922a4407253aa594dfd","63b41b22a4407253aa59501d"],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}
Fetches all corporate requests for courses
GET/course-requests
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Admins
Response
{"pending":[object],"accepted":[object,object,object,object,object],"rejected":[]}
Fetches all reports issued by users
GET/reports
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Admins
Response
["userId":"63b35175d21f21568822c464","username":"individual","courseName":"Test Course","problemType":"financial","problem":"This is a problem 2","status":"unseen","comments":[],"createdAt":"1672696255786","updatedAt":"1672696255786"},{"userId":"63b34ec7d21f21568822c219","username":"instructor2","courseName":"Test Course","problemType":"technical","problem":"This is a problem","status":"unseen","comments":[],"createdAt":"1672695695111","updatedAt":"1672695695111"}]
Creates a new course
POST/create-course
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
Accessible by: Instructors
Request Body
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description"}
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"0","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":[],"published":true,"closed":false,"userReviews":[],"accepted":[],"pending":[],"rejected":[],"subtitles":[],"createdAt":"1672695681007","updatedAt":"1672695681007"}
Deletes a specified course
DELETE/my-courses/${courseId}/delete-course
Parameter | Type | Description |
---|---|---|
authorization |
string |
Required. Holds the token for authorization. |
id |
string |
Required. Specifies the course. |
Accessible by: Instructors
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"0","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":[],"published":true,"closed":false,"userReviews":[],"accepted":[],"pending":[],"rejected":[],"subtitles":[],"createdAt":"1672695681007","updatedAt":"1672695681007"}
Edits course details
PUT/my-courses/edit-course/${courseid}
Parameter | Type | Description |
---|---|---|
courseid |
string |
Required. Specifies the course. |
Accessible by: Instructors
Request Body
{"title":"Test Course 5","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"0","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":[],"published":true,"closed":false,"userReviews":[],"accepted":[],"pending":[],"rejected":[],"subtitles":[],"createdAt":"1672695681007","updatedAt":"1672695681007"}
Response
{"title":"Test Course 5","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"0","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":[],"published":true,"closed":false,"userReviews":[],"accepted":[],"pending":[],"rejected":[],"subtitles":[],"createdAt":"1672695681007","updatedAt":"1672695681007"}
Adds a section to a specified subtitle
PUT/my-courses/edit-course/${courseid}/${subtitleid}/add-section
Parameter | Type | Description |
---|---|---|
courseid |
string |
Required. Specifies the course. |
subtitleid |
string |
Required. Specifies the subtitle. |
Accessible by: Instructors
Request Body
{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]}
Response
{"title":"Test Course 5","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"0","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":[],"published":true,"closed":false,"userReviews":[],"accepted":[],"pending":[],"rejected":[],"subtitles":[],"createdAt":"1672695681007","updatedAt":"1672695681007"}
Adds a subtitle to a specific course
PUT/my-courses/edit-course/${courseid}/add-subtitle
Parameter | Type | Description |
---|---|---|
courseid |
string |
Required. Specifies the course. |
Accessible by: Instructors
Request Body
{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]}
Response
{"title":"Test Course 5","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"0","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":[],"published":true,"closed":false,"userReviews":[],"accepted":[],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[],"createdAt":"1672695681007","updatedAt":"1672695681007"}
Edits a specified subtitle to a specific course
PUT/my-courses/edit-course/${courseid}/edit-subtitle/${subtitleid}
Parameter | Type | Description |
---|---|---|
courseid |
string |
Required. Specifies the course. |
Accessible by: Instructors
Request Body
{"title":"Test Subtitle 5","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]}
Response
{"title":"Test Course 5","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"0","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":[],"published":true,"closed":false,"userReviews":[],"accepted":[],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 5","description":"Subtitle 1 Description","sections":[],"createdAt":"1672695681007","updatedAt":"1672695681007"}
Edits a specified section in a specific subtitle to a specific course
PUT/my-courses/edit-course/${courseid}/${subtitleid}/edit-section/${sectionid}
Parameter | Type | Description |
---|---|---|
courseid |
string |
Required. Specifies the course. |
subtitleid |
string |
Required. Specifies the subtitle. |
sectionid |
string |
Required. Specifies the section. |
Accessible by: Instructors
Request Body
{"title":"Test Excercise 5","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]}
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":["63b35175d21f21568822c464","63b34ed7d21f21568822c21c","63b41653a4407253aa594b8e","63b41922a4407253aa594dfd","63b41b22a4407253aa59501d"],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 5","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}
Deletes a specified subtitle to a specific course
PUT/my-courses/edit-course/${courseid}/delete-subtitle/${subtitleid}/
Parameter | Type | Description |
---|---|---|
courseid |
string |
Required. Specifies the course. |
Accessible by: Instructors
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":["63b35175d21f21568822c464","63b34ed7d21f21568822c21c","63b41653a4407253aa594b8e","63b41922a4407253aa594dfd","63b41b22a4407253aa59501d"],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}
Deletes a specified section in a specific subtitle to a specific course
PUT/my-courses/edit-course/${courseid}/${subtitleid}/delete-section/${sectionid}
Parameter | Type | Description |
---|---|---|
courseid |
string |
Required. Specifies the course. |
subtitleid |
string |
Required. Specifies the subtitle. |
sectionid |
string |
Required. Specifies the section. |
Accessible by: Instructors
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":["63b35175d21f21568822c464","63b34ed7d21f21568822c21c","63b41653a4407253aa594b8e","63b41922a4407253aa594dfd","63b41b22a4407253aa59501d"],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}
Sets a promotion on a course
PUT/my-courses/${courseid}/set-promotion
Parameter | Type | Description |
---|---|---|
id |
string |
Required. Specifies the course. |
Accessible by: Instructors
Request Body
{
"percentage": "100",
"startDate": "2023-01-03T12:15:23.000+00:00",
"endDate": "2023-01-04T13:19:23.000+00:00"
}
Response
{"title":"Test Course","price":"299.99","subject":["Test Subject","Test Subject 2"],"views":"10","preview_video":"https://www.youtube.com/watch?v=C0DPdy98e4c","summary":"This is a description","instructor":["63b34ec7d21f21568822c219"],"owners":["63b35175d21f21568822c464","63b34ed7d21f21568822c21c","63b41653a4407253aa594b8e","63b41922a4407253aa594dfd","63b41b22a4407253aa59501d"],"published":true,"closed":false,"userReviews":[{"user":"63b41b22a4407253aa59501d","review":"course review","rating":"5",}],"accepted":[{"trainee":"63b34ed7d21f21568822c21c","date":"1672696364291"},{"trainee":"63b41922a4407253aa594dfd","date":"1672747649513"},{"trainee":"63b41b22a4407253aa59501d","date":"1672747842457"}],"pending":[],"rejected":[],"subtitles":[{"title":"Test Subtitle 1","description":"Subtitle 1 Description","sections":[{"title":"Test Excercise 1","minutes":"40","description":"Excercise 1 Description","content":{"exercise":{"questions":["Question 1","Question 2"],"choices":[{"c1":"Correct Answer","c2":"Wrong 1","c3":"Wrong 2","c4":"Wrong 3"},{"c1":"Wrong 1","c2":"Wrong 2","c3":"Correct Answer","c4":"Wrong 3"}],"answers":["1","3"]},},},{"title":"Test Video 1 ","minutes":"0","description":"Video 1 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}},{"title":"Test Exercise 2","minutes":"20"},"description":"Exercise 2 Description","content":{"exercise":{"questions":["Question 3"],"choices":[{"c1":"Wrong 1","c2":"Wrong 2","c3":"Wrong 3","c4":"Correct Answer"}],"answers":["4"]}}}]},{"title":"Test Subtitle 2","description":"Subtitle 2 Description","sections":[{"title":"Test Video 2","minutes":"0","description":"Video 2 Description","content":{"video":{"link":"https://www.youtube.com/watch?v=C0DPdy98e4c"}}}]}}],"createdAt":"1672695681007","updatedAt":"1672748201914","promotion":{"percentage":"100","startDate":"1672748123000","endDate":"1672838363000","type":"admin"}}
Sets a promotion for multiple courses
PUT/set-multiple-promotions
Parameters: None.
Accessible by: Instructors
Request Body
{
"courses":["63b34f81d21f21568822c23a","63b419a4a4407253aa594e2c"]
"percentage": "100",
"startDate": "2023-01-03T12:15:23.000+00:00",
"endDate": "2023-01-04T13:19:23.000+00:00"
}
Response
"done"
Testing was done using postman. Check out the API References section above for all the endpoints.
Run this command in the server folder
node index
and this command in the client folder
npm start
then you can proceed to use the website.
After running the project, you can search and browse the available courses. You can then proceed to create an account to buy and take our courses. After signing up, you can purchase a course using your credit card information. Then the course is added to your catalog and you can view it at any time. You get a completion certificate for each course you finish. Happy Learning!
After running the project, you can proceed to login with your information. You can then use our wizard to create and edit your courses. Once you are happy with the content, you can publish your course. Now all you need to do is wait for our userbase to start buying your course. You can check your profile to see the money owed for each month since you were first added to the site as a user.
After running the project, you can proceed to login with your information. You can select from the panels what action you want to perform. This includes add promotions to any course, adding new users, viewing and resolving user reports on courses, and accepting corporate requests for course access.
You can open an issue if you have any suggestions for us to implement or you can create a branch directly and submit a pull request with your changes. For any inquiries you can email us at 5amclubacl@gmail.com.