1+ /**
2+ * ReviewForm.jsx
3+ *
4+ * Form component for submitting course reviews.
5+ * Allows users to:
6+ * - Select a star rating (1-5)
7+ * - Write a text review (minimum 10 characters)
8+ * - Optionally provide their name
9+ *
10+ * Validates input and displays success/error messages.
11+ */
12+
113import { useState } from 'react' ;
214import { submitReview } from '../api' ;
15+ import { MIN_RATING , MAX_RATING , MIN_COMMENT_LENGTH , SUCCESS_MESSAGE_DURATION } from '../constants' ;
316
417function ReviewForm ( { courseId, onReviewSubmitted } ) {
518 const [ rating , setRating ] = useState ( 0 ) ;
@@ -18,8 +31,13 @@ function ReviewForm({ courseId, onReviewSubmitted }) {
1831 return ;
1932 }
2033
21- if ( comment . trim ( ) . length < 10 ) {
22- setError ( 'Comment must be at least 10 characters' ) ;
34+ if ( rating < MIN_RATING || rating > MAX_RATING ) {
35+ setError ( `Rating must be between ${ MIN_RATING } and ${ MAX_RATING } ` ) ;
36+ return ;
37+ }
38+
39+ if ( comment . trim ( ) . length < MIN_COMMENT_LENGTH ) {
40+ setError ( `Comment must be at least ${ MIN_COMMENT_LENGTH } characters` ) ;
2341 return ;
2442 }
2543
@@ -42,8 +60,8 @@ function ReviewForm({ courseId, onReviewSubmitted }) {
4260 // Notify parent to reload data
4361 onReviewSubmitted ( ) ;
4462
45- // Hide success message after 3 seconds
46- setTimeout ( ( ) => setSuccess ( false ) , 3000 ) ;
63+ // Hide success message after configured duration
64+ setTimeout ( ( ) => setSuccess ( false ) , SUCCESS_MESSAGE_DURATION ) ;
4765 } else {
4866 setError ( result . error || 'Failed to submit review' ) ;
4967 }
@@ -54,6 +72,12 @@ function ReviewForm({ courseId, onReviewSubmitted }) {
5472 }
5573 } ;
5674
75+ // Generate array of star ratings based on constants
76+ const ratingOptions = Array . from (
77+ { length : MAX_RATING } ,
78+ ( _ , i ) => i + MIN_RATING
79+ ) ;
80+
5781 return (
5882 < div className = "bg-white rounded-lg shadow-sm border border-gray-200 p-6 sticky top-8" >
5983 < h2 className = "text-xl font-bold text-gray-900 mb-4" > Write a Review</ h2 >
@@ -65,7 +89,7 @@ function ReviewForm({ courseId, onReviewSubmitted }) {
6589 Your Rating *
6690 </ label >
6791 < div className = "flex gap-2" >
68- { [ 1 , 2 , 3 , 4 , 5 ] . map ( ( star ) => (
92+ { ratingOptions . map ( ( star ) => (
6993 < button
7094 key = { star }
7195 type = "button"
@@ -80,7 +104,7 @@ function ReviewForm({ courseId, onReviewSubmitted }) {
80104 </ div >
81105 { rating > 0 && (
82106 < p className = "text-sm text-gray-600 mt-1" >
83- You rated: { rating } out of 5
107+ You rated: { rating } out of { MAX_RATING }
84108 </ p >
85109 ) }
86110 </ div >
@@ -99,7 +123,7 @@ function ReviewForm({ courseId, onReviewSubmitted }) {
99123 required
100124 />
101125 < p className = "text-xs text-gray-500 mt-1" >
102- { comment . length } characters (minimum 10 )
126+ { comment . length } characters (minimum { MIN_COMMENT_LENGTH } )
103127 </ p >
104128 </ div >
105129
0 commit comments