1
1
import React , { useState , useEffect } from 'react' ;
2
- import bgHero from '../assets/bgHero.png' ;
3
- import { IoCaretForwardOutline } from "react-icons/io5" ;
4
- import { IoCaretBackOutline } from "react-icons/io5" ;
5
2
import axios from 'axios' ;
6
-
7
- interface Testimonial {
8
- quote : string ;
9
- author : string ;
10
- image : string ;
11
- }
12
-
13
- interface Feedback {
14
- id : string ;
15
- rating : number ;
16
- comment : string ;
17
- userId : string ;
18
- createdAt : string ;
19
- user : {
20
- id : string ;
21
- username : string ;
22
- avatar : string ;
23
- } ;
24
- }
3
+ import { IoCaretForwardOutline , IoCaretBackOutline } from "react-icons/io5" ;
4
+ import { MdOutlineStarOutline , MdOutlineStar } from "react-icons/md" ;
5
+ import bgHero from '../assets/bgHero.png' ;
6
+ import { IUserFeedback } from '../types' ;
7
+ import { ImQuotesLeft , ImQuotesRight } from "react-icons/im" ;
25
8
26
9
const TestimonialSlider : React . FC = ( ) => {
27
10
const [ currentIndex , setCurrentIndex ] = useState < number > ( 0 ) ;
28
11
const [ slidesToShow , setSlidesToShow ] = useState < number > ( 1 ) ;
29
12
const [ isHovered , setIsHovered ] = useState < boolean > ( false ) ;
30
- const [ testimonials , setTestimonials ] = useState < Testimonial [ ] > ( [ ] ) ;
13
+ const [ testimonials , setTestimonials ] = useState < IUserFeedback [ ] > ( [ ] ) ;
31
14
32
15
useEffect ( ( ) => {
33
16
const updateSlidesToShow = ( ) => {
@@ -45,6 +28,12 @@ const TestimonialSlider: React.FC = () => {
45
28
return ( ) => window . removeEventListener ( 'resize' , updateSlidesToShow ) ;
46
29
} , [ ] ) ;
47
30
31
+ useEffect ( ( ) => {
32
+ axios . get ( '/api/v1/user/getfeedback' )
33
+ . then ( response => setTestimonials ( response . data ) )
34
+ . catch ( error => console . error ( 'Error fetching testimonials:' , error ) ) ;
35
+ } , [ ] ) ;
36
+
48
37
useEffect ( ( ) => {
49
38
let intervalId : ReturnType < typeof setInterval > ;
50
39
@@ -57,25 +46,6 @@ const TestimonialSlider: React.FC = () => {
57
46
return ( ) => clearInterval ( intervalId ) ;
58
47
} , [ slidesToShow , isHovered , testimonials . length ] ) ;
59
48
60
- useEffect ( ( ) => {
61
- const fetchFeedback = async ( ) => {
62
- try {
63
- const response = await axios . get ( '/api/v1/user/getfeedback' ) ;
64
- const data : Feedback [ ] = response . data ;
65
- const formattedTestimonials = data . map ( ( feedback ) => ( {
66
- quote : feedback . comment ,
67
- author : feedback . user . username ,
68
- image : feedback . user . avatar ,
69
- } ) ) ;
70
- setTestimonials ( formattedTestimonials ) ;
71
- } catch ( error ) {
72
- console . error ( 'Error fetching feedback:' , error ) ;
73
- }
74
- } ;
75
-
76
- fetchFeedback ( ) ;
77
- } , [ ] ) ;
78
-
79
49
const goToNext = ( ) => {
80
50
setCurrentIndex ( ( prevIndex ) => ( prevIndex + slidesToShow ) % testimonials . length ) ;
81
51
} ;
@@ -92,6 +62,16 @@ const TestimonialSlider: React.FC = () => {
92
62
setIsHovered ( false ) ;
93
63
} ;
94
64
65
+ const renderStars = ( rating : number ) => {
66
+ return (
67
+ < div className = "flex" >
68
+ { [ ...Array ( 5 ) ] . map ( ( _ , index ) => (
69
+ index < rating ? < MdOutlineStar key = { index } size = { 20 } className = "text-yellow-500" /> : < MdOutlineStarOutline key = { index } size = { 20 } className = "text-gray-300" />
70
+ ) ) }
71
+ </ div >
72
+ ) ;
73
+ } ;
74
+
95
75
return (
96
76
< div
97
77
className = "testimonial-slider-container w-full flex flex-col text-center py-10 text-[#000435] bg-white dark:text-white dark:bg-[#000435]"
@@ -107,19 +87,29 @@ const TestimonialSlider: React.FC = () => {
107
87
>
108
88
< IoCaretBackOutline />
109
89
</ button >
110
- < div className = "flex overflow-hidden max-w-full" >
111
- { testimonials . slice ( currentIndex , currentIndex + slidesToShow ) . map ( ( testimonial , index ) => (
112
- < div key = { index } className = "testimonial border border-blue-400 dark:border-gray-00 px-2 py-4 md:py-24 rounded-md mx-2 p-6 md:p-10 rounded-lg shadow-lg bg-white dark:bg-[#000435] text-[#000435] dark:text-white flex flex-col items-center justify-center min-w-[260px] md:min-w-[350px] lg:min-w-[400px]" >
113
- < img
114
- src = { testimonial . image || `https://ui-avatars.com/api/?name=${ testimonial . author } &background=0ea5e9&color=fff&rounded=true&bold=true` }
115
- alt = { `${ testimonial . author } 's picture` }
116
- className = "w-24 h-24 md:w-32 md:h-32 rounded-full mb-6 border-4 p-1 border-[#a238ff] dark:border-white"
117
- />
118
- < p className = "text-lg md:text-2xl italic mb-4 text-center" > "{ testimonial . quote } "</ p >
119
- < h4 className = "text-base md:text-xl font-semibold text-center" > - { testimonial . author } </ h4 >
90
+ < div className = "max-w-screen-xl px-4 py-8 mx-auto text-center lg:py-16 lg:px-6" >
91
+ { testimonials . slice ( currentIndex , currentIndex + slidesToShow ) . map ( ( testimonial , index ) => (
92
+ < figure key = { index } className = "max-w-screen-md mx-auto" >
93
+ < div className = 'flex justify-start mb-5' >
94
+ < ImQuotesLeft size = { 30 } />
120
95
</ div >
121
- ) ) }
122
- </ div >
96
+ < blockquote >
97
+ < p className = "text-2xl font-medium text-gray-900 dark:text-white" > { testimonial . comment } </ p >
98
+ </ blockquote >
99
+ < div className = 'flex justify-end mt-5' >
100
+ < ImQuotesRight size = { 30 } />
101
+ </ div >
102
+ < figcaption className = "flex items-center justify-center mt-6 space-x-3" >
103
+ < img className = "w-12 h-12 rounded-full" src = { testimonial . user . avatar || `https://ui-avatars.com/api/?name=${ testimonial . user . username } &background=0ea5e9&color=fff&rounded=true&bold=true` } alt = "profile picture" />
104
+ < div className = "flex flex-col items-center divide-y-2 divide-gray-500 dark:divide-gray-700" >
105
+ < div className = "pb-1 text-sm font-light text-gray-500 dark:text-gray-400" > { renderStars ( testimonial . rating ) } </ div >
106
+ < div className = "pt-1 font-medium text-gray-900 dark:text-white" > { testimonial . user . username } </ div >
107
+ </ div >
108
+ </ figcaption >
109
+ </ figure >
110
+ ) ) }
111
+ </ div >
112
+
123
113
< button
124
114
className = "next-arrow text-4xl cursor-pointer transform hover:scale-125 transition-transform duration-300"
125
115
onClick = { goToNext }
@@ -140,4 +130,4 @@ const TestimonialSlider: React.FC = () => {
140
130
) ;
141
131
} ;
142
132
143
- export default TestimonialSlider ;
133
+ export default TestimonialSlider ;
0 commit comments