22
33'use client' ;
44
5- import { useState , useEffect } from 'react' ;
6- import { useSelector } from 'react-redux' ;
7- import axios from 'axios' ;
5+ import { useState , useMemo } from 'react' ;
86import { PieChart , Pie , Cell , Tooltip , Legend , ResponsiveContainer } from 'recharts' ;
97import { ENDPOINTS } from '~/utils/URL' ;
10- import { events as mockEvents } from './mockData' ;
8+ import { events } from './mockData' ;
119import styles from './AttendanceNoShowCharts.module.css' ;
10+ import { useSelector } from 'react-redux' ;
1211
13- const attendanceColors = [ '#0088FE' , '#FF8042' ] ;
12+ const attendanceColors = [ '#0088FE' , '#FF8042' , '#FFBB28' ] ;
1413const noShowColors = [ '#00C49F' , '#FF0000' ] ;
1514
1615// Status color mapping
@@ -133,18 +132,21 @@ const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, per
133132 < text
134133 x = { x }
135134 y = { y }
136- fill = "black "
137- textAnchor = { x > cx ? 'start' : 'end' }
135+ fill = "white "
136+ textAnchor = "middle"
138137 dominantBaseline = "central"
139138 fontSize = "12"
139+ fontWeight = "bold"
140140 >
141- { `${ ( percent * 100 ) . toFixed ( 1 ) } %` }
141+ { percent > 0 ? `${ ( percent * 100 ) . toFixed ( 0 ) } %` : '' }
142142 </ text >
143143 ) ;
144144} ;
145145
146146const CustomTooltip = ( { active, payload } ) => {
147+ console . log ( active , payload ) ;
147148 if ( active && payload && payload . length ) {
149+ console . log ( 'Tooltip payload:' , payload ) ;
148150 return (
149151 < div className = { styles . chartTooltip } >
150152 < p className = { styles . chartTooltipItem } > { `${ payload [ 0 ] . name } : ${ payload [ 0 ] . value } ` } </ p >
@@ -155,76 +157,14 @@ const CustomTooltip = ({ active, payload }) => {
155157} ;
156158
157159function AttendanceNoShowCharts ( ) {
158- const [ events , setEvents ] = useState ( mockEvents ) ;
159- const [ selectedEvent , setSelectedEvent ] = useState ( null ) ;
160- const [ loading , setLoading ] = useState ( true ) ;
160+ const [ selectedId , setSelectedId ] = useState ( events [ 0 ] . id ) ;
161+ const [ loading , setLoading ] = useState ( false ) ;
161162 const [ error , setError ] = useState ( null ) ;
162163 const darkMode = useSelector ( state => state . theme . darkMode ) ;
163-
164- // Fetch events data from backend
165- useEffect ( ( ) => {
166- const fetchEvents = async ( ) => {
167- setLoading ( true ) ;
168- setError ( null ) ;
169- try {
170- const response = await axios . get ( ENDPOINTS . EVENT_ATTENDANCE_STATS ) ;
171-
172- // Check if response has data in expected format
173- if ( response . data && Array . isArray ( response . data ) ) {
174- // Transform API data to match mock data format if needed
175- const transformedEvents = response . data . map ( transformEvent ) ;
176-
177- setEvents ( transformedEvents ) ;
178- if ( transformedEvents . length > 0 ) {
179- setSelectedEvent ( transformedEvents [ 0 ] ) ;
180- }
181- } else if ( response . data && response . data . events && Array . isArray ( response . data . events ) ) {
182- // Handle nested response structure
183- const transformedEvents = response . data . events . map ( transformEvent ) ;
184-
185- setEvents ( transformedEvents ) ;
186- if ( transformedEvents . length > 0 ) {
187- setSelectedEvent ( transformedEvents [ 0 ] ) ;
188- }
189- } else {
190- // If data format doesn't match, fall back to mock data
191- throw new Error ( 'Unexpected data format from API' ) ;
192- }
193- } catch ( err ) {
194- // Fall back to mock data if API is unavailable or returns error
195- // eslint-disable-next-line no-console
196- console . warn ( 'Failed to fetch events from API, using mock data:' , err . message ) ;
197- // Calculate status for mock events
198- const mockEventsWithStatus = mockEvents . map ( event => ( {
199- ...event ,
200- status : calculateEventStatus ( event ) || event . status ,
201- } ) ) ;
202- setEvents ( mockEventsWithStatus ) ;
203- if ( mockEventsWithStatus . length > 0 ) {
204- setSelectedEvent ( mockEventsWithStatus [ 0 ] ) ;
205- }
206- setError ( 'Using mock data - API endpoint not available' ) ;
207- } finally {
208- setLoading ( false ) ;
209- }
210- } ;
211-
212- fetchEvents ( ) ;
213- } , [ ] ) ;
214-
215- // Update selectedEvent when events change
216- useEffect ( ( ) => {
217- if ( events . length > 0 && ! selectedEvent ) {
218- setSelectedEvent ( events [ 0 ] ) ;
219- }
220- } , [ events , selectedEvent ] ) ;
164+ const selectedEvent = useMemo ( ( ) => events . find ( e => e . id === selectedId ) , [ selectedId ] ) ;
221165
222166 const handleEventChange = e => {
223- const selectedEventId = e . target . value ;
224- const newSelectedEvent = events . find ( event => event . id === selectedEventId ) ;
225- if ( newSelectedEvent ) {
226- setSelectedEvent ( newSelectedEvent ) ;
227- }
167+ setSelectedId ( e . target . value ) ;
228168 } ;
229169
230170 const calculatePercentage = ( value , total ) => {
@@ -478,14 +418,19 @@ function AttendanceNoShowCharts() {
478418 ) }
479419
480420 { /* No-Show Chart */ }
481- < div className = { styles . chartWrapper } >
482- < h3 className = { styles . chartSectionTitle } >
483- Registration vs Attendance
484- { currentStatus === 'In Progress' && (
485- < span className = { styles . chartLiveBadge } > (Live)</ span >
486- ) }
421+ < div style = { { width : '100%' } } >
422+ < h3
423+ style = { {
424+ fontSize : '18px' ,
425+ fontWeight : '500' ,
426+ color : '#111827' ,
427+ marginBottom : '12px' ,
428+ textAlign : 'center' ,
429+ } }
430+ >
431+ No-Show Breakdown
487432 </ h3 >
488- < div className = { styles . chartContainer } >
433+ < div style = { { height : '300px' , width : '100%' } } >
489434 < ResponsiveContainer width = "100%" height = "100%" >
490435 < PieChart >
491436 < Pie
0 commit comments