0% found this document useful (0 votes)
4 views151 pages

STUDIPAL Project1

The document is a project report on 'STUDIPAL', an online study courses website developed for students to access educational resources and improve their learning experience. It outlines the project's objectives, feasibility study, tools used, and hardware/software requirements, emphasizing the importance of digital learning. The report is submitted for partial fulfillment of the BCA degree at Desh Bhagat University.

Uploaded by

mehleenkaur3
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views151 pages

STUDIPAL Project1

The document is a project report on 'STUDIPAL', an online study courses website developed for students to access educational resources and improve their learning experience. It outlines the project's objectives, feasibility study, tools used, and hardware/software requirements, emphasizing the importance of digital learning. The report is submitted for partial fulfillment of the BCA degree at Desh Bhagat University.

Uploaded by

mehleenkaur3
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

PROJECT REPORT

ON
STUDIPAL

Submitted to
In Partial Fulfilment of the requirements for the degree of
Desh Bhagat University
TH
(BCA 6 Semester)

Project Guide: Submitted By


Mr Rahul Thour Name:- Dilpreet Singh
Roll No.
ACKNOWLEDGEMENT
The successful completion of this work is a great joy. We would
like to express my gratitude to all those who have been of great
help during this effort. We are grateful Department of Computer
Science & Applications, Desh Bhagat University, Mandi
Gobindgarh. For providing the opportunity to carry out this work.

We are extremely grateful and remain indebted to our guide Mr.


TEACHER NAME for being a source of inspiration and for his
constant support in the Design, Implementation and Evaluation
of the project. We are thankful to them for their constant
constructive criticism and invaluable suggestions, which
benefited us a lot while developing the project on “PROJECT
NAME ”. They have been a constant source of inspiration and
motivation for hard work. They have been a constant source of
inspiration and motivation for hard work. They have been very
co-operative throughout this project work. Through this column,
it would be our utmost pleasure to express our warm thanks to
him for their encouragement, co-operation and consent without
which we mightn’t be able to accomplish this project.

We also express our gratitude to Mr. HOD NAME (HOD) for


providing us the infrastructure to carry out the project and to all
staff members who were directly and indirectly instrument in
enabling us to stay committed for the project.
DILPREET SINGH
DATE: ___________
DECLARATION FROM STUDENTS

We hereby declare that the work, which is presented in this


report for the partial fulfillment for the award of the BCA , is an
authentic record of work carried by us during Fourth Semester.

No part of this has been submitted to any other University or


Institution for the award of any other degree or diploma

PLACE: LUDHIANA PROJECT GUIDE


Date:
Table Of Content

S. TITLE Page No.


No.

1. Introduction to project

2. Objectives of project

3. Feasibility study

4. Database design

5. Tools Used

6. Hardware and software requirements

7. Coding

8. Output

9. Future Scope

10. Bibliography
Introduction To Project

STUDIPAL is an online study courses website designed to


provide students with easy access to educational resources,
online courses, study materials, and learning support services.
The platform helps students improve their knowledge and skills
through a simple and user-friendly interface.
The website offers different categories of courses such as
programming, web development, computer science, and other
academic subjects. Students can explore courses, view
learning materials, and access educational content anytime and
anywhere through the internet.
STUDIPAL is developed to make online learning more
convenient, interactive, and accessible for students. The project
also helps in understanding modern web technologies,
database management, and frontend-backend integration used
in educational platforms.
This project aims to support digital learning and provide a
better online education experience for students through an
organized and efficient study platform.
Objective of Project

The main objective of the STUDIPAL project is to provide


students with an easy and effective online learning platform
where they can access study courses, educational materials,
and learning resources from anywhere.
This project aims to make education more accessible,
organized, and user-friendly for students. The website is
designed to help learners improve their skills and knowledge
through online courses and digital learning support.
The major objectives of the project are:
 To provide online study courses in different subjects and
technologies.
 To create a simple and interactive platform for students.
 To help students access learning materials anytime and
anywhere.
 To improve the online learning experience through a user-
friendly interface.
 To develop practical knowledge of web development and
database management.
 To encourage digital learning and modern education
methods.

The project also focuses on making the learning process more


convenient, efficient, and beneficial for students.
Feasibility Study
What Is a Feasibility Study?
A feasibility study is an assessment of the practicality of a
proposed plan or project. It analyse the viability of a project to
determine whether the project or venture is likely to succeed.
The study is also designed to identify potential issues and
problems that could arise while pursuing the project.
Key Takeaways:
 A feasibility study assesses the potential success of a
proposed project by defining its expected costs and
projected benefits in detail.
 A feasibility study helps determine whether an online
learning platform like STUDIPAL can successfully meet
student needs and educational goals.
 It is useful to have a backup plan in case the original
project faces technical or operational difficulties.
How to Conduct a Feasibility Study?
The exact format of a feasibility study depends on the type of
project or organization. However, the following important
factors are generally involved:
 Conduct a preliminary analysis and collect feedback from
students, teachers, and users regarding the online study
platform.
 Analyse the collected data carefully to ensure the
information is accurate and useful.
 Conduct market research to identify the demand for online
study courses and digital learning platforms.
 Prepare an operational and project plan, including the
technologies, tools, and resources required for
development.
 Estimate development cost, maintenance cost, and future
improvements of the website.
 Prepare a projected report including expected benefits,
usability, and performance of the project.
 Identify possible technical issues, security concerns, and
user-related challenges, along with solutions for handling
them.
 Make a final decision regarding the successful
implementation of the project.
Main Objective of a Feasibility Study
The main objective of the feasibility study is to determine
whether the STUDIPAL online study courses website can be
developed successfully and used effectively by students. It
helps identify technical, financial, and operational requirements
while ensuring that the project can fulfil educational needs
efficiently.
Steps in a Feasibility Study
A feasibility study begins with a preliminary analysis. Feedback
is collected from users, market research is conducted, and the
project plan is prepared. All collected information is analyzed to
make an initial decision about the project.
If the project is feasible, the next stage includes identifying
technological requirements, studying user needs, preparing the
development strategy, outlining human resource requirements,
scheduling project activities, and estimating financial
requirements.
Who Conducts a Feasibility Study?
A feasibility study may be conducted by project developers,
faculty members, project guides, or technical experts. If
required, organizations may also hire professional consultants
for detailed analysis and guidance.
Types of Feasibility
A feasibility study considers the feasibility of four important
aspects of a project:
 Technical Feasibility: Identifies the hardware, software,
internet requirements, and technical skills needed to
develop and maintain the STUDIPAL website.
 Financial Feasibility: Estimates the overall project cost,
maintenance expenses, and expected benefits of the
platform.
 Market Feasibility: Analyse the growing demand for online
learning platforms, educational websites, student users,
and digital learning opportunities.
 Organizational Feasibility: Describes the management
structure, educational content handling, and support
system required for successful project operation.

Tools Used
The following tools were used to complete the STUDIPAL
project:
 Visual Studio Code
 HTML
 CSS
 JavaScript
 Notepad
 Database Management System
Visual Studio Code
Visual Studio Code is a powerful and lightweight code editor
used for developing websites and software applications. It
provides an efficient environment for writing, editing, debugging,
and managing code.
With support for multiple programming languages and
extensions, Visual Studio Code helps developers create
responsive and user-friendly web applications such as
STUDIPAL.
Why Use Visual Studio Code?
 Easy and user-friendly interface
 Fast and efficient code editing
 Support for HTML, CSS, JavaScript, and many other
languages
 Built-in debugging features
 Extension support for additional functionality
 Integrated terminal and version control support
Develop Your Code
Visual Studio Code provides useful features such as syntax
highlighting, auto-completion, code suggestions, and project
organization tools that help developers write clean and efficient
code.
Debug Your Code
The debugging tools in Visual Studio Code help identify and fix
errors quickly. Developers can test functionality, monitor
variables, and improve website performance effectively.
Test Your Code
Testing tools help ensure that the STUDIPAL website functions
correctly and provides a smooth user experience for students
and users.
Deploy Your App
After development and testing, the STUDIPAL website can be
deployed on web servers or hosting platforms so students can
access online study courses and educational resources
through the internet.

HTML BASICS

HTML Introduction- HTML stands for Hypertext Markup


Language. It is the standard language used to create and
structure content on the web. HTML is a markup language, not
a programming language, meaning it annotates text to define
how it is structured and displayed by web browsers. It forms
the building blocks of all websites and is complemented by CSS
for style and JavaScript for interactivity.

Why Learn HTML?-

Here are 5 common reasons to learn HTML:

1. Build Websites: HTML is the basic building block for


creating any website. Learning HTML can help you pursue a
career in web development.
2. Customize Content: Allows you to edit or tweak web
pages, emails, or templates to fit your needs.
3. Understand how the web works: Helps you grasp how the
internet works and how web pages are structured.
4. Employment Opportunities: According to Bureau of Labor
Statistics projects that employment for web developers will
grow 16% between 2022-2032, which is much faster than
the average across all occupations.
5. Learn Easily: HTML is beginner-friendly, making it a great
first step into the world of coding and technology

Features of HTML-
• It is easy to learn and easy to use.
• It is platform-independent.
• Images, videos, and audio can be added to a web
page.
• Hypertext can be added to the text.

• It is a markup language.

HTML Element and HTML Tag- HTML Element and HTML Tags
are related but distinct. An HTML element is the complete
structure, including the opening tag, content (if any), and the
closing tag (if applicable). On the other hand, A tag is the actual
keyword or name enclosed in angle brackets (< >) that tells the
browser what kind of content to expect.
HTML Page Structure- The basic structure of an HTML page is
shown below. It contains the essential building-block elements
(i.e. doctype declaration, HTML, head, title, and body elements)
upon which all web pages are created.

• <!DOCTYPE html> – This is the document type


declaration, not a tag. It declares that the document is an
HTML5 document.
• <html> – This is called the HTML root element. All
other elements are contained within it.
• <head> – The head tag contains the “behind the
scenes” elements for a webpage. Elements within the
head aren’t visible on the front end of a webpage.
• <title> – The title is what is displayed on the top of
your browser when you visit a website and contains the
title of the webpage that you are viewing.
• <p>– The <p> tag represents a paragraph of text.
• <body> – The body tag is used to enclose all the
visible content of a webpage. In other words, the body
content is what the browser will show on the front end.
Open Notepad: Search for "notepad" in the Windows
search bar and open the application.

An HTML document can be created using an HTML text editor.


Save the text file using the “.html” or “.html” extension. Once
saved as an HTML document, the file can be opened as a
webpage in the browser.

NOTEPAD

Notepad is a simple, built-in text editor that allows you to open,


edit, and save text files, including HTML files. One can
absolutely use Notepad, the basic text editor in Windows, to
edit and create HTML files, though it's a simple tool without
advanced features like syntax highlighting or live previews.
How to use it for HTML:
• Open Notepad: Search for "notepad" in the Windows
search bar and open the application.
• Type your HTML code: Enter your HTML code into
the Notepad window, using tags and other HTML
elements.

• Save as an HTML file: Go to "File" > "Save As" and


choose a location to save the file. In the "Save as type"
dropdown, select "All Files" and then enter a filename with
the ".html" extension (e.g., "my_page.html"). • Open in
a browser: Double-click the saved HTML file to open it in
your default web browser.

MICROSOFT WORD

Microsoft Word (MS Word) is a widely used word processor


software developed by Microsoft, part of the Microsoft Office
suite, used for creating and editing documents like letters,
reports, and resumes, with files typically saved with a .docx
extension.
Functionality: MS Word allows users to create,

format, and edit documents, offering features like spell
check, grammar check, thesaurus, tracking changes, and
mail merge.
• Features: MS Word offers advanced features for
formatting and editing documents, including specialized
tools for designing, spelling and grammar checks, and an
integrated thesaurus..
• Uses: Creating Documents, Writing and formatting
letters, reports, resumes, essays, and other documents.
MS Word is a popular tool for students and researchers.

CASCADING STYLE SHEETS(CSS)

Cascading Style Sheets (CSS) is a style sheet language used


for specifying the presentation and styling of a document
written in a markup language such as HTML or XML. CSS is a
cornerstone technology of the World Wide Web, alongside
HTML and JavaScript.
CSS is designed to enable the separation of content and
presentation, including layout, colours, and fonts. This
separation can improve content accessibility, since the content
can be written without concern for its presentation; provide
more flexibility and control in the specification of presentation
characteristics; enable multiple web pages to share formatting
by specifying the relevant CSS in a separate .CSS file, which
reduces complexity and repetition in the structural content; and
enable the .CSS file to be cached to improve the page load
speed between the pages that share the file and its formatting.

HYPERTEXT PRE-PROCESSING(PHP)

PHP (originally standing for "Personal Home Page" but now a


recursive acronym for "PHP: Hypertext Preprocessor") is a
widely used, open-source, server-side scripting language
primarily used for web development, allowing developers to
create dynamic web pages and applications.
Here's a more detailed look at PHP:

Key Features:

• Server-Side Scripting: PHP code is executed on the server


before being sent to the client's browser, allowing for dynamic
content generation and database interaction.
• Dynamic Content: PHP enables the creation of web pages
that change based on user input, database data, or other
factors.
• Database Integration: PHP provides built-in functions for
interacting with various databases, including MySQL,
PostgreSQL, and others.
HTML Embedding: PHP code can be easily embedded

within HTML, simplifying the process of creating dynamic web


pages.
HARDWARE AND SOFTWARE REQUIREMENTS

Hardware requirements:

Hardware Requirements

Processor Premium 2.6GHz

Random Access 1GB RAM


Memory

Hard Disk 180 GB

Display Direct X9 capable video and running


1024x768 or higher resolution display

Mouse Mouse or compatible devices

Keyboard Keyboard or any compatible devices

Printer Laser jet

Software requirements:

SOFTWARE REQUIREMENTS

Operating system Microsoft windows versions


23H2/ Windows 11

Front End Visual Studio Code 2022

Back End Microsoft Edge


SOURCE CODE
[Link]

import { useState } from "react";

import { Link, useLocation } from "react-router-dom";

import { Menu, X, ChevronDown } from "lucide-react";

import { useUser } from "../context/UserContext";

export default function Navbar() {

const [isOpen, setIsOpen] = useState(false);

const [loginOpen, setLoginOpen] = useState(false);

const location = useLocation();

const { user } = useUser(); //logged-in user from context

const toggleMenu = () => setIsOpen(!isOpen);

const handleCloseMenu = () => {

setIsOpen(false);

setLoginOpen(false);

};

const navLinks = [

{ to: "/", label: "Dashboard" },

{ to: "/courses", label: "Courses" },

{ to: "/about", label: "About" },

{ to: "/contact", label: "Contact" },

];

const isActive = (path) => [Link] === path;


// Hide Navbar

if (

[Link]("/user/dashboard") ||

[Link]("/mentor/dashboard") ||

[Link]("/admin/dashboard") ||

[Link]("/course-lessons") ||

[Link]("/course/") && [Link]("/lessons")

){

return null;

return (

<nav className="bg-white shadow-md sticky top-0 z-50">

<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">

<div className="flex justify-between h-16 items-center">

{/* Logo */}

<div className="flex items-center">

<Link to="/" className="text-2xl font-bold text-indigo-600">

Studipal

</Link>

</div>

{/* Desktop Menu */}

<div className="hidden md:flex space-x-8 items-center">

{[Link]((link) => (

<Link

key={[Link]}

to={[Link]}

className={`${

isActive([Link])
? "text-indigo-600 font-semibold"

: "text-gray-700 hover:text-indigo-600"

}`}

>

{[Link]}

</Link>

))}

{/* Show Login dropdown*/}

{!user && (

<div className="relative">

<button

onClick={() => setLoginOpen(!loginOpen)}

className="flex items-center px-4 py-2 bg-white text-indigo-600 rounded-


lg font-medium hover:bg-gray-100"

>

Login <ChevronDown className="ml-1 w-4 h-4" />

</button>

{loginOpen && (

<div className="absolute right-0 mt-2 bg-white text-black rounded-lg


shadow-lg w-40">

<Link

to="/user/login"

onClick={handleCloseMenu}

className="block px-4 py-2 hover:bg-gray-100"

>

User

</Link>

<Link

to="/mentor/login"
onClick={handleCloseMenu}

className="block px-4 py-2 hover:bg-gray-100"

>

Mentor

</Link>

<Link

to="/admin/login"

onClick={handleCloseMenu}

className="block px-4 py-2 hover:bg-gray-100"

>

Admin

</Link>

</div>

)}

</div>

)}

</div>

{/* Mobile Menu Button */}

<div className="md:hidden flex items-center">

<button

onClick={toggleMenu}

className="text-gray-700 focus:outline-none"

>

{isOpen ? <X size={24} /> : <Menu size={24} />}

</button>

</div>

</div>

</div>
{/* Mobile Menu */}

{isOpen && (

<div className="md:hidden bg-white shadow-lg">

<div className="px-4 py-4 space-y-2">

{[Link]((link) => (

<Link

key={[Link]}

to={[Link]}

onClick={handleCloseMenu}

className={`block ${

isActive([Link])

? "text-indigo-600 font-semibold"

: "text-gray-700 hover:text-indigo-600"

}`}

>

{[Link]}

</Link>

))}

{/*Show Login dropdown*/}

{!user && (

<div>

<button

onClick={() => setLoginOpen(!loginOpen)}

className="w-full flex justify-between items-center bg-indigo-600 text-


white py-2 px-4 rounded-lg hover:bg-indigo-700"

>

Login

<ChevronDown

className={`ml-2 w-4 h-4 transform transition-transform ${

loginOpen ? "rotate-180" : ""


}`}

/>

</button>

{loginOpen && (

<div className="mt-2 bg-white border rounded-lg shadow-lg">

<Link

to="/user/login"

onClick={handleCloseMenu}

className="block px-4 py-2 text-gray-700 hover:bg-gray-100"

>

User

</Link>

<Link

to="/mentor/login"

onClick={handleCloseMenu}

className="block px-4 py-2 text-gray-700 hover:bg-gray-100"

>

Mentor

</Link>

<Link

to="/admin/login"

onClick={handleCloseMenu}

className="block px-4 py-2 text-gray-700 hover:bg-gray-100"

>

Admin

</Link>

</div>

)}

</div>
)}

</div>

</div>

)}

</nav>

);

CONTEXT
[Link]

// src/context/[Link]

import { createContext, useContext, useState, useEffect } from "react";

import axios from "axios";

import { useNavigate } from "react-router-dom";

const AdminContext = createContext();

export const AdminProvider = ({ children }) => {

const [admin, setAdmin] = useState(null);

const [token, setToken] = useState([Link]("adminToken"));

const [loading, setLoading] = useState(false);

const navigate = useNavigate();

const login = async (email, password) => {

try {

setLoading(true);

const res = await [Link](

"[Link]

{ email, password },
{ withCredentials: true }

);

if ([Link]?.token) {

setToken([Link]);

setAdmin([Link]);

[Link]("adminToken", [Link]);

[Link]("role", "admin");

navigate("/admin/dashboard");

} catch (error) {

throw [Link]?.data?.message || "Login failed";

} finally {

setLoading(false);

};

const logout = () => {

setAdmin(null);

setToken(null);

[Link]("adminToken");

[Link]("role");

navigate("/", { replace: true });

};

useEffect(() => {

const fetchAdmin = async () => {

if (!token) return;

try {

const res = await [Link]("[Link] {


headers: { Authorization: `Bearer ${token}` },

withCredentials: true,

});

setAdmin([Link]);

} catch (error) {

[Link]("Admin fetch failed:", error);

logout();

};

fetchAdmin();

}, [token]);

return (

<[Link] value={{ admin, token, login, logout, loading }}>

{children}

</[Link]>

);

};

export const useAdmin = () => useContext(AdminContext);

[Link]

// src/context/[Link]

import { createContext, useContext, useState, useEffect } from "react";

import axios from "axios";

import { useNavigate } from "react-router-dom";

const MentorContext = createContext();


export const MentorProvider = ({ children }) => {

const [mentor, setMentor] = useState(null);

const [token, setToken] = useState([Link]("mentorToken"));

const [loading, setLoading] = useState(false);

const navigate = useNavigate();

// Login mentor

const login = async (email, password) => {

try {

setLoading(true);

const res = await [Link](

"[Link]

{ email, password },

{ withCredentials: true }

);

if ([Link]?.token) {

// Save token in state + localStorage

setToken([Link]);

[Link]("mentorToken", [Link]);

[Link]("role", "mentor");

// Save mentor info

if ([Link]) {

setMentor([Link]);

navigate("/mentor/dashboard");

}
} catch (error) {

throw [Link]?.data?.message || "Login failed";

} finally {

setLoading(false);

};

const logout = () => {

setMentor(null);

setToken(null);

[Link]("mentorToken");

[Link]("role");

navigate("/", { replace: true });

};

//Auto fetch mentor

useEffect(() => {

const fetchMentor = async () => {

if (!token) return;

try {

const res = await [Link]("[Link] {

headers: { Authorization: `Bearer ${token}` },

withCredentials: true,

});

setMentor([Link] || [Link]);

} catch (error) {

[Link]("Mentor fetch failed:", error);

logout();

}
};

fetchMentor();

}, [token]);

return (

<[Link] value={{ mentor, token, login, logout, loading }}>

{children}

</[Link]>

);

};

export const useMentor = () => useContext(MentorContext);

[Link]

// src/context/[Link]

import { AdminProvider } from "./AdminContext";

import { MentorProvider } from "./MentorContext";

import { UserProvider } from "./UserContext";

export default function RoleProvider({ children }) {

return (
<AdminProvider>

<MentorProvider>

<UserProvider>

{children}

</UserProvider>

</MentorProvider>

</AdminProvider>

);

[Link]

// src/context/[Link]

import { createContext, useContext, useState, useEffect } from "react";

import axios from "axios";

import { useNavigate } from "react-router-dom";

const UserContext = createContext();

export const UserProvider = ({ children }) => {

const [user, setUser] = useState(null);

const [token, setToken] = useState([Link]("userToken"));

const [loading, setLoading] = useState(false);

const navigate = useNavigate();

// Register user
const register = async (name, email, password) => {

try {

setLoading(true);

const res = await [Link](

"[Link]

{ name, email, password },

{ withCredentials: true }

);

if ([Link]?.token) {

// auto login after register

setToken([Link]);

[Link]("userToken", [Link]);

[Link]("role", "user");

if ([Link]) setUser([Link]);

navigate("/user/dashboard");

return [Link];

} catch (error) {

throw [Link]?.data?.message || "Registration failed";

} finally {

setLoading(false);

};

// Login user

const login = async (email, password) => {

try {
setLoading(true);

const res = await [Link](

"[Link]

{ email, password },

{ withCredentials: true }

);

if ([Link]?.token) {

setToken([Link]);

[Link]("userToken", [Link]);

[Link]("role", "user");

if ([Link]) setUser([Link]);

navigate("/user/dashboard");

return [Link];

} catch (error) {

throw [Link]?.data?.message || "Login failed";

} finally {

setLoading(false);

};

// Logout user

const logout = () => {

setUser(null);

setToken(null);

[Link]("userToken");

[Link]("role");
navigate("/", { replace: true });

};

//Auto fetch user

useEffect(() => {

const fetchUser = async () => {

if (!token) return;

try {

const res = await [Link]("[Link] {

headers: { Authorization: `Bearer ${token}` },

withCredentials: true,

});

setUser([Link]);

} catch (error) {

[Link]("User fetch failed:", error);

logout(); // clear invalid token

};

fetchUser();

}, [token]);

return (

<[Link]

value={{ user, token, register, login, logout, loading }}

>

{children}

</[Link]>

);

};
export const useUser = () => useContext(UserContext);

PAGES
[Link]

// src/pages/[Link]

import { useEffect } from "react";

import { useLocation } from "react-router-dom";

export default function About() {

const location = useLocation();

// Scroll to top

useEffect(() => {

[Link](0, 0);

}, [location]);

return (

<div className="max-w-6xl mx-auto px-6 py-12">


<h1 className="text-4xl font-bold text-indigo-600 mb-6 text-center">

About Studipal

</h1>

<p className="text-lg text-gray-700 text-center mb-12">

Studipal is your ultimate Learning Management System designed to help

learners, mentors, and administrators connect, grow, and achieve

success.

</p>

<div className="grid md:grid-cols-2 gap-10 mb-16">

<div className="bg-white p-8 rounded-xl shadow hover:shadow-lg transition">

<h2 className="text-2xl font-semibold text-indigo-700 mb-4">

🎯 Our Mission

</h2>

<p className="text-gray-700">

To empower learners worldwide by providing quality education,

mentorship, and tools that make learning engaging, accessible, and

effective.

</p>

</div>

<div className="bg-white p-8 rounded-xl shadow hover:shadow-lg transition">

<h2 className="text-2xl font-semibold text-indigo-700 mb-4">

🌍 Our Vision

</h2>

<p className="text-gray-700">

To build a global community where students learn, mentors guide, and

administrators ensure a smooth and secure education ecosystem.

</p>

</div>

</div>
<section className="mb-16">

<h2 className="text-3xl font-bold text-gray-800 text-center mb-10">

What Makes Studipal Unique?

</h2>

<div className="grid md:grid-cols-3 gap-8">

<div className="bg-indigo-50 p-6 rounded-xl shadow hover:shadow-lg


transition">

<h3 className="text-xl font-semibold mb-3">

📚 Interactive Learning

</h3>

<p className="text-gray-700">

Courses designed with practical projects and real-world use cases

so you can learn by doing.

</p>

</div>

<div className="bg-indigo-50 p-6 rounded-xl shadow hover:shadow-lg


transition">

<h3 className="text-xl font-semibold mb-3"> 👩 🏫 Expert Mentors</h3>

<p className="text-gray-700">

Get guidance from experienced mentors who provide personalized

support and feedback.

</p>

</div>

<div className="bg-indigo-50 p-6 rounded-xl shadow hover:shadow-lg


transition">

<h3 className="text-xl font-semibold mb-3"> 🛡 Secure Platform</h3>

<p className="text-gray-700">

Advanced admin tools and data protection ensure a safe and

reliable experience for all users.

</p>
</div>

</div>

</section>

<section className="text-center">

<h2 className="text-3xl font-bold text-gray-800 mb-6">Our Team</h2>

<p className="text-gray-700 max-w-3xl mx-auto mb-10">

Behind Studipal is a passionate team of developers, educators, and

innovators working together to transform education into a seamless and

enjoyable journey.

</p>

<div className="grid md:grid-cols-3 gap-8">

{[

{ name: "Satpal", role: "Founder & Developer" },

{ name: "Mentor Team", role: "Guides & Educators" },

{ name: "Admin Team", role: "Support & Management" },

].map((member, idx) => (

<div

key={idx}

className="bg-white p-6 rounded-xl shadow hover:shadow-lg transition"

>

<h3 className="text-xl font-semibold text-indigo-700">

{[Link]}

</h3>

<p className="text-gray-600">{[Link]}</p>

</div>

))}

</div>

</section>

</div>
);

[Link]

// SRC/PAGES/[Link]

IMPORT { USEEFFECT } FROM "REACT";

IMPORT { USELOCATION } FROM "REACT-ROUTER-DOM";

EXPORT DEFAULT FUNCTION ABOUT() {

CONST LOCATION = USELOCATION();

// SCROLL TO TOP

USEEFFECT(() => {

[Link](0, 0);

}, [LOCATION]);

RETURN (
<DIV CLASSNAME="MAX-W-6XL MX-AUTO PX-6 PY-12">

<H1 CLASSNAME="TEXT-4XL FONT-BOLD TEXT-INDIGO-600 MB-6 TEXT-


CENTER">

ABOUT STUDIPAL

</H1>

<P CLASSNAME="TEXT-LG TEXT-GRAY-700 TEXT-CENTER MB-12">

STUDIPAL IS YOUR ULTIMATE LEARNING MANAGEMENT SYSTEM DESIGNED


TO HELP

LEARNERS, MENTORS, AND ADMINISTRATORS CONNECT, GROW, AND


ACHIEVE

SUCCESS.

</P>

<DIV CLASSNAME="GRID MD:GRID-COLS-2 GAP-10 MB-16">

<DIV CLASSNAME="BG-WHITE P-8 ROUNDED-XL SHADOW HOVER:SHADOW-LG


TRANSITION">

<H2 CLASSNAME="TEXT-2XL FONT-SEMIBOLD TEXT-INDIGO-700 MB-4">

🎯 OUR MISSION

</H2>

<P CLASSNAME="TEXT-GRAY-700">

TO EMPOWER LEARNERS WORLDWIDE BY PROVIDING QUALITY EDUCATION,

MENTORSHIP, AND TOOLS THAT MAKE LEARNING ENGAGING, ACCESSIBLE,


AND

EFFECTIVE.

</P>

</DIV>

<DIV CLASSNAME="BG-WHITE P-8 ROUNDED-XL SHADOW HOVER:SHADOW-LG


TRANSITION">

<H2 CLASSNAME="TEXT-2XL FONT-SEMIBOLD TEXT-INDIGO-700 MB-4">

🌍 OUR VISION

</H2>

<P CLASSNAME="TEXT-GRAY-700">
TO BUILD A GLOBAL COMMUNITY WHERE STUDENTS LEARN, MENTORS
GUIDE, AND

ADMINISTRATORS ENSURE A SMOOTH AND SECURE EDUCATION


ECOSYSTEM.

</P>

</DIV>

</DIV>

<SECTION CLASSNAME="MB-16">

<H2 CLASSNAME="TEXT-3XL FONT-BOLD TEXT-GRAY-800 TEXT-CENTER MB-


10">

WHAT MAKES STUDIPAL UNIQUE?

</H2>

<DIV CLASSNAME="GRID MD:GRID-COLS-3 GAP-8">

<DIV CLASSNAME="BG-INDIGO-50 P-6 ROUNDED-XL SHADOW


HOVER:SHADOW-LG TRANSITION">

<H3 CLASSNAME="TEXT-XL FONT-SEMIBOLD MB-3">

📚 INTERACTIVE LEARNING

</H3>

<P CLASSNAME="TEXT-GRAY-700">

COURSES DESIGNED WITH PRACTICAL PROJECTS AND REAL-WORLD USE


CASES

SO YOU CAN LEARN BY DOING.

</P>

</DIV>

<DIV CLASSNAME="BG-INDIGO-50 P-6 ROUNDED-XL SHADOW


HOVER:SHADOW-LG TRANSITION">

<H3 CLASSNAME="TEXT-XL FONT-SEMIBOLD MB-3"> 👩 🏫 EXPERT


MENTORS</H3>

<P CLASSNAME="TEXT-GRAY-700">

GET GUIDANCE FROM EXPERIENCED MENTORS WHO PROVIDE


PERSONALIZED

SUPPORT AND FEEDBACK.


</P>

</DIV>

<DIV CLASSNAME="BG-INDIGO-50 P-6 ROUNDED-XL SHADOW


HOVER:SHADOW-LG TRANSITION">

<H3 CLASSNAME="TEXT-XL FONT-SEMIBOLD MB-3"> 🛡 SECURE


PLATFORM</H3>

<P CLASSNAME="TEXT-GRAY-700">

ADVANCED ADMIN TOOLS AND DATA PROTECTION ENSURE A SAFE AND

RELIABLE EXPERIENCE FOR ALL USERS.

</P>

</DIV>

</DIV>

</SECTION>

<SECTION CLASSNAME="TEXT-CENTER">

<H2 CLASSNAME="TEXT-3XL FONT-BOLD TEXT-GRAY-800 MB-6">OUR


TEAM</H2>

<P CLASSNAME="TEXT-GRAY-700 MAX-W-3XL MX-AUTO MB-10">

BEHIND STUDIPAL IS A PASSIONATE TEAM OF DEVELOPERS, EDUCATORS,


AND

INNOVATORS WORKING TOGETHER TO TRANSFORM EDUCATION INTO A


SEAMLESS AND

ENJOYABLE JOURNEY.

</P>

<DIV CLASSNAME="GRID MD:GRID-COLS-3 GAP-8">

{[

{ NAME: "SATPAL", ROLE: "FOUNDER & DEVELOPER" },

{ NAME: "MENTOR TEAM", ROLE: "GUIDES & EDUCATORS" },

{ NAME: "ADMIN TEAM", ROLE: "SUPPORT & MANAGEMENT" },

].MAP((MEMBER, IDX) => (

<DIV

KEY={IDX}
CLASSNAME="BG-WHITE P-6 ROUNDED-XL SHADOW HOVER:SHADOW-LG
TRANSITION"

>

<H3 CLASSNAME="TEXT-XL FONT-SEMIBOLD TEXT-INDIGO-700">

{[Link]}

</H3>

<P CLASSNAME="TEXT-GRAY-600">{[Link]}</P>

</DIV>

))}

</DIV>

</SECTION>

</DIV>

);

[Link]

IMPORT { USESTATE } FROM "REACT";

IMPORT { USEADMIN } FROM "../CONTEXT/ADMINCONTEXT";

EXPORT DEFAULT FUNCTION ADMINLOGIN() {

CONST [EMAIL, SETEMAIL] = USESTATE("");

CONST [PASSWORD, SETPASSWORD] = USESTATE("");

CONST [ERROR, SETERROR] = USESTATE("");

CONST { LOGIN, LOADING } = USEADMIN();

CONST HANDLESUBMIT = ASYNC (E) => {

[Link]();

SETERROR("");
TRY {

AWAIT LOGIN(EMAIL, PASSWORD);

} CATCH (ERR) {

SETERROR(ERR || "LOGIN FAILED. TRY AGAIN.");

};

RETURN (

<DIV CLASSNAME="MIN-H-SCREEN FLEX ITEMS-CENTER JUSTIFY-CENTER BG-


GRAY-100 PX-4">

<DIV CLASSNAME="MAX-W-MD W-FULL BG-WHITE P-8 ROUNDED-2XL SHADOW-


LG">

<H2 CLASSNAME="TEXT-2XL FONT-BOLD TEXT-CENTER TEXT-GRAY-800 MB-


6">

ADMIN LOGIN

</H2>

{ERROR && (

<DIV CLASSNAME="MB-4 P-2 TEXT-SM TEXT-RED-700 BG-RED-100


ROUNDED">

{ERROR}

</DIV>

)}

<FORM ONSUBMIT={HANDLESUBMIT} CLASSNAME="SPACE-Y-4">

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700 FONT-MEDIUM MB-1">

EMAIL

</LABEL>

<INPUT

TYPE="EMAIL"

CLASSNAME="W-FULL PX-3 PY-2 BORDER ROUNDED-LG FOCUS:RING


FOCUS:RING-BLUE-300 OUTLINE-NONE"
VALUE={EMAIL}

ONCHANGE={(E) => SETEMAIL([Link])}

REQUIRED

/>

</DIV>

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700 FONT-MEDIUM MB-1">

PASSWORD

</LABEL>

<INPUT

TYPE="PASSWORD"

CLASSNAME="W-FULL PX-3 PY-2 BORDER ROUNDED-LG FOCUS:RING


FOCUS:RING-BLUE-300 OUTLINE-NONE"

VALUE={PASSWORD}

ONCHANGE={(E) => SETPASSWORD([Link])}

REQUIRED

/>

</DIV>

<BUTTON

TYPE="SUBMIT"

DISABLED={LOADING}

CLASSNAME="W-FULL BG-BLUE-600 TEXT-WHITE PY-2 ROUNDED-LG


HOVER:BG-BLUE-700 TRANSITION DISABLED:OPACITY-50"

>

{LOADING ? "LOGGING IN..." : "LOGIN"}

</BUTTON>

</FORM>

</DIV>

</DIV>
);

[Link]

IMPORT { USELOCATION } FROM "REACT-ROUTER-DOM";

IMPORT { USEEFFECT, USESTATE } FROM "REACT";

IMPORT AXIOS FROM "AXIOS";

IMPORT { TOAST } FROM "REACT-HOT-TOAST";

EXPORT DEFAULT FUNCTION CONTACT() {

CONST LOCATION = USELOCATION();

// SCROLL TO TOP

USEEFFECT(() => {

[Link](0, 0);

}, [LOCATION]);

CONST [FORMDATA, SETFORMDATA] = USESTATE({


NAME: "",

EMAIL: "",

MESSAGE: "",

});

CONST [LOADING, SETLOADING] = USESTATE(FALSE);

CONST HANDLECHANGE = (E) => {

SETFORMDATA({ ...FORMDATA, [[Link]]: [Link] });

};

CONST HANDLESUBMIT = ASYNC (E) => {

[Link]();

SETLOADING(TRUE);

TRY {

CONST RES = AWAIT [Link](

`${[Link].VITE_API_URL}/CONTACT`,

FORMDATA

);

[Link]([Link] || "MESSAGE SENT SUCCESSFULLY!");

SETFORMDATA({ NAME: "", EMAIL: "", MESSAGE: "" });

} CATCH (ERROR) {

[Link]([Link]?.DATA?.MESSAGE || "FAILED TO SEND


MESSAGE");

} FINALLY {

SETLOADING(FALSE);

};

RETURN (

<DIV CLASSNAME="MAX-W-5XL MX-AUTO PX-6 PY-12">


<H1 CLASSNAME="TEXT-4XL FONT-BOLD TEXT-INDIGO-600 MB-6 TEXT-
CENTER">

CONTACT US

</H1>

<P CLASSNAME="TEXT-GRAY-700 TEXT-CENTER MB-10">

HAVE QUESTIONS ABOUT <STRONG>STUDIPAL</STRONG>? WE’D LOVE TO


HEAR FROM

YOU. REACH US ANYTIME USING THE DETAILS BELOW.

</P>

{/* CONTACT INFORMATION */}

<DIV CLASSNAME="GRID MD:GRID-COLS-2 GAP-8 MB-16">

<DIV CLASSNAME="BG-WHITE P-6 ROUNDED-XL SHADOW HOVER:SHADOW-LG


TRANSITION">

<H2 CLASSNAME="TEXT-2XL FONT-SEMIBOLD TEXT-INDIGO-700 MB-4">

📧 EMAIL

</H2>

<P CLASSNAME="TEXT-GRAY-700">DILPREETLOTEY25@[Link]</P>

</DIV>

<DIV CLASSNAME="BG-WHITE P-6 ROUNDED-XL SHADOW HOVER:SHADOW-LG


TRANSITION">

<H2 CLASSNAME="TEXT-2XL FONT-SEMIBOLD TEXT-INDIGO-700 MB-4">

📞 PHONE

</H2>

<P CLASSNAME="TEXT-GRAY-700">+91 9988799198</P>

</DIV>

<DIV CLASSNAME="BG-WHITE P-6 ROUNDED-XL SHADOW HOVER:SHADOW-LG


TRANSITION">

<H2 CLASSNAME="TEXT-2XL FONT-SEMIBOLD TEXT-INDIGO-700 MB-4">

🏢 ADDRESS
</H2>

<P CLASSNAME="TEXT-GRAY-700">

STUDIPAL HQ, 155 VPO GILL, LUDHIANA PUNJAB, INDIA

</P>

</DIV>

<DIV CLASSNAME="BG-WHITE P-6 ROUNDED-XL SHADOW HOVER:SHADOW-LG


TRANSITION">

<H2 CLASSNAME="TEXT-2XL FONT-SEMIBOLD TEXT-INDIGO-700 MB-4">

🌐 WEBSITE

</H2>

<P CLASSNAME="TEXT-GRAY-700">[Link]</P>

</DIV>

</DIV>

{/* CONTACT FORM */}

<DIV CLASSNAME="BG-GRAY-50 P-8 ROUNDED-XL SHADOW-MD">

<H2 CLASSNAME="TEXT-2XL FONT-SEMIBOLD TEXT-INDIGO-700 MB-6 TEXT-


CENTER">

SEND US A MESSAGE

</H2>

<FORM ONSUBMIT={HANDLESUBMIT} CLASSNAME="SPACE-Y-6 MAX-W-2XL


MX-AUTO">

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700 FONT-MEDIUM MB-2">

YOUR NAME

</LABEL>

<INPUT

TYPE="TEXT"

NAME="NAME"

VALUE={[Link]}
ONCHANGE={HANDLECHANGE}

PLACEHOLDER="ENTER YOUR NAME"

CLASSNAME="W-FULL PX-4 PY-2 BORDER ROUNDED-LG FOCUS:RING-2


FOCUS:RING-INDIGO-500 OUTLINE-NONE"

REQUIRED

/>

</DIV>

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700 FONT-MEDIUM MB-2">

EMAIL

</LABEL>

<INPUT

TYPE="EMAIL"

NAME="EMAIL"

VALUE={[Link]}

ONCHANGE={HANDLECHANGE}

PLACEHOLDER="ENTER YOUR EMAIL"

CLASSNAME="W-FULL PX-4 PY-2 BORDER ROUNDED-LG FOCUS:RING-2


FOCUS:RING-INDIGO-500 OUTLINE-NONE"

REQUIRED

/>

</DIV>

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700 FONT-MEDIUM MB-2">

MESSAGE

</LABEL>

<TEXTAREA

ROWS="5"

NAME="MESSAGE"

VALUE={[Link]}

ONCHANGE={HANDLECHANGE}
PLACEHOLDER="WRITE YOUR MESSAGE..."

CLASSNAME="W-FULL PX-4 PY-2 BORDER ROUNDED-LG FOCUS:RING-2


FOCUS:RING-INDIGO-500 OUTLINE-NONE"

REQUIRED

></TEXTAREA>

</DIV>

<BUTTON

TYPE="SUBMIT"

DISABLED={LOADING}

CLASSNAME="W-FULL BG-INDIGO-600 TEXT-WHITE FONT-MEDIUM PY-3


ROUNDED-LG HOVER:BG-INDIGO-700 TRANSITION DISABLED:OPACITY-60"

>

{LOADING ? "SENDING..." : "SEND MESSAGE"}

</BUTTON>

</FORM>

</DIV>

</DIV>

);

}
[Link]

// SRC/PAGES/[Link]

IMPORT { USEEFFECT, USESTATE } FROM "REACT";

IMPORT { USEPARAMS, USENAVIGATE } FROM "REACT-ROUTER-DOM";

IMPORT AXIOS FROM "AXIOS";

IMPORT { USEMENTOR } FROM "../CONTEXT/MENTORCONTEXT";

IMPORT { PLUSCIRCLE, X } FROM "LUCIDE-REACT";

EXPORT DEFAULT FUNCTION COURSELESSONS() {

CONST { COURSEID } = USEPARAMS();

CONST NAVIGATE = USENAVIGATE();

CONST { MENTOR, TOKEN } = USEMENTOR();

CONST [COURSE, SETCOURSE] = USESTATE(NULL);

CONST [LESSONS, SETLESSONS] = USESTATE([]);

CONST [CURRENTVIDEO, SETCURRENTVIDEO] = USESTATE(NULL);


CONST [LOADING, SETLOADING] = USESTATE(TRUE);

CONST [ERROR, SETERROR] = USESTATE("");

CONST [SHOWADDLESSON, SETSHOWADDLESSON] = USESTATE(FALSE);

CONST [LESSONFORM, SETLESSONFORM] = USESTATE({

TITLE: "",

CONTENT: "",

VIDEO: NULL,

THUMBNAIL: NULL,

});

// FETCH COURSE AND LESSONS

USEEFFECT(() => {

CONST FETCHDATA = ASYNC () => {

IF (!COURSEID) RETURN;

SETLOADING(TRUE);

SETERROR("");

TRY {

CONST HEADERS = MENTOR ? { AUTHORIZATION: `BEARER ${TOKEN}` } : {};

CONST [COURSERES, LESSONSRES] = AWAIT [Link]([

[Link](

`HTTP://LOCALHOST:3000/API/V1/COURSE/GET-ONE-
COURSE/${COURSEID}`,

{ HEADERS }

),

[Link](

`HTTP://LOCALHOST:3000/API/V1/LESSON/${

MENTOR ? "MENTOR/GET-ALL-LESSONS" : "GET-ALL-LESSONS"

}/${COURSEID}`,

{ HEADERS }

),

]);
SETCOURSE([Link] || NULL);

CONST SORTEDLESSONS = ([Link] || []).SORT(

(A, B) => [Link] - [Link]

);

SETLESSONS(SORTEDLESSONS);

IF ([Link] > 0) SETCURRENTVIDEO(SORTEDLESSONS[0]);

} CATCH (ERR) {

[Link]("ERROR FETCHING COURSE OR LESSONS:", ERR);

SETERROR("FAILED TO LOAD COURSE OR LESSONS.");

} FINALLY {

SETLOADING(FALSE);

};

FETCHDATA();

}, [COURSEID, MENTOR, TOKEN]);

CONST HANDLEADDLESSON = ASYNC (E) => {

[Link]();

IF (![Link]) RETURN ALERT("PLEASE SELECT A VIDEO FILE.");

TRY {

CONST FORMDATA = NEW FORMDATA();

[Link]("TITLE", [Link]);

[Link]("CONTENT", [Link]);

IF ([Link]) [Link]("VIDEOURL",
[Link]);

IF ([Link])
[Link]("THUMBNAIL", [Link]);

AWAIT [Link](

`HTTP://LOCALHOST:3000/API/V1/LESSON/ADD-LESSON/${COURSEID}`,

FORMDATA,

HEADERS: {

AUTHORIZATION: `BEARER ${TOKEN}`,

"CONTENT-TYPE": "MULTIPART/FORM-DATA",

},

);

CONST LESSONSRES = AWAIT [Link](

`HTTP://LOCALHOST:3000/API/V1/LESSON/MENTOR/GET-ALL-
LESSONS/${COURSEID}`,

{ HEADERS: { AUTHORIZATION: `BEARER ${TOKEN}` } }

);

CONST SORTEDLESSONS = ([Link] || []).SORT(

(A, B) => [Link] - [Link]

);

SETLESSONS(SORTEDLESSONS);

SETLESSONFORM({ TITLE: "", CONTENT: "", VIDEO: NULL, THUMBNAIL: NULL });

SETSHOWADDLESSON(FALSE);

IF (!CURRENTVIDEO && [Link] > 0)

SETCURRENTVIDEO(SORTEDLESSONS[0]);

} CATCH (ERR) {

[Link]("FAILED TO SAVE LESSON:", ERR);

ALERT([Link]?.DATA?.MESSAGE || "ERROR SAVING LESSON");

}
};

IF (LOADING) RETURN <P CLASSNAME="TEXT-CENTER MT-10">LOADING...</P>;

IF (ERROR) RETURN <P CLASSNAME="TEXT-CENTER MT-10 TEXT-RED-


600">{ERROR}</P>;

RETURN (

<DIV CLASSNAME="MIN-H-SCREEN BG-GRAY-100 P-6">

<BUTTON

ONCLICK={() => NAVIGATE(-1)}

CLASSNAME="MB-4 TEXT-BLUE-600 HOVER:UNDERLINE"

>

&LARR; BACK

</BUTTON>

{/* COURSE BANNER */}

{COURSE && (

<DIV CLASSNAME="BG-GRAY-800 TEXT-WHITE ROUNDED-XL OVERFLOW-


HIDDEN MB-6 RELATIVE">

<IMG

SRC={[Link] || "/[Link]"}

ALT={[Link]}

CLASSNAME="W-FULL H-60 OBJECT-COVER OPACITY-80"

/>

<DIV CLASSNAME="ABSOLUTE BOTTOM-4 LEFT-6">

<H1 CLASSNAME="TEXT-3XL FONT-BOLD">{[Link]}</H1>

<P CLASSNAME="TEXT-GRAY-200 MT-1">{[Link]}</P>

</DIV>

</DIV>

)}
<DIV CLASSNAME="FLEX FLEX-COL LG:FLEX-ROW GAP-6">

{/* LESSONS LIST */}

<DIV CLASSNAME="LG:W-1/3 SPACE-Y-4 OVERFLOW-Y-AUTO MAX-H-[70VH]">

{[Link]((LESSON, INDEX) => (

<DIV

KEY={LESSON._ID}

CLASSNAME={`BG-WHITE SHADOW ROUNDED-XL CURSOR-POINTER


OVERFLOW-HIDDEN ${

CURRENTVIDEO?._ID === LESSON._ID

? "BORDER-2 BORDER-BLUE-600"

: ""

}`}

ONCLICK={() => SETCURRENTVIDEO(LESSON)}

>

<IMG

SRC={[Link] || "/[Link]"}

ALT={[Link]}

CLASSNAME="W-FULL H-28 OBJECT-COVER"

/>

<DIV CLASSNAME="P-3">

<H3 CLASSNAME="FONT-BOLD TEXT-LG">

{INDEX + 1}. {[Link]}

</H3>

<P CLASSNAME="TEXT-GRAY-500 TEXT-SM LINE-CLAMP-2">

{[Link]}

</P>

</DIV>

</DIV>

))}

</DIV>
{/* VIDEO PLAYER */}

<DIV CLASSNAME="LG:W-2/3 BG-BLACK ROUNDED-XL SHADOW OVERFLOW-


HIDDEN">

{CURRENTVIDEO ? (

<VIDEO

KEY={CURRENTVIDEO._ID}

SRC={[Link]}

CONTROLS

AUTOPLAY

CLASSNAME="W-FULL H-80 LG:H-[500PX] OBJECT-COVER"

/>

):(

<P CLASSNAME="TEXT-WHITE P-6">SELECT A LESSON TO PLAY</P>

)}

</DIV>

</DIV>

{/* ADD LESSON MODAL */}

{MENTOR && SHOWADDLESSON && (

<DIV CLASSNAME="FIXED INSET-0 BG-BLACK BG-OPACITY-50 FLEX ITEMS-


CENTER JUSTIFY-CENTER Z-50">

<DIV CLASSNAME="BG-WHITE ROUNDED-2XL SHADOW-LG W-FULL MAX-W-


LG P-6 RELATIVE">

<BUTTON

ONCLICK={() => SETSHOWADDLESSON(FALSE)}

CLASSNAME="ABSOLUTE TOP-4 RIGHT-4 TEXT-GRAY-500 HOVER:TEXT-


GRAY-700"

>

<X CLASSNAME="W-6 H-6" />

</BUTTON>

<H2 CLASSNAME="TEXT-2XL FONT-BOLD MB-6 TEXT-CENTER TEXT-GREEN-


600">
ADD NEW LESSON

</H2>

<FORM ONSUBMIT={HANDLEADDLESSON} CLASSNAME="SPACE-Y-4">

<INPUT

TYPE="TEXT"

PLACEHOLDER="LESSON TITLE"

VALUE={[Link]}

ONCHANGE={(E) =>

SETLESSONFORM({ ...LESSONFORM, TITLE: [Link] })

CLASSNAME="W-FULL P-2 BORDER ROUNDED-LG FOCUS:RING-2


FOCUS:RING-GREEN-500"

REQUIRED

/>

<TEXTAREA

PLACEHOLDER="CONTENT / DESCRIPTION"

VALUE={[Link]}

ONCHANGE={(E) =>

SETLESSONFORM({ ...LESSONFORM, CONTENT: [Link] })

CLASSNAME="W-FULL P-2 BORDER ROUNDED-LG FOCUS:RING-2


FOCUS:RING-GREEN-500"

REQUIRED

/>

<INPUT

TYPE="FILE"

ACCEPT="VIDEO/*"

ONCHANGE={(E) =>

SETLESSONFORM({ ...LESSONFORM, VIDEO: [Link][0] })

CLASSNAME="W-FULL P-2 BORDER ROUNDED-LG FOCUS:RING-2


FOCUS:RING-GREEN-500"

REQUIRED

/>

<INPUT

TYPE="FILE"

ACCEPT="IMAGE/*"

ONCHANGE={(E) =>

SETLESSONFORM({ ...LESSONFORM, THUMBNAIL: [Link][0] })

CLASSNAME="W-FULL P-2 BORDER ROUNDED-LG FOCUS:RING-2


FOCUS:RING-GREEN-500"

/>

<DIV CLASSNAME="FLEX GAP-3 MT-4">

<BUTTON

TYPE="SUBMIT"

CLASSNAME="FLEX-1 BG-GREEN-600 TEXT-WHITE PY-2 ROUNDED-LG


HOVER:BG-GREEN-700"

>

SAVE

</BUTTON>

<BUTTON

TYPE="BUTTON"

ONCLICK={() => SETSHOWADDLESSON(FALSE)}

CLASSNAME="FLEX-1 BG-GRAY-300 TEXT-GRAY-800 PY-2 ROUNDED-LG


HOVER:BG-GRAY-400"

>

CANCEL

</BUTTON>

</DIV>

</FORM>

</DIV>
</DIV>

)}

</DIV>

);

[Link]

// SRC/PAGES/[Link]

IMPORT { USEEFFECT, USESTATE } FROM "REACT";

IMPORT { LINK, USENAVIGATE } FROM "REACT-ROUTER-DOM";

IMPORT AXIOS FROM "AXIOS";

IMPORT { USEUSER } FROM "../CONTEXT/USERCONTEXT";

EXPORT DEFAULT FUNCTION COURSES() {

CONST [COURSES, SETCOURSES] = USESTATE([]);

CONST [LOADING, SETLOADING] = USESTATE(TRUE);

CONST { USER, TOKEN } = USEUSER();

CONST NAVIGATE = USENAVIGATE();

// FETCH ALL APPROVED COURSES

USEEFFECT(() => {

CONST FETCHCOURSES = ASYNC () => {

TRY {

CONST RES = AWAIT [Link](

"HTTP://LOCALHOST:3000/API/V1/COURSE/GET-ALL-COURSES"

);
SETCOURSES([Link] || []);

} CATCH (ERR) {

[Link]("ERROR FETCHING COURSES:", ERR);

} FINALLY {

SETLOADING(FALSE);

};

FETCHCOURSES();

}, []);

CONST HANDLEENROLL = ASYNC (COURSEID) => {

IF (!USER) {

NAVIGATE("/USER/LOGIN");

RETURN;

TRY {

AWAIT [Link](

`HTTP://LOCALHOST:3000/API/V1/COURSES/ENROLL/${COURSEID}`,

{},

HEADERS: { AUTHORIZATION: `BEARER ${TOKEN}` },

);

ALERT(" SUCCESSFULLY ENROLLED!");

} CATCH (ERR) {

[Link]("ENROLL FAILED:", ERR);

ALERT(" ENROLLMENT FAILED. PLEASE TRY AGAIN.");

};
IF (LOADING) {

RETURN (

<DIV CLASSNAME="TEXT-CENTER PY-20 TEXT-GRAY-600 TEXT-LG">

LOADING COURSES...

</DIV>

);

RETURN (

<DIV CLASSNAME="MAX-W-7XL MX-AUTO PX-4 PY-12">

<H1 CLASSNAME="TEXT-4XL FONT-BOLD TEXT-INDIGO-600 MB-6 TEXT-


CENTER">

EXPLORE OUR COURSES

</H1>

<P CLASSNAME="TEXT-LG TEXT-GRAY-700 TEXT-CENTER MB-12">

UPSKILL YOURSELF WITH OUR PROFESSIONALLY CURATED COURSES.

</P>

{[Link] === 0 ? (

<P CLASSNAME="TEXT-CENTER TEXT-GRAY-500">

NO COURSES AVAILABLE RIGHT NOW.

</P>

):(

<DIV CLASSNAME="GRID SM:GRID-COLS-2 MD:GRID-COLS-3 LG:GRID-COLS-4


GAP-8">

{[Link]((COURSE) => (

<DIV

KEY={COURSE._ID}

CLASSNAME="BG-WHITE ROUNDED-XL SHADOW-MD HOVER:SHADOW-2XL


HOVER:SCALE-105 TRANSITION-TRANSFORM DURATION-300 OVERFLOW-HIDDEN
GROUP"
>

{/* THUMBNAIL WITH GRADIENT OVERLAY */}

<DIV CLASSNAME="RELATIVE">

<IMG

SRC={[Link]}

ALT={[Link]}

CLASSNAME="W-FULL H-48 OBJECT-COVER"

/>

<DIV CLASSNAME="ABSOLUTE INSET-0 BG-GRADIENT-TO-T FROM-


BLACK/50 TO-TRANSPARENT OPACITY-0 GROUP-HOVER:OPACITY-100
TRANSITION-OPACITY"></DIV>

<SPAN CLASSNAME="ABSOLUTE TOP-2 RIGHT-2 BG-INDIGO-600 TEXT-


WHITE TEXT-XS PX-3 PY-1 ROUNDED-FULL FONT-MEDIUM">

{[Link]}

</SPAN>

<H2 CLASSNAME="ABSOLUTE BOTTOM-2 LEFT-2 TEXT-WHITE FONT-


SEMIBOLD TEXT-SM SM:TEXT-BASE LINE-CLAMP-2">

{[Link]}

</H2>

</DIV>

{/* COURSE INFO */}

<DIV CLASSNAME="P-4">

<P CLASSNAME="TEXT-GRAY-600 TEXT-SM MB-4 LINE-CLAMP-3">

{[Link]}

</P>

{/* ENROLL/LOGIN BUTTON */}

<DIV CLASSNAME="FLEX JUSTIFY-CENTER">

{USER ? (

<BUTTON

ONCLICK={() => HANDLEENROLL(COURSE._ID)}


CLASSNAME="W-FULL BG-INDIGO-600 HOVER:BG-INDIGO-700 TEXT-
WHITE FONT-MEDIUM PY-2 ROUNDED-LG TRANSITION-ALL DURATION-300
SHADOW HOVER:SHADOW-LG"

>

ENROLL NOW

</BUTTON>

):(

<LINK

TO="/USER/LOGIN"

CLASSNAME="W-FULL TEXT-CENTER BG-INDIGO-600 HOVER:BG-


INDIGO-700 TEXT-WHITE FONT-MEDIUM PY-2 ROUNDED-LG TRANSITION-ALL
DURATION-300 SHADOW HOVER:SHADOW-LG"

>

LOGIN TO ENROLL

</LINK>

)}

</DIV>

</DIV>

</DIV>

))}

</DIV>

)}

</DIV>

);

}
[Link]

// SRC/PAGES/[Link]

IMPORT { LINK } FROM "REACT-ROUTER-DOM";

EXPORT DEFAULT FUNCTION LANDINGPAGE() {

RETURN (

<DIV CLASSNAME="BG-GRAY-50">

{/* HERO SECTION */}

<SECTION CLASSNAME="BG-GRADIENT-TO-R FROM-INDIGO-600 TO-BLUE-600


TEXT-WHITE PY-20">

<DIV CLASSNAME="MAX-W-6XL MX-AUTO PX-6 TEXT-CENTER">

<H1 CLASSNAME="TEXT-4XL MD:TEXT-6XL FONT-BOLD MB-4">

WELCOME TO STUDIPAL 🎓
</H1>

<P CLASSNAME="TEXT-LG MD:TEXT-XL MB-6">

LEARN, MENTOR, AND GROW WITH THE ULTIMATE LEARNING


MANAGEMENT

SYSTEM.

</P>

<DIV CLASSNAME="FLEX JUSTIFY-CENTER GAP-4">

<LINK

TO="/COURSES"

CLASSNAME="PX-6 PY-3 BG-WHITE TEXT-INDIGO-600 FONT-SEMIBOLD


ROUNDED-LG SHADOW HOVER:BG-GRAY-100 TRANSITION"

>

EXPLORE COURSES

</LINK>

<LINK

TO="/USER/REGISTER"

CLASSNAME="PX-6 PY-3 BG-YELLOW-400 TEXT-GRAY-900 FONT-SEMIBOLD


ROUNDED-LG SHADOW HOVER:BG-YELLOW-500 TRANSITION"

>

GET STARTED

</LINK>

</DIV>

</DIV>

</SECTION>

<SECTION CLASSNAME="PY-16 PX-6 MAX-W-6XL MX-AUTO TEXT-CENTER">

<H2 CLASSNAME="TEXT-3XL FONT-BOLD TEXT-GRAY-800 MB-10">WHY


CHOOSE STUDIPAL?</H2>

<DIV CLASSNAME="GRID MD:GRID-COLS-3 GAP-8">

<DIV CLASSNAME="BG-WHITE P-6 ROUNDED-XL SHADOW HOVER:SHADOW-


LG TRANSITION">

<H3 CLASSNAME="TEXT-XL FONT-SEMIBOLD MB-2"> 📚 LEARN


ANYTIME</H3>

<P CLASSNAME="TEXT-GRAY-600">

ACCESS A VARIETY OF COURSES ACROSS TECHNOLOGY, DESIGN, AND


MORE —

AT YOUR OWN PACE.

</P>

</DIV>

<DIV CLASSNAME="BG-WHITE P-6 ROUNDED-XL SHADOW HOVER:SHADOW-


LG TRANSITION">

<H3 CLASSNAME="TEXT-XL FONT-SEMIBOLD MB-2"> 👩 🏫 MENTOR


SUPPORT</H3>
<P CLASSNAME="TEXT-GRAY-600">

GET GUIDANCE FROM EXPERIENCED MENTORS TO STAY ON THE RIGHT


TRACK.

</P>

</DIV>

<DIV CLASSNAME="BG-WHITE P-6 ROUNDED-XL SHADOW HOVER:SHADOW-


LG TRANSITION">

<H3 CLASSNAME="TEXT-XL FONT-SEMIBOLD MB-2"> 🛡 ADMIN


CONTROL</H3>

<P CLASSNAME="TEXT-GRAY-600">

A SECURE PLATFORM WITH POWERFUL ADMIN TOOLS TO MANAGE


LEARNERS AND

MENTORS.

</P>

</DIV>

</DIV>

</SECTION>

<SECTION CLASSNAME="PY-16 PX-6 BG-GRAY-100">

<DIV CLASSNAME="MAX-W-6XL MX-AUTO TEXT-CENTER">

<H2 CLASSNAME="TEXT-3XL FONT-BOLD TEXT-GRAY-800 MB-10">

POPULAR COURSES

</H2>

<DIV CLASSNAME="GRID MD:GRID-COLS-3 GAP-8">

{[

TITLE: "FULL STACK WEB DEVELOPMENT",

DESC: "MASTER THE MERN STACK WITH HANDS-ON PROJECTS.",

},

TITLE: "DATA SCIENCE & ML",

DESC: "LEARN PYTHON, PANDAS, AND MACHINE LEARNING.",


},

TITLE: "UI/UX DESIGN",

DESC: "DESIGN STUNNING USER EXPERIENCES WITH FIGMA.",

},

].MAP((COURSE, IDX) => (

<DIV

KEY={IDX}

CLASSNAME="BG-WHITE P-6 ROUNDED-XL SHADOW HOVER:SHADOW-LG


TRANSITION"

>

<H3 CLASSNAME="TEXT-XL FONT-SEMIBOLD MB-


2">{[Link]}</H3>

<P CLASSNAME="TEXT-GRAY-600 MB-4">{[Link]}</P>

<LINK

TO="/COURSES"

CLASSNAME="TEXT-INDIGO-600 FONT-MEDIUM HOVER:UNDERLINE"

>

LEARN MORE →

</LINK>

</DIV>

))}

</DIV>

</DIV>

</SECTION>

<SECTION CLASSNAME="PY-16 PX-6 BG-INDIGO-600 TEXT-WHITE TEXT-


CENTER">

<H2 CLASSNAME="TEXT-3XL FONT-BOLD MB-4">

READY TO START YOUR LEARNING JOURNEY?

</H2>
<P CLASSNAME="MB-6">

JOIN THOUSANDS OF LEARNERS ALREADY BUILDING THEIR FUTURE WITH


STUDIPAL.

</P>

<LINK

TO="/USER/REGISTER"

CLASSNAME="PX-6 PY-3 BG-YELLOW-400 TEXT-GRAY-900 FONT-SEMIBOLD


ROUNDED-LG SHADOW HOVER:BG-YELLOW-500 TRANSITION"

>

SIGN UP NOW

</LINK>

</SECTION>

<FOOTER CLASSNAME="BG-GRAY-900 TEXT-GRAY-400 PY-6 TEXT-CENTER">

<P>© {NEW DATE().GETFULLYEAR()} STUDIPAL. ALL RIGHTS RESERVED.</P>

<DIV CLASSNAME="FLEX JUSTIFY-CENTER GAP-4 MT-2">

<LINK TO="/ABOUT" CLASSNAME="HOVER:TEXT-WHITE">

ABOUT

</LINK>

<LINK TO="/CONTACT" CLASSNAME="HOVER:TEXT-WHITE">

CONTACT

</LINK>

</DIV>

</FOOTER>

</DIV>

);

}
[Link]

// SRC/PAGES/[Link]

IMPORT { USESTATE, USEEFFECT } FROM "REACT";

IMPORT { LINK, USENAVIGATE } FROM "REACT-ROUTER-DOM";

IMPORT { USEUSER } FROM "../CONTEXT/USERCONTEXT";

EXPORT DEFAULT FUNCTION USERLOGIN() {

CONST [FORMDATA, SETFORMDATA] = USESTATE({ EMAIL: "", PASSWORD: "" });

CONST [ERROR, SETERROR] = USESTATE("");

CONST NAVIGATE = USENAVIGATE();

CONST { LOGIN, LOADING, TOKEN } = USEUSER();

//REDIRECT IF ALREADY LOGGED IN

USEEFFECT(() => {

IF (TOKEN) {

NAVIGATE("/USER/DASHBOARD", { REPLACE: TRUE });

}, [TOKEN, NAVIGATE]);

CONST HANDLECHANGE = (E) => {

SETFORMDATA({

...FORMDATA,

[[Link]]: [Link],
});

};

CONST HANDLESUBMIT = ASYNC (E) => {

[Link]();

SETERROR("");

TRY {

AWAIT LOGIN([Link], [Link]);

//BACK BUTTON WON'T RETURN TO LOGIN

NAVIGATE("/USER/DASHBOARD", { REPLACE: TRUE });

} CATCH (ERR) {

SETERROR(ERR);

};

RETURN (

<DIV CLASSNAME="FLEX ITEMS-CENTER JUSTIFY-CENTER MIN-H-SCREEN BG-


GRAY-100 PX-4">

<DIV CLASSNAME="BG-WHITE P-8 ROUNDED-2XL SHADOW-MD W-FULL MAX-W-


MD">

<H2 CLASSNAME="TEXT-2XL FONT-BOLD TEXT-CENTER TEXT-INDIGO-600 MB-


6">

USER LOGIN

</H2>

{ERROR && (

<DIV CLASSNAME="MB-4 P-2 TEXT-SM TEXT-RED-700 BG-RED-100


ROUNDED">

{ERROR}

</DIV>

)}
<FORM ONSUBMIT={HANDLESUBMIT} CLASSNAME="SPACE-Y-4">

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700">EMAIL</LABEL>

<INPUT

TYPE="EMAIL"

NAME="EMAIL"

VALUE={[Link]}

ONCHANGE={HANDLECHANGE}

PLACEHOLDER="ENTER YOUR EMAIL"

CLASSNAME="W-FULL MT-1 P-2 BORDER ROUNDED-LG FOCUS:RING-2


FOCUS:RING-INDIGO-500 OUTLINE-NONE"

REQUIRED

/>

</DIV>

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700">PASSWORD</LABEL>

<INPUT

TYPE="PASSWORD"

NAME="PASSWORD"

VALUE={[Link]}

ONCHANGE={HANDLECHANGE}

PLACEHOLDER="ENTER YOUR PASSWORD"

CLASSNAME="W-FULL MT-1 P-2 BORDER ROUNDED-LG FOCUS:RING-2


FOCUS:RING-INDIGO-500 OUTLINE-NONE"

REQUIRED

/>

</DIV>

<BUTTON

TYPE="SUBMIT"
DISABLED={LOADING}

CLASSNAME={`W-FULL TEXT-WHITE PY-2 ROUNDED-LG ${

LOADING

? "BG-GRAY-400 CURSOR-NOT-ALLOWED"

: "BG-INDIGO-600 HOVER:BG-INDIGO-700"

}`}

>

{LOADING ? "LOGGING IN..." : "LOGIN"}

</BUTTON>

</FORM>

<P CLASSNAME="TEXT-CENTER TEXT-GRAY-600 MT-4">

DON’T HAVE AN ACCOUNT?{" "}

<LINK

TO="/USER/REGISTER"

CLASSNAME="TEXT-INDIGO-600 FONT-SEMIBOLD HOVER:UNDERLINE"

>

REGISTER

</LINK>

</P>

</DIV>

</DIV>

);

}
[Link]

IMPORT { USEEFFECT, USESTATE } FROM "REACT";

IMPORT AXIOS FROM "AXIOS";

IMPORT { USEMENTOR } FROM "../CONTEXT/MENTORCONTEXT";

IMPORT TOAST FROM "REACT-HOT-TOAST"

IMPORT {

USERS,

BOOKOPEN,

PLUSCIRCLE,

LOGOUT,

LAYOUTDASHBOARD,

CLOCK,

CHECKCIRCLE,

MENU,

X,

} FROM "LUCIDE-REACT";

IMPORT {

PIE,

CELL,

PIECHART,

BARCHART,

BAR,

XAXIS,

YAXIS,

CARTESIANGRID,
TOOLTIP,

LEGEND,

RESPONSIVECONTAINER,

} FROM "RECHARTS";

IMPORT { USENAVIGATE } FROM "REACT-ROUTER-DOM";

EXPORT DEFAULT FUNCTION MENTORDASHBOARD() {

CONST { MENTOR, TOKEN, LOGOUT } = USEMENTOR();

CONST NAVIGATE = USENAVIGATE();

CONST [STATS, SETSTATS] = USESTATE({});

CONST [COURSES, SETCOURSES] = USESTATE([]);

CONST [LOADING, SETLOADING] = USESTATE(TRUE);

CONST [ACTIVETAB, SETACTIVETAB] = USESTATE("STATS");

CONST [SHOWADDCOURSE, SETSHOWADDCOURSE] = USESTATE(FALSE);

CONST [SHOWADDLESSON, SETSHOWADDLESSON] = USESTATE(FALSE);

CONST [SELECTEDCOURSE, SETSELECTEDCOURSE] = USESTATE(NULL);

CONST [SIDEBAROPEN, SETSIDEBAROPEN] = USESTATE(FALSE);

CONST [COURSEFORM, SETCOURSEFORM] = USESTATE({

NAME: "",

DESCRIPTION: "",

CATEGORY: "",

THUMBNAIL: NULL,

});

CONST [LESSONFORM, SETLESSONFORM] = USESTATE({

TITLE: "",

CONTENT: "",
VIDEO: NULL,

ORDER: 1,

});

// FETCH COURSES AND STATS

CONST FETCHCOURSES = ASYNC () => {

IF (!TOKEN) RETURN;

TRY {

CONST HEADERS = { AUTHORIZATION: `BEARER ${TOKEN}` };

CONST RES = AWAIT [Link](

"HTTP://LOCALHOST:3000/API/V1/COURSE/MENTOR/GET-ALL-COURSES",

{ HEADERS, WITHCREDENTIALS: TRUE }

);

CONST ALLCOURSES = [Link] || [];

SETCOURSES(ALLCOURSES);

CONST TOTALCOURSES = [Link];

CONST PENDINGCOURSES = [Link](

(C) => [Link] === "PENDING"

).LENGTH;

CONST APPROVEDCOURSES = [Link](

(C) => [Link] === "APPROVED"

).LENGTH;

CONST REJECTEDCOURSES = [Link](

(C) => [Link] === "REJECTED"

).LENGTH;

SETSTATS({

TOTALCOURSES,

PENDINGCOURSES,

APPROVEDCOURSES,
REJECTEDCOURSES,

});

} CATCH (ERROR) {

[Link]("ERROR FETCHING COURSES:", ERROR);

} FINALLY {

SETLOADING(FALSE);

};

USEEFFECT(() => {

FETCHCOURSES();

}, [TOKEN]);

//ADD COURSE

CONST HANDLEADDCOURSE = ASYNC (E) => {

[Link]();

TRY {

CONST FORMDATA = NEW FORMDATA();

[Link]("NAME", [Link]);

[Link]("DESCRIPTION", [Link]);

[Link]("CATEGORY", [Link]);

IF ([Link])

[Link]("THUMBNAIL", [Link]);

AWAIT [Link](

"HTTP://LOCALHOST:3000/API/V1/COURSE/ADD-COURSE",

FORMDATA,

HEADERS: {

AUTHORIZATION: `BEARER ${TOKEN}`,


"CONTENT-TYPE": "MULTIPART/FORM-DATA",

},

WITHCREDENTIALS: TRUE,

);

[Link]("COURSE ADDED SUCCESSFULLY!");

SETCOURSEFORM({

NAME: "",

DESCRIPTION: "",

CATEGORY: "",

THUMBNAIL: NULL,

});

SETSHOWADDCOURSE(FALSE);

FETCHCOURSES();

} CATCH (ERROR) {

[Link]("FAILED TO ADD COURSE:", ERROR);

ALERT([Link]?.DATA?.MESSAGE || "ERROR ADDING COURSE");

};

//ADD LESSON

CONST HANDLEADDLESSON = ASYNC (E) => {

[Link]();

IF (![Link]) RETURN ALERT("PLEASE SELECT A VIDEO FILE.");

TRY {

CONST FORMDATA = NEW FORMDATA();

[Link]("TITLE", [Link]);

[Link]("CONTENT", [Link]);
[Link]("ORDER", [Link] || 1);

[Link]("VIDEOURL", [Link]);

AWAIT [Link](

`HTTP://LOCALHOST:3000/API/V1/LESSON/ADD-
LESSON/${SELECTEDCOURSE._ID}`,

FORMDATA,

HEADERS: {

AUTHORIZATION: `BEARER ${TOKEN}`,

"CONTENT-TYPE": "MULTIPART/FORM-DATA",

},

);

[Link]("LESSON ADDED SUCCESSFULLY!");

SETLESSONFORM({ TITLE: "", CONTENT: "", VIDEO: NULL, ORDER: 1 });

SETSHOWADDLESSON(FALSE);

FETCHCOURSES();

} CATCH (ERROR) {

[Link]("LESSON ERROR:", [Link]?.DATA ||


[Link]);

ALERT([Link]?.DATA?.MESSAGE || "ERROR ADDING LESSON");

};

IF (LOADING) RETURN <P CLASSNAME="TEXT-CENTER MT-10">LOADING...</P>;

//COURSE GRID

CONST COURSEGRID = ({ COURSES }) => (

<DIV CLASSNAME="GRID GRID-COLS-1 SM:GRID-COLS-2 LG:GRID-COLS-3 GAP-6">


{[Link]((COURSE) => (

<DIV

KEY={COURSE._ID}

CLASSNAME="BG-WHITE SHADOW ROUNDED-XL OVERFLOW-HIDDEN P-4"

>

<IMG

SRC={[Link] || "/[Link]"}

ALT={[Link]}

CLASSNAME="W-FULL H-40 OBJECT-COVER ROUNDED-LG"

/>

<H4 CLASSNAME="FONT-BOLD TEXT-LG MT-2">{[Link]}</H4>

<P CLASSNAME="TEXT-SM TEXT-GRAY-600 LINE-CLAMP-2">

{[Link]}

</P>

<P CLASSNAME="TEXT-SM TEXT-GRAY-500 MT-1">

STATUS: {[Link] || "PENDING"}

</P>

<BUTTON

ONCLICK={() => {

SETSELECTEDCOURSE(COURSE);

SETSHOWADDLESSON(TRUE);

}}

CLASSNAME="MT-2 W-FULL FLEX ITEMS-CENTER JUSTIFY-CENTER GAP-2


PX-3 PY-2 BG-GRAY-600 TEXT-WHITE ROUNDED-LG HOVER:BG-GRAY-700"

>

<PLUSCIRCLE CLASSNAME="W-5 H-5" /> ADD LESSON

</BUTTON>

<BUTTON

ONCLICK={() => NAVIGATE(`/COURSE/${COURSE._ID}/LESSONS`)}


CLASSNAME="MT-2 W-FULL FLEX ITEMS-CENTER JUSTIFY-CENTER GAP-2
PX-3 PY-2 BG-BLUE-600 TEXT-WHITE ROUNDED-LG HOVER:BG-BLUE-700"

>

VIEW LESSONS

</BUTTON>

</DIV>

))}

</DIV>

);

RETURN (

<DIV CLASSNAME="MIN-H-SCREEN BG-GRAY-100 FLEX">

{/* SIDEBAR */}

<DIV

CLASSNAME={`FIXED INSET-Y-0 LEFT-0 W-64 BG-WHITE SHADOW-LG P-4 FLEX


FLEX-COL TRANSFORM TRANSITION-TRANSFORM DURATION-300 Z-40

${

SIDEBAROPEN ? "TRANSLATE-X-0" : "-TRANSLATE-X-FULL"

} MD:TRANSLATE-X-0`}

>

<DIV CLASSNAME="FLEX JUSTIFY-BETWEEN ITEMS-CENTER MB-8">

<H2 CLASSNAME="TEXT-2XL FONT-BOLD FLEX ITEMS-CENTER GAP-2">

<LAYOUTDASHBOARD CLASSNAME="W-6 H-6 TEXT-BLUE-600" /> MENTOR


PANEL

</H2>

<BUTTON CLASSNAME="MD:HIDDEN" ONCLICK={() =>


SETSIDEBAROPEN(FALSE)}>

<X CLASSNAME="W-6 H-6" />

</BUTTON>

</DIV>

<UL CLASSNAME="SPACE-Y-3 FLEX-1">


{[

{ KEY: "STATS", LABEL: "DASHBOARD", ICON: USERS },

{ KEY: "COURSES", LABEL: "MY COURSES", ICON: BOOKOPEN },

{ KEY: "PENDING", LABEL: "PENDING COURSES", ICON: CLOCK },

{ KEY: "APPROVED", LABEL: "APPROVED COURSES", ICON: CHECKCIRCLE },

].MAP(({ KEY, LABEL, ICON: ICON }) => (

<LI KEY={KEY}>

<BUTTON

ONCLICK={() => {

SETACTIVETAB(KEY);

SETSIDEBAROPEN(FALSE);

}}

CLASSNAME={`W-FULL FLEX ITEMS-CENTER GAP-3 PX-3 PY-2 ROUNDED-


LG TRANSITION ${

ACTIVETAB === KEY

? "BG-BLUE-600 TEXT-WHITE"

: "HOVER:BG-GRAY-100 TEXT-GRAY-700"

}`}

>

<ICON CLASSNAME="W-5 H-5" /> {LABEL}

</BUTTON>

</LI>

))}

<LI>

<BUTTON

ONCLICK={() => {

SETSHOWADDCOURSE(TRUE);

SETSIDEBAROPEN(FALSE);

}}

CLASSNAME="W-FULL FLEX ITEMS-CENTER GAP-3 PX-3 PY-2 ROUNDED-LG


TRANSITION BG-GREEN-600 TEXT-WHITE HOVER:BG-GREEN-700"

>

<PLUSCIRCLE CLASSNAME="W-5 H-5" /> ADD COURSE

</BUTTON>

</LI>

</UL>

<BUTTON

ONCLICK={LOGOUT}

CLASSNAME="MT-6 W-FULL PX-4 PY-2 BG-RED-600 TEXT-WHITE ROUNDED-


LG HOVER:BG-RED-700 FLEX ITEMS-CENTER JUSTIFY-CENTER GAP-2"

>

<LOGOUT CLASSNAME="W-5 H-5" /> LOGOUT

</BUTTON>

</DIV>

<DIV CLASSNAME="FLEX-1 P-6 MD:ML-64">

<DIV CLASSNAME="MD:HIDDEN FLEX JUSTIFY-BETWEEN ITEMS-CENTER MB-


6">

<H2 CLASSNAME="TEXT-XL FONT-BOLD TEXT-GREEN-700">

WELCOME, {MENTOR?.NAME}

</H2>

<BUTTON

CLASSNAME="TEXT-GRAY-600"

ONCLICK={() => SETSIDEBAROPEN(TRUE)}

>

<MENU CLASSNAME="W-6 H-6" />

</BUTTON>

</DIV>

<H2 CLASSNAME="HIDDEN MD:BLOCK TEXT-2XL FONT-BOLD MB-6 TEXT-


GREEN-700">

WELCOME, {MENTOR?.NAME || "MENTOR"}

</H2>

{ACTIVETAB === "STATS" && (

<DIV>

<DIV CLASSNAME="GRID GRID-COLS-1 SM:GRID-COLS-2 LG:GRID-COLS-4


GAP-6 MB-8">

<DIV CLASSNAME="BG-WHITE SHADOW ROUNDED-LG P-5 TEXT-CENTER">

<P CLASSNAME="TEXT-GRAY-600">TOTAL COURSES</P>

<P CLASSNAME="FONT-BOLD TEXT-3XL TEXT-INDIGO-600">

{[Link]}

</P>

</DIV>

<DIV CLASSNAME="BG-WHITE SHADOW ROUNDED-LG P-5 TEXT-CENTER">

<P CLASSNAME="TEXT-GRAY-600">APPROVED</P>

<P CLASSNAME="FONT-BOLD TEXT-3XL TEXT-GREEN-600">

{[Link]}

</P>

</DIV>

<DIV CLASSNAME="BG-WHITE SHADOW ROUNDED-LG P-5 TEXT-CENTER">

<P CLASSNAME="TEXT-GRAY-600">PENDING</P>

<P CLASSNAME="FONT-BOLD TEXT-3XL TEXT-YELLOW-500">

{[Link]}

</P>

</DIV>

<DIV CLASSNAME="BG-WHITE SHADOW ROUNDED-LG P-5 TEXT-CENTER">

<P CLASSNAME="TEXT-GRAY-600">REJECTED</P>

<P CLASSNAME="FONT-BOLD TEXT-3XL TEXT-RED-500">

{[Link]}

</P>
</DIV>

</DIV>

{/* CHART */}

<DIV CLASSNAME="BG-WHITE SHADOW ROUNDED-LG P-6">

<H3 CLASSNAME="TEXT-LG FONT-SEMIBOLD TEXT-GRAY-800 TEXT-


CENTER MB-4">

COURSE STATUS OVERVIEW

</H3>

<DIV CLASSNAME="H-96">

<RESPONSIVECONTAINER WIDTH="100%" HEIGHT="100%">

<PIECHART>

<PIE

DATA={[

{ NAME: "APPROVED", VALUE: [Link] || 0 },

{ NAME: "PENDING", VALUE: [Link] || 0 },

{ NAME: "REJECTED", VALUE: [Link] || 0 },

]}

DATAKEY="VALUE"

NAMEKEY="NAME"

CX="50%"

CY="50%"

INNERRADIUS={80}

OUTERRADIUS={130}

PADDINGANGLE={4}

LABEL={({ NAME, VALUE }) => `${NAME}: ${VALUE}`}

>

<CELL FILL="#22C55E" /> {/* APPROVED - GREEN */}

<CELL FILL="#EAB308" /> {/* PENDING - YELLOW */}

<CELL FILL="#EF4444" /> {/* REJECTED - RED */}

</PIE>
<TOOLTIP />

<LEGEND VERTICALALIGN="BOTTOM" HEIGHT={36} />

</PIECHART>

</RESPONSIVECONTAINER>

</DIV>

</DIV>

</DIV>

)}

{ACTIVETAB === "COURSES" && (

<DIV>

<H3 CLASSNAME="TEXT-XL FONT-BOLD MB-4">MY COURSES</H3>

<COURSEGRID COURSES={COURSES} />

</DIV>

)}

{ACTIVETAB === "PENDING" && (

<DIV>

<H3 CLASSNAME="TEXT-XL FONT-BOLD MB-4">PENDING COURSES</H3>

<COURSEGRID

COURSES={[Link]((C) => [Link] === "PENDING")}

/>

</DIV>

)}

{ACTIVETAB === "APPROVED" && (

<DIV>

<H3 CLASSNAME="TEXT-XL FONT-BOLD MB-4">APPROVED COURSES</H3>

<COURSEGRID

COURSES={[Link]((C) => [Link] === "APPROVED")}


/>

</DIV>

)}

{/* ADD COURSE MODAL */}

{SHOWADDCOURSE && (

<DIV CLASSNAME="FIXED INSET-0 BG-BLACK BG-OPACITY-50 FLEX ITEMS-


CENTER JUSTIFY-CENTER Z-50 P-4">

<FORM

ONSUBMIT={HANDLEADDCOURSE}

CLASSNAME="BG-WHITE P-6 ROUNDED-XL W-FULL MAX-W-MD FLEX FLEX-


COL GAP-3"

>

<H3 CLASSNAME="TEXT-LG FONT-BOLD">ADD COURSE</H3>

<INPUT

TYPE="TEXT"

PLACEHOLDER="NAME"

VALUE={[Link]}

ONCHANGE={(E) =>

SETCOURSEFORM({ ...COURSEFORM, NAME: [Link] })

REQUIRED

CLASSNAME="BORDER P-2 ROUNDED"

/>

<INPUT

TYPE="TEXT"

PLACEHOLDER="CATEGORY"

VALUE={[Link]}

ONCHANGE={(E) =>

SETCOURSEFORM({ ...COURSEFORM, CATEGORY: [Link] })

}
REQUIRED

CLASSNAME="BORDER P-2 ROUNDED"

/>

<TEXTAREA

PLACEHOLDER="DESCRIPTION"

VALUE={[Link]}

ONCHANGE={(E) =>

SETCOURSEFORM({ ...COURSEFORM, DESCRIPTION: [Link] })

REQUIRED

CLASSNAME="BORDER P-2 ROUNDED"

/>

<INPUT

TYPE="FILE"

ACCEPT="IMAGE/*"

ONCHANGE={(E) =>

SETCOURSEFORM({ ...COURSEFORM, THUMBNAIL: [Link][0] })

/>

<DIV CLASSNAME="FLEX JUSTIFY-END GAP-2 MT-2">

<BUTTON

TYPE="BUTTON"

ONCLICK={() => SETSHOWADDCOURSE(FALSE)}

CLASSNAME="PX-4 PY-2 BG-GRAY-400 ROUNDED-LG"

>

CANCEL

</BUTTON>

<BUTTON

TYPE="SUBMIT"

CLASSNAME="PX-4 PY-2 BG-BLUE-600 TEXT-WHITE ROUNDED-LG"


>

ADD

</BUTTON>

</DIV>

</FORM>

</DIV>

)}

{/* ADD LESSON MODAL */}

{SHOWADDLESSON && SELECTEDCOURSE && (

<DIV CLASSNAME="FIXED INSET-0 BG-BLACK BG-OPACITY-50 FLEX ITEMS-


CENTER JUSTIFY-CENTER Z-50 P-4">

<FORM

ONSUBMIT={HANDLEADDLESSON}

CLASSNAME="BG-WHITE P-6 ROUNDED-XL W-FULL MAX-W-MD FLEX FLEX-


COL GAP-3"

>

<H3 CLASSNAME="TEXT-LG FONT-BOLD">

ADD LESSON TO {[Link]}

</H3>

<INPUT

TYPE="TEXT"

PLACEHOLDER="LESSON TITLE"

VALUE={[Link]}

ONCHANGE={(E) =>

SETLESSONFORM({ ...LESSONFORM, TITLE: [Link] })

REQUIRED

CLASSNAME="BORDER P-2 ROUNDED"

/>

<TEXTAREA
PLACEHOLDER="CONTENT"

VALUE={[Link]}

ONCHANGE={(E) =>

SETLESSONFORM({ ...LESSONFORM, CONTENT: [Link] })

REQUIRED

CLASSNAME="BORDER P-2 ROUNDED"

/>

<INPUT

TYPE="FILE"

ACCEPT="VIDEO/*"

ONCHANGE={(E) =>

SETLESSONFORM({ ...LESSONFORM, VIDEO: [Link][0] })

REQUIRED

CLASSNAME="BORDER P-2 ROUNDED"

/>

<INPUT

TYPE="NUMBER"

PLACEHOLDER="ORDER"

VALUE={[Link]}

ONCHANGE={(E) =>

SETLESSONFORM({ ...LESSONFORM, ORDER: [Link] })

CLASSNAME="BORDER P-2 ROUNDED"

/>

<DIV CLASSNAME="FLEX JUSTIFY-END GAP-2 MT-2">

<BUTTON

TYPE="BUTTON"

ONCLICK={() => SETSHOWADDLESSON(FALSE)}


CLASSNAME="PX-4 PY-2 BG-GRAY-400 ROUNDED-LG"

>

CANCEL

</BUTTON>

<BUTTON

TYPE="SUBMIT"

CLASSNAME="PX-4 PY-2 BG-GREEN-600 TEXT-WHITE ROUNDED-LG"

>

ADD LESSON

</BUTTON>

</DIV>

</FORM>

</DIV>

)}

</DIV>

</DIV>

);

[Link]

// SRC/PAGES/[Link]

IMPORT { USESTATE } FROM "REACT";

IMPORT { USEMENTOR } FROM "../CONTEXT/MENTORCONTEXT";


EXPORT DEFAULT FUNCTION MENTORLOGIN() {

CONST [EMAIL, SETEMAIL] = USESTATE("");

CONST [PASSWORD, SETPASSWORD] = USESTATE("");

CONST [ERROR, SETERROR] = USESTATE("");

CONST { LOGIN, LOADING } = USEMENTOR();

CONST HANDLESUBMIT = ASYNC (E) => {

[Link]();

SETERROR("");

TRY {

AWAIT LOGIN(EMAIL, PASSWORD);

} CATCH (ERR) {

SETERROR(ERR);

};

RETURN (

<DIV CLASSNAME="MIN-H-SCREEN FLEX ITEMS-CENTER JUSTIFY-CENTER BG-


GRAY-100 PX-4">

<DIV CLASSNAME="MAX-W-MD W-FULL BG-WHITE P-8 ROUNDED-2XL SHADOW-


LG">

<H2 CLASSNAME="TEXT-2XL FONT-BOLD TEXT-CENTER TEXT-GRAY-800 MB-


6">

MENTOR LOGIN

</H2>

{ERROR && (

<DIV CLASSNAME="MB-4 P-2 TEXT-SM TEXT-RED-700 BG-RED-100


ROUNDED">

{ERROR}

</DIV>

)}

<FORM ONSUBMIT={HANDLESUBMIT} CLASSNAME="SPACE-Y-4">


<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700 FONT-MEDIUM MB-1">

EMAIL

</LABEL>

<INPUT

TYPE="EMAIL"

CLASSNAME="W-FULL PX-3 PY-2 BORDER ROUNDED-LG FOCUS:RING


FOCUS:RING-BLUE-300 OUTLINE-NONE"

VALUE={EMAIL}

ONCHANGE={(E) => SETEMAIL([Link])}

REQUIRED

/>

</DIV>

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700 FONT-MEDIUM MB-1">

PASSWORD

</LABEL>

<INPUT

TYPE="PASSWORD"

CLASSNAME="W-FULL PX-3 PY-2 BORDER ROUNDED-LG FOCUS:RING


FOCUS:RING-BLUE-300 OUTLINE-NONE"

VALUE={PASSWORD}

ONCHANGE={(E) => SETPASSWORD([Link])}

REQUIRED

/>

</DIV>

<BUTTON

TYPE="SUBMIT"

DISABLED={LOADING}
CLASSNAME="W-FULL BG-BLUE-600 TEXT-WHITE PY-2 ROUNDED-LG
HOVER:BG-BLUE-700 TRANSITION DISABLED:OPACITY-50"

>

{LOADING ? "LOGGING IN..." : "LOGIN"}

</BUTTON>

</FORM>

</DIV>

</DIV>

);

[Link]

// SRC/PAGES/[Link]

IMPORT { USESTATE } FROM "REACT";

IMPORT { USEMENTOR } FROM "../CONTEXT/MENTORCONTEXT";


EXPORT DEFAULT FUNCTION MENTORLOGIN() {

CONST [EMAIL, SETEMAIL] = USESTATE("");

CONST [PASSWORD, SETPASSWORD] = USESTATE("");

CONST [ERROR, SETERROR] = USESTATE("");

CONST { LOGIN, LOADING } = USEMENTOR();

CONST HANDLESUBMIT = ASYNC (E) => {

[Link]();

SETERROR("");

TRY {

AWAIT LOGIN(EMAIL, PASSWORD);

} CATCH (ERR) {

SETERROR(ERR);

};

RETURN (

<DIV CLASSNAME="MIN-H-SCREEN FLEX ITEMS-CENTER JUSTIFY-CENTER BG-


GRAY-100 PX-4">

<DIV CLASSNAME="MAX-W-MD W-FULL BG-WHITE P-8 ROUNDED-2XL SHADOW-


LG">

<H2 CLASSNAME="TEXT-2XL FONT-BOLD TEXT-CENTER TEXT-GRAY-800 MB-


6">

MENTOR LOGIN

</H2>

{ERROR && (

<DIV CLASSNAME="MB-4 P-2 TEXT-SM TEXT-RED-700 BG-RED-100


ROUNDED">

{ERROR}

</DIV>

)}
<FORM ONSUBMIT={HANDLESUBMIT} CLASSNAME="SPACE-Y-4">

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700 FONT-MEDIUM MB-1">

EMAIL

</LABEL>

<INPUT

TYPE="EMAIL"

CLASSNAME="W-FULL PX-3 PY-2 BORDER ROUNDED-LG FOCUS:RING


FOCUS:RING-BLUE-300 OUTLINE-NONE"

VALUE={EMAIL}

ONCHANGE={(E) => SETEMAIL([Link])}

REQUIRED

/>

</DIV>

<DIV>

<LABEL CLASSNAME="BLOCK TEXT-GRAY-700 FONT-MEDIUM MB-1">

PASSWORD

</LABEL>

<INPUT

TYPE="PASSWORD"

CLASSNAME="W-FULL PX-3 PY-2 BORDER ROUNDED-LG FOCUS:RING


FOCUS:RING-BLUE-300 OUTLINE-NONE"

VALUE={PASSWORD}

ONCHANGE={(E) => SETPASSWORD([Link])}

REQUIRED

/>

</DIV>

<BUTTON

TYPE="SUBMIT"
DISABLED={LOADING}

CLASSNAME="W-FULL BG-BLUE-600 TEXT-WHITE PY-2 ROUNDED-LG


HOVER:BG-BLUE-700 TRANSITION DISABLED:OPACITY-50"

>

{LOADING ? "LOGGING IN..." : "LOGIN"}

</BUTTON>

</FORM>

</DIV>

</DIV>

);

[Link]

IMPORT { USEEFFECT, USESTATE } FROM "REACT";

IMPORT AXIOS FROM "AXIOS";

IMPORT { USEUSER } FROM "../CONTEXT/USERCONTEXT";


IMPORT TOAST FROM "REACT-HOT-TOAST";

IMPORT { MENU, X } FROM "LUCIDE-REACT";

EXPORT DEFAULT FUNCTION USERDASHBOARD() {

CONST { USER, TOKEN, LOGOUT } = USEUSER();

CONST [ALLCOURSES, SETALLCOURSES] = USESTATE([]);

CONST [ENROLLEDCOURSES, SETENROLLEDCOURSES] = USESTATE([]);

CONST [SELECTEDCOURSE, SETSELECTEDCOURSE] = USESTATE(NULL);

CONST [LESSONS, SETLESSONS] = USESTATE([]);

CONST [LOADING, SETLOADING] = USESTATE(TRUE);

CONST [VIEWENROLLED, SETVIEWENROLLED] = USESTATE(FALSE);

CONST [SIDEBAROPEN, SETSIDEBAROPEN] = USESTATE(FALSE);

USEEFFECT(() => {

CONST FETCHCOURSES = ASYNC () => {

IF (!TOKEN) RETURN;

SETLOADING(TRUE);

TRY {

CONST [COURSESRES, ENROLLEDRES] = AWAIT [Link]([

[Link]("HTTP://LOCALHOST:3000/API/V1/COURSE/GET-ALL-COURSES"),

[Link]("HTTP://LOCALHOST:3000/API/V1/USER-ENROLL/GET-
ENROLLED", {

HEADERS: { AUTHORIZATION: `BEARER ${TOKEN}` },

}),

]);

CONST APPROVEDCOURSES = ([Link] || []).FILTER(

(C) => C && [Link] === "APPROVED" && C._ID

);

SETALLCOURSES(APPROVEDCOURSES);
CONST ENROLLEDFULL = ([Link] || []).FILTER((C) => C &&
C._ID);

SETENROLLEDCOURSES(ENROLLEDFULL);

} CATCH (ERR) {

[Link](ERR);

[Link]("FAILED TO FETCH COURSES");

} FINALLY {

SETLOADING(FALSE);

};

FETCHCOURSES();

}, [TOKEN]);

CONST FETCHLESSONS = ASYNC (COURSEID) => {

TRY {

CONST RES = AWAIT [Link](

`HTTP://LOCALHOST:3000/API/V1/LESSON/GET-ALL-LESSONS/${COURSEID}`,

{ HEADERS: { AUTHORIZATION: `BEARER ${TOKEN}` } }

);

SETLESSONS([Link] || []);

CONST COURSE =

[Link]((C) => C && C._ID === COURSEID) ||

[Link]((C) => C && C._ID === COURSEID);

SETSELECTEDCOURSE(COURSE || NULL);

} CATCH (ERR) {

[Link](ERR);

[Link]("FAILED TO FETCH LESSONS");

}
};

CONST HANDLEENROLL = ASYNC (COURSEID) => {

IF ([Link]((C) => C && C._ID === COURSEID)) {

[Link]("YOU ARE ALREADY ENROLLED IN THIS COURSE");

RETURN;

TRY {

CONST RES = AWAIT [Link](

`HTTP://LOCALHOST:3000/API/V1/USER-ENROLL/${COURSEID}`,

{},

{ HEADERS: { AUTHORIZATION: `BEARER ${TOKEN}` } }

);

IF ([Link]) {

[Link]("ENROLLED SUCCESSFULLY!");

CONST ENROLLEDCOURSE = [Link]((C) => C && C._ID ===


COURSEID);

IF (ENROLLEDCOURSE) SETENROLLEDCOURSES((PREV) => [...PREV,


ENROLLEDCOURSE]);

ELSE {

CONST COURSERES = AWAIT [Link](

`HTTP://LOCALHOST:3000/API/V1/COURSE/GET-COURSE/${COURSEID}`,

{ HEADERS: { AUTHORIZATION: `BEARER ${TOKEN}` } }

);

IF ([Link]?.DATA && [Link]._ID)

SETENROLLEDCOURSES((PREV) => [...PREV, [Link]]);

} ELSE [Link]([Link] || "ENROLLMENT FAILED");

} CATCH (ERR) {
[Link]("ENROLL ERROR:", [Link]?.DATA || ERR);

[Link]([Link]?.DATA?.MESSAGE || "ENROLLMENT FAILED");

};

IF (LOADING) RETURN <P CLASSNAME="TEXT-CENTER MT-10 TEXT-


LG">LOADING...</P>;

CONST COURSESTODISPLAY = VIEWENROLLED ? ENROLLEDCOURSES :


ALLCOURSES;

RETURN (

<DIV CLASSNAME="MIN-H-SCREEN BG-GRAY-100 FLEX">

<ASIDE

CLASSNAME={`FIXED INSET-Y-0 LEFT-0 W-64 BG-WHITE SHADOW-LG P-6 FLEX


FLEX-COL TRANSFORM TRANSITION-TRANSFORM DURATION-300 Z-40

${SIDEBAROPEN ? "TRANSLATE-X-0" : "-TRANSLATE-X-FULL"} MD:TRANSLATE-


X-0`}

>

<DIV CLASSNAME="FLEX JUSTIFY-BETWEEN ITEMS-CENTER MB-8


MD:HIDDEN">

<H2 CLASSNAME="TEXT-2XL FONT-BOLD">DASHBOARD</H2>

<BUTTON ONCLICK={() => SETSIDEBAROPEN(FALSE)}>

<X CLASSNAME="W-6 H-6" />

</BUTTON>

</DIV>

<H2 CLASSNAME="TEXT-BLUE-600 HIDDEN MD:BLOCK TEXT-3XL FONT-BOLD


">STUDIPAL</H2>

<HR CLASSNAME="MY-2" />

{/* <H2 CLASSNAME="HIDDEN MD:BLOCK TEXT-2XL FONT-BOLD MB-8">USER


DASHBOARD</H2> */}

<BUTTON
ONCLICK={() => {

SETVIEWENROLLED(FALSE);

SETSIDEBAROPEN(FALSE);

}}

CLASSNAME={`MB-2 PX-4 PY-2 ROUNDED-LG W-FULL TEXT-WHITE ${

!VIEWENROLLED

? "BG-BLUE-600 HOVER:BG-BLUE-700"

: "BG-GRAY-300 HOVER:BG-GRAY-400"

} TRANSITION`}

>

ALL COURSES

</BUTTON>

<BUTTON

ONCLICK={() => {

SETVIEWENROLLED(TRUE);

SETSIDEBAROPEN(FALSE);

}}

CLASSNAME={`MB-2 PX-4 PY-2 ROUNDED-LG W-FULL TEXT-WHITE ${

VIEWENROLLED

? "BG-BLUE-600 HOVER:BG-BLUE-700"

: "BG-GRAY-300 HOVER:BG-GRAY-400"

} TRANSITION`}

>

ENROLLED COURSES

</BUTTON>

<BUTTON

ONCLICK={LOGOUT}

CLASSNAME="MT-AUTO PX-4 PY-2 BG-RED-600 TEXT-WHITE ROUNDED-LG


HOVER:BG-RED-700 TRANSITION"

>
LOGOUT

</BUTTON>

</ASIDE>

<MAIN CLASSNAME="FLEX-1 P-6 MD:ML-64 OVERFLOW-Y-AUTO">

<DIV CLASSNAME="MD:HIDDEN FLEX JUSTIFY-BETWEEN ITEMS-CENTER MB-


6">

<H2 CLASSNAME="TEXT-2XL FONT-BOLD TEXT-BLUE-600">STUDIPAL</H2>

<BUTTON ONCLICK={() => SETSIDEBAROPEN(TRUE)}>

<MENU CLASSNAME="W-6 H-6" />

</BUTTON>

</DIV>

{!SELECTEDCOURSE && (

<>

<H1 CLASSNAME="TEXT-XL SM:TEXT-2XL FONT-BOLD MB-6 TEXT-GRAY-


800">

<SPAN CLASSNAME="BLOCK TEXT-XL SM:TEXT-2XL TEXT-GREEN-600 MB-


2">

WELCOME, {USER?.NAME}

</SPAN>

<HR />

{VIEWENROLLED ? "ENROLLED COURSES" : "ALL COURSES"}

</H1>

{[Link] === 0 && (

<P CLASSNAME="TEXT-GRAY-500 TEXT-CENTER">NO COURSES TO


DISPLAY.</P>

)}

<DIV CLASSNAME="GRID GRID-COLS-1 SM:GRID-COLS-2 MD:GRID-COLS-3


LG:GRID-COLS-4 GAP-6">
{COURSESTODISPLAY

.FILTER((COURSE) => COURSE && COURSE._ID)

.MAP((COURSE) => {

CONST ISENROLLED = [Link](

(C) => C && C._ID === COURSE._ID

);

RETURN (

<DIV

KEY={COURSE._ID}

CLASSNAME="BG-WHITE ROUNDED-XL SHADOW-MD HOVER:SHADOW-


2XL HOVER:SCALE-105 TRANSITION-TRANSFORM DURATION-300 OVERFLOW-
HIDDEN GROUP"

>

<DIV CLASSNAME="RELATIVE">

<IMG

SRC={[Link] || "/[Link]"}

ALT={[Link] || "COURSE"}

CLASSNAME="W-FULL H-48 OBJECT-COVER"

/>

<DIV CLASSNAME="ABSOLUTE INSET-0 BG-GRADIENT-TO-T FROM-


BLACK/50 TO-TRANSPARENT OPACITY-0 GROUP-HOVER:OPACITY-100
TRANSITION-OPACITY"></DIV>

<SPAN CLASSNAME="ABSOLUTE TOP-2 RIGHT-2 BG-INDIGO-600


TEXT-WHITE TEXT-XS PX-3 PY-1 ROUNDED-FULL FONT-MEDIUM">

{[Link] || "GENERAL"}

</SPAN>

<H2 CLASSNAME="ABSOLUTE BOTTOM-2 LEFT-2 TEXT-WHITE FONT-


SEMIBOLD TEXT-SM SM:TEXT-BASE LINE-CLAMP-2">

{[Link] || "UNTITLED COURSE"}

</H2>

</DIV>
<DIV CLASSNAME="P-4">

<P CLASSNAME="TEXT-GRAY-600 TEXT-SM MB-3 LINE-CLAMP-3">

{[Link] || "NO DESCRIPTION AVAILABLE."}

</P>

<P CLASSNAME="TEXT-SM TEXT-GRAY-500 MB-3">

MENTOR: {[Link]?.NAME || "N/A"}

</P>

<DIV CLASSNAME="FLEX JUSTIFY-CENTER">

{ISENROLLED ? (

<BUTTON

ONCLICK={() => FETCHLESSONS(COURSE._ID)}

CLASSNAME="W-FULL BG-BLUE-600 HOVER:BG-BLUE-700 TEXT-


WHITE FONT-MEDIUM PY-2 ROUNDED-LG TRANSITION-ALL DURATION-300
SHADOW HOVER:SHADOW-LG"

>

VIEW LESSONS

</BUTTON>

):(

<BUTTON

ONCLICK={() => HANDLEENROLL(COURSE._ID)}

CLASSNAME="W-FULL BG-GREEN-600 HOVER:BG-GREEN-700


TEXT-WHITE FONT-MEDIUM PY-2 ROUNDED-LG TRANSITION-ALL DURATION-300
SHADOW HOVER:SHADOW-LG"

>

ENROLL NOW

</BUTTON>

)}

</DIV>

</DIV>

</DIV>

);

})}
</DIV>

</>

)}

{SELECTEDCOURSE && (

<>

<BUTTON

ONCLICK={() => {

SETSELECTEDCOURSE(NULL);

SETLESSONS([]);

}}

CLASSNAME="MB-6 PX-4 PY-2 BG-GRAY-300 ROUNDED-LG HOVER:BG-


GRAY-400 TRANSITION"

>

← BACK TO COURSES
</BUTTON>

<H2 CLASSNAME="TEXT-2XL FONT-BOLD MB-6 TEXT-GRAY-800">

{[Link]} - LESSONS

</H2>

<DIV CLASSNAME="GRID GRID-COLS-1 SM:GRID-COLS-2 LG:GRID-COLS-3


GAP-6">

{[Link] === 0 ? (

<P CLASSNAME="TEXT-GRAY-500">NO LESSONS AVAILABLE.</P>

):(

[Link](

(LESSON) =>

LESSON &&

LESSON._ID && (

<DIV
KEY={LESSON._ID}

CLASSNAME="BG-WHITE ROUNDED-XL SHADOW-MD


HOVER:SHADOW-LG TRANSITION OVERFLOW-HIDDEN"

>

<DIV CLASSNAME="P-4">

<H4 CLASSNAME="FONT-BOLD TEXT-LG MB-


2">{[Link]}</H4>

<P CLASSNAME="TEXT-SM TEXT-GRAY-600 MB-2 LINE-CLAMP-3">

{[Link]}

</P>

{[Link] && (

<VIDEO

CONTROLS

CLASSNAME="W-FULL H-48 ROUNDED-LG MT-2"

>

<SOURCE SRC={[Link]} TYPE="VIDEO/MP4" />

</VIDEO>

)}

</DIV>

</DIV>

)}

</DIV>

</>

)}

</MAIN>

</DIV>

);

}
ROUTES

[Link]

IMPORT { NAVIGATE } FROM "REACT-ROUTER-DOM";

IMPORT { USEUSER } FROM "../CONTEXT/USERCONTEXT";

IMPORT { USEMENTOR } FROM "../CONTEXT/MENTORCONTEXT";

IMPORT { USEADMIN } FROM "../CONTEXT/ADMINCONTEXT";

EXPORT DEFAULT FUNCTION PROTECTEDROUTE({ CHILDREN, ROLE }) {

IF (ROLE === "USER") {

CONST { TOKEN } = USEUSER();


RETURN TOKEN ? CHILDREN : <NAVIGATE TO="/USER/LOGIN" REPLACE />;

IF (ROLE === "MENTOR") {

CONST { TOKEN } = USEMENTOR();

RETURN TOKEN ? CHILDREN : <NAVIGATE TO="/MENTOR/LOGIN" REPLACE />;

IF (ROLE === "ADMIN") {

CONST { TOKEN } = USEADMIN();

RETURN TOKEN ? CHILDREN : <NAVIGATE TO="/ADMIN/LOGIN" REPLACE />;

RETURN <NAVIGATE TO="/" REPLACE />;

[Link]

IMPORT { NAVIGATE } FROM "REACT-ROUTER-DOM";

IMPORT { USEUSER } FROM "../CONTEXT/USERCONTEXT";

IMPORT { USEMENTOR } FROM "../CONTEXT/MENTORCONTEXT";

IMPORT { USEADMIN } FROM "../CONTEXT/ADMINCONTEXT";

EXPORT DEFAULT FUNCTION PUBLICROUTE({ CHILDREN, ROLE }) {

CONST { TOKEN: USERTOKEN } = USEUSER();

CONST { TOKEN: MENTORTOKEN } = USEMENTOR();

CONST { TOKEN: ADMINTOKEN } = USEADMIN();


IF (ROLE === "USER" && USERTOKEN) RETURN <NAVIGATE
TO="/USER/DASHBOARD" REPLACE />;

IF (ROLE === "MENTOR" && MENTORTOKEN) RETURN <NAVIGATE


TO="/MENTOR/DASHBOARD" REPLACE />;

IF (ROLE === "ADMIN" && ADMINTOKEN) RETURN <NAVIGATE


TO="/ADMIN/DASHBOARD" REPLACE />;

RETURN CHILDREN;

BACKEND
CONTROLLER-ADMIN

CONST CONST BCRYPT = REQUIRE("BCRYPT");

CONST JWT = REQUIRE("JSONWEBTOKEN");

CONST ADMIN = REQUIRE("../MODELS/[Link]");

CONST COURSE = REQUIRE("../MODELS/[Link]")

CONST MENTOR = REQUIRE("../MODELS/[Link]")

CONST USER = REQUIRE("../MODELS/[Link]");

// REGISTER ADMIN

CONST REGISTERADMIN = ASYNC (REQ, RES) => {

TRY {

CONST { NAME, EMAIL, PASSWORD } = [Link];

IF (!NAME || !EMAIL || !PASSWORD) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "ALL FIELDS ARE


REQUIRED" });
}

CONST EMAILLOWER = [Link]().TOLOWERCASE();

CONST EXISTINGADMIN = AWAIT [Link]({ EMAIL: EMAILLOWER });

IF (EXISTINGADMIN) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "ADMIN ALREADY


REGISTERED" });

CONST HASHEDPASSWORD = AWAIT [Link](PASSWORD, 10);

CONST NEWADMIN = NEW ADMIN({ NAME, EMAIL: EMAILLOWER, PASSWORD:


HASHEDPASSWORD });

CONST SAVEDADMIN = AWAIT [Link]();

[Link](201).JSON({

STATUS: 1,

MESSAGE: "ADMIN REGISTERED SUCCESSFULLY",

DATA: { ID: SAVEDADMIN._ID, NAME: [Link], EMAIL:


[Link] },

});

} CATCH (ERROR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: `SERVER ERROR:


${[Link]}` });

};

// LOGIN ADMIN

CONST LOGINADMIN = ASYNC (REQ, RES) => {

TRY {

CONST { EMAIL, PASSWORD } = [Link];

IF (!EMAIL || !PASSWORD) {
RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "ALL FIELDS ARE
REQUIRED" });

CONST EMAILLOWER = [Link]().TOLOWERCASE();

CONST ADMIN = AWAIT [Link]({ EMAIL: EMAILLOWER });

IF (!ADMIN) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "ADMIN NOT


REGISTERED" });

CONST ISMATCH = AWAIT [Link](PASSWORD, [Link]);

IF (!ISMATCH) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "EMAIL OR


PASSWORD IS WRONG" });

CONST TOKEN = [Link]({ ID: ADMIN._ID, ROLE: "ADMIN" },


[Link].JWT_SECRET, { EXPIRESIN: "7D" });

[Link]("TOKEN", TOKEN, {

HTTPONLY: TRUE,

SECURE: [Link].NODE_ENV === "PRODUCTION",

SAMESITE: "STRICT",

MAXAGE: 7 * 24 * 60 * 60 * 1000,

});

[Link](200).JSON({ STATUS: 1, MESSAGE: "ADMIN LOGIN SUCCESSFUL",


TOKEN });

} CATCH (ERROR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: `SERVER ERROR:


${[Link]}` });
}

};

// ADDING MENTOR

CONST ADDMENTOR = ASYNC (REQ, RES) => {

TRY {

CONST { NAME, EMAIL, PASSWORD } = [Link];

IF (!NAME || !EMAIL || !PASSWORD) {

RETURN [Link](403).JSON({

MESSAGE: "ALL FIELDS ARE REQUIRED",

});

CONST EXISTINGMENTOR = AWAIT [Link]({ EMAIL });

IF (EXISTINGMENTOR) {

RETURN [Link](403).JSON({

MESSAGE: "MENTOR ALREADY REGISTERED",

});

CONST HASHEDPASSWORD = AWAIT [Link](PASSWORD, 10);

CONST MENTOR = NEW MENTOR({

NAME,

EMAIL,

PASSWORD: HASHEDPASSWORD,

});
CONST SAVEDMENTOR = AWAIT [Link]();

[Link](201).JSON({

STATUS: 1,

MESSAGE: "MENTOR CREATED SUCCESSFULLY",

SAVEDMENTOR,

});

} CATCH (ERROR) {

[Link](500).JSON({

STATUS: 0,

MESSAGE: `SERVER ERROR: ${[Link]}`,

});

};

//APPROVE A PENDING COURSE

CONST APPROVECOURSE = ASYNC (REQ, RES) => {

TRY {

CONST { ID } = [Link]; // PENDING COURSE ID

CONST PENDINGCOURSE = AWAIT [Link](ID);

IF (!PENDINGCOURSE || [Link] !== "PENDING") {

RETURN [Link](404).JSON({ STATUS: 0, MESSAGE: "PENDING COURSE


NOT FOUND" });

// IF THIS IS AN UPDATE VERSION

IF ([Link]) {

// ARCHIVE OLD APPROVED COURSE

AWAIT [Link]([Link],
{ STATUS: "ARCHIVED" });
}

// APPROVE THE PENDING COURSE

[Link] = "APPROVED";

AWAIT [Link]();

[Link](200).JSON({

STATUS: 1,

MESSAGE: "COURSE APPROVED SUCCESSFULLY",

DATA: PENDINGCOURSE

});

} CATCH (ERROR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: `SERVER ERROR:


${[Link]}` });

};

//REJECT A PENDING COURSE

CONST REJECTCOURSE = ASYNC (REQ, RES) => {

TRY {

CONST { ID } = [Link];

CONST PENDINGCOURSE = AWAIT [Link](ID);

IF (!PENDINGCOURSE || [Link] !== "PENDING") {

RETURN [Link](404).JSON({ STATUS: 0, MESSAGE: "PENDING COURSE


NOT FOUND" });

[Link] = "REJECTED";

AWAIT [Link]();
[Link](200).JSON({

STATUS: 1,

MESSAGE: "COURSE REJECTED SUCCESSFULLY",

DATA: PENDINGCOURSE

});

} CATCH (ERROR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: `SERVER ERROR:


${[Link]}` });

};

//GET ADMIN STATS

CONST GETADMINSTATS = ASYNC (REQ, RES) => {

TRY {

CONST TOTALUSERS = AWAIT [Link]();

CONST TOTALMENTORS = AWAIT [Link]();

CONST TOTALPENDINGCOURSES = AWAIT


[Link]({ STATUS: "PENDING" });

CONST TOTALAPPROVEDCOURSES = AWAIT


[Link]({ STATUS: "APPROVED" });

CONST TOTALREJECTEDCOURSES = AWAIT


[Link]({ STATUS: "REJECTED" });

CONST TOTALCOURSES = AWAIT [Link]();

[Link](200).JSON({

STATUS: 1,

MESSAGE: "ADMIN STATS FETCHED SUCCESSFULLY",

DATA: {

TOTALUSERS,

TOTALMENTORS,

TOTALPENDINGCOURSES,

TOTALAPPROVEDCOURSES,
TOTALREJECTEDCOURSES,

TOTALCOURSES,

},

});

} CATCH (ERROR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: `SERVER ERROR:


${[Link]}` });

};

// GET ALL MENTORS

CONST GETALLMENTORS = ASYNC (REQ, RES) => {

TRY {

CONST MENTORS = AWAIT [Link]().SELECT("-PASSWORD"); // EXCLUDE


PASSWORD IF ANY

[Link]({

STATUS: 1,

MESSAGE: "ALL MENTORS FETCHED SUCCESSFULLY",

DATA: MENTORS,

});

} CATCH (ERROR) {

[Link](500).JSON({

STATUS: 0,

MESSAGE: "ERROR FETCHING MENTORS",

ERROR: [Link],

});

};

// GET ALL COURSES

CONST GETALLCOURSES = ASYNC (REQ, RES) => {


TRY {

CONST COURSES = AWAIT [Link]().POPULATE("MENTOR", "NAME


EMAIL"); // POPULATE MENTOR INFO IF NEEDED

[Link]({

STATUS: 1,

MESSAGE: "ALL COURSES FETCHED SUCCESSFULLY",

DATA: COURSES,

});

} CATCH (ERROR) {

[Link](500).JSON({

STATUS: 0,

MESSAGE: "ERROR FETCHING COURSES",

ERROR: [Link],

});

};

[Link] = { REGISTERADMIN, LOGINADMIN,APPROVECOURSE,


REJECTCOURSE, ADDMENTOR, GETADMINSTATS, GETALLMENTORS,
GETALLCOURSES};

CONTROLLER-CONTACT

REQUIRE("DOTENV").CONFIG();

CONST CONTACT = REQUIRE("../MODELS/[Link]");

CONST SENDEMAIL = REQUIRE("../UTILS/SENDEMAIL");

CONST SUBMITCONTACT = ASYNC (REQ, RES) => {

TRY {

CONST { NAME, EMAIL, MESSAGE, SUBJECT = "" } = [Link];


IF (!NAME || !EMAIL || !MESSAGE) {

RETURN [Link](400).JSON({

SUCCESS: FALSE,

MESSAGE: "ALL FIELDS ARE REQUIRED.",

});

CONST NEWCONTACT = NEW CONTACT({ NAME, EMAIL, MESSAGE });

AWAIT [Link]();

CONST ADMINSUBJECT = `NEW CONTACT FORM SUBMISSION: ${SUBJECT ||


"CONTACT INQUIRY"}`;

CONST ADMINHTML = `

<H2>NEW CONTACT FORM SUBMISSION</H2>

<P><STRONG>NAME:</STRONG> ${NAME}</P>

<P><STRONG>EMAIL:</STRONG> ${EMAIL}</P>

<P><STRONG>MESSAGE:</STRONG></P>

<P>${MESSAGE}</P>

`;

CONST USERSUBJECT = `WE RECEIVED YOUR MESSAGE: ${SUBJECT ||


"CONTACT INQUIRY"}`;

CONST USERHTML = `

<H2>THANK YOU FOR REACHING OUT!</H2>

<P>HI ${NAME},</P>

<P>THANKS FOR CONTACTING US. WE’VE RECEIVED YOUR MESSAGE AND


WILL RESPOND SHORTLY.</P>

<HR/>

<P><STRONG>YOUR MESSAGE:</STRONG></P>

<P>${MESSAGE}</P>
<HR/>

<P>BEST REGARDS,<BR/>THE STUDIPAL TEAM</P>

`;

AWAIT SENDEMAIL([Link].EMAIL_USER, ADMINSUBJECT, ADMINHTML);

AWAIT SENDEMAIL(EMAIL, USERSUBJECT, USERHTML);

[Link](200).JSON({

SUCCESS: TRUE,

MESSAGE: "FORM SUBMITTED SUCCESSFULLY!",

});

} CATCH (ERR) {

[Link]("ERROR IN SUBMITCONTACT:", ERR);

[Link](500).JSON({

SUCCESS: FALSE,

MESSAGE: "SOMETHING WENT WRONG.",

ERROR: [Link],

});

};

// GET ALL CONTACTS

CONST GETALLCONTACTS = ASYNC (REQ, RES) => {

TRY {

CONST CONTACTS = AWAIT [Link]();

[Link](200).JSON({

SUCCESS: TRUE,

MESSAGE: "CONTACTS FETCHED SUCCESSFULLY.",

DATA: CONTACTS,

});
} CATCH (ERROR) {

[Link](500).JSON({

SUCCESS: FALSE,

MESSAGE: "FAILED TO FETCH CONTACTS.",

ERROR: [Link],

});

};

// GET SINGLE CONTACT BY ID

CONST GETCONTACTBYID = ASYNC (REQ, RES) => {

TRY {

CONST CONTACT = AWAIT [Link]([Link]);

IF (!CONTACT) {

RETURN RES

.STATUS(404)

.JSON({ SUCCESS: FALSE, MESSAGE: "CONTACT NOT FOUND." });

[Link](200).JSON({

SUCCESS: TRUE,

MESSAGE: "CONTACT FETCHED SUCCESSFULLY.",

DATA: CONTACT,

});

} CATCH (ERROR) {

[Link](500).JSON({

SUCCESS: FALSE,

MESSAGE: "ERROR FETCHING CONTACT.",

ERROR: [Link],

});

}
};

// DELETE ALL CONTACTS

CONST DELETEALL = ASYNC (REQ, RES) => {

TRY {

AWAIT [Link]();

[Link](200).JSON({

SUCCESS: TRUE,

MESSAGE: "ALL CONTACTS DELETED SUCCESSFULLY.",

});

} CATCH (ERROR) {

[Link](500).JSON({

SUCCESS: FALSE,

MESSAGE: "FAILED TO DELETE ALL CONTACTS.",

ERROR: [Link],

});

};

// DELETE CONTACT BY ID

CONST DELETECONTACT = ASYNC (REQ, RES) => {

TRY {

CONST CONTACT = AWAIT [Link]([Link]);

IF (!CONTACT) {

RETURN RES

.STATUS(404)

.JSON({ SUCCESS: FALSE, MESSAGE: "CONTACT NOT FOUND." });

RES

.STATUS(200)

.JSON({ SUCCESS: TRUE, MESSAGE: "CONTACT DELETED SUCCESSFULLY." });


} CATCH (ERROR) {

[Link](500).JSON({

SUCCESS: FALSE,

MESSAGE: "ERROR DELETING CONTACT.",

ERROR: [Link],

});

};

[Link] = {

SUBMITCONTACT,

GETALLCONTACTS,

GETCONTACTBYID,

DELETEALL,

DELETECONTACT,

};

[Link]
CONST BCRYPT = REQUIRE("BCRYPT");

CONST JWT = REQUIRE("JSONWEBTOKEN");

CONST USER = REQUIRE("../MODELS/[Link]");

// REGISTER USER

CONST REGISTERUSER = ASYNC (REQ, RES) => {

TRY {

CONST { NAME, EMAIL, PASSWORD } = [Link];

IF (!NAME || !EMAIL || !PASSWORD) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "ALL FIELDS ARE


REQUIRED" });

}
CONST EMAILLOWER = [Link]().TOLOWERCASE();

CONST EXISTINGUSER = AWAIT [Link]({ EMAIL: EMAILLOWER });

IF (EXISTINGUSER) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "USER ALREADY


REGISTERED" });

CONST HASHEDPASSWORD = AWAIT [Link](PASSWORD, 10);

CONST NEWUSER = NEW USER({ NAME, EMAIL: EMAILLOWER, PASSWORD:


HASHEDPASSWORD });

CONST SAVEDUSER = AWAIT [Link]();

[Link](201).JSON({

STATUS: 1,

MESSAGE: "USER REGISTERED SUCCESSFULLY",

DATA: { ID: SAVEDUSER._ID, NAME: [Link], EMAIL:


[Link] },

});

} CATCH (ERROR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: `SERVER ERROR:


${[Link]}` });

};

// LOGIN USER

CONST LOGINUSER = ASYNC (REQ, RES) => {

TRY {

CONST { EMAIL, PASSWORD } = [Link];

IF (!EMAIL || !PASSWORD) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "ALL FIELDS ARE


REQUIRED" });

CONST EMAILLOWER = [Link]().TOLOWERCASE();

CONST USER = AWAIT [Link]({ EMAIL: EMAILLOWER });

IF (!USER) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "USER NOT


REGISTERED" });

CONST ISMATCH = AWAIT [Link](PASSWORD, [Link]);

IF (!ISMATCH) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "EMAIL OR


PASSWORD IS WRONG" });

CONST TOKEN = [Link]({ ID: USER._ID, ROLE: "USER" },


[Link].JWT_SECRET, { EXPIRESIN: "7D" });

[Link]("TOKEN", TOKEN, {

HTTPONLY: TRUE,

SECURE: [Link].NODE_ENV === "PRODUCTION",

SAMESITE: "STRICT",

MAXAGE: 7 * 24 * 60 * 60 * 1000,

});

[Link](200).JSON({ STATUS: 1, MESSAGE: "USER LOGIN SUCCESSFUL",


TOKEN });

} CATCH (ERROR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: `SERVER ERROR:


${[Link]}` });
}

};

//GET PROFILE

CONST GETPROFILE = ASYNC (REQ, RES) => {

TRY {

CONST USER = AWAIT [Link]([Link]).SELECT("-PASSWORD");

IF (!USER) {

RETURN [Link](404).JSON({ STATUS: 0, MESSAGE: "USER NOT FOUND" });

[Link]({ STATUS: 1, DATA: USER });

} CATCH (ERR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: "SERVER ERROR" });

};

//UPDATE NAME

CONST UPDATENAME = ASYNC (REQ, RES) => {

TRY {

CONST { NAME } = [Link];

IF (!NAME) {

RETURN [Link](400).JSON({ STATUS: 0, MESSAGE: "NAME IS REQUIRED"


});

CONST USER = AWAIT [Link](

[Link],

{ NAME },

{ NEW: TRUE }

).SELECT("-PASSWORD");
[Link]({ STATUS: 1, MESSAGE: "NAME UPDATED SUCCESSFULLY", DATA:
USER });

} CATCH (ERR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: "SERVER ERROR" });

};

//UPDATE PASSWORD

CONST UPDATEPASSWORD = ASYNC (REQ, RES) => {

TRY {

CONST { OLDPASSWORD, NEWPASSWORD } = [Link];

IF (!OLDPASSWORD || !NEWPASSWORD) {

RETURN RES

.STATUS(400)

.JSON({ STATUS: 0, MESSAGE: "BOTH OLD AND NEW PASSWORD ARE


REQUIRED" });

CONST USER = AWAIT [Link]([Link]);

IF (!USER)

RETURN [Link](404).JSON({ STATUS: 0, MESSAGE: "USER NOT FOUND" });

CONST ISMATCH = AWAIT [Link](OLDPASSWORD,


[Link]);

IF (!ISMATCH) {

RETURN RES

.STATUS(400)

.JSON({ STATUS: 0, MESSAGE: "OLD PASSWORD IS INCORRECT" });

[Link] = AWAIT [Link](NEWPASSWORD, 10);


AWAIT [Link]();

[Link]({ STATUS: 1, MESSAGE: "PASSWORD UPDATED SUCCESSFULLY" });

} CATCH (ERR) {

[Link](500).JSON({ STATUS: 0, MESSAGE: "SERVER ERROR" });

};

[Link] = { REGISTERUSER, LOGINUSER, GETPROFILE, UPDATENAME,


UPDATEPASSWORD};

DATABASE

CONST MONGOOSE = REQUIRE("MONGOOSE");

CONST CONNECTDB = ASYNC () => {

TRY {

AWAIT [Link]([Link].MONGO_URI);

[Link]("DATABASE CONNECTED SUCCESSFULLY");

} CATCH (ERROR) {

[Link]("DATABASE CONNECTING ERROR");

};
[Link] = CONNECTDB;

MODELS-ADMIN

CONST MONGOOSE = REQUIRE("MONGOOSE")

CONST ADMINSCHEMA = NEW [Link]({

NAME:{

TYPE: STRING,

REQUIRED: TRUE

},

EMAIL:{

TYPE: STRING,

REQUIRED: TRUE

},

PASSWORD:{

TYPE: STRING,

REQUIRED: TRUE

})

[Link] = NEW [Link]("ADMIN", ADMINSCHEMA)

CONTACT-MODELS

CONST MONGOOSE = REQUIRE("MONGOOSE");

CONST CONTACTSCHEMA = NEW [Link](

{
NAME: { TYPE: STRING, REQUIRED: TRUE },

EMAIL: { TYPE: STRING, REQUIRED: TRUE },

MESSAGE: { TYPE: STRING, REQUIRED: TRUE },

},

TIMESTAMPS: TRUE,

);

CONST CONTACT = [Link]("CONTACT", CONTACTSCHEMA);

[Link] = CONTACT;

COURSE-MODELS

CONST MONGOOSE = REQUIRE("MONGOOSE");

CONST COURSESCHEMA = NEW [Link]({

NAME: {

TYPE: STRING,

REQUIRED: TRUE

},

DESCRIPTION: {

TYPE: STRING,

REQUIRED: TRUE

},

CATEGORY: {

TYPE: STRING,

REQUIRED: TRUE

},

THUMBNAIL: {

TYPE: STRING,
REQUIRED: FUNCTION () {

// ONLY REQUIRE THUMBNAIL WHEN ADDING A NEW COURSE

RETURN [Link] === "PENDING";

},

MENTOR: {

TYPE: [Link],

REF: "MENTOR"

},

STUDENTSENROLLED: [{

TYPE: [Link],

REF: "USER"

}],

STATUS: { //ADMIN WILL APPROVE OR REJECT

TYPE: STRING,

ENUM: ["PENDING", "APPROVED", "REJECTED"],

DEFAULT: "PENDING"

},

ORIGINALCOURSEID: {

TYPE: [Link],

REF: "COURSE"

}, {

TIMESTAMPS: TRUE

});

[Link] = [Link]("COURSE", COURSESCHEMA);

==
ENROLL-MODELS

CONST { DEFAULT: MONGOOSE } = REQUIRE("MONGOOSE");

CONST ENROLLMENTSCHEMA = NEW [Link]({

COURSEID: {

TYPE: [Link],

REF: "COURSE",

},

USERID: {

TYPE: [Link],

REF: "USER",

REQUIRED: TRUE,

},

STATUS: {

TYPE: STRING,

ENUM: ["PENDING", "COMPLETED"],

DEFAULT: "PENDING",

},

PROGRESS: {

TYPE: NUMBER,

DEFAULT: 0, // PERCENTAGE (0–100)

},

ENROLLEDAT: {

TYPE: DATE,

DEFAULT: [Link],

},

COMPLETEDAT: DATE,
});

CONST ENROLLMODEL = NEW [Link]("ENROLL",


ENROLLMENTSCHEMA);

[Link] = ENROLLMODEL;

ROUTES-ADMIN

CONST EXPRESS = REQUIRE("EXPRESS")

CONST { REGISTERADMIN, LOGINADMIN, APPROVECOURSE, REJECTCOURSE,


ADDMENTOR, GETADMINSTATS, GETALLMENTORS, GETALLCOURSES } =
REQUIRE("../CONTROLLERS/[Link]")

CONST ADMINAUTHENTICATION = REQUIRE("../MIDDLEWARE/[Link]")

CONST { GETPENDINGCOURSES } =
REQUIRE("../CONTROLLERS/[Link]")

CONST { GETCOURSELESSONS } =
REQUIRE("../CONTROLLERS/[Link]")

CONST ADMINROUTER = [Link]()

[Link]("/REGISTER", REGISTERADMIN)

[Link]("/LOGIN", LOGINADMIN)

[Link]("/ME", ADMINAUTHENTICATION, (REQ, RES) => {


[Link]([Link]) // 👈 SEND ADMIN DETAILS (WITHOUT PASSWORD)

})

[Link]("/ADD-MENTOR", ADDMENTOR)

[Link]("/APPROVE-COURSE/:ID", ADMINAUTHENTICATION,
APPROVECOURSE);

[Link]("/REJECT-COURSE/:ID", ADMINAUTHENTICATION,
REJECTCOURSE);

[Link]("/STATS", ADMINAUTHENTICATION, GETADMINSTATS);

[Link]("/PENDING-COURSES", ADMINAUTHENTICATION,
GETPENDINGCOURSES)

[Link]("/ALL-MENTORS", ADMINAUTHENTICATION,
GETALLMENTORS);

[Link]("/ALL-COURSES", ADMINAUTHENTICATION, GETALLCOURSES);

[Link]("/COURSE/:COURSEID/LESSONS", ADMINAUTHENTICATION,
GETCOURSELESSONS);

[Link] = ADMINROUTER

ROUTES-CONTACT

CONST EXPRESS = REQUIRE("EXPRESS");

CONST ROUTER = [Link]();

CONST { SUBMITCONTACT } =
REQUIRE("../CONTROLLERS/[Link]");

[Link]("/", SUBMITCONTACT);
[Link] = ROUTER;

ROUTES-COURSE

CONST EXPRESS = REQUIRE("EXPRESS")

CONST UPLOAD = REQUIRE("../MIDDLEWARE/UPLOADS")

CONST { ADDCOURSE, GETALLCOURSES, GETONECOURSE, UPDATECOURSE,


DELETECOURSE, GETALLCOURSESMENTOR } =
REQUIRE("../CONTROLLERS/[Link]")

CONST MENTORAUTHENTICATION = REQUIRE("../MIDDLEWARE/[Link]")

// CONST USERAUTHENTICATION = REQUIRE("../MIDDLEWARE/[Link]")

CONST COURSEROUTER = [Link]()

[Link]("/ADD-
COURSE",MENTORAUTHENTICATION,[Link]("THUMBNAIL"),ADDCOURSE)

[Link]("/GET-ALL-COURSES",GETALLCOURSES)

[Link]("/MENTOR/GET-ALL-COURSES",
MENTORAUTHENTICATION,GETALLCOURSESMENTOR)

[Link]("/GET-ONE-COURSE/:ID",
MENTORAUTHENTICATION,GETONECOURSE)

[Link]("/UPDATE-COURSE/:ID",
MENTORAUTHENTICATION,UPDATECOURSE)

[Link]("/DELETE-COURSE/:ID",
MENTORAUTHENTICATION,DELETECOURSE)

[Link] = COURSEROUTER
[Link]

C CONST CLOUDINARY = REQUIRE("CLOUDINARY").V2

REQUIRE("DOTENV").CONFIG();

[Link]({

CLOUD_NAME: [Link].CLOUDINARY_CLOUD_NAME,

API_KEY: [Link].CLOUDINARY_API_KEY,

API_SECRET: [Link].CLOUDINARY_API_SECRET,

});

[Link] = CLOUDINARY;

SEND [Link]

REQUIRE("DOTENV").CONFIG();

CONST NODEMAILER = REQUIRE("NODEMAILER");

CONST SENDEMAIL = ASYNC (TO, SUBJECT, HTML) => {

IF (![Link].EMAIL_USER || ![Link].EMAIL_PASS) {

THROW NEW ERROR("EMAIL CREDENTIALS ARE NOT CONFIGURED IN


ENVIRONMENT VARIABLES.");

TRY {

CONST TRANSPORTER = [Link]({

HOST: "[Link]",
PORT: 587,

SECURE: FALSE,

AUTH: {

USER: [Link].EMAIL_USER,

PASS: [Link].EMAIL_PASS,

},

TLS: {

REJECTUNAUTHORIZED: FALSE,

},

});

AWAIT [Link]();

CONST RESULT = AWAIT [Link]({

FROM: `"STUDIPAL CONTACT" <${[Link].EMAIL_USER}>`,

TO,

SUBJECT,

HTML,

});

[Link]("EMAIL SENT SUCCESSFULLY:", [Link]);

RETURN RESULT;

} CATCH (ERROR) {

[Link]("ERROR SENDING EMAIL:", ERROR);

THROW NEW ERROR(`EMAIL COULD NOT BE SENT: ${[Link]}`);

};

[Link] = SENDEMAIL;
[Link]

REQUIRE("DOTENV").CONFIG();

CONST EXPRESS = REQUIRE("EXPRESS")

CONST COOKIEPARSER = REQUIRE("COOKIE-PARSER")

CONST COURSEROUTER = REQUIRE("./ROUTES/[Link]")

CONST USERROUTER = REQUIRE("./ROUTES/[Link]")

CONST MENTORROUTER = REQUIRE("./ROUTES/[Link]")

CONST ADMINROUTER = REQUIRE("./ROUTES/[Link]")


CONST LESSONROUTER = REQUIRE("./ROUTES/[Link]")

CONST CONNECTDB = REQUIRE("./DATABASE/DB")

CONST ENROLLROUTER = REQUIRE("./ROUTES/[Link]")

CONST CONTACTROUTER = REQUIRE("./ROUTES/[Link]")

CONST CORS = REQUIRE("CORS")

CONST APP = EXPRESS()

CONST PORT = [Link] || 3000

[Link]([Link]());

[Link](COOKIEPARSER());

[Link](CORS({

ORIGIN: "HTTP://LOCALHOST:5173",

CREDENTIALS: TRUE

}));

CONNECTDB().THEN(()=>{

[Link]("/API/V1/COURSE", COURSEROUTER)

[Link]("/API/V1/USER", USERROUTER)

[Link]("/API/V1/MENTOR", MENTORROUTER)

[Link]("/API/V1/ADMIN", ADMINROUTER)

[Link]("/API/V1/LESSON", LESSONROUTER)

[Link]("/API/V1/USER-ENROLL", ENROLLROUTER)

[Link]("/API/V1/CONTACT",CONTACTROUTER)

[Link](PORT,()=>{

[Link](`DATABASE RUNNING ON PORT HTTP://LOCALHOST:${PORT}`)

})

})
.CATCH((ERROR)=>{

[Link]("DATABASE CONNECTION FAILED:", ERROR);

})

[Link]

"NAME": "SERVER",

"VERSION": "1.0.0",

"MAIN": "[Link]",

"SCRIPTS": {

"TEST": "ECHO \"ERROR: NO TEST SPECIFIED\" && EXIT 1",

"START": "NODEMON [Link]",

"DEV": "NODEMON [Link]"

},

"KEYWORDS": [],

"AUTHOR": "",

"LICENSE": "ISC",

"DESCRIPTION": "",

"DEPENDENCIES": {

"BCRYPT": "^6.0.0",

"BCRYPTJS": "^3.0.2",

"CLOUDINARY": "^2.7.0",

"COOKIE-PARSER": "^1.4.7",

"CORS": "^2.8.5",

"DOTENV": "^17.2.1",

"EXPRESS": "^5.1.0",
"JSONWEBTOKEN": "^9.0.2",

"MONGOOSE": "^8.17.0",

"MULTER": "^2.0.2",

"NODEMAILER": "^7.0.10",

"NODEMON": "^3.1.10",

"RESEND": "^6.12.3",

"STREAMIFIER": "^0.1.1"

}
OUTPUT

ADMIN LOGIN
ADMIN PORTAL
HOW TO ADD MENTOR
HOME PAGE
MENTOR CREDENTIONAL

NAME :
EMAIL :
PASSWORD :
MENTOR PORTOL-DASHBOARD
MENTOR CAN ADD COURSE –
HOW TO CREATE ACCOUNT IN STUDIPAL

NAME :
EMAIL :
PASSWORD :
YOU CAN ENROLL COURSCES IN STUDIPAL
BIBLIOGRAPHY

* SOFTWARE ENGINEERING BY ROGER S. PRESSMAN

* [Link] DOCUMENTATION

* [Link] OFFICIAL DOCUMENTATION

* MONGODB MANUAL

* [Link] GUIDE

* MDN WEB DOCS

* TAILWIND CSS DOCUMENTATION

WEB REFERENCES

HTTPS://[Link]

HTTPS://[Link]

HTTPS://[Link]

HTTPS://[Link]

HTTPS://[Link]

You might also like