curd of courses and lectures backend and front end:- models/User.js :- const mongoose = require('mongoose'); const userSchema = new mongoose.Schema({ name: { type: String, required: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, role: { type: String, enum: ['admin','student'], default: 'student' }, enrolledCourses: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Course' }] }, { timestamps: true }); module.exports = mongoose.model('User', userSchema); models/Course.js :- const mongoose = require('mongoose'); const courseSchema = new mongoose.Schema({ title: { type: String, required: true }, description: String, image: String, createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' } }, { timestamps: true }); module.exports = mongoose.model('Course', courseSchema); models/Lecture.js :- const mongoose = require('mongoose'); const lectureSchema = new mongoose.Schema({ title: { type: String, required: true }, content: { type: String, required: true }, videoUrl: String, course: { type: mongoose.Schema.Types.ObjectId, ref: 'Course', required: true } }, { timestamps: true }); module.exports = mongoose.model('Lecture', lectureSchema); .env file code :- PORT=5000 JWT_SECRET=Yx9$kD@7v!wLqP3z#NcRtUe2FgHbJmX1 MONGO_URI=mongodb://localhost:27017/mydbcourse middleware/auth.js file code:- // middleware/auth.js const jwt = require('jsonwebtoken'); require('dotenv').config(); /** * Middleware to authenticate requests by verifying JWT token. * Expects Authorization header in the format: 'Bearer '. * On success, attaches decoded token payload to req.user. */ const auth = (req, res, next) => { const header = req.headers.authorization; console.log('Authorization header:', header); if (!header) { return res.status(401).json({ message: 'No token provided in Authorization header' }); } const token = header.split(' ')[1]; if (!token) { return res.status(401).json({ message: 'Malformed token in Authorization header' }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); console.log('Decoded token:', decoded); req.user = decoded; // decoded token contains user id and role next(); } catch (err) { console.error('Token verification failed:', err); return res.status(401).json({ message: 'Invalid or expired token' }); } }; /** * Middleware to authorize admin users only. * Checks if req.user.role === 'admin'. */ const adminOnly = (req, res, next) => { if (req.user && req.user.role === 'admin') { return next(); } return res.status(403).json({ message: 'Admin only access' }); }; module.exports = { auth, adminOnly }; routes/courses.js file code:- // routes/courses.js const express = require('express'); const router = express.Router(); const Course = require('../models/Course'); const User = require('../models/User'); // βœ… Add this line const { auth, adminOnly } = require('../middleware/auth'); // Create course (admin only) router.post('/', auth, adminOnly, async (req, res) => { const { title, description, image } = req.body; try { const course = new Course({ title, description, image, createdBy: req.user.id, }); await course.save(); res.status(201).json(course); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); // Get all courses (public) router.get('/', async (req, res) => { try { const courses = await Course.find().populate('createdBy', 'name'); res.json(courses); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); // Get single course router.get('/:id', async (req, res) => { try { const course = await Course.findById(req.params.id).populate('createdBy', 'name'); if (!course) return res.status(404).json({ message: 'Course not found' }); res.json(course); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); // Update course (admin only) router.put('/:id', auth, adminOnly, async (req, res) => { try { const course = await Course.findByIdAndUpdate(req.params.id, req.body, { new: true }); if (!course) return res.status(404).json({ message: 'Course not found' }); res.json(course); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); // Delete course (admin only) router.delete('/:id', auth, adminOnly, async (req, res) => { try { const course = await Course.findByIdAndDelete(req.params.id); if (!course) return res.status(404).json({ message: 'Course not found' }); res.json({ message: 'Course deleted' }); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); // Assign a course to a student router.post('/:courseId/assign/:studentId', auth, adminOnly, async (req, res) => { const { courseId, studentId } = req.params; console.log('πŸ” Assign route hit:', { courseId, studentId, user: req.user }); try { const student = await User.findById(studentId); console.log('Student fetched:', student); if (!student) { console.log('Student not found'); return res.status(404).json({ message: 'Student not found' }); } if (!student.enrolledCourses) { console.log('student.enrolledCourses undefined, initializing array'); student.enrolledCourses = []; } if (!student.enrolledCourses.includes(courseId)) { student.enrolledCourses.push(courseId); await student.save(); console.log('Course assigned, student saved'); } else { console.log('Course already assigned to this student'); } res.json({ message: 'Course assigned to student successfully' }); } catch (err) { console.error('Assign error:', err); res.status(500).json({ message: 'Server error', error: err.message }); } }); // GET enrolled courses router.get('/my/enrolled', auth, async (req, res) => { try { const userId = req.user.id; const user = await User.findById(userId).populate('enrolledCourses'); if (!user) { return res.status(404).json({ message: 'User not found' }); } res.json(user.enrolledCourses); // Array of course objects } catch (err) { console.error('Error in /my/enrolled:', err); res.status(500).json({ message: 'Server error', error: err.message }); } }); module.exports = router; routes/lectures.js file code:- const express = require('express'); const router = express.Router(); const Lecture = require('../models/Lecture'); const Course = require('../models/Course'); const { auth, adminOnly } = require('../middleware/auth'); // Create a lecture router.post('/', auth, adminOnly, async (req, res) => { const { title, content, videoUrl, courseId } = req.body; try { const lecture = new Lecture({ title, content, videoUrl, course: courseId }); await lecture.save(); res.status(201).json(lecture); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); // Get lectures for a course router.get('/:courseId', auth, async (req, res) => { try { const lectures = await Lecture.find({ course: req.params.courseId }); res.json(lectures); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); // Update a lecture router.put('/:id', auth, adminOnly, async (req, res) => { try { const lecture = await Lecture.findByIdAndUpdate(req.params.id, req.body, { new: true }); res.json(lecture); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); // Delete a lecture router.delete('/:id', auth, adminOnly, async (req, res) => { try { await Lecture.findByIdAndDelete(req.params.id); res.json({ message: 'Lecture deleted' }); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); module.exports = router; routes/auth.js file (register and login ) code:- // routes/auth.js const express = require('express'); const router = express.Router(); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const User = require('../models/User'); const { auth, adminOnly } = require('../middleware/auth'); require('dotenv').config(); // Register router.post('/register', async (req, res) => { const { name, email, password, role } = req.body; console.log("Incoming registration data:", req.body); try { const existing = await User.findOne({ email }); if (existing) return res.status(400).json({ message: 'User already exists' }); const hashedPassword = await bcrypt.hash(password, 10); const user = new User({ name, email, password: hashedPassword, role }); await user.save(); res.status(201).json({ message: 'User registered' }); } catch (err) { console.error("Register error:", err); // πŸ” Add this res.status(500).json({ message: 'Server error', error: err.message }); } }); // Login router.post('/login', async (req, res) => { const { email, password } = req.body; try { const user = await User.findOne({ email }); if (!user) return res.status(400).json({ message: 'Invalid credentials' }); const isMatch = await bcrypt.compare(password, user.password); if (!isMatch) return res.status(400).json({ message: 'Invalid credentials' }); const token = jwt.sign( { id: user._id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '1d' } ); res.json({ token, user: { id: user._id, name: user.name, role: user.role } }); } catch (err) { res.status(500).json({ message: 'Server error' }); } }); // Get all students - admin only router.get('/students', auth, adminOnly, async (req, res) => { try { const students = await User.find({ role: 'student' }).select('-password'); res.json(students); } catch (err) { console.error(err); res.status(500).json({ message: 'Server error' }); } }); module.exports = router; finally main file code :- server.js :- const express = require('express'); const mongoose = require('mongoose'); const cors = require('cors'); require('dotenv').config(); const authRoutes = require('./routes/auth'); const courseRoutes = require('./routes/courses'); const lectureRoutes = require('./routes/lectures'); const app = express(); app.use(express.json()); app.use(cors()); app.use('/api/auth', authRoutes); app.use('/api/courses', courseRoutes); app.use('/api/lectures', lectureRoutes); const PORT = process.env.PORT || 5000; const MONGO = process.env.MONGO_URI; mongoose.connect(MONGO, { useNewUrlParser: true, useUnifiedTopology: true, }).then(() => { console.log('Mongo connected'); app.listen(PORT, () => console.log('Server started on', PORT)); }).catch(err => console.error(err)); ====================== Front end code :- src/api/axios.js file code:- import axios from "axios"; const API = axios.create({ baseURL: "http://localhost:5000/api", // backend base URL }); // Attach token to each request if exists API.interceptors.request.use((req) => { const token = localStorage.getItem("token"); if (token) { req.headers.Authorization = `Bearer ${token}`; } return req; }); export default API; src/pages/Coures.jsx file code:- import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import API from "../api/axios"; export default function Courses() { const [courses, setCourses] = useState([]); const [user, setUser] = useState(null); useEffect(() => { const storedUser = localStorage.getItem("user"); if (storedUser) { const parsed = JSON.parse(storedUser); setUser(parsed); if (parsed.role === "student") { API.get("/courses/my/enrolled").then((res) => setCourses(res.data)); } else { API.get("/courses").then((res) => setCourses(res.data)); } } }, []); return (

All Courses

{/* Show Add Course link only if user is admin */} {user?.role === "admin" && ( βž• Add Course )}
); } src/pages/AddCourse.jsx file :- import { useState } from "react"; import { useNavigate } from "react-router-dom"; import API from "../api/axios"; export default function AddCourse() { const [form, setForm] = useState({ title: "", description: "", image: "" }); const navigate = useNavigate(); const handleChange = (e) => setForm({ ...form, [e.target.name]: e.target.value }); const handleSubmit = async (e) => { e.preventDefault(); try { await API.post("/courses", form); navigate("/courses"); } catch (err) { alert("❌ Only admin can create courses"); } }; return (

Add Course

); } src/pages/CourseDetail.jsx file code:- import { useEffect, useState } from "react"; import { useParams, useNavigate, Link } from "react-router-dom"; import API from "../api/axios"; export default function CourseDetail() { const { id } = useParams(); const [course, setCourse] = useState(null); const [user, setUser] = useState(null); const navigate = useNavigate(); useEffect(() => { API.get(`/courses/${id}`).then((res) => setCourse(res.data)); const storedUser = localStorage.getItem("user"); if (storedUser) setUser(JSON.parse(storedUser)); }, [id]); const handleDelete = async () => { try { await API.delete(`/courses/${id}`); navigate("/courses"); } catch (err) { alert("❌ Not authorized or error occurred"); } }; if (!course) return

Loading...

; return (

{course.title}

{course.description}

{course.title} {/* Admin actions */} {user?.role === "admin" && (
πŸŽ“ Assign to Student ✏️ Edit πŸ“˜ Manage Lectures
)}
); } src/pages/UpdateCourse.jsx file :- import { useEffect, useState } from "react"; import { useParams, useNavigate } from "react-router-dom"; import API from "../api/axios"; export default function UpdateCourse() { const { id } = useParams(); const [form, setForm] = useState({ title: "", description: "", image: "" }); const navigate = useNavigate(); useEffect(() => { API.get(`/courses/${id}`).then((res) => { setForm({ title: res.data.title, description: res.data.description, image: res.data.image, }); }); }, [id]); const handleChange = (e) => setForm({ ...form, [e.target.name]: e.target.value }); const handleSubmit = async (e) => { e.preventDefault(); try { await API.put(`/courses/${id}`, form); navigate(`/courses/${id}`); } catch (err) { alert("❌ Only admin can update courses"); } }; return (

Edit Course

); } src/pages/AssignCourse.jsx file code:- // Example idea - AssignCourse.js import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; import API from "../api/axios"; export default function AssignCourse() { const { courseId } = useParams(); const [students, setStudents] = useState([]); const [selected, setSelected] = useState(""); useEffect(() => { API.get('/auth/students') .then((res) => setStudents(res.data)) .catch((err) => { console.error('Failed to fetch students:', err); alert('Failed to load students'); }); }, []); const assign = async () => { try { if (!selected) { alert('Please select a student!'); return; } await API.post(`/courses/${courseId}/assign/${selected}`); alert('βœ… Assigned'); } catch (error) { console.error(error); alert('❌ Error assigning course'); } }; return (

Assign Course to Student

); } src/pages/EnrolledCoures.jsx file code:- import React, { useEffect, useState } from 'react'; function EnrolledCourses() { const [courses, setCourses] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const token = localStorage.getItem('token'); useEffect(() => { const fetchEnrolledCourses = async () => { try { const res = await fetch('http://localhost:5000/api/courses/my/enrolled', { headers: { Authorization: `Bearer ${token}`, }, }); if (!res.ok) { const errData = await res.json(); throw new Error(errData.message || 'Failed to fetch enrolled courses'); } const data = await res.json(); setCourses(data); } catch (err) { console.error('Error loading enrolled courses:', err); setError(err.message); } finally { setLoading(false); } }; fetchEnrolledCourses(); }, [token]); return (

My Enrolled Courses

{loading ? (

Loading...

) : error ? (

{error}

) : courses.length === 0 ? (

You have not enrolled in any courses yet.

) : ( )}
); } export default EnrolledCourses; src/pages/Lectures.jsx file code:- import React, { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; function LecturesPage() { const { courseId } = useParams(); const [lectures, setLectures] = useState([]); const [course, setCourse] = useState(null); // NEW: course info const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // Form state const [title, setTitle] = useState(''); const [content, setContent] = useState(''); const [videoUrl, setVideoUrl] = useState(''); const [editingId, setEditingId] = useState(null); const token = localStorage.getItem('token'); // Fetch course and lectures useEffect(() => { const fetchCourseAndLectures = async () => { try { // Fetch course const courseRes = await fetch(`http://localhost:5000/api/courses/${courseId}`); if (!courseRes.ok) throw new Error('Failed to load course'); const courseData = await courseRes.json(); setCourse(courseData); // Fetch lectures const lectureRes = await fetch(`http://localhost:5000/api/lectures/${courseId}`, { headers: { Authorization: `Bearer ${token}` }, }); if (!lectureRes.ok) throw new Error('Failed to load lectures'); const lecturesData = await lectureRes.json(); setLectures(lecturesData); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchCourseAndLectures(); }, [courseId, token]); const handleSubmit = async (e) => { e.preventDefault(); const endpoint = editingId ? `http://localhost:5000/api/lectures/${editingId}` : `http://localhost:5000/api/lectures`; const method = editingId ? 'PUT' : 'POST'; try { const res = await fetch(endpoint, { method, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify({ title, content, videoUrl, courseId }), }); if (!res.ok) throw new Error('Failed to save lecture'); const data = await res.json(); if (editingId) { setLectures((prev) => prev.map((lec) => (lec._id === editingId ? data : lec)) ); } else { setLectures((prev) => [...prev, data]); } setTitle(''); setContent(''); setVideoUrl(''); setEditingId(null); } catch (err) { alert(err.message); } }; const handleDelete = async (id) => { if (!window.confirm('Are you sure you want to delete this lecture?')) return; try { const res = await fetch(`http://localhost:5000/api/lectures/${id}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, }); if (!res.ok) throw new Error('Failed to delete lecture'); setLectures((prev) => prev.filter((l) => l._id !== id)); } catch (err) { alert(err.message); } }; const handleEdit = (lecture) => { setTitle(lecture.title); setContent(lecture.content); setVideoUrl(lecture.videoUrl || ''); setEditingId(lecture._id); }; return (
{/* COURSE NAME */} {course ?

Lectures for: {course.title}

:

Lectures

} {loading ? (

Loading...

) : error ? (

{error}

) : lectures.length === 0 ? (

No lectures found.

) : ( )}

{editingId ? 'Edit Lecture' : 'Add New Lecture'}

setTitle(e.target.value)} required />