diff --git a/BackEnd/controller/course/courseController.js b/BackEnd/controller/course/courseController.js index 5ad7e7e..1859b8b 100644 --- a/BackEnd/controller/course/courseController.js +++ b/BackEnd/controller/course/courseController.js @@ -1,387 +1,427 @@ -const Course = require('../../models/course/courseSchema') - -const Fuse = require('fuse.js') -const CourseSection = require('../../models/course/courseSectionSchema') -const CourseSubtitle = require('../../models/course/courseSubtitleSchema') -const Question = require('../../models/course/questionSchema') -const CourseSectionProgress = require('../../models/course/courseProgress/courseSectionProgress') - +const Course = require("../../models/course/courseSchema"); + +const Fuse = require("fuse.js"); +const CourseSection = require("../../models/course/courseSectionSchema"); +const CourseSubtitle = require("../../models/course/courseSubtitleSchema"); +const Question = require("../../models/course/questionSchema"); +const CourseSectionProgress = require("../../models/course/courseProgress/courseSectionProgress"); +const Payment = require("../../models/lib/payment/paymentSchema"); +const Trainee = require("../../models/traineeSchema"); +const Instructor = require("../../models/InstructorSchema"); const stripe = require("stripe")( - process.env.STRIPE_KEY || - "sk_test_51MFdfGDZGE0sbGNF5ijUysPTPes2023txzn262u9e3xrA8hgD3Sou1KumZqfRU88MG0xz6DLZNRAQWdWM8N8G0Ra00Em82CNAr" - ); - + process.env.STRIPE_KEY || + "sk_test_51MFdfGDZGE0sbGNF5ijUysPTPes2023txzn262u9e3xrA8hgD3Sou1KumZqfRU88MG0xz6DLZNRAQWdWM8N8G0Ra00Em82CNAr" +); //get all courses available const getAllCourses = async (req, res) => { - const courses = await Course.find().sort({ - subscriberNumber: -1 - }) + const courses = await Course.find().sort({ + subscriberNumber: -1, + }); - res.status(200).json(courses) -} + res.status(200).json(courses); +}; //get a course const getCourseById = async (req, res) => { - const _id = req.query + const _id = req.query; - const course = await Course.findById(_id) + const course = await Course.findById(_id); - if (!course) { - return res.status(404).json({ - error: 'course not found' - }) - } + if (!course) { + return res.status(404).json({ + error: "course not found", + }); + } - res.status(200).json(course) -} + res.status(200).json(course); +}; const getCourseByInstructor = async (req, res) => { - - const courses = await Course.find().sort({ - createdAt: -1 - }) - const options = { - includeScore: true, - keys: ['name'] - } - const fuse = new Fuse(courses, (options)) - const result = fuse.search(req.instructor._id) - res.status(200).json(result) -} + const courses = await Course.find().sort({ + createdAt: -1, + }); + const options = { + includeScore: true, + keys: ["name"], + }; + const fuse = new Fuse(courses, options); + const result = fuse.search(req.instructor._id); + res.status(200).json(result); +}; const getCourseByTitle = async (req, res) => { - const courses = await Course.find().sort({ - createdAt: -1 - }) - const options = { - includeScore: true, - keys: ['name'] - } - const fuse = new Fuse(courses, options) - const result = fuse.search(req.title) - res.status(200).json(result) -} + const courses = await Course.find().sort({ + createdAt: -1, + }); + const options = { + includeScore: true, + keys: ["name"], + }; + const fuse = new Fuse(courses, options); + const result = fuse.search(req.title); + res.status(200).json(result); +}; const getCourseBySubject = async (req, res) => { - const courses = await Course.find().sort({ - createdAt: -1 - }) - const options = { - includeScore: true, - keys: ['subject'] - } - const fuse = new Fuse(courses, options) - const result = fuse.search(req.subject) - res.status(200).json(result) -} + const courses = await Course.find().sort({ + createdAt: -1, + }); + const options = { + includeScore: true, + keys: ["subject"], + }; + const fuse = new Fuse(courses, options); + const result = fuse.search(req.subject); + res.status(200).json(result); +}; //get course title and total hours and ratings const getAll = async (req, res) => { - const courses = await Course.find({}, ) -} + const courses = await Course.find({}); +}; const getCoursesByCategory = async (req, res) => { - const { - category - } = req.body - try { - const courses = await Course.getCoursesByCategory(category) - res.status(200).json(courses) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + const { category } = req.body; + try { + const courses = await Course.getCoursesByCategory(category); + res.status(200).json(courses); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getCoursesByPrice = async (req, res) => { - const { - price - } = req.body - console.log(req.body) - console.log(price) - try { - const courses = await Course.getCoursesByPrice(price) - res.status(200).json(courses) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + const { price } = req.body; + console.log(req.body); + console.log(price); + try { + const courses = await Course.getCoursesByPrice(price); + res.status(200).json(courses); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getCoursesByPriceFromLowToHigh = async (req, res) => { - try { - const courses = await Course.getCoursesByPriceFromLowToHigh() - res.status(200).json(courses) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + try { + const courses = await Course.getCoursesByPriceFromLowToHigh(); + res.status(200).json(courses); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const search = async (req, res) => { - const { - searchedword - } = req.body - - - try { - const courses = await Course.search(searchedword) - - res.status(200).json(courses) - } catch (error) { - res.status(400).json({ - error: error.message - }) - - - } -} + const { searchedword } = req.body; + + try { + const courses = await Course.search(searchedword); + + res.status(200).json(courses); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getCoursesByPriceFromHighToLow = async (req, res) => { - try { - const courses = await Course.getCoursesByPriceFromHighToLow() - res.status(200).json(courses) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + try { + const courses = await Course.getCoursesByPriceFromHighToLow(); + res.status(200).json(courses); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getCoursesByRating = async (req, res) => { - const { - rating - } = req.body - try { - const courses = await Course.getCourseByRating(rating) - res.status(200).json(courses) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + const { rating } = req.body; + try { + const courses = await Course.getCourseByRating(rating); + res.status(200).json(courses); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getCoursesByRatingFromLowToHigh = async (req, res) => { - try { - const courses = await Course.getCoursesByRatingFromLowToHigh() - res.status(200).json(courses) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + try { + const courses = await Course.getCoursesByRatingFromLowToHigh(); + res.status(200).json(courses); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getCoursesByRatingFromHighToLow = async (req, res) => { - try { - const courses = await Course.getCoursesByRatingFromHighToLow() - res.status(200).json(courses) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + try { + const courses = await Course.getCoursesByRatingFromHighToLow(); + res.status(200).json(courses); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getCourseSections = async (req, res) => { - - const { - _id - } = req.query - - try { - if (!_id) - throw Error('All fields must be filled') - - const course = await Course.find({ - _id - }) - if (!course) - throw Error('Course Does not Exist') - - const sections = await CourseSection.find({ - course_id : _id - }) - if (!sections) - throw Error('No Sections Exist in this Course') - - res.status(200).json(sections) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + const { _id } = req.query; + + try { + if (!_id) throw Error("All fields must be filled"); + + const course = await Course.find({ + _id, + }); + if (!course) throw Error("Course Does not Exist"); + + const sections = await CourseSection.find({ + course_id: _id, + }); + if (!sections) throw Error("No Sections Exist in this Course"); + + res.status(200).json(sections); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getCourseSubtitles = async (req, res) => { - - const { - course_id, - section_id, - } = req.query - - console.log(req.query) - - try { - if ( !course_id || !section_id) - throw Error('All fields must be filled') - - const course = await Course.find({ - course_id - }) - if (!course) - throw Error('Course Does not Exist') - - const sections = await CourseSection.find({ - course_id - }) - if (!sections) - throw Error('No Sections Exist in this Course') - - const subtitles = await CourseSubtitle.find({ - course_id, - section_id - }) - if (!subtitles)//THIS ERROR SHOULD NEVER APPEAR AS WE ALWAYS MAKE THE COURSE AND HANDLE IT IF IT APPEARED D: - throw Error('No Subtitles Exist in this Course') - - res.status(200).json(subtitles) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + const { course_id, section_id } = req.query; + + console.log(req.query); + + try { + if (!course_id || !section_id) throw Error("All fields must be filled"); + + const course = await Course.find({ + course_id, + }); + if (!course) throw Error("Course Does not Exist"); + + const sections = await CourseSection.find({ + course_id, + }); + if (!sections) throw Error("No Sections Exist in this Course"); + + const subtitles = await CourseSubtitle.find({ + course_id, + section_id, + }); + if (!subtitles) + //THIS ERROR SHOULD NEVER APPEAR AS WE ALWAYS MAKE THE COURSE AND HANDLE IT IF IT APPEARED D: + throw Error("No Subtitles Exist in this Course"); + + res.status(200).json(subtitles); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getQuestion = async (req, res) => { - - const { - _id - } = req.query - - try { - if (!_id) - throw Error('All fields must be filled') - - const question = await Question.findById({ - _id - }) - if (!question) - throw Error('Question Does not Exist') - - res.status(200).json(question) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + const { _id } = req.query; + + try { + if (!_id) throw Error("All fields must be filled"); + + const question = await Question.findById({ + _id, + }); + if (!question) throw Error("Question Does not Exist"); + + res.status(200).json(question); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const getSectionProgress = async (req, res) => { - - const { - user_id, - course_id, - } = req.query - - try { - if (!user_id || !course_id) - throw Error('All fields must be filled') - - const sectionProgress = await CourseSectionProgress.findOne({ - user_id:user_id, - course_id:course_id, - }) - if (!sectionProgress) - throw Error('Sectoion Progress Does not Exist') - - res.status(200).json(sectionProgress) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + const { user_id, course_id } = req.query; + + try { + if (!user_id || !course_id) throw Error("All fields must be filled"); + + const sectionProgress = await CourseSectionProgress.findOne({ + user_id: user_id, + course_id: course_id, + }); + if (!sectionProgress) throw Error("Sectoion Progress Does not Exist"); + + res.status(200).json(sectionProgress); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const payForCourse = async (req, res) => { - const { course_id, user_id } = req.body; - - try { - //find course by id - - const course = await Course.findById({ - _id: course_id, - }); - if (!course) throw Error("Course Does not Exist"); - const title = course.title; - const description = course.description; - const price = course.price; - const checkoutSession = await stripe.checkout.sessions.create({ - session_id: {checkoutSession}, - success_url: `http://localhost:3001/course/coursePagePaid/${course_id}&${user_id}&${session_id}`, - - cancel_url: "http://localhost:3000/", - client_reference_id: user_id, - line_items: [ - { - quantity: 1, - price_data: { - currency: "usd", - unit_amount: price, - product_data: { - name: title, - description: description, - }, + const { course_id, user_id } = req.body; + + try { + const course = await Course.findById({ + _id: course_id, + }); + if (!course) throw Error("Course Does not Exist"); + const title = course.title; + const description = course.description; + const price = Number(course.price + "00"); + const checkoutSession = await stripe.checkout.sessions.create({ + success_url: `http://localhost:3001/course/coursePage/${course_id}?session_id={CHECKOUT_SESSION_ID}`, + cancel_url: `http://localhost:3001/course/coursePage/${course_id}`, + client_reference_id: user_id, + line_items: [ + { + quantity: 1, + price_data: { + currency: "usd", + unit_amount: price, + product_data: { + name: title, + description: description, }, }, - ], - mode: "payment", - }); - - res.status(200).json(checkoutSession.url); - } catch (error) { - res.status(400).json({ - error: error.message, - }); - } - }; - - const saveCheckout = async (req, res) => { - const { session_id, course_id } = req.query; - try { - const session = await stripe.checkout.sessions.retrieve(session_id); - const payment = new Payment({ - user_id: session.client_reference_id, + }, + ], + mode: "payment", + }); + + res.status(200).json(checkoutSession.url); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; + +const saveCheckout = async (req, res) => { + const { session_id, course_id } = req.body; + try { + const session = await stripe.checkout.sessions.retrieve(session_id); + const user_id = session.client_reference_id; + const course = await Course.findById({ + _id: course_id, + }); + const instructor = await Instructor.findById({ + _id: course.instructor_id, + }); + const paymentSearch = await Payment.findOne({ + session_id: session_id, + }); + + await Instructor.findByIdAndUpdate( + { + _id: course.instructor_id, + }, + { + credit: instructor.credit + course.price, + } + ); + if (paymentSearch) throw Error("Payment Already Exists"); + const payment = await Payment.create({ + payment_title: course.title, + user_id: session.client_reference_id, + course_id: course_id, + session_id: session_id, + price: course.price, + currency: session.currency, + type: session.payment_method_types[0], + status: "paid", + }); + const trainee = await Trainee.joinCourse(user_id, course_id); + + res.status(200).json({ payment: payment, trainee: trainee }); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; +const updateTraineeProgress = async (req, res) => { + const { user_id, section_id, course_id } = req.body; + try { + const course = await Course.findById({ + _id: course_id, + }); + const courseSectionProgress = await CourseSectionProgress.findOne({ + user_id: user_id, + course_id: course_id, + }); + if (!courseSectionProgress) + await CourseSectionProgress.create({ + user_id: user_id, course_id: course_id, - session_id: session_id, - amount: session.price, - currency: session.currency, - type: session.payment_method_types[0], - }); - res.status(200).json(payment); - } catch (error) { - res.status(400).json({ - error: error.message, + sectionTitle: course.title, }); - } - }; - - + const trainee = await Trainee.findById(user_id); + if (!trainee) throw Error("Trainee Does not Exist"); + //add section id under course id in trainee progress + let progressLength; + const ownedCourses = trainee.ownedCourses.map((course) => { + if (course.course_id == course_id) { + if (course.sectionProgress?.includes(section_id)) + throw Error("section already exists"); + course.sectionProgress.push(section_id); + progressLength = course.sectionProgress.length; + } + return course; + }); + + await Trainee.findByIdAndUpdate( + { + _id: user_id, + }, + { + ownedCourses: ownedCourses, + } + ); + await CourseSectionProgress.findOneAndUpdate( + { + user_id: user_id, + course_id: course_id, + }, + { + finishedPercentage: (progressLength / ~~course.materialNumber) * 100, + } + ); + + return res.status(200).json(trainee); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; module.exports = { - getAllCourses, - getCourseById, - getCoursesByCategory, - getCoursesByPriceFromLowToHigh, - getCoursesByPriceFromHighToLow, - getCoursesByRating, - getCoursesByRatingFromLowToHigh, - getCoursesByRatingFromHighToLow, - getCoursesByPrice, - getCourseSections, - getCourseSubtitles, - getQuestion, - search, - getSectionProgress, - payForCourse, - saveCheckout, -} \ No newline at end of file + getAllCourses, + getCourseById, + getCoursesByCategory, + getCoursesByPriceFromLowToHigh, + getCoursesByPriceFromHighToLow, + getCoursesByRating, + getCoursesByRatingFromLowToHigh, + getCoursesByRatingFromHighToLow, + getCoursesByPrice, + getCourseSections, + getCourseSubtitles, + getQuestion, + search, + getSectionProgress, + payForCourse, + saveCheckout, + updateTraineeProgress, +}; diff --git a/BackEnd/controller/trainee/traineeController.js b/BackEnd/controller/trainee/traineeController.js index fe7f31a..8a1e9f5 100644 --- a/BackEnd/controller/trainee/traineeController.js +++ b/BackEnd/controller/trainee/traineeController.js @@ -1,175 +1,200 @@ -const Instructor = require('../../models/InstructorSchema') -const Course = require('../../models/course/courseSchema') -const Trainee = require('../../models/traineeSchema') -const CourseSectionProgress = require('../../models/course/courseProgress/courseSectionProgress') +const Instructor = require("../../models/InstructorSchema"); +const Course = require("../../models/course/courseSchema"); +const Trainee = require("../../models/traineeSchema"); +const CourseSectionProgress = require("../../models/course/courseProgress/courseSectionProgress"); +const Payment = require("../../models/lib/payment/paymentSchema"); const getTraineebyId = async (req, res) => { - const _id = req.query + const _id = req.query; - const trainee = await Trainee.findById(_id) + const trainee = await Trainee.findById(_id); - if (!trainee) { - return res.status(404).json({ - error: 'user not found' - }) - } + if (!trainee) { + return res.status(404).json({ + error: "user not found", + }); + } - return res.status(200).json(trainee) -} + return res.status(200).json(trainee); +}; const joinCourse = async (req, res) => { - const { - _id, - course_id, - } = req.body - - try { - const trainee = await Trainee.joinCourse(_id,course_id) - res.status(200).json({ - trainee, - }) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + const { _id, course_id } = req.body; + + try { + const trainee = await Trainee.joinCourse(_id, course_id); + res.status(200).json({ + trainee, + }); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; + const rateCourse = async (req, res) => { - const { - user_id, - course_id, - rating - } = req.body - - try { - if(!user_id) - throw Error('userID not Entered') - const course = await Course.rateCourse(user_id,course_id, rating) - - res.status(200).json({ - course, - }) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} + const { user_id, course_id, rating } = req.body; + + try { + if (!user_id) throw Error("userID not Entered"); + const course = await Course.rateCourse(user_id, course_id, rating); + + res.status(200).json({ + course, + }); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; const reviewInstructor = async (req, res) => { - const { - _id, - instructor_id, - type, - reviewString - } = req.body - - try { - const review = await Trainee.reviewInstructor(_id,instructor_id, type, reviewString) - - res.status(200).json({ - review, - }) - } catch (error) { - res.status(400).json({ - error: error.message - }) - } -} -const getPreview = async (req,res) => { - const {courseId} = req.body - - try{ - const previewURl = await Course.find({_id:courseId}).select({coursePreviewUrl:1 , _id:0}) - res.status(200).json({ - previewURl - }) - }catch(error){ - console.log(error) - res.status(400).json({ - error: error.message - }) - } -} -const requestRefund = async (req,res) => { - const { - _id, - course_id - } = req.body - - try{ - if(!_id) - throw Error('userId not Entered') - if(!course_id) - throw Error('courseId not Entered') - - const course = await Course.findOne({ - _id: course_id - }) - var trainee = await Trainee.findOne({ - _id - }) - const sectionProgress = await CourseSectionProgress.findOne({ - user_id:_id, - course_id:course_id - }) - if (!course) - throw Error('Course Does not Exist') - if (!trainee) - throw Error('Trainee Does not Exist') - if (!sectionProgress) - throw Error('Section Progress Does not Exist') - const percentage = sectionProgress.finishedPercentage; - - var ownedCourses = trainee.ownedCourses - - for (let i = 0; i < ownedCourses.length; i++) { - console.log(ownedCourses[i].course_id) - if(ownedCourses[i].course_id == course_id) - { - ownedCourses.splice(i, 1); - - } - } - trainee = await Trainee.findByIdAndUpdate({ - _id - },{ - ownedCourses - }) - - await CourseSectionProgress.deleteOne({ - user_id:_id, - course_id:course_id - }) - - if(percentage < 50) + const { _id, instructor_id, type, reviewString } = req.body; + + try { + const review = await Trainee.reviewInstructor( + _id, + instructor_id, + type, + reviewString + ); + + res.status(200).json({ + review, + }); + } catch (error) { + res.status(400).json({ + error: error.message, + }); + } +}; +const getPreview = async (req, res) => { + const { courseId } = req.body; + + try { + const previewURl = await Course.find({ _id: courseId }).select({ + coursePreviewUrl: 1, + _id: 0, + }); + res.status(200).json({ + previewURl, + }); + } catch (error) { + console.log(error); + res.status(400).json({ + error: error.message, + }); + } +}; +const requestRefund = async (req, res) => { + const { payment_id } = req.body; + + try { + if (!payment_id) throw Error("payment_id not Entered"); + const payment = await Payment.findOne({ + _id: payment_id, + }); + + const course = await Course.findOne({ + _id: payment.course_id, + }); + var trainee = await Trainee.findOne({ + _id: payment.user_id, + }); + const instructor = await Instructor.findById({ + _id: course.instructor_id, + }); + let sectionProgress = await CourseSectionProgress.findOne({ + user_id: payment.user_id, + course_id: payment.course_id, + }); + if (!sectionProgress) + sectionProgress = await CourseSectionProgress.create({ + user_id: payment.user_id, + course_id: payment.course_id, + sectionTitle: "Introduction", + }); + if (!course) throw Error("Course Does not Exist"); + if (!trainee) throw Error("Trainee Does not Exist"); + + const percentage = sectionProgress.finishedPercentage; + if (percentage > 50) { + res.status(200).json({ + message: + "Sorry you can't refund this course you Exceeded 50% of the materials", + }); + } else { + let ownedCourses = trainee.ownedCourses; + ownedCourses = ownedCourses.filter( + (course) => course.course_id.toString() != payment.course_id + ); + await Instructor.findByIdAndUpdate( { - res.status(200).json({ - ownedCourses - }) + _id: course.instructor_id, + }, + { + credit: instructor.credit - course.price, } - else{ - res.status(200).json({ - message: "Sorry you can't refund this course you Exceeded 50% of the materials" - }) + ); + trainee = await Trainee.findByIdAndUpdate( + { + _id: payment.user_id, + }, + { + credit: trainee.credit + course.price, + ownedCourses: ownedCourses, } - - - - }catch(error){ - console.log(error) - res.status(400).json({ - error: error.message - }) + ); + paymentUpdate = await Payment.findByIdAndUpdate( + { + _id: payment_id, + }, + { + status: "Refunded", + } + ); + + await CourseSectionProgress.deleteOne({ + user_id: payment.user_id, + course_id: payment.course_id, + }); + res.status(200).json({ + trainee, + paymentUpdate, + instructor, + }); } -} + } catch (error) { + console.log(error); + res.status(400).json({ + error: error.message, + }); + } +}; + +const getPaymentById = async (req, res) => { + const { _id } = req.query; + try { + const payments = await Payment.find({ user_id: _id }); + res.status(200).json({ + payments, + }); + } catch (error) { + console.log(error); + res.status(400).json({ + error: error.message, + }); + } +}; module.exports = { - joinCourse, - rateCourse, - reviewInstructor, - getTraineebyId, - getPreview, - requestRefund, - -} \ No newline at end of file + joinCourse, + rateCourse, + reviewInstructor, + getTraineebyId, + getPreview, + requestRefund, + getPaymentById, +}; diff --git a/BackEnd/models/InstructorSchema.js b/BackEnd/models/InstructorSchema.js index 5b00077..1f13590 100644 --- a/BackEnd/models/InstructorSchema.js +++ b/BackEnd/models/InstructorSchema.js @@ -1,125 +1,149 @@ -const mongoose = require('mongoose') -const Discount = require('./lib/payment/discountSchema') -const User = require('../models/UserSchema') +const mongoose = require("mongoose"); +const Discount = require("./lib/payment/discountSchema"); +const User = require("../models/UserSchema"); -const Schema = mongoose.Schema +const Schema = mongoose.Schema; -const InstructorSchema = new Schema({ +const InstructorSchema = new Schema( + { _id: { - type: mongoose.Schema.Types.ObjectId, - ref: 'User', - required: true + type: mongoose.Schema.Types.ObjectId, + ref: "User", + required: true, }, name: { - type: String, + type: String, }, biography: { - type: String, + type: String, }, - offered_courses: [{ + offered_courses: [ + { course_id: mongoose.Schema.Types.ObjectId, //TODO - }], - defined_discounts: [{ + }, + ], + defined_discounts: [ + { discount_id: mongoose.Schema.Types.ObjectId, - discountName :String - }], + discountName: String, + }, + ], prefferedSubject: { - type: String, - enum: ['Web Development', 'Intermediate', 'Mathematics', 'Web Design'], + type: String, + enum: ["Web Development", "Intermediate", "Mathematics", "Web Design"], }, - reviews: [{ + reviews: [ + { reviewer_id: mongoose.Schema.Types.ObjectId, review_id: mongoose.Schema.Types.ObjectId, //type: String, - reviewString : String, - }], - issues: [{ + reviewString: String, + }, + ], + issues: [ + { issue_id: mongoose.Schema.Types.ObjectId, status: String, - }], - -}, { - timestamps: true -}) - -InstructorSchema.statics.signup = async function (email, username, password, firstname, lastname, gender) { - - const role = 'instructor' - const user = await User.signup(email, username, password, firstname, lastname, gender,role) - - - const instructor = await this.create({ - _id: user._id, - name:firstname + lastname, - }) - - return instructor - -} - -InstructorSchema.statics.addDiscount = async function (instructor_id, name, percentage, start_date, end_date) { - - const instructor = await this.findOne({ - _id: instructor_id - }) - - if (!instructor) - throw Error('Instructor does not Exist') - - var discount = await Discount.create({ - name, - percentage, - start_date, - end_date - }) - if(!discount) - throw Error('Discount not created') - - var discountObj = { - discount_id : discount._id, - discountName:name + }, + ], + credit: { + type: Number, + default: 0, + }, + }, + { + timestamps: true, + } +); + +InstructorSchema.statics.signup = async function ( + email, + username, + password, + firstname, + lastname, + gender +) { + const role = "instructor"; + const user = await User.signup( + email, + username, + password, + firstname, + lastname, + gender, + role + ); + + const instructor = await this.create({ + _id: user._id, + name: firstname + lastname, + }); + + return instructor; +}; + +InstructorSchema.statics.addDiscount = async function ( + instructor_id, + name, + percentage, + start_date, + end_date +) { + const instructor = await this.findOne({ + _id: instructor_id, + }); + + if (!instructor) throw Error("Instructor does not Exist"); + + var discount = await Discount.create({ + name, + percentage, + start_date, + end_date, + }); + if (!discount) throw Error("Discount not created"); + + var discountObj = { + discount_id: discount._id, + discountName: name, + }; + + await this.findByIdAndUpdate( + { + _id: instructor_id, + }, + { + $push: { + defined_discounts: discountObj, + }, } + ); - await this.findByIdAndUpdate({ - _id: instructor_id - }, { - $push: { - defined_discounts: discountObj - }, - } - ) - - return discount - -} + return discount; +}; //mehtaga had y3mlha ashan feh hagat kteer awy zay el discount abl man apply el discount lazm nt2kd eno aslan bydy el course dah -InstructorSchema.statics.isTeachCourse = async function (instructor_id, course_id) { - - -} -InstructorSchema.statics.changeBiography = async function (_id,newBiography) { - - if ( !_id ||!newBiography ) - throw Error('All fields must be filled') - - const user = await this.findOne({ - _id - }) - - if (!user) - throw Error('Incorrect id / User not Found') - - - return await this.findByIdAndUpdate({ - _id - }, { - biography: newBiography - }) - -} - - - - +InstructorSchema.statics.isTeachCourse = async function ( + instructor_id, + course_id +) {}; +InstructorSchema.statics.changeBiography = async function (_id, newBiography) { + if (!_id || !newBiography) throw Error("All fields must be filled"); + + const user = await this.findOne({ + _id, + }); + + if (!user) throw Error("Incorrect id / User not Found"); + + return await this.findByIdAndUpdate( + { + _id, + }, + { + biography: newBiography, + } + ); +}; -module.exports = mongoose.model('Instructor', InstructorSchema) \ No newline at end of file +module.exports = mongoose.model("Instructor", InstructorSchema); diff --git a/BackEnd/models/course/courseSectionSchema.js b/BackEnd/models/course/courseSectionSchema.js index 217203e..b24f5f2 100644 --- a/BackEnd/models/course/courseSectionSchema.js +++ b/BackEnd/models/course/courseSectionSchema.js @@ -1,19 +1,19 @@ -const mongoose = require('mongoose') -const courseMaterialSchema = require('./courseMaterialSchema') -const courseSubtitleSchema = require('./courseSubtitleSchema') +const mongoose = require("mongoose"); +const courseMaterialSchema = require("./courseMaterialSchema"); +const courseSubtitleSchema = require("./courseSubtitleSchema"); //Rabena ma3 el nas el gaya tktb hena -const Schema = mongoose.Schema +const Schema = mongoose.Schema; - -const CourseSectionSchema = new Schema({ +const CourseSectionSchema = new Schema( + { course_id: { - type: mongoose.Schema.Types.ObjectId, - ref: 'Course', - required: true + type: mongoose.Schema.Types.ObjectId, + ref: "Course", + required: true, }, sectionTitle: { - type: String, + type: String, }, // totalPoints: { // type: Number, //Ghaleban mesh hanstkhdmhom bttl3 3altool mel subtitle 3ala el course table @@ -24,59 +24,72 @@ const CourseSectionSchema = new Schema({ // maxGrade: { // type: Number, // }, - subtitles: [{ - subtitle_id : mongoose.Schema.Types.ObjectId, + subtitles: [ + { + subtitle_id: mongoose.Schema.Types.ObjectId, subtitleTitle: String, maxGrade: Number, totalPoints: Number, totalHours: Number, - }], - previewImage: {//TODO - type: String, + }, + ], + previewImage: { + //TODO + type: String, }, -}, { - timestamps: true -}) + }, + { + timestamps: true, + } +); -CourseSectionSchema.statics.addSection = async function (course_id, sectionTitle,subtitelTitle,subtitlePreviewVideoUrl) { +CourseSectionSchema.statics.addSection = async function ( + course_id, + sectionTitle, + subtitelTitle, + subtitlePreviewVideoUrl +) { + if (!course_id || !sectionTitle || !subtitelTitle || !subtitlePreviewVideoUrl) + throw error("All fields must be filled"); - if (!course_id || !sectionTitle || !subtitelTitle || !subtitlePreviewVideoUrl) - throw error('All fields must be filled') + const course = await this.find({ + _id: course_id, + }); + if (!course) throw Error("Course Does not Exist"); - const course = await this.find({ - _id: course_id - }) - if (!course) - throw Error('Course Does not Exist') - - const section = await this.create({ - course_id, - sectionTitle - }) - const section_id = section._id; + const section = await this.create({ + course_id, + sectionTitle, + }); + const section_id = section._id; - const subtitle = await courseSubtitleSchema.createSubtitle(course_id, section_id, subtitelTitle,subtitlePreviewVideoUrl,'Lecture') + const subtitle = await courseSubtitleSchema.createSubtitle( + course_id, + section_id, + subtitelTitle, + subtitlePreviewVideoUrl, + "Lecture" + ); - const subtitleObj = { - subtitle_id : subtitle._id, - subtitelTitle, - maxGrade: 0, - totalPoints: 0, - totalHours: 0, - } + const subtitleObj = { + subtitle_id: subtitle._id, + subtitelTitle, + maxGrade: 0, + totalPoints: 0, + totalHours: 0, + }; - const sectionObj = await this.findByIdAndUpdate({ - _id: section_id - }, { - $push: { - subtitles: subtitleObj - }, + const sectionObj = await this.findByIdAndUpdate( + { + _id: section_id, + }, + { + $push: { + subtitles: subtitleObj, + }, } - ) - return sectionObj; - -} - - + ); + return sectionObj; +}; -module.exports = mongoose.model('course Section', CourseSectionSchema) \ No newline at end of file +module.exports = mongoose.model("course Section", CourseSectionSchema); diff --git a/BackEnd/models/lib/payment/paymentSchema.js b/BackEnd/models/lib/payment/paymentSchema.js index e403719..4f981ac 100644 --- a/BackEnd/models/lib/payment/paymentSchema.js +++ b/BackEnd/models/lib/payment/paymentSchema.js @@ -1,48 +1,57 @@ -const mongoose = require('mongoose') +const mongoose = require("mongoose"); -const Schema = mongoose.Schema - - -const PaymentSchema = new Schema({ +const Schema = mongoose.Schema; +const PaymentSchema = new Schema( + { course_id: { - type: mongoose.Schema.Types.ObjectId, - ref: 'Course', - required: true + type: mongoose.Schema.Types.ObjectId, + ref: "Course", + required: true, }, user_id: { - type: mongoose.Schema.Types.ObjectId, - ref: 'User', - required: true + type: mongoose.Schema.Types.ObjectId, + ref: "User", + required: true, + }, + session_id: { + type: String, + required: true, + unique: true, + }, + payment_title: { + type: String, + required: true, }, price: { - type: Number, - required: true + type: Number, + required: true, }, status: { - type: Boolean, + type: String, + enum: ["pending", "paid", "failed", "refunded"], + required: true, }, type: { - type: String, - enum: ['masterCard', 'visa', 'quiz', 'grade'], //todo - required: true + type: String, + enum: ["card", "quiz", "grade"], //todo + required: true, }, currency: { - type: String, - enum: ['egp', 'usd', 'euro', 'aed'], - required: true + type: String, + enum: ["egp", "usd", "euro", "aed"], + required: true, }, discount: { - discount_id: mongoose.Schema.Types.ObjectId, - percentage: Number, - start_date: Date, - end_data: Date + discount_id: mongoose.Schema.Types.ObjectId, + percentage: Number, + start_date: Date, + end_data: Date, }, + }, + { + timestamps: true, + } +); -}, { - timestamps: true -}) - - - -module.exports = mongoose.model('payment', PaymentSchema) \ No newline at end of file +module.exports = mongoose.model("payment", PaymentSchema); diff --git a/BackEnd/models/traineeSchema.js b/BackEnd/models/traineeSchema.js index 6c3d76e..36d65ae 100644 --- a/BackEnd/models/traineeSchema.js +++ b/BackEnd/models/traineeSchema.js @@ -1,164 +1,190 @@ -const mongoose = require('mongoose') -const Schema = mongoose.Schema -const User = require('../models/UserSchema') -const Instructor = require('../models/InstructorSchema') -const Course = require('../models/course/courseSchema') -const Review = require('../models/lib/reviewSchema') -const CourseProgress = require('./course/courseProgress/courseProgressSchema') - -const TraineeSchema = new Schema({ - +const mongoose = require("mongoose"); +const Schema = mongoose.Schema; +const User = require("../models/UserSchema"); +const Instructor = require("../models/InstructorSchema"); +const Course = require("../models/course/courseSchema"); +const Review = require("../models/lib/reviewSchema"); +const CourseProgress = require("./course/courseProgress/courseProgressSchema"); + +const TraineeSchema = new Schema( + { _id: { - type: mongoose.Schema.Types.ObjectId, - required: true, - ref: 'User', + type: mongoose.Schema.Types.ObjectId, + required: true, + ref: "User", }, name: { - type: String, + type: String, }, isCorporate: { - type: Boolean, - required: true + type: Boolean, + required: true, }, credticard_details: { - type: String, - + type: String, }, - ownedCourses: [{ + ownedCourses: [ + { course_id: mongoose.Schema.Types.ObjectId, - courseTitle:String, //TODO - }], - followedCourses: [{ + courseTitle: String, //TODO + sectionProgress: [ + { + section_id: mongoose.Schema.Types.ObjectId, + }, + ], + }, + ], + + followedCourses: [ + { course_id: String, //TODO - }], + }, + ], totalPoints: { - type: Number, - + type: Number, }, - info: [{ + info: [ + { degree: String, currentJobTitle: String, universityName: String, universityFaculty: String, yearsExperience: String, - company: String - - }], - //lesa fee ba2y -}, { + company: String, + }, + ], + credit: { + type: Number, + default: 0, + }, + }, + { timestamps: true, -}) -TraineeSchema.statics.signup = async function (email, username, password, firstname, lastname, gender) { - - const role = 'trainee' - const user = await User.signup(email, username, password, firstname, lastname, gender,role) - - const _id = user._id; - - - - const trainee = await this.create({ - _id, - isCorporate: false, - name:firstname + lastname, - }) - - - return trainee - -} -TraineeSchema.statics.reviewInstructor = async function (_id, instructor_id, type, reviewString) { - - if (!_id || !instructor_id || !type || !reviewString) - throw Error('All fields must be filled') - - var instructor = await Instructor.findOne({ - instructor_id - }) - if (!instructor) - throw Error('Instructor Does not Exist') - - const review = await Review.create({ - reviewer_id: _id, - reviewed_id:instructor_id, - type : type, - review : reviewString, - }) - - const instructorReview = { - reviewer_id:_id, - review_id: review._id.toString(), - reviewString:reviewString, - + } +); +TraineeSchema.statics.signup = async function ( + email, + username, + password, + firstname, + lastname, + gender +) { + const role = "trainee"; + const user = await User.signup( + email, + username, + password, + firstname, + lastname, + gender, + role + ); + + const _id = user._id; + + const trainee = await this.create({ + _id, + isCorporate: false, + name: firstname + lastname, + }); + + return trainee; +}; +TraineeSchema.statics.reviewInstructor = async function ( + _id, + instructor_id, + type, + reviewString +) { + if (!_id || !instructor_id || !type || !reviewString) + throw Error("All fields must be filled"); + + var instructor = await Instructor.findOne({ + instructor_id, + }); + if (!instructor) throw Error("Instructor Does not Exist"); + + const review = await Review.create({ + reviewer_id: _id, + reviewed_id: instructor_id, + type: type, + review: reviewString, + }); + + const instructorReview = { + reviewer_id: _id, + review_id: review._id.toString(), + reviewString: reviewString, + }; + + instructor = await Instructor.findByIdAndUpdate( + { + _id: instructor_id, + }, + { + $push: { + reviews: instructorReview, + }, } + ); - instructor = await Instructor.findByIdAndUpdate({ - _id: instructor_id - }, { - $push: { - reviews: instructorReview - }, - } - - ) - - return review; -} + return review; +}; //Should only be called after payment is confirmed TraineeSchema.statics.joinCourse = async function (_id, course_id) { - - if (!_id || !course_id) - throw Error('All fields must be filled') - - const user = await User.findOne({ - _id - }) - if (!user) - throw Error('User Does not Exist') - - const course = await Course.findOne({ - course_id - }) - if (!course) - throw Error('Course Does not Exist') - - const courseProgress = await CourseProgress.create({ - course_id, - user_id:_id, - courseTitle:course.title, - username:user.username, - }) - - const courseObj = { - course_id:course_id, - courseTitle:course.title - } - const trainee = await this.findByIdAndUpdate({ - _id - }, { - $push: { - ownedCourses: courseObj - }, - } - - ) - - const enrolledStudent = { - user_id: user._id, - username:user.username, + if (!_id || !course_id) throw Error("All fields must be filled"); + + const user = await User.findOne({ + _id, + }); + if (!user) throw Error("User Does not Exist"); + + const course = await Course.findOne({ + course_id, + }); + if (!course) throw Error("Course Does not Exist"); + + const courseProgress = await CourseProgress.create({ + course_id, + user_id: _id, + courseTitle: course.title, + username: user.username, + }); + + const courseObj = { + course_id: course_id, + courseTitle: course.title, + }; + const trainee = await this.findByIdAndUpdate( + { + _id, + }, + { + $push: { + ownedCourses: courseObj, + }, } - - await Course.findByIdAndUpdate({ - _id:course_id - },{ - $push: { - enrolledStudents: enrolledStudent, - }, - subscriberNumber : ~~course.subscriberNumber + 1 - }) + ); - return trainee; -} + const enrolledStudent = { + user_id: user._id, + username: user.username, + }; + + await Course.findByIdAndUpdate( + { + _id: course_id, + }, + { + $push: { + enrolledStudents: enrolledStudent, + }, + subscriberNumber: ~~course.subscriberNumber + 1, + } + ); + return trainee; +}; -module.exports = mongoose.model('trainee', TraineeSchema) \ No newline at end of file +module.exports = mongoose.model("trainee", TraineeSchema); diff --git a/BackEnd/routes/course/courseRouter.js b/BackEnd/routes/course/courseRouter.js index e9da8c5..ac611d2 100644 --- a/BackEnd/routes/course/courseRouter.js +++ b/BackEnd/routes/course/courseRouter.js @@ -1,46 +1,39 @@ -const express = require('express') -const course = require('../../models/course/courseSchema') -const CourseStudyRouter = require("./courseStudyRouter") +const express = require("express"); +const course = require("../../models/course/courseSchema"); +const CourseStudyRouter = require("./courseStudyRouter"); const { - getAllCourses, - getCourseById, - getCoursesByCategory, - getCoursesByPrice, - getCoursesByRating, - getCoursesByPriceFromLowToHigh, - getCoursesByPriceFromHighToLow, - getCourseSections, - getCourseSubtitles, - getQuestion, - search -} = require('../../controller/course/courseController'); - + getAllCourses, + getCourseById, + getCoursesByCategory, + getCoursesByPrice, + getCoursesByRating, + getCoursesByPriceFromLowToHigh, + getCoursesByPriceFromHighToLow, + getCourseSections, + getCourseSubtitles, + getQuestion, + updateTraineeProgress, + search, +} = require("../../controller/course/courseController"); + +const { rateCourse } = require("../../controller/trainee/traineeController"); const { - rateCourse -} = require('../../controller/trainee/traineeController'); -const { getQuestionGrade } = require('../../controller/trainee/traineeCourseController'); - - - + getQuestionGrade, +} = require("../../controller/trainee/traineeCourseController"); const router = express.Router(); +router.use("/courseStudy", CourseStudyRouter); -router.use("/courseStudy", CourseStudyRouter) - - - -router.get('/', getCourseById) -router.get('/getAllCourses', getAllCourses) - - -router.post('/getCourseByCategory', getCoursesByCategory) -router.post('/getCoursesByPrice', getCoursesByPrice) -router.post('/getCoursesByRating', getCoursesByRating) -router.post('/search', search) - -router.post('/course/rateCourse', rateCourse) +router.get("/", getCourseById); +router.get("/getAllCourses", getAllCourses); +router.post("/getCourseByCategory", getCoursesByCategory); +router.post("/getCoursesByPrice", getCoursesByPrice); +router.post("/getCoursesByRating", getCoursesByRating); +router.post("/search", search); +router.post("/course/rateCourse", rateCourse); +router.post("/updateTraineeProgress", updateTraineeProgress); -module.exports = router \ No newline at end of file +module.exports = router; diff --git a/BackEnd/routes/libRouter.js b/BackEnd/routes/libRouter.js index 00f49a6..9b2dcd5 100644 --- a/BackEnd/routes/libRouter.js +++ b/BackEnd/routes/libRouter.js @@ -1,31 +1,31 @@ -const express = require('express') -const { - getCourseById, - getCourseSections, - getCourseSubtitles, - getQuestion, - getSectionProgress, - saveCheckout, - payForCourse -} = require('../controller/course/courseController') -const { getMaterial } = require('../controller/trainee/traineeCourseController') -const { getIssue } = require('../controller/userController') - -const router = express.Router() - - -router.get('/Course', getCourseById) -router.get('/CourseSections', getCourseSections) -router.get('/CourseSubtitles', getCourseSubtitles) -router.get('/CourseMaterial', getMaterial) -router.get('/Question', getQuestion) -router.get('/Issue', getIssue) - -router.get('/CourseSectionProgress', getSectionProgress) - -router.post('/payCourse', payForCourse) - -router.get('/saveCheckout', saveCheckout) - - -module.exports = router \ No newline at end of file +const express = require("express"); +const { + getCourseById, + getCourseSections, + getCourseSubtitles, + getQuestion, + getSectionProgress, + saveCheckout, + payForCourse, +} = require("../controller/course/courseController"); +const { + getMaterial, +} = require("../controller/trainee/traineeCourseController"); +const { getIssue } = require("../controller/userController"); + +const router = express.Router(); + +router.get("/Course", getCourseById); +router.get("/CourseSections", getCourseSections); +router.get("/CourseSubtitles", getCourseSubtitles); +router.get("/CourseMaterial", getMaterial); +router.get("/Question", getQuestion); +router.get("/Issue", getIssue); + +router.get("/CourseSectionProgress", getSectionProgress); + +router.post("/payCourse", payForCourse); + +router.post("/saveCheckout", saveCheckout); + +module.exports = router; diff --git a/BackEnd/routes/traineeRouter.js b/BackEnd/routes/traineeRouter.js index 8caa88a..3e1518b 100644 --- a/BackEnd/routes/traineeRouter.js +++ b/BackEnd/routes/traineeRouter.js @@ -1,62 +1,63 @@ -const express = require('express') -const { requestCourse } = require('../controller/trainee/corporateController') +const express = require("express"); +const { requestCourse } = require("../controller/trainee/corporateController"); const { - rateCourse, - reviewInstructor, - getTraineebyId, - joinCourse, - getPreview, - requestRefund -} = require('../controller/trainee/traineeController') + rateCourse, + reviewInstructor, + getTraineebyId, + joinCourse, + getPreview, + requestRefund, + getPaymentById, +} = require("../controller/trainee/traineeController"); const { - answerQuestion, - getQuestionGrade, - getQuizGrade, - getJoinedCourses, - getEmailandSendCertifiate, - getMyReviews, - editInstructorReview, - deleteInstructorReview, - getReview -} = require('../controller/trainee/traineeCourseController') -const User = require('../models/userSchema') + answerQuestion, + getQuestionGrade, + getQuizGrade, + getJoinedCourses, + getEmailandSendCertifiate, + getMyReviews, + editInstructorReview, + deleteInstructorReview, + getReview, +} = require("../controller/trainee/traineeCourseController"); +const User = require("../models/userSchema"); -const router = express.Router() +const router = express.Router(); -router.post('/joinCourse', joinCourse) +router.post("/joinCourse", joinCourse); -router.post('/rateCourse', rateCourse) +router.post("/rateCourse", rateCourse); -router.post('/reviewInstructor', reviewInstructor) +router.post("/reviewInstructor", reviewInstructor); -router.post('/answerQuestion', answerQuestion) +router.post("/answerQuestion", answerQuestion); -router.post('/getCertificate' , getEmailandSendCertifiate) +router.post("/getCertificate", getEmailandSendCertifiate); -router.post('/getPreview', getPreview) +router.post("/getPreview", getPreview); -router.get('/getTrainee',getTraineebyId) +router.get("/getTrainee", getTraineebyId); -router.get('/questionGrade', getQuestionGrade) +router.get("/questionGrade", getQuestionGrade); -router.post('/quizGrade', getQuizGrade) +router.post("/quizGrade", getQuizGrade); -router.get('/myCourses', getJoinedCourses) +router.get("/myCourses", getJoinedCourses); -router.post('/requestRefund', requestRefund) +router.post("/requestRefund", requestRefund); -router.get('/getReview', getReview) +router.get("/getPayments", getPaymentById); -router.get('/myInstructorReviews', getMyReviews) +router.get("/getReview", getReview); -router.post('/editInstructorReview', editInstructorReview) +router.get("/myInstructorReviews", getMyReviews); -router.post('/deleteInstructorReview', deleteInstructorReview) +router.post("/editInstructorReview", editInstructorReview); +router.post("/deleteInstructorReview", deleteInstructorReview); //ALL ROUTES BELOW HERE ARE FOR CORPORATE TRAINEE ONLY -router.post('/requestCourse', requestCourse) +router.post("/requestCourse", requestCourse); - -module.exports = router \ No newline at end of file +module.exports = router; diff --git a/frontend/src/App.js b/frontend/src/App.js index 4194c5b..2a40517 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,189 +1,288 @@ -import { BrowserRouter as Router,Routes, Route} from 'react-router-dom'; -import './App.css'; -import React from 'react'; - - -import Signin from './Components/Authentication/Signin' -import AdminSignup from './pages/admin'; -import GuestPage from './pages/guestPage'; -import { TraineePage } from './pages/traineePage'; -import { HomePage } from './pages/homePage'; -import InstructorPage from './pages/instructor'; -import { CourseDashboard } from './pages/courseDashboard'; -import { CoursePage } from './pages/coursePage'; - -import SearchCoursePage from './pages/searchCoursePage'; -import { InstructorEditProfile } from './pages/instructorEditProfile'; -import { TraineeEditProfile } from './pages/TraineeEditProfile'; -import SidebarPage from './pages/sidebarPage'; -import { InstructorAddCourse } from './pages/instructorAddCoursePage'; - -import InstructorAddQuizPage from './pages/instructorAddQuizPage'; - -import VideoPage from './Components/Video Page/videoPage'; -import Navbar from './Components/General/Navbar/navbar'; -import InstructorCard from './Components/Instructor/instructorCard'; -import TemplatePage from './pages/Template/TemplatePage'; - -import SignUpInstructor from './Components/Authentication/signUpInstructor'; -import SignUpTrainee from './Components/Authentication/signUpTrainee'; - -import SignUp from './Components/Authentication/signUpForm'; -import InstructorAddSectionPage from './pages/instructorAddSectionPage'; -import InstructorAddDiscountPage from './pages/instructorAddDiscountPage'; -import CourseCard from './Components/Cards/courseCard'; -import Dropdown2 from './Components/General/Buttons/CategoryChoices'; - - - -import LoginComponent from './Components/LoginComponent'; -import Login from './pages/login'; -import Terms from './pages/terms'; -import QuizPage from './pages/quizPage'; -import InstructorAddSubtitle from './Components/Instructor/instructorAddSubtitle'; -import InstructorCoursePage from './pages/instructorCoursePage'; -import RateCourse from './Components/Cards/rateCourse'; -import RateInstructor from './Components/Cards/rateInstructor'; -import InstructorHomePage from './pages/instructor'; -import InstructorEditBio from './pages/instructorEditBio'; -import InstructorEditEmail from './pages/instructorEditEmail'; -import InstructorEditPassword from './pages/instructorEditPassword'; -import UserPage from './pages/UserPage'; -import InstructorCardBig from './Components/Instructor/instructorCardBig'; - -import SectionPage from './pages/sectionPage'; -import TermsInstructor from './pages/TermsInstructor'; -import TermsTrainee from './pages/TermsTrainee'; -import AllCourses from './pages/AllCourses'; -import Temp from './pages/Temp'; - - - -import SubtitlePage from './pages/subtitlePage'; -import MaterialPage from './pages/materialPage'; -import Drawer from './Components/drawer'; -import Search from './pages/search'; -import QuestionsComponents from './Components/Instructor/questionsComponents'; -import QuestionCard from './Components/Cards/questionCard'; -import QuestionCard2 from './Components/Cards/questionCard2'; -import QuizResultsPage from './pages/quizResultsPage'; -import ViewInstructorReviews from './pages/ViewInstructorReviews'; -import ForgetPassword from './Components/Authentication/forgetPassword'; - -import AdminReportsPage from './pages/adminReportsPage'; -import TraineeOwnedCourses from './pages/traineeOwnedCourses'; -import FaqPage from './pages/faqPage'; -import AdminCourseRequests from './pages/adminCourseRequests'; -import InstructorAddPreviewURL from './Components/Instructor/instructorAddPreviewURL'; -import InstructorAddPreviewPage from './pages/instructorAddPreviewPage'; -import AddDiscount from './Components/Admin/addDiscount'; -import AdminViewCourses from './pages/adminViewCourses'; -import PreviewPage from './pages/previewPage'; -import ResetPasswordPage from './pages/resetPasswordPage'; -import InstructorDrawer from './Components/InstructorDrawer'; -import TraineeInstructorReviews from './pages/traineeInstructorReviews'; -import TraineeEditReview from './pages/traineeEditReview'; - - - - +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; +import "./App.css"; +import React from "react"; + +import Signin from "./Components/Authentication/Signin"; +import AdminSignup from "./pages/admin"; +import GuestPage from "./pages/guestPage"; +import { TraineePage } from "./pages/traineePage"; +import { HomePage } from "./pages/homePage"; +import InstructorPage from "./pages/instructor"; +import { CourseDashboard } from "./pages/courseDashboard"; +import { CoursePage } from "./pages/coursePage"; + +import SearchCoursePage from "./pages/searchCoursePage"; +import { InstructorEditProfile } from "./pages/instructorEditProfile"; +import { TraineeEditProfile } from "./pages/TraineeEditProfile"; +import SidebarPage from "./pages/sidebarPage"; +import { InstructorAddCourse } from "./pages/instructorAddCoursePage"; + +import InstructorAddQuizPage from "./pages/instructorAddQuizPage"; + +import VideoPage from "./Components/Video Page/videoPage"; +import Navbar from "./Components/General/Navbar/navbar"; +import InstructorCard from "./Components/Instructor/instructorCard"; +import TemplatePage from "./pages/Template/TemplatePage"; + +import SignUpInstructor from "./Components/Authentication/signUpInstructor"; +import SignUpTrainee from "./Components/Authentication/signUpTrainee"; + +import SignUp from "./Components/Authentication/signUpForm"; +import InstructorAddSectionPage from "./pages/instructorAddSectionPage"; +import InstructorAddDiscountPage from "./pages/instructorAddDiscountPage"; +import CourseCard from "./Components/Cards/courseCard"; +import Dropdown2 from "./Components/General/Buttons/CategoryChoices"; + +import LoginComponent from "./Components/LoginComponent"; +import Login from "./pages/login"; +import Terms from "./pages/terms"; +import QuizPage from "./pages/quizPage"; +import InstructorAddSubtitle from "./Components/Instructor/instructorAddSubtitle"; +import InstructorCoursePage from "./pages/instructorCoursePage"; +import RateCourse from "./Components/Cards/rateCourse"; +import RateInstructor from "./Components/Cards/rateInstructor"; +import InstructorHomePage from "./pages/instructor"; +import InstructorEditBio from "./pages/instructorEditBio"; +import InstructorEditEmail from "./pages/instructorEditEmail"; +import InstructorEditPassword from "./pages/instructorEditPassword"; +import UserPage from "./pages/UserPage"; +import InstructorCardBig from "./Components/Instructor/instructorCardBig"; + +import SectionPage from "./pages/sectionPage"; +import TermsInstructor from "./pages/TermsInstructor"; +import TermsTrainee from "./pages/TermsTrainee"; +import AllCourses from "./pages/AllCourses"; +import Temp from "./pages/Temp"; + +import SubtitlePage from "./pages/subtitlePage"; +import MaterialPage from "./pages/materialPage"; +import Drawer from "./Components/drawer"; +import Search from "./pages/search"; +import QuestionsComponents from "./Components/Instructor/questionsComponents"; +import QuestionCard from "./Components/Cards/questionCard"; +import QuestionCard2 from "./Components/Cards/questionCard2"; +import QuizResultsPage from "./pages/quizResultsPage"; +import ViewInstructorReviews from "./pages/ViewInstructorReviews"; +import ForgetPassword from "./Components/Authentication/forgetPassword"; + +import AdminReportsPage from "./pages/adminReportsPage"; +import TraineeOwnedCourses from "./pages/traineeOwnedCourses"; +import FaqPage from "./pages/faqPage"; +import AdminCourseRequests from "./pages/adminCourseRequests"; +import InstructorAddPreviewURL from "./Components/Instructor/instructorAddPreviewURL"; +import InstructorAddPreviewPage from "./pages/instructorAddPreviewPage"; +import AddDiscount from "./Components/Admin/addDiscount"; +import AdminViewCourses from "./pages/adminViewCourses"; +import PreviewPage from "./pages/previewPage"; +import ResetPasswordPage from "./pages/resetPasswordPage"; +import InstructorDrawer from "./Components/InstructorDrawer"; +import TraineeInstructorReviews from "./pages/traineeInstructorReviews"; +import TraineeEditReview from "./pages/traineeEditReview"; function App() { return ( <> - - - - } /> - } /> - } /> - } /> - } /> - } /> - }/> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - } /> - - - - - } /> - } /> - } /> - } /> - - - }/> - } /> - - {/* } /> */} - } /> - } /> - }/> - }/> - }/> - - }/> - }/> - }/> - }/> - }/> - - - - - - - {/* }/> + + + } /> + } + /> + } /> + } /> + } + /> + } /> + } + /> + } /> + } /> + } + /> + } + /> + } + /> + } /> + } + /> + } /> + } /> + } + /> + } + /> + } + /> + } + /> + } /> + } + /> + } + /> + } /> + } /> + } /> + } /> + } + /> + + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } + /> + } /> + + } + /> + + } /> + } + /> + } + /> + } /> + + } /> + } /> + + {/* } /> */} + } /> + } /> + } /> + } /> + } /> + + } /> + } /> + } + /> + } + /> + } + /> + + {/* }/> }/> }/> }/> }/> */} - - - - - - - + + - - ) + ); } export default App; diff --git a/frontend/src/Components/Cards/buyCourseCard.js b/frontend/src/Components/Cards/buyCourseCard.js index 42f7065..b079a1e 100644 --- a/frontend/src/Components/Cards/buyCourseCard.js +++ b/frontend/src/Components/Cards/buyCourseCard.js @@ -1,163 +1,191 @@ -import React from 'react' -import { useState, useEffect } from 'react'; -import axios from 'axios' -import img1 from "../images/Hotel.png" -import img2 from "../images/Swimming.png" -import img3 from "../images/Wi-Fi.png" -import img4 from "../images/Restaurant.png" -import img5 from "../images/Group.png" -import img6 from "../images/Lesson.png" -import img7 from "../images/Level.png" -import img8 from "../images/Clock.png" -import img9 from "../images/students.png" +import React from "react"; +import { useState, useEffect } from "react"; +import axios from "axios"; +import img1 from "../images/Hotel.png"; +import img2 from "../images/Swimming.png"; +import img3 from "../images/Wi-Fi.png"; +import img4 from "../images/Restaurant.png"; +import img5 from "../images/Group.png"; +import img6 from "../images/Lesson.png"; +import img7 from "../images/Level.png"; +import img8 from "../images/Clock.png"; +import img9 from "../images/students.png"; +import "../css/buyCourseCard.css"; +import { useParams } from "react-router-dom"; +export default function BuyCourseCard({ course, payFunction }) { + const [trainee, setTrainee] = useState(false); + const { id } = useParams(); + var [isOwenedCourse, setIsOwnedCourse] = useState(false); -import "../css/buyCourseCard.css" -import { Link } from 'react-router-dom' -import { TraineeEditProfile } from '../../pages/TraineeEditProfile'; -export default function BuyCourseCard({course,traineeID,payPage}) { - - - //const [trainee,setTrainee] = useState(false); - const [trainee,setTrainee] = useState([]); - //const [payPageLink,setPayPageLink] = useState('') - // const [isCorporate, setIsCorprate] = useState(false) - //var [isOwenedCourse, setIsOwnedCourse] = useState(false) - //var isCorprate = false - //var isOwnCourse = false - - const getTraineeById = async () => { - - const res = await axios.get(`http://localhost:3000/trainee/getTrainee?_id=${traineeID}`) + const getTraineeById = async () => { + const user_id = window.localStorage.getItem("user_id"); + if (user_id) { + const res = await axios + .get(`http://localhost:3000/trainee/getTrainee?_id=${user_id}`) .catch((err) => console.log(err)); - const data = await res.data; - return data; - - }; + const data = await res.data; - useEffect(() =>{ - getTraineeById().then((data) => setTrainee(data)) - },[]) + for (let i = 0; i < res.data.ownedCourses.length; i++) { + if (res.data.ownedCourses[i].course_id == id) { + setIsOwnedCourse(true); + } + } + return data; + } + }; - const sendCourseRequest = async () => { - const res = await axios.post("http://localhost:3000/trainee/requestCourse",{_id:traineeID,course_id:course._id}) + const payCourse = async () => { + if (window.localStorage.getItem("user_id") == null) { + window.location = "/login"; + } else { + const res = await axios + .post("http://localhost:3000/lib/payCourse", { + course_id: id, + user_id: window.localStorage.getItem("user_id"), + }) .catch((err) => console.log(err)); - const data = await res.data; - - return data; - - }; - - - const handleCourseRequest=(e)=>{ - e.preventDefault() + window.location = res.data; + } + }; - if(trainee.isCorporate == true){ - sendCourseRequest(); - } + const checkUrl = () => { + let search = window.location.search; + let params = new URLSearchParams(search); + const session_id = params.get("session_id"); + if (session_id) { + axios + .post("http://localhost:3000/lib/saveCheckout", { + session_id: session_id, + course_id: id, + }) + .then((res) => { + setIsOwnedCourse(true); + window.history.replaceState( + {}, + document.title, + "/course/coursePage/" + id + ); + }); } + }; + useEffect(() => { + checkUrl(); + getTraineeById().then((data) => setTrainee(data)); + }, []); - return ( -
-
-
- course photo -
-
- + const sendCourseRequest = async () => { + const res = await axios + .post("http://localhost:3000/trainee/requestCourse", { + _id: window.localStorage.getItem("user_id"), + course_id: id, + }) + .catch((err) => console.log(err)); + const data = await res.data; -
-
- - {course.category} -
-
- icon1 - icon2 - icon3 -
-
-

{course.title} With Chris Bryant

-
-
-
- rating -
-
- rating -
-
- rating -
-
- rating -
-
- rating -
-
-
- -
-
- price -
-
- -
-
- -
-
- level Icon -
-
- -
-
- level Icon -
-
- -
-
- level Icon -
-
- -
-
- level Icon -
-
- -
-
-

- {course.summary} -

- + return data; + }; -
+ const handleCourseRequest = (e) => { + e.preventDefault(); + + if (trainee.isCorporate == true) { + sendCourseRequest(); + } + }; -
- { trainee.isCorporate && } -
- - -
- {/* */} - - - - - - - {/* // */} -
+ return ( +
+
+
+ course photo +
+
+ +
+
+ + {course.category} +
+
+ icon1 + icon2 + icon3 +
+
+

{course.title} With Chris Bryant

+
+
+
+ rating +
+
+ rating +
+
+ rating +
+
+ rating +
+
+ rating +
+
+
+ +
+
+ price +
+
+ +
+
+ +
+
+ level Icon +
+
+ +
+
+ level Icon +
+
+ +
+
+ level Icon +
+
+ +
+
+ level Icon +
+
+ +
+
+

{course.summary}

+
+ {trainee.isCorporate && ( + + )} +
+ {!isOwenedCourse && ( +
+ +
+ )} +
- ) + ); } diff --git a/frontend/src/Components/Cards/courseCard.js b/frontend/src/Components/Cards/courseCard.js index 8f7da81..cdd3a3b 100644 --- a/frontend/src/Components/Cards/courseCard.js +++ b/frontend/src/Components/Cards/courseCard.js @@ -1,66 +1,74 @@ -import React from 'react'; -import { useState , useEffect} from 'react'; -import axios from 'axios'; -import "../css/courseCard.css" -import img1 from "../images/Course Image.png" -import img2 from "../images/Clock Icon.png" -import img3 from "../images/Lesson Icon.png" -import img4 from "../images/Level Icon.png" -import { Link } from 'react-router-dom'; +import React from "react"; +import { useState, useEffect } from "react"; +import axios from "axios"; +import "../css/courseCard.css"; +import img1 from "../images/Course Image.png"; +import img2 from "../images/Clock Icon.png"; +import img3 from "../images/Lesson Icon.png"; +import img4 from "../images/Level Icon.png"; +import { Link } from "react-router-dom"; -export default function CourseCard({course, traineeID}) { - const [instructorName,setInstructorName] = useState(''); +export default function CourseCard({ course }) { + const [instructorName, setInstructorName] = useState(""); const getInstructor = async () => { - const res = await axios.get(`http://localhost:3000/instructor/getInstructor?_id=${course.instructor_id}`) - .catch((err) => console.log(err)); + const res = await axios + .get( + `http://localhost:3000/instructor/getInstructor?_id=${course.instructor_id}` + ) + .catch((err) => console.log(err)); const data = await res.data; - + return data; - }; - useEffect(() =>{ - - getInstructor().then((data) => setInstructorName(data.name)) - - },[]); + useEffect(() => { + getInstructor().then((data) => setInstructorName(data.name)); + }, []); return ( -
-
-
- - Course Img -
+
+
+
+ Course Img +
-
- -

{course.title}

- +
+ +

{course.title}

+ -
-

- {course.summary} -

-
-
- - - -
- +
+ +
+

{course.summary}

+
+
+ + + +
-
- - - - - - -
+
+ + + + +
-
); } diff --git a/frontend/src/Components/Cards/sectionCard.js b/frontend/src/Components/Cards/sectionCard.js index cbe6682..67e55df 100644 --- a/frontend/src/Components/Cards/sectionCard.js +++ b/frontend/src/Components/Cards/sectionCard.js @@ -1,39 +1,87 @@ -import React from 'react' -import { useState , useEffect } from 'react' -import axios from 'axios' -import img1 from "../images/Course Image.png" -import img2 from "../images/Clock Icon.png" -import img3 from "../images/Lesson Icon.png" -import img4 from "../images/Level Icon.png" -import "../css/sectionCard.css" -import { Link } from 'react-router-dom' +import React from "react"; +import { useState, useEffect } from "react"; +import axios from "axios"; +import img1 from "../images/Course Image.png"; +import img2 from "../images/Clock Icon.png"; +import img3 from "../images/Lesson Icon.png"; +import img4 from "../images/Level Icon.png"; +import "../css/sectionCard.css"; +import { Link } from "react-router-dom"; -export default function SectionCard({section, traineeID}) { +export default function SectionCard({ section , traineeID }) { + const [isDone, setIsDone] = useState(false); + const updateProgress = async () => { + const user_id = window.localStorage.getItem("user_id"); + if (user_id) { + await axios + .post("http://localhost:3000/course/updateTraineeProgress", { + user_id: user_id, + section_id: section._id, + course_id: section.course_id, + }) + .then((res) => { + window.location.reload(); + }) + .catch((err) => console.log(err)); + } + }; + const getTraineeById = async () => { + const user_id = window.localStorage.getItem("user_id"); + if (user_id) { + await axios + .get(`http://localhost:3000/trainee/getTrainee?_id=${user_id}`) + .then((res) => { + for (let i = 0; i < res.data.ownedCourses.length; i++) { + if (res.data.ownedCourses[i].course_id === section.course_id) { + for ( + let j = 0; + j < res.data.ownedCourses[i].sectionProgress?.length; + j++ + ) { + if ( + res.data.ownedCourses[i].sectionProgress[j]._id === + section._id + ) { + setIsDone(true); + } + } + } + } + }) + .catch((err) => console.log(err)); + } + }; + + useEffect(() => { + getTraineeById(); + }); return (
-
- -
- section Img -
- -
-

{section.sectionTitle}

- - -

- - - -

-
- -
- +
+
+ section Img +
-
-
+
+

{section.sectionTitle}

+

+ + + +

+
+ +
+
- ) + ); } diff --git a/frontend/src/Components/General/Navbar/TraineeNavbar.js b/frontend/src/Components/General/Navbar/TraineeNavbar.js index de1ecc2..4a4bba3 100644 --- a/frontend/src/Components/General/Navbar/TraineeNavbar.js +++ b/frontend/src/Components/General/Navbar/TraineeNavbar.js @@ -1,111 +1,208 @@ -import React from 'react' +import React from "react"; // import "../../css/navbar.css" -import "../../css/traineeNavbar.css" -import search from "../../images/search.png" -import img1 from "../../images/Union.png" -import img2 from "../../images/notification.png" -import img3 from "../../images/question-circle.png" -import img4 from "../../images/settings.png" -import img5 from "../../images/Avatar.png" -import img6 from "../../images/arrow.png" -import Dropdown2 from '../Buttons/CategoryChoices' -import { InstructorEditProfile } from '../../../pages/instructorEditProfile' -import NavyButton from '../Buttons/navyButton' -import { useState,useEffect } from 'react' -import CourseCard from '../../Cards/courseCard' -import { Link } from 'react-router-dom' -import axios from 'axios' +import { AiFillWallet } from "react-icons/ai"; +import "../../css/traineeNavbar.css"; +import search from "../../images/search.png"; +import img1 from "../../images/Union.png"; +import img2 from "../../images/notification.png"; +import img3 from "../../images/question-circle.png"; +import img4 from "../../images/settings.png"; +import img5 from "../../images/Avatar.png"; +import img6 from "../../images/arrow.png"; +import Dropdown2 from "../Buttons/CategoryChoices"; +import { InstructorEditProfile } from "../../../pages/instructorEditProfile"; +import NavyButton from "../Buttons/navyButton"; +import { useState, useEffect } from "react"; +import CourseCard from "../../Cards/courseCard"; +import axios from "axios"; +import Button from "react-bootstrap/Button"; +import Modal from "react-bootstrap/Modal"; +import "../../css/traineeNavbar.css"; +import { Link } from "react-router-dom"; export default function TraineeNavbar() { - const [searchedword,setSearchedword] = useState('') - const [courses,setCourses] = useState([]) - const courseSearch = async () => { - console.log("boodaa") - const res = await axios.post("http://localhost:3000/course/search" , { - searchedword:searchedword + const [searchedword, setSearchedword] = useState(""); + const [courses, setCourses] = useState([]); + const [trainee, setTrainee] = useState([]); + const [modalIsOpen, setIsOpen] = React.useState(false); + const [transactions, setTransactions] = useState([]); + function openModal() { + setIsOpen(true); + } + + function closeModal() { + setIsOpen(false); + } + const courseSearch = async () => { + const res = await axios + .post("http://localhost:3000/course/search", { + searchedword: searchedword, + }) + .catch((err) => console.log(err)); + const data = await res.data; + + return data; + }; + const getCourses = async () => { + const res = await axios + .get("http://localhost:3000/course/getAllCourses") + .catch((err) => console.log(err)); + const data = await res.data; + + return data; + }; + + const getTraineeById = async () => { + const user_id = window.localStorage.getItem("user_id"); + if (user_id) { + const res = await axios + .get(`http://localhost:3000/trainee/getTrainee?_id=${user_id}`) + .then((res) => { + setTrainee(res.data); }) .catch((err) => console.log(err)); - const data = await res.data; - - return data; - - }; - const getCourses = async () => { - console.log("boodaa") - const res = await axios.get("http://localhost:3000/course/getAllCourses") + } + }; + const getPayments = async () => { + const user_id = window.localStorage.getItem("user_id"); + if (user_id) { + const res = await axios + .get(`http://localhost:3000/trainee/getPayments?_id=${user_id}`) + .then((res) => { + setTransactions(res.data.payments); + }) .catch((err) => console.log(err)); - const data = await res.data; - - return data; - - }; - useEffect(() =>{ - getCourses().then((data) => setCourses(data)) - - },[]) - useEffect(() =>{ - courseSearch().then((data) => setCourses(data)) - - },[]) - - const handleGoBack=(e)=>{ - e.preventDefault() - - window.history.back(); - - } - - + } + }; + + useEffect(() => { + getCourses().then((data) => setCourses(data)); + }, []); + useEffect(() => { + courseSearch().then((data) => setCourses(data)); + }, []); + + const handleGoBack = (e) => { + e.preventDefault(); + + window.history.back(); + }; + + const refundPayment = async (payment_id) => { + axios + .post(`http://localhost:3000/trainee/requestRefund`, { + payment_id: payment_id, + }) + .then((res) => { + getPayments(); + }) + .catch((err) => console.log(err)); + }; + + useEffect(() => { + getCourses(); + getTraineeById(); + getPayments(); + }, []); + useEffect(() => { + courseSearch().then((data) => setCourses(data)); + }, []); return (
-
- +
- +
-

LearnHub

-
- -
- -
+

LearnHub

+
+ +
-
- icon - icon - icon - icon - icon - +
+ + + + + Wallet + + + You currently have {trainee.credit} EGP in your wallet. +
Here is a list of your recent transactions: +

+ {transactions?.map((transaction) => ( +
+

{transaction?.payment_title}

+

+ {transaction?.price} {"EGP".toUpperCase()} +

+ +
+ ))} +
+ + + +
+
+ + icon + + + icon + + + icon + + + icon + + + icon + + + icon + + <>
+
- - - -
- - ) + ); } diff --git a/frontend/src/Components/General/Navbar/instructorNavbar.js b/frontend/src/Components/General/Navbar/instructorNavbar.js index 81a1a7f..135602e 100644 --- a/frontend/src/Components/General/Navbar/instructorNavbar.js +++ b/frontend/src/Components/General/Navbar/instructorNavbar.js @@ -1,93 +1,105 @@ -import React from 'react' -import "../../css/navbar.css" -import search from "../../images/search.png" -import img1 from "../../images/Union.png" -import img2 from "../../images/notification.png" -import img3 from "../../images/question-circle.png" -import img4 from "../../images/settings.png" -import img5 from "../../images/Avatar.png" -import img6 from "../../images/arrow.png" - -import { InstructorEditProfile } from '../../../pages/instructorEditProfile' -import NavyButton from '../Buttons/navyButton' -import { Link } from 'react-router-dom' - -export default function InstNavbar({props}) { - - const handleGoBack=(e)=>{ - e.preventDefault() - - window.history.back(); - - } - +import React, { useEffect, useState } from "react"; +import "../../css/navbar.css"; +import axios from "axios"; +import search from "../../images/search.png"; +import img1 from "../../images/Union.png"; +import img2 from "../../images/notification.png"; +import img3 from "../../images/question-circle.png"; +import img4 from "../../images/settings.png"; +import img5 from "../../images/Avatar.png"; +import img6 from "../../images/arrow.png"; +import Dropdown2 from "../Buttons/CategoryChoices"; +import { InstructorEditProfile } from "../../../pages/instructorEditProfile"; +import NavyButton from "../Buttons/navyButton"; +import { AiFillWallet } from "react-icons/ai"; +import { Link } from "react-router-dom"; + +export default function InstNavbar({ props }) { + const [instructor, setInstructor] = useState([]); + const getInstructorById = async () => { + const user_id = window.localStorage.getItem("user_id"); + if (user_id) { + const res = await axios + .get(`http://localhost:3000/instructor/getInstructor?_id=${user_id}`) + .then((res) => { + setInstructor(res.data); + }) + .catch((err) => console.log(err)); + } + }; + useEffect(() => { + getInstructorById(); + }, []); + const handleGoBack = (e) => { + e.preventDefault(); + + window.history.back(); + }; return (
- -
- -
- -
-

LearnHub

- -
- -
- -
- -
-
    -
  • - - My Reviews - -
  • - -
  • - - My Courses - -
  • - -
  • - - - Add Course - -
  • - -
  • - - Edit Profile - -
  • - -
  • - - Log Out - -
  • - - -
  • - Reports -
  • - -
- -
- -
- icon - icon - icon - icon - icon - -
- +
+ +
+ +
+

LearnHub

+
+ +
+ +
+ +
+
    +
  • + My Reviews +
  • + +
  • + My Courses +
  • + +
  • + Add Course +
  • + +
  • + Edit Profile +
  • + +
  • + Log Out +
  • + +
  • + Reports +
  • +
+
+ +
+ + + icon + + + icon + + + icon + + + icon + + + icon + +
- ) + ); } diff --git a/frontend/src/Components/LoginComponent.js b/frontend/src/Components/LoginComponent.js index be4a2bd..77518cb 100644 --- a/frontend/src/Components/LoginComponent.js +++ b/frontend/src/Components/LoginComponent.js @@ -1,133 +1,88 @@ -import React from 'react' -import "./loginComponent.css" -import login from "./images/user.svg" -import lock from "./images/lock.svg" -import { useState , useEffect} from 'react'; -import axios from 'axios' -import { Link } from 'react-router-dom'; +import React from "react"; +import "./loginComponent.css"; +import login from "./images/user.svg"; +import lock from "./images/lock.svg"; +import { useState, useEffect } from "react"; +import axios from "axios"; +import { Link } from "react-router-dom"; export default function LoginComponent() { - const[password,setPass] =useState('') - const[email,setEmail] =useState('') - const[userID,setUserID] = useState([]) - const[userRole,setUserRole] = useState(''); - - const[userIsInstructor,setUserIsInstructor] = useState(false); - const[userIsAdmin,setUserIsAdmin] = useState(false); - const[userIsTrainee,setUserIsTrainee] = useState(false); - + const [password, setPass] = useState(""); + const [email, setEmail] = useState(""); const loginUser = async () => { // console.log("boodaa") const res = await axios .post("http://localhost:3000/login/", { - email:email,password:password + email: email, + password: password, + }) + .then((res) => { + window.localStorage.setItem("user_id", res.data.user._id); + if (res.data.role === "instructor") { + window.location.href = `/instructor/${res.data.user._id}`; + } else if (res.data.role === "admin") { + window.location.href = `/admin/${res.data.user._id}`; + } else { + window.location.href = `/trainee/${res.data.user._id}`; + } }) .catch((err) => console.log(err)); const data = await res.data; - console.log(userID) - console.log(userRole) return data; }; - const handleSubmitt=(e)=>{ - e.preventDefault() - console.log("hi") - - - loginUser().then((data) => console.log(data)); - } - - useEffect(() =>{ - loginUser().then((data) => setUserID(data.user._id)) - loginUser().then((data) => setUserRole(data.role)) - }); - - const handleSignIn=(e)=>{ - e.preventDefault() - - if(userRole == 'instructor'){ - setUserIsInstructor(true) - } - else if(userRole == 'admin'){ - setUserIsAdmin(true) - } - else{ - setUserIsTrainee(true) - } - - - } + const handleSignIn = (e) => { + e.preventDefault(); + loginUser(); + }; return (
-

WELCOME BACK

+

WELCOME BACK

-
-
-
+
-
- setEmail(e.target.value)} - value={email} - - className='user' type="email" placeholder=" email" /> - -
-
-
- setPass(e.target.value)} - value={password} - - className='pass' type="password" placeholder=" Password" /> - - +
+ setEmail(e.target.value)} + value={email} + className="user" + type="email" + placeholder=" email" + /> +
+
+
+ setPass(e.target.value)} + value={password} + className="pass" + type="password" + placeholder=" Password" + /> +
+
- -
-
- - -
- -
-
- - - +
+
-

DONT HAVE AN ACCOUNT ?

- +

DONT HAVE AN ACCOUNT ?

+ - image - image + image + image
- - ) + ); } diff --git a/frontend/src/Components/css/navbar.css b/frontend/src/Components/css/navbar.css index aa63ad2..eccbf47 100644 --- a/frontend/src/Components/css/navbar.css +++ b/frontend/src/Components/css/navbar.css @@ -1,74 +1,73 @@ -.Nav-signedIn{ - background-color: #FAFDFF; - display: flex; - justify-content: space-between; - padding: 10px 0px; - height: 80px; +.Nav-signedIn { + background-color: #fafdff; + display: flex; + justify-content: space-between; + padding: 10px 0px; + height: 80px; } .sidemenu_button { - width: 30px; - border: none; - background-color: transparent; - /* padding: 0px 10px; */ - margin-top: 5px; - margin-left: 20px; - } + width: 30px; + border: none; + background-color: transparent; + /* padding: 0px 10px; */ + margin-top: 5px; + margin-left: 20px; +} -.Nav-title{ - padding: 5px 0px; - margin-left: 20px; +.Nav-title { + padding: 5px 0px; + margin-left: 20px; } -.Nav-search{ - padding: 10px 0px; - margin-left: 200px; +.Nav-search { + padding: 10px 0px; + margin-left: 200px; } -.Nav-search > input{ - border: none; - border-radius: 20px; - width: 200px; - background-color: rgb(224, 222, 222); +.Nav-search > input { + border: none; + border-radius: 20px; + width: 200px; + background-color: rgb(224, 222, 222); } -.Nav-search > input:focus{ - outline: none; +.Nav-search > input:focus { + outline: none; } -.Nav-actions > ul{ - list-style: none; - padding: 0px; +.Nav-actions > ul { + list-style: none; + padding: 0px; } -.Nav-actions > ul > li{ - list-style: none; - display: inline-table; +.Nav-actions > ul > li { + list-style: none; + display: inline-table; } -.Nav-actions > ul > li > a{ +.Nav-actions > ul > li > a { text-decoration: none; font-size: 20px; padding: 20px; color: #253858; } -.Nav-actions > ul > li > a:hover{ - text-decoration: none; - color: #436fba; - } - -.Nav-userInfo{ - padding: 6px 0px; +.Nav-actions > ul > li > a:hover { + text-decoration: none; + color: #436fba; } -.Nav-userInfo > a{ - padding: 0px 10px; +.Nav-userInfo { + display: flex; + flex-direction: row; + align-items: center; + gap: 25px; + margin-right: 20px; +} +.setting_icon { + border-radius: 16px; + top: 15px; + height: 32px; + width: 32px; + background-color: rgba(255, 255, 255, 0.00009999999747378752); } - -.setting_icon{ - border-radius: 16px; - top: 15px; - height: 32px; - width: 32px; - background-color: rgba(255, 255, 255, 0.00009999999747378752); - } \ No newline at end of file diff --git a/frontend/src/Components/css/traineeNavbar.css b/frontend/src/Components/css/traineeNavbar.css index e69de29..3b36d72 100644 --- a/frontend/src/Components/css/traineeNavbar.css +++ b/frontend/src/Components/css/traineeNavbar.css @@ -0,0 +1,18 @@ +.wallet { + display: flex; + flex-direction: row; + align-items: center; + gap: 15px; +} + +.transaction { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 20px; + margin-bottom: 20px; +} + +.transaction-button { + align-items: center; + justify-content: center; +} diff --git a/frontend/src/pages/coursePage.js b/frontend/src/pages/coursePage.js index b5a1ef4..86d01a0 100644 --- a/frontend/src/pages/coursePage.js +++ b/frontend/src/pages/coursePage.js @@ -1,85 +1,55 @@ -import React from 'react' -import { useState, useEffect } from 'react' -import axios from 'axios' -import { useParams } from 'react-router-dom' -import BuyCourseCard from '../Components/Cards/buyCourseCard' -import Rating from '../Components/Cards/rating' -import RatingsCard from '../Components/Course/ratingsCard' -import Navbar from '../Components/General/Navbar/navbar' -import "../Components/css/coursePage.css" -import InstructorCardBig from '../Components/Instructor/instructorCardBig' -import TraineeNavbar from '../Components/General/Navbar/TraineeNavbar' +import React from "react"; +import { useState, useEffect } from "react"; +import axios from "axios"; +import { useParams } from "react-router-dom"; +import BuyCourseCard from "../Components/Cards/buyCourseCard"; +import Rating from "../Components/Cards/rating"; +import RatingsCard from "../Components/Course/ratingsCard"; +import Navbar from "../Components/General/Navbar/navbar"; +import "../Components/css/coursePage.css"; +import InstructorCardBig from "../Components/Instructor/instructorCardBig"; +import TraineeNavbar from "../Components/General/Navbar/TraineeNavbar"; export const CoursePage = () => { - const { id } = useParams(); - const { traineeID } = useParams(); - - const [course,setCourse] = useState([]); - const [instructor,setInstructor] = useState([]); - const [payPageLink,setPayPageLink] = useState('') + const [course, setCourse] = useState([]); - const getCourseById = async () => { - const res = await axios.get(`http://localhost:3000/course/?_id=${id}`) - .catch((err) => console.log(err)); - const data = await res.data; - - return data; - - }; + const getCourseById = async () => { + const res = await axios + .get(`http://localhost:3000/course/?_id=${id}`) + .catch((err) => console.log(err)); + const data = await res.data; + return data; + }; - const payCourse = async () => { - const res = await axios.post("http://localhost:3000/lib/payCourse",{ - course_id: id , user_id: traineeID - }) - .catch((err) => console.log(err)); - const data = await res.data; - - return data; - - }; + // const getInstructor = async () => { + // const res = await axios.get(`http://localhost:3000/instructor/getInstructor?_id=${course.instructorid}`) + // .catch((err) => console.log(err)); + // const Instdata = await res.data; + // return Instdata; - useEffect(() =>{ - payCourse().then((data) => setPayPageLink(data)) - },[]) + // }; - console.log(payPageLink) - const x= payPageLink.data; - // const getInstructor = async () => { - // const res = await axios.get(`http://localhost:3000/instructor/getInstructor?_id=${course.instructorid}`) - // .catch((err) => console.log(err)); - // const Instdata = await res.data; - - // return Instdata; - - // }; + // useEffect(() =>{ + // getInstructor().then((Instdata) => setInstructor(Instdata)) - // useEffect(() =>{ - // getInstructor().then((Instdata) => setInstructor(Instdata)) - - // },[]) + // },[]) - useEffect(() =>{ - getCourseById().then((data) => setCourse(data)) - },[]) - - console.log(course) + useEffect(() => { + getCourseById().then((data) => setCourse(data)); + }, []); return (
- - +
- +
{/*
*/} -
- -
+
- - ) -} + ); +}; diff --git a/frontend/src/pages/materialPage.js b/frontend/src/pages/materialPage.js index bc1d2e9..8af15b7 100644 --- a/frontend/src/pages/materialPage.js +++ b/frontend/src/pages/materialPage.js @@ -36,7 +36,6 @@ const [quizes,setQuizes] = useState([]); {quizes && quizes.map((quiz) =>( - //

{quiz._id}

))}
diff --git a/frontend/src/pages/sectionPage.js b/frontend/src/pages/sectionPage.js index 2808e80..b2230c3 100644 --- a/frontend/src/pages/sectionPage.js +++ b/frontend/src/pages/sectionPage.js @@ -1,78 +1,74 @@ -//import React from 'react' -import {useState, useEffect , React} from 'react' -import { Form, useParams } from 'react-router-dom' -import SectionCard from '../Components/Cards/sectionCard' -import axios from 'axios' -import TraineeNavbar from '../Components/General/Navbar/TraineeNavbar' -import Progress_bar from '../Components/General/ProgressBar' - - +import React from "react"; +import { useState, useEffect } from "react"; +import { useParams } from "react-router-dom"; +import SectionCard from "../Components/Cards/sectionCard"; +import Navbar from "../Components/General/Navbar/navbar"; +import axios from "axios"; +import Progress_bar from "../Components/General/ProgressBar"; export default function SectionPage() { - //const{pdf}="completion.pdf"; - const{courseid} = useParams(); - const {traineeID} = useParams(); - const [sections,setSections] = useState([]); - - - const getsectionsbyCourse_id = async () => { - const res = await axios.get(`http://localhost:3000/lib/CourseSections?_id=${courseid}`) - .catch((err) => console.log(err)); - const data = await res.data; - return data; - - }; - - const downloadCertificateandsendViaEmail = async () => { - const res = await axios.post("http://localhost:3000/trainee/getCertificate",{ - trainee_id:traineeID - }) - .catch((err) => console.log(err)); - const data = await res.data; - console.log(data) - - return data; - - }; - - useEffect(() =>{ - getsectionsbyCourse_id().then((data) => setSections(data)) - -   },[]); - - const handleClick=(e)=>{ - e.preventDefault() - - downloadCertificateandsendViaEmail().then((data) => console.log(data)); - - } - - - + const { courseid, traineeID } = useParams(); + const [sections, setSections] = useState([]); + const [progress, setProgress] = useState(0); + const getsectionsbyCourse_id = async () => { + const res = await axios + .get(`http://localhost:3000/lib/CourseSections?_id=${courseid}`) + .catch((err) => console.log(err)); + const data = await res.data; + + return data; + }; + + useEffect(() => { + getsectionsbyCourse_id().then((data) => setSections(data)); + getCourseSections(); + }, []); + + const getCourseSections = async () => { + await axios + .get( + `http://localhost:3000/lib//CourseSectionProgress?course_id=${courseid}&user_id=${traineeID} + )}` + ) + .then((res) => { + setProgress(res.data.finishedPercentage); + }) + .catch((err) => console.log(err)); + }; + + const downloadCertificateandsendViaEmail = async () => { + const res = await axios + .post("http://localhost:3000/trainee/getCertificate", { + trainee_id: window.localStorage.getItem("user_id"), + }) + .catch((err) => console.log(err)); + const data = await res.data; + console.log(data); + + return data; + }; + + const handleClick = (e) => { + e.preventDefault(); + + downloadCertificateandsendViaEmail().then((data) => console.log(data)); + }; return (
- - - -
- - {sections && sections.map((section) =>( - -       ))} - -
- - - - - - - - - - -
- ) + + +

{courseid}

+ +
+ {sections && + sections.map((section) => )} +
+ + + + + +
+ ); } diff --git a/frontend/src/pages/traineePage.js b/frontend/src/pages/traineePage.js index d8c46db..e4b74d2 100644 --- a/frontend/src/pages/traineePage.js +++ b/frontend/src/pages/traineePage.js @@ -1,173 +1,147 @@ -import React from 'react'; -import CourseCard from '../Components/Cards/courseCard'; -import TraineeNavbar from "../Components/General/Navbar/TraineeNavbar" +import React from "react"; +import CourseCard from "../Components/Cards/courseCard"; +import TraineeNavbar from "../Components/General/Navbar/TraineeNavbar"; import { BrowserRouter as Router, Switch, Route, Link, - useParams + useParams, } from "react-router-dom"; -import {useState,useEffect} from 'react'; -import axios from 'axios'; +import { useState, useEffect } from "react"; +import axios from "axios"; -import "../Components/css/traineePage.css" -import InstructorCard from '../Components/Instructor/instructorCard' +import "../Components/css/traineePage.css"; +import InstructorCard from "../Components/Instructor/instructorCard"; // import image1 from "../Components/images/image1.svg" // import image2 from "../Components/images/Learn.svg" // import image3 from "../Components/images/sponser.svg" // import image4 from "../Components/images/Mission.svg" -import image5 from "../Components/images/profile1.svg" -import image9 from "../Components/images/profile2.png" -import image10 from "../Components/images/profile3.png" -import image11 from "../Components/images/profile4.svg" -import image6 from "../Components/images/hat.svg" -import image7 from "../Components/images/grad.svg" -import image8 from "../Components/images/star.svg" +import image5 from "../Components/images/profile1.svg"; +import image9 from "../Components/images/profile2.png"; +import image10 from "../Components/images/profile3.png"; +import image11 from "../Components/images/profile4.svg"; +import image6 from "../Components/images/hat.svg"; +import image7 from "../Components/images/grad.svg"; +import image8 from "../Components/images/star.svg"; export const TraineePage = () => { - - const [courses,setCourses] = useState([]); - const {traineeID} = useParams(); - + const [courses, setCourses] = useState([]); + const { traineeID } = useParams(); const getCourses = async () => { - const res = await axios.get("http://localhost:3000/course/getAllCourses") - .catch((err) => console.log(err)); + const res = await axios + .get("http://localhost:3000/course/getAllCourses") + .catch((err) => console.log(err)); const data = await res.data; - + return data; - }; + useEffect(() => { + getCourses().then((data) => setCourses(data)); + }, []); - - useEffect(() =>{ - getCourses().then((data) => setCourses(data)) - - },[]) - - - - - return (
- -
- +
+
- - - - - + + + - - - - - + + + - - -

Learn Through our Experts

-
-
- - image - +
+ + image - +

19 Courses

25,599 Students

3

Abdullah shoeib

UI/UX Designer

- image - image - - image + image + image + + image
-
- - image +
+ + image - +

19 Coursesd

25,599 Students

3

Mazen Hejazy

UI/UX Designer

- image - image - - image + image + image + + image
-
- - image - +
+ + image - +

19 Courses

25,599 Students

3

Marwan Ashraf

UI/UX Designer

- image - image - - image + image + image + + image
-
- image - +
+ image +

19 Courses

25,599 Students

3

Ghazouly El-hendy

UI/UX Designer

- image - image - - image + image + image + + image
-
- - {courses && courses.map((course , i) =>( - i<3 && - - - ))} - - - - - - - - - + + {courses && + courses.map( + (course, i) => + i < 3 && + )} + + + +
- ) -} + ); +};