@@ -6,9 +6,18 @@ export function ReviewView(props) {
66 const { formData, setFormData } = props ;
77 const [ showGradeOptions , setShowGradeOptions ] = useState ( false ) ;
88 const [ showRecommendOptions , setShowRecommendOptions ] = useState ( false ) ;
9+ const [ expandedReviews , setExpandedReviews ] = useState ( { } ) ;
910 const gradeRef = useRef ( null ) ;
1011 const recommendRef = useRef ( null ) ;
1112
13+ // Function to get user initials from their name
14+ const getInitials = ( name ) => {
15+ if ( ! name ) return "N/A" ;
16+ const words = name . trim ( ) . split ( " " ) ;
17+ if ( words . length === 1 ) return words [ 0 ] [ 0 ] ?. toUpperCase ( ) || "N/A" ;
18+ return `${ words [ 0 ] [ 0 ] ?. toUpperCase ( ) || "" } ${ words [ words . length - 1 ] [ 0 ] ?. toUpperCase ( ) || "" } ` ;
19+ } ;
20+
1221 useEffect ( ( ) => {
1322 function handleClickOutside ( event ) {
1423 if ( gradeRef . current && ! gradeRef . current . contains ( event . target ) ) {
@@ -25,6 +34,14 @@ export function ReviewView(props) {
2534 } ;
2635 } , [ ] ) ;
2736
37+ // Function to toggle expanded state for a review
38+ const toggleExpanded = ( index ) => {
39+ setExpandedReviews ( ( prev ) => ( {
40+ ...prev ,
41+ [ index ] : ! prev [ index ] ,
42+ } ) ) ;
43+ } ;
44+
2845 return (
2946 < div className = "max-w-3xl mx-auto" >
3047 < div className = "mt-6" >
@@ -50,7 +67,6 @@ export function ReviewView(props) {
5067 />
5168 </ div >
5269
53-
5470 { /* Professor Rating */ }
5571 < div className = "text-center" >
5672 < p className = "font-semibold text-gray-700 text-sm mb-1" > Professor Rating</ p >
@@ -73,7 +89,7 @@ export function ReviewView(props) {
7389 { formData . grade || "Select" }
7490 </ div >
7591 { showGradeOptions && (
76- < div className = "absolute left-1/2 -translate-x-1/2 mt-2 bg-white p-2 rounded-md shadow-lg Disturbance shadow-lg z-10 flex space-x-2 animate-fadeIn" >
92+ < div className = "absolute left-1/2 -translate-x-1/2 mt-2 bg-white p-2 rounded-md shadow-lg z-10 flex space-x-2 animate-fadeIn" >
7793 { grades . map ( ( grade ) => (
7894 < button
7995 key = { grade }
@@ -139,14 +155,14 @@ export function ReviewView(props) {
139155 </ div >
140156
141157 < div className = "mt-4" >
142- < input
143- type = "text"
144- placeholder = "Enter professor name"
145- maxLength = { 100 }
146- className = "w-full border border-gray-300 rounded-md p-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors duration-200"
147- value = { formData . professorName }
148- onChange = { ( e ) => setFormData ( { ...formData , professorName : e . target . value } ) }
149- />
158+ < input
159+ type = "text"
160+ placeholder = "Enter professor name"
161+ maxLength = { 100 }
162+ className = "w-full border border-gray-300 rounded-md p-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors duration-200"
163+ value = { formData . professorName }
164+ onChange = { ( e ) => setFormData ( { ...formData , professorName : e . target . value } ) }
165+ />
150166 </ div >
151167
152168 < div className = "relative mt-4" >
@@ -173,92 +189,107 @@ export function ReviewView(props) {
173189 < div className = "mt-6" >
174190 < h3 className = "text-lg font-semibold text-gray-800 mb-4" > Previous Reviews</ h3 >
175191 < div className = "space-y-6" >
176- { /* {props.reviews.map((rev, i) => ( */ }
177- { [ ...props . reviews ] . sort ( ( a , b ) => new Date ( b . timestamp ) - new Date ( a . timestamp ) ) . map ( ( rev , i ) => (
178- < div key = { i } className = "bg-white shadow-md rounded-lg p-4" >
179- < div className = "flex justify-between items-center mb-2" >
180- < p className = "font-semibold text-gray-800" > { rev . userName } </ p >
181- < p className = "text-sm text-gray-500" >
182- Posted on { new Date ( rev . timestamp ) . toLocaleDateString ( "en-US" , {
183- month : "long" ,
184- day : "numeric" ,
185- year : "numeric" ,
186- } ) }
187- </ p >
188- </ div >
189- < div className = "grid grid-cols-2 md:grid-cols-3 gap-4 mb-2" >
190- < div >
191- < p className = "text-sm font-semibold text-gray-700" > Overall Rating</ p >
192- { /* <RatingComponent
193- className="flex space-x-1 text-sm"
194- value={rev.overallRating}
195- readOnly={true}
196- /> */ }
197- { rev . overallRating > 0 ? (
198- < RatingComponent
199- className = "flex space-x-1 text-sm"
200- value = { rev . overallRating }
201- readOnly = { true }
202- />
203- ) : (
204- < p className = "text-sm text-gray-600" > N/A</ p >
205- ) }
206-
207- </ div >
208- < div >
209- < p className = "text-sm font-semibold text-gray-700" > Difficulty Rating</ p >
210- { rev . difficultyRating > 0 ? (
211- < RatingComponent
212- className = "flex space-x-1 text-sm"
213- value = { rev . difficultyRating }
214- readOnly = { true }
215- />
216- ) : (
217- < p className = "text-sm text-gray-600" > N/A</ p >
218- ) }
219-
220- </ div >
221- < div >
222- < p className = "text-sm font-semibold text-gray-700" > Professor Rating</ p >
223- { rev . professorRating > 0 ? (
224- < RatingComponent
225- className = "flex space-x-1 text-sm"
226- value = { rev . professorRating }
227- readOnly = { true }
228- />
229- ) : (
230- < p className = "text-sm text-gray-600" > N/A</ p >
231- ) }
232-
233- </ div >
234- < div >
235- < p className = "text-sm font-semibold text-gray-700" > Professor</ p >
236- { /* <p className="text-sm text-gray-600">{rev.professorName}</p> */ }
237- < p className = "text-sm text-gray-600" > { rev . professorName || "N/A" } </ p >
238-
239- </ div >
240- < div >
241- < p className = "text-sm font-semibold text-gray-700" > Grade</ p >
242- { /* <p className="text-sm text-gray-600">{rev.grade}</p> */ }
243- < p className = "text-sm text-gray-600" > { rev . grade || "N/A" } </ p >
244-
245- </ div >
246- < div >
247- < p className = "text-sm font-semibold text-gray-700" > Recommended</ p >
248- { /* <p className="text-sm text-gray-600">{rev.recommend ? "Yes" : "No"}</p> */ }
249- < p className = "text-sm text-gray-600" >
250- { rev . recommend === true ? "Yes" : rev . recommend === false ? "No" : "N/A" }
251- </ p >
192+ { [ ...props . reviews ]
193+ . sort ( ( a , b ) => new Date ( b . timestamp ) - new Date ( a . timestamp ) )
194+ . map ( ( rev , i ) => {
195+ const maxLength = 200 ;
196+ const isLongReview = rev . text . length > maxLength ;
197+ const isExpanded = expandedReviews [ i ] || false ;
252198
199+ return (
200+ < div key = { i } className = "bg-white shadow-md rounded-lg p-4" >
201+ < div className = "flex justify-between items-center mb-2" >
202+ < div className = "flex items-center gap-2" >
203+ < div className = "w-6 h-6 rounded-full bg-blue-600 text-white flex items-center justify-center text-sm font-semibold" >
204+ { getInitials ( rev . userName ) }
205+ </ div >
206+ < p className = "font-semibold text-gray-800" > { rev . userName } </ p >
207+ </ div >
208+ < p className = "text-sm text-gray-500" >
209+ Posted on{ " " }
210+ { new Date ( rev . timestamp ) . toLocaleDateString ( "en-US" , {
211+ month : "long" ,
212+ day : "numeric" ,
213+ year : "numeric" ,
214+ } ) }
215+ </ p >
216+ </ div >
217+ < div className = "grid grid-cols-2 md:grid-cols-3 gap-4 mb-2" >
218+ < div >
219+ < p className = "text-sm font-semibold text-gray-700" > Overall Rating</ p >
220+ { rev . overallRating > 0 ? (
221+ < RatingComponent
222+ className = "flex space-x-1 text-sm"
223+ value = { rev . overallRating }
224+ readOnly = { true }
225+ />
226+ ) : (
227+ < p className = "text-sm text-gray-600" > N/A</ p >
228+ ) }
229+ </ div >
230+ < div >
231+ < p className = "text-sm font-semibold text-gray-700" > Difficulty Rating</ p >
232+ { rev . difficultyRating > 0 ? (
233+ < RatingComponent
234+ className = "flex space-x-1 text-sm"
235+ value = { rev . difficultyRating }
236+ readOnly = { true }
237+ />
238+ ) : (
239+ < p className = "text-sm text-gray-600" > N/A</ p >
240+ ) }
241+ </ div >
242+ < div >
243+ < p className = "text-sm font-semibold text-gray-700" > Professor Rating</ p >
244+ { rev . professorRating > 0 ? (
245+ < RatingComponent
246+ className = "flex space-x-1 text-sm"
247+ value = { rev . professorRating }
248+ readOnly = { true }
249+ />
250+ ) : (
251+ < p className = "text-sm text-gray-600" > N/A</ p >
252+ ) }
253+ </ div >
254+ < div >
255+ < p className = "text-sm font-semibold text-gray-700" > Professor</ p >
256+ < p className = "text-sm text-gray-600" > { rev . professorName || "N/A" } </ p >
257+ </ div >
258+ < div >
259+ < p className = "text-sm font-semibold text-gray-700" > Grade</ p >
260+ < p className = "text-sm text-gray-600" > { rev . grade || "N/A" } </ p >
261+ </ div >
262+ < div >
263+ < p className = "text-sm font-semibold text-gray-700" > Recommended</ p >
264+ < p className = "text-sm text-gray-600" >
265+ { rev . recommend === true ? "Yes" : rev . recommend === false ? "No" : "N/A" }
266+ </ p >
267+ </ div >
268+ </ div >
269+ < div >
270+ < p className = "text-sm font-semibold text-gray-700" > Review</ p >
271+ < div
272+ className = { `text-sm text-gray-600 transition-all duration-300 ${
273+ isExpanded || ! isLongReview ? "" : "max-h-10 overflow-hidden"
274+ } `}
275+ >
276+ { isExpanded || ! isLongReview
277+ ? rev . text
278+ : `${ rev . text . slice ( 0 , maxLength ) } ...` }
279+ </ div >
280+ { isLongReview && (
281+ < button
282+ onClick = { ( ) => toggleExpanded ( i ) }
283+ className = "mt-1 text-blue-600 hover:text-blue-800 text-sm font-semibold focus:outline-none"
284+ >
285+ { isExpanded ? "Read Less" : "Read More" }
286+ </ button >
287+ ) }
288+ </ div >
253289 </ div >
254- </ div >
255- < div >
256- < p className = "text-sm font-semibold text-gray-700" > Review</ p >
257- < p className = "text-sm text-gray-600" > { rev . text } </ p >
258- </ div >
259- </ div >
260- ) ) }
261- { props . reviews . length === 0 && < p className = "text-gray-600" > No reviews yet.</ p > }
290+ ) ;
291+ } ) }
292+ { props . reviews . length === 0 && < p className = "text-sm text-gray-600" > No reviews yet.</ p > }
262293 </ div >
263294 </ div >
264295 </ div >
0 commit comments