Skip to content

Commit

Permalink
fix some issue in rating and review slider and fromat code
Browse files Browse the repository at this point in the history
  • Loading branch information
amitamrutiya committed Nov 11, 2023
1 parent b932b5c commit 27cddfd
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 29 deletions.
33 changes: 11 additions & 22 deletions backend/controllers/RatingAndReview.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ const mongoose = require("mongoose");

// create Rating and review
exports.createRating = async (req, res) => {
console.log("----------------------------------------");
try {
// get data
const { rating, review, courseId } = req.body;
const { userId } = req.user.id;
const userId = req.user.id;

// validate data
if (!rating || !review || !courseId || !userId) {
Expand All @@ -17,25 +18,15 @@ exports.createRating = async (req, res) => {
.json({ success: false, message: "Please enter all the fields" });
}

// check if user is enrolled or not
const user = await User.findById(userId);
if (!user.courses.includes(courseId)) {
return res.status(400).json({
success: false,
message: "You are not enrolled in this course",
});
}

// TODO : not forget to run this method
// const courseDetails = await Course.findOne({
// _id: courseId,
// studentsEnrolled: { $elemMatch: { $eq: userId } },
// });
const courseDetails = await Course.findOne({
_id: courseId,
studentsEnrolled: { $elemMatch: { $eq: userId } },
}); //check if user is enrolled or not

if (!courseDetails) {
return res.status(400).json({
return res.status(404).json({
success: false,
message: "You are not enrolled in this course",
message: "Student is not enrolled in the course",
});
}

Expand All @@ -61,15 +52,12 @@ exports.createRating = async (req, res) => {

// update course with this rating/review
const updatedCourseDetails = await Course.findByIdAndUpdate(
courseId,
{ _id: courseId },
{
$push: { ratingAndReviews: ratingAndReview._id },
},
{ new: true }
)
.populate("updatedCourseDetails")
.exec();
console.log(updatedCourseDetails);
);

// send response
return res.status(200).json({
Expand Down Expand Up @@ -137,6 +125,7 @@ exports.getAllRatingAndReview = async (req, res) => {
.populate({ path: "course", select: "courseName" })
.exec();

console.log("allReviews", allReviews);
if (!allReviews) {
return res.status(400).json({
success: false,
Expand Down
38 changes: 38 additions & 0 deletions frontend/src/components/common/RatingStars.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useEffect, useState } from "react"
import {TiStarFullOutline, TiStarHalfOutline, TiStarOutline,} from "react-icons/ti"


function RatingStars({ Review_Count, Star_Size }){
const [starCount, SetStarCount] = useState({
full: 0,
half: 0,
empty: 0,
})

useEffect(() => {
const wholeStars = Math.floor(Review_Count) || 0
SetStarCount({
full: wholeStars,
half: Number.isInteger(Review_Count) ? 0 : 1,
empty: Number.isInteger(Review_Count) ? 5 - wholeStars : 4 - wholeStars,
})
}, [Review_Count])


return (
<div className="flex gap-1 text-yellow-100">
{[...new Array(starCount.full)].map((_, i) => {
return <TiStarFullOutline key={i} size={Star_Size || 20} />
})}
{[...new Array(starCount.half)].map((_, i) => {
return <TiStarHalfOutline key={i} size={Star_Size || 20} />
})}
{[...new Array(starCount.empty)].map((_, i) => {
return <TiStarOutline key={i} size={Star_Size || 20} />
})}
</div>
)
}


export default RatingStars
99 changes: 99 additions & 0 deletions frontend/src/components/common/ReviewSlider.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { useEffect, useState } from "react";
import ReactStars from "react-rating-stars-component";

import { Swiper, SwiperSlide } from "swiper/react"; // Import Swiper React components
import "swiper/css"; // Import Swiper styles
import "swiper/css/free-mode";
import "swiper/css/pagination";
import "../../App.css";
import { FaStar } from "react-icons/fa"; // Icons

import { apiConnector } from "../../services/apiconnector"; // Get apiFunction and the endpoint
import { ratingsEndpoints } from "../../services/apis";

function ReviewSlider() {
const [reviews, setReviews] = useState([]);
const truncateWords = 15;

useEffect(() => {
(async () => {
const { data } = await apiConnector(
"GET",
ratingsEndpoints.REVIEWS_DETAILS_API
);
if (data?.success) {
setReviews(data?.data);
}
})();
}, []);

return (
<div className="text-white">
<div className="my-[50px] h-[184px] w-[650px] lg:w-[1260px] ">
<Swiper
className="w-full"
slidesPerView={3}
spaceBetween={25}
loop={true}
freeMode={true}
autoplay={{ delay: 2500, disableOnInteraction: false }}
>
{reviews.map((review, i) => {
return (
<SwiperSlide key={i}>
<div className="flex flex-col gap-3 bg-richblack-800 p-3 text-[14px] text-richblack-25">
<div className="flex items-center gap-4">
<img
src={
review?.user?.image
? review?.user?.image
: `https://api.dicebear.com/5.x/initials/svg?seed=${review?.user?.firstName}+${review?.user?.lastName}`
}
alt=""
className="h-9 w-9 rounded-full object-cover"
/>

<div className="flex flex-col">
<h1 className="font-semibold text-richblack-5">{`${review?.user?.firstName} ${review?.user?.lastName}`}</h1>
<h2 className="text-[12px] font-medium text-richblack-500">
{" "}
{review?.course?.courseName}{" "}
</h2>
</div>
</div>

<p className="font-medium text-richblack-25">
{review?.review.split(" ").length > truncateWords
? `${review?.review
.split(" ")
.slice(0, truncateWords)
.join(" ")} ...`
: `${review?.review}`}
</p>

<div className="flex items-center gap-2 ">
<h3 className="font-semibold text-yellow-100">
{" "}
{review.rating.toFixed(1)}{" "}
</h3>
<ReactStars
count={5}
value={review.rating}
size={20}
edit={false}
activeColor="#ffd700"
emptyIcon={<FaStar />}
fullIcon={<FaStar />}
/>
</div>
</div>
</SwiperSlide>
);
})}
</Swiper>
</div>
</div>
);
}

export default ReviewSlider;
8 changes: 8 additions & 0 deletions frontend/src/hooks/useRouteMatch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useLocation, matchPath } from "react-router-dom";

export default function useRouteMatch(path) {
const location = useLocation();
return matchPath(location.pathname, { path });
}

// this custom hook check if current location is same as path or not;
5 changes: 2 additions & 3 deletions frontend/src/pages/About.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import FoundingStory from "../assets/Images/FoundingStory.png";
import BannerImage1 from "../assets/Images/aboutus1.webp";
import BannerImage2 from "../assets/Images/aboutus2.webp";
import BannerImage3 from "../assets/Images/aboutus3.webp";

import ContactFormSection from "../components/core/AboutPage/ContactFormSection.jsx";
import LearningGrid from "../components/core/AboutPage/LearningGrid";
import Quote from "../components/core/AboutPage/Quote";
import StatsComponenet from "../components/core/AboutPage/Stats";
import HighlightText from "../components/core/HomePage/HighlightText";
// import ReviewSlider from "../components/common/ReviewSlider";
import ReviewSlider from "../components/common/ReviewSlider";
import Footer from "../components/common/Footer";

const About = () => {
Expand Down Expand Up @@ -128,7 +127,7 @@ const About = () => {
{" "}
Reviews from other learners{" "}
</h1>
{/* <ReviewSlider /> */}
<ReviewSlider />
</div>
<Footer />
</div>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/Contact.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Footer from "../components/common/Footer";
import ContactDetails from "../components/ContactPage/ContactDetails";
import ContactForm from "../components/ContactPage/ContactForm";
// import ReviewSlider from "../components/common/ReviewSlider"
import ReviewSlider from "../components/common/ReviewSlider"

const Contact = () => {
return (
Expand All @@ -24,7 +24,7 @@ const Contact = () => {
{" "}
Reviews from other learners{" "}
</h1>
{/* <ReviewSlider /> */}
<ReviewSlider />
</div>

<Footer />
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/Home.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Footer from "../components/common/Footer";
import InstructorSection from "../components/core/HomePage/InstructorSection";
import LearningLanguageSection from "../components/core/HomePage/LearningLanguageSection";
import TimelineSection from "../components/core/HomePage/TimelineSection";
// import ReviewSlider from "../components/common/ReviewSlider";
import ReviewSlider from "../components/common/ReviewSlider";

function Home() {
return (
Expand Down Expand Up @@ -172,7 +172,7 @@ function Home() {
Reviews from Other Learners{" "}
</h1>
{/* Review Slider here */}
{/* <ReviewSlider /> */}
<ReviewSlider />
</div>
{/* Footer */}
<Footer />
Expand Down
50 changes: 50 additions & 0 deletions frontend/src/pages/ViewCourse.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Outlet, useParams } from "react-router-dom";

import CourseReviewModal from "../components/core/ViewCourse/CourseReviewModal";
import VideoDetailsSidebar from "../components/core/ViewCourse/VideoDetailsSidebar";
import { getFullDetailsOfCourse } from "../services/operations/courseDetailsAPI";
import {
setCompletedLectures,
setCourseSectionData,
setEntireCourseData,
setTotalNoOfLectures,
} from "../slices/viewCourseSlice";

export default function ViewCourse() {
const { courseId } = useParams();
const { token } = useSelector((state) => state.auth);
const dispatch = useDispatch();
const [reviewModal, setReviewModal] = useState(false);

useEffect(() => {
(async () => {
const courseData = await getFullDetailsOfCourse(courseId, token);
dispatch(setCourseSectionData(courseData.courseDetails.courseContent));
dispatch(setEntireCourseData(courseData.courseDetails));
dispatch(setCompletedLectures(courseData.completedVideos));
let lectures = 0;
courseData?.courseDetails?.courseContent?.forEach((sec) => {
lectures += sec.subSections.length;
});
dispatch(setTotalNoOfLectures(lectures));
})();
}, []);

return (
<>
<div className="relative flex min-h-[calc(100vh-3.5rem)]">
<VideoDetailsSidebar setReviewModal={setReviewModal} />

<div className="h-[calc(100vh-3.5rem)] flex-1 overflow-auto">
<div className="mx-6">
<Outlet />
</div>
</div>
</div>
{reviewModal && <CourseReviewModal setReviewModal={setReviewModal} />}{" "}
{/* when we open reviewModal or click on review then CourseReviewModal will be active */}
</>
);
}

0 comments on commit 27cddfd

Please sign in to comment.