@@ -6,6 +6,7 @@ import axios from 'axios';
66import Select from 'react-select' ;
77import DatePicker from 'react-datepicker' ;
88
9+ import { ENDPOINTS } from '../../../utils/URL' ;
910import styles from './LessonsLearntChart.module.css' ;
1011import 'react-datepicker/dist/react-datepicker.css' ;
1112
@@ -15,29 +16,58 @@ const useLessonsData = (selectedProjects, startDate, endDate) => {
1516 const [ allProjects , setAllProjects ] = useState ( [ ] ) ;
1617 const [ lessonsData , setLessonsData ] = useState ( [ ] ) ;
1718 const [ isLoading , setIsLoading ] = useState ( true ) ;
19+ const [ error , setError ] = useState ( null ) ;
1820
1921 useEffect ( ( ) => {
2022 const fetchProjects = async ( ) => {
2123 try {
22- const response = await axios . get ( '/api/projects' ) ;
23- setAllProjects ( response . data ) ;
24- } catch ( error ) { }
24+ const response = await axios . get ( ENDPOINTS . BM_PROJECTS ) ;
25+ const projects = Array . isArray ( response . data ) ? response . data : [ ] ;
26+ setAllProjects ( projects ) ;
27+ } catch ( err ) {
28+ console . error ( 'Error fetching projects:' , err ) ;
29+ setAllProjects ( [ ] ) ;
30+ }
2531 } ;
2632 fetchProjects ( ) ;
2733 } , [ ] ) ;
2834
2935 useEffect ( ( ) => {
3036 const fetchLessons = async ( ) => {
3137 setIsLoading ( true ) ;
38+ setError ( null ) ;
3239 try {
33- const params = {
34- projects : selectedProjects . map ( p => p . value ) . join ( ',' ) ,
35- from : startDate ?. toISOString ( ) ,
36- to : endDate ?. toISOString ( ) ,
37- } ;
38- const response = await axios . get ( '/api/lessons-learnt' , { params } ) ;
39- setLessonsData ( response . data ) ;
40- } catch ( error ) {
40+ const params = { } ;
41+
42+ if ( selectedProjects && selectedProjects . length > 0 ) {
43+ params . projectId = selectedProjects . length === 1 ? selectedProjects [ 0 ] . value : 'ALL' ;
44+ }
45+
46+ if ( startDate ) {
47+ params . startDate = startDate . toISOString ( ) ;
48+ }
49+ if ( endDate ) {
50+ params . endDate = endDate . toISOString ( ) ;
51+ }
52+
53+ const response = await axios . get ( `${ ENDPOINTS . BM_LESSONS } -learnt` , { params } ) ;
54+
55+ const responseData = response . data ?. data || response . data || [ ] ;
56+ const lessonsArray = Array . isArray ( responseData ) ? responseData : [ ] ;
57+
58+ const transformedData = lessonsArray . map ( item => ( {
59+ projectName : item . project || 'Unknown Project' ,
60+ projectId : item . projectId ,
61+ lessonsCount : item . lessonsCount || 0 ,
62+ percentage :
63+ parseFloat ( ( item . changePercentage || '0%' ) . replace ( '%' , '' ) . replace ( '+' , '' ) ) || 0 ,
64+ changePercentage : item . changePercentage || '0%' ,
65+ } ) ) ;
66+
67+ setLessonsData ( transformedData ) ;
68+ } catch ( err ) {
69+ console . error ( 'Error fetching lessons learnt:' , err ) ;
70+ setError ( err . message || 'Failed to fetch lessons data' ) ;
4171 setLessonsData ( [ ] ) ;
4272 } finally {
4373 setIsLoading ( false ) ;
@@ -46,7 +76,7 @@ const useLessonsData = (selectedProjects, startDate, endDate) => {
4676 fetchLessons ( ) ;
4777 } , [ selectedProjects , startDate , endDate ] ) ;
4878
49- return { allProjects, lessonsData, isLoading } ;
79+ return { allProjects, lessonsData, isLoading, error } ;
5080} ;
5181
5282function ChartTitle ( { title } ) {
@@ -58,7 +88,7 @@ const LessonsLearntChart = () => {
5888 const [ startDate , setStartDate ] = useState ( null ) ;
5989 const [ endDate , setEndDate ] = useState ( null ) ;
6090
61- const { allProjects, lessonsData, isLoading } = useLessonsData (
91+ const { allProjects, lessonsData, isLoading, error } = useLessonsData (
6292 selectedProjects ,
6393 startDate ,
6494 endDate ,
@@ -68,23 +98,58 @@ const LessonsLearntChart = () => {
6898 setSelectedProjects ( selected || [ ] ) ;
6999 } ;
70100
101+ const projectOptions = Array . isArray ( allProjects )
102+ ? allProjects
103+ . filter ( proj => proj && ( proj . _id || proj . id ) )
104+ . map ( proj => ( {
105+ value : proj . _id || proj . id ,
106+ label : proj . name || 'Unnamed Project' ,
107+ } ) )
108+ : [ ] ;
109+
110+ const safeLabels = Array . isArray ( lessonsData )
111+ ? lessonsData . map ( d => d ?. projectName || 'Unknown' )
112+ : [ ] ;
113+
114+ const safeData = Array . isArray ( lessonsData ) ? lessonsData . map ( d => d ?. lessonsCount || 0 ) : [ ] ;
115+
71116 const chartData = {
72- labels : lessonsData . map ( d => d . projectName ) ,
117+ labels : safeLabels ,
73118 datasets : [
74119 {
75- label : 'Lessons Learnt ' ,
76- data : lessonsData . map ( d => d . percentage ) ,
120+ label : 'Lessons Count ' ,
121+ data : safeData ,
77122 backgroundColor : '#10b981' ,
78123 } ,
79124 ] ,
80125 } ;
81126
82127 const chartOptions = {
83128 responsive : true ,
129+ maintainAspectRatio : false ,
84130 plugins : {
85131 title : {
86132 display : false ,
87133 } ,
134+ tooltip : {
135+ callbacks : {
136+ afterLabel : context => {
137+ const dataIndex = context . dataIndex ;
138+ if ( Array . isArray ( lessonsData ) && lessonsData [ dataIndex ] ) {
139+ return `Change: ${ lessonsData [ dataIndex ] . changePercentage || '0%' } ` ;
140+ }
141+ return '' ;
142+ } ,
143+ } ,
144+ } ,
145+ } ,
146+ scales : {
147+ y : {
148+ beginAtZero : true ,
149+ ticks : {
150+ stepSize : 1 ,
151+ } ,
152+ } ,
88153 } ,
89154 } ;
90155
@@ -97,45 +162,55 @@ const LessonsLearntChart = () => {
97162 < label > Select Projects</ label >
98163 < Select
99164 isMulti
100- options = { allProjects . map ( proj => ( {
101- value : proj . id ,
102- label : proj . name ,
103- } ) ) }
165+ options = { projectOptions }
104166 value = { selectedProjects }
105167 onChange = { handleProjectChange }
168+ placeholder = "Select projects..."
169+ isClearable
106170 />
107171 </ div >
108172 < div className = { styles . filter } >
109173 < label > From</ label >
110- < DatePicker selected = { startDate } onChange = { date => setStartDate ( date ) } />
174+ < DatePicker
175+ selected = { startDate }
176+ onChange = { date => setStartDate ( date ) }
177+ placeholderText = "Start date"
178+ isClearable
179+ />
111180 </ div >
112181 < div className = { styles . filter } >
113182 < label > To</ label >
114- < DatePicker selected = { endDate } onChange = { date => setEndDate ( date ) } />
183+ < DatePicker
184+ selected = { endDate }
185+ onChange = { date => setEndDate ( date ) }
186+ placeholderText = "End date"
187+ isClearable
188+ />
115189 </ div >
116190 </ div >
117191
118192 < div className = { styles . chartWrapper } >
119193 { isLoading ? (
120194 < p > Loading...</ p >
121- ) : lessonsData . length === 0 ? (
195+ ) : error ? (
196+ < p > Error loading data: { error } </ p >
197+ ) : ! Array . isArray ( lessonsData ) || lessonsData . length === 0 ? (
122198 < p > No lessons data available for the selected criteria</ p >
123199 ) : (
124200 < >
125- < Bar data = { chartData } options = { chartOptions } />
201+ < div style = { { height : '400px' , width : '100%' } } >
202+ < Bar data = { chartData } options = { chartOptions } />
203+ </ div >
126204 < div className = { styles . percentageLabels } >
127205 { lessonsData . map ( ( d , idx ) => (
128206 < span
129- key = { idx }
207+ key = { d ?. projectId || idx }
130208 className = { styles . percentageLabel }
131209 style = { {
132- left :
133- lessonsData . length > 0
134- ? `${ ( idx + 0.5 ) * ( 100 / lessonsData . length ) } %`
135- : '0%' ,
210+ left : `${ ( idx + 0.5 ) * ( 100 / lessonsData . length ) } %` ,
136211 } }
137212 >
138- { d . percentage } %
213+ { d ?. changePercentage || '0%' }
139214 </ span >
140215 ) ) }
141216 </ div >
0 commit comments