From b1394f53306a34e66ec6c33ce38528104301d386 Mon Sep 17 00:00:00 2001
From: Faisal Misbah
{course.description}
) : null} @@ -146,6 +168,8 @@ export default async function CatalogCoursePage({ + {reviews ?Course rating
+
+
+ {ratings.count} rating{ratings.count === 1 ? "" : "s"} +
++ No ratings yet. Learners can rate the course after completing it. +
+ ) : ( +{row.review}
+ ) : null} +diff --git a/frontend/src/components/learn/catalog-course-card.tsx b/frontend/src/components/learn/catalog-course-card.tsx index 718c3f95d..6d4c6e538 100644 --- a/frontend/src/components/learn/catalog-course-card.tsx +++ b/frontend/src/components/learn/catalog-course-card.tsx @@ -1,6 +1,7 @@ import { EnrollmentBadge } from "@buildment/learning-ui/components/learn/enrollment-badge"; import Link from "next/link"; import { CourseCover } from "@/components/learn/course-cover"; +import { StarRating } from "@/components/learn/star-rating"; import { formatPriceCents } from "@/lib/format-price"; export type CatalogCourseCardProps = { @@ -17,6 +18,8 @@ export type CatalogCourseCardProps = { enrolledLabel?: string | null; subcategory?: string | null; tags?: string[]; + ratingAverage?: number | null; + ratingCount?: number; }; /** The whole card is the link: a big target on a phone, and one tab stop per course. */ @@ -34,6 +37,8 @@ export function CatalogCourseCard({ enrolledLabel, subcategory, tags = [], + ratingAverage = null, + ratingCount = 0, }: CatalogCourseCardProps) { const meta = [difficulty ? difficulty.toLowerCase() : null, estimatedHours ? `${estimatedHours} hours` : null] .filter(Boolean) @@ -48,6 +53,13 @@ export function CatalogCourseCard({ {meta ?
{meta}
: null} {subcategory ?{subcategory}
: null}{tags.slice(0, 3).join(" · ")}
: null} {instructorName ?With {instructorName}
: null} {description ? ( diff --git a/frontend/src/components/learn/chapter-complete-celebration-modal.tsx b/frontend/src/components/learn/chapter-complete-celebration-modal.tsx index d11fe28cb..1a9f6960d 100644 --- a/frontend/src/components/learn/chapter-complete-celebration-modal.tsx +++ b/frontend/src/components/learn/chapter-complete-celebration-modal.tsx @@ -1,11 +1,13 @@ "use client"; import { cn } from "@/lib/utils"; -import { useEffect, useRef } from "react"; +import { useEffect, useRef, useState } from "react"; import Link from "next/link"; import { ArrowRight, CheckCircle2, X } from "lucide-react"; import { Button, buttonVariants } from "@/components/ui/button"; import { Progress, ProgressLabel } from "@/components/ui/progress"; +import { StarRatingInput } from "@/components/learn/star-rating"; +import { saveCourseRatingAction } from "@/server/actions/course-rating"; export function ChapterCompleteCelebrationModal({ open, @@ -16,6 +18,7 @@ export function ChapterCompleteCelebrationModal({ courseTotal, nextHref, nextTitle, + courseSlug, }: { open: boolean; onClose: () => void; @@ -26,12 +29,29 @@ export function ChapterCompleteCelebrationModal({ courseTotal: number; nextHref?: string; nextTitle?: string; + /** Enables the one-time rating prompt when the course is complete. */ + courseSlug?: string; }) { + const [rating, setRating] = useState(0); + const [review, setReview] = useState(""); + const [ratingPending, setRatingPending] = useState(false); + const [ratingSaved, setRatingSaved] = useState(false); + const [ratingError, setRatingError] = useState{percent}% complete
) : null} + {courseComplete && courseSlug ? ( +Thanks for rating the course.
+ ) : ( + <> +How was the course?
++ Your rating helps other learners decide. +
+Your rating
+“{saved.review}”
+ ) : null} ++ Your rating helps other learners decide and helps us fix the parts that did not work. +
+ +{error}
: null} + +
+
Learner reviews
++ {reviews.count} rating{reviews.count === 1 ? "" : "s"} +
+{item.review}
+{percent}% complete
Thanks for rating the course.
- ) : ( - <> -How was the course?
-- Your rating helps other learners decide. -
-Your rating
-“{saved.review}”
++ “{saved.review}” +
) : null}- Your rating helps other learners decide and helps us fix the parts that did not work. -
++ You're past the halfway mark — your rating helps other learners decide and helps us improve. +
+