1- import React , { useEffect , useState } from 'react' ;
2- import {
3- BarChart , Bar , XAxis , YAxis , LabelList , ResponsiveContainer
4- } from 'recharts' ;
1+ import { BarChart , Bar , XAxis , YAxis , LabelList , ResponsiveContainer } from 'recharts' ;
2+ import { useState , useEffect } from 'react' ;
53
6- const categories = [ " Plumbing" , " Electrical" , " Structural" , " Mechanical" ] ;
7- const projects = [ " Project A" , " Project B" , " Project C" ] ;
4+ const categories = [ ' Plumbing' , ' Electrical' , ' Structural' , ' Mechanical' ] ;
5+ const projects = [ ' Project A' , ' Project B' , ' Project C' ] ;
86
97export default function ExpenseBarChart ( ) {
108 const [ projectId , setProjectId ] = useState ( '' ) ;
119 const [ categoryFilter , setCategoryFilter ] = useState ( 'ALL' ) ;
1210 const [ startDate , setStartDate ] = useState ( '' ) ;
1311 const [ endDate , setEndDate ] = useState ( '' ) ;
1412 const [ data , setData ] = useState ( [ ] ) ;
13+ const [ errorMessage , setErrorMessage ] = useState ( '' ) ;
1514
1615 useEffect ( ( ) => {
1716 async function fetchData ( ) {
1817 try {
1918 const rawData = [
20- { projectId : 'Project A' , category : 'Plumbing' , plannedCost : 1000 , actualCost : 1200 , date : '2025-04-01' } ,
21- { projectId : 'Project A' , category : 'Electrical' , plannedCost : 1500 , actualCost : 1300 , date : '2025-04-01' } ,
22- { projectId : 'Project B' , category : 'Plumbing' , plannedCost : 1100 , actualCost : 1050 , date : '2025-04-02' } ,
23- { projectId : 'Project B' , category : 'Structural' , plannedCost : 2200 , actualCost : 2150 , date : '2025-04-02' } ,
24- { projectId : 'Project C' , category : 'Mechanical' , plannedCost : 1300 , actualCost : 1350 , date : '2025-04-03' } ,
25- { projectId : 'Project C' , category : 'Electrical' , plannedCost : 1400 , actualCost : 1600 , date : '2025-04-03' } ,
19+ {
20+ projectId : 'Project A' ,
21+ category : 'Plumbing' ,
22+ plannedCost : 1000 ,
23+ actualCost : 1200 ,
24+ date : '2025-04-01' ,
25+ } ,
26+ {
27+ projectId : 'Project A' ,
28+ category : 'Electrical' ,
29+ plannedCost : 1500 ,
30+ actualCost : 1300 ,
31+ date : '2025-04-01' ,
32+ } ,
33+ {
34+ projectId : 'Project B' ,
35+ category : 'Plumbing' ,
36+ plannedCost : 1100 ,
37+ actualCost : 1050 ,
38+ date : '2025-04-02' ,
39+ } ,
40+ {
41+ projectId : 'Project B' ,
42+ category : 'Structural' ,
43+ plannedCost : 2200 ,
44+ actualCost : 2150 ,
45+ date : '2025-04-02' ,
46+ } ,
47+ {
48+ projectId : 'Project C' ,
49+ category : 'Mechanical' ,
50+ plannedCost : 1300 ,
51+ actualCost : 1350 ,
52+ date : '2025-04-03' ,
53+ } ,
54+ {
55+ projectId : 'Project C' ,
56+ category : 'Electrical' ,
57+ plannedCost : 1400 ,
58+ actualCost : 1600 ,
59+ date : '2025-04-03' ,
60+ } ,
2661 ] ;
2762
2863 const filtered = rawData . filter ( entry => {
@@ -47,7 +82,7 @@ export default function ExpenseBarChart() {
4782
4883 setData ( Object . values ( aggregated ) ) ;
4984 } catch ( error ) {
50- console . error ( "Error processing mock data:" , error ) ;
85+ setErrorMessage ( 'Something went wrong while loading chart data.' ) ;
5186 }
5287 }
5388
@@ -58,6 +93,11 @@ export default function ExpenseBarChart() {
5893 < div style = { { width : '100%' , padding : '0.5rem' } } >
5994 < div style = { { textAlign : 'center' , marginBottom : '0.75rem' } } >
6095 < h4 style = { { margin : 0 , color : '#555' , fontSize : '1.2rem' } } > Planned vs Actual Cost</ h4 >
96+ { errorMessage && (
97+ < div style = { { color : 'red' , fontSize : '0.9rem' , marginTop : '0.5rem' } } >
98+ { errorMessage }
99+ </ div >
100+ ) }
61101 </ div >
62102
63103 < div
@@ -68,46 +108,95 @@ export default function ExpenseBarChart() {
68108 alignItems : 'center' ,
69109 gap : '1rem' ,
70110 fontSize : '0.75rem' ,
71- marginBottom : '0.5rem'
111+ marginBottom : '0.5rem' ,
72112 } }
73113 >
74- < label style = { { minWidth : '150px' } } > Project:
75- < select value = { projectId } onChange = { ( e ) => setProjectId ( e . target . value ) } style = { { marginLeft : '0.3rem' , width : '100%' } } >
114+ < label style = { { minWidth : '150px' } } >
115+ Project:
116+ < select
117+ value = { projectId }
118+ onChange = { e => setProjectId ( e . target . value ) }
119+ style = { { marginLeft : '0.3rem' , width : '100%' } }
120+ >
76121 < option value = "" > All</ option >
77- { projects . map ( p => < option key = { p } value = { p } > { p } </ option > ) }
122+ { projects . map ( p => (
123+ < option key = { p } value = { p } >
124+ { p }
125+ </ option >
126+ ) ) }
78127 </ select >
79128 </ label >
80- < label style = { { minWidth : '150px' } } > Category:
81- < select value = { categoryFilter } onChange = { ( e ) => setCategoryFilter ( e . target . value ) } style = { { marginLeft : '0.3rem' , width : '100%' } } >
129+ < label style = { { minWidth : '150px' } } >
130+ Category:
131+ < select
132+ value = { categoryFilter }
133+ onChange = { e => setCategoryFilter ( e . target . value ) }
134+ style = { { marginLeft : '0.3rem' , width : '100%' } }
135+ >
82136 < option value = "ALL" > All</ option >
83- { categories . map ( cat => < option key = { cat } value = { cat } > { cat } </ option > ) }
137+ { categories . map ( cat => (
138+ < option key = { cat } value = { cat } >
139+ { cat }
140+ </ option >
141+ ) ) }
84142 </ select >
85143 </ label >
86- < label style = { { minWidth : '150px' } } > Start Date:
87- < input type = "date" value = { startDate } onChange = { ( e ) => setStartDate ( e . target . value ) } style = { { marginLeft : '0.3rem' , width : '100%' } } />
144+ < label style = { { minWidth : '150px' } } >
145+ Start Date:
146+ < input
147+ type = "date"
148+ value = { startDate }
149+ onChange = { e => setStartDate ( e . target . value ) }
150+ style = { { marginLeft : '0.3rem' , width : '100%' } }
151+ />
88152 </ label >
89- < label style = { { minWidth : '150px' } } > End Date:
90- < input type = "date" value = { endDate } onChange = { ( e ) => setEndDate ( e . target . value ) } style = { { marginLeft : '0.3rem' , width : '100%' } } />
153+ < label style = { { minWidth : '150px' } } >
154+ End Date:
155+ < input
156+ type = "date"
157+ value = { endDate }
158+ onChange = { e => setEndDate ( e . target . value ) }
159+ style = { { marginLeft : '0.3rem' , width : '100%' } }
160+ />
91161 </ label >
92162 </ div >
93163
94- < div style = { { display : 'flex' , justifyContent : 'center' , gap : '1rem' , fontSize : '0.75rem' , marginBottom : '0.75rem' , flexWrap : 'wrap' } } >
164+ < div
165+ style = { {
166+ display : 'flex' ,
167+ justifyContent : 'center' ,
168+ gap : '1rem' ,
169+ fontSize : '0.75rem' ,
170+ marginBottom : '0.75rem' ,
171+ flexWrap : 'wrap' ,
172+ } }
173+ >
95174 < span style = { { display : 'flex' , alignItems : 'center' , gap : '0.25rem' } } >
96- < span style = { { width : 10 , height : 10 , backgroundColor : '#4285F4' , display : 'inline-block' } } /> Planned
175+ < span
176+ style = { { width : 10 , height : 10 , backgroundColor : '#4285F4' , display : 'inline-block' } }
177+ /> { ' ' }
178+ Planned
97179 </ span >
98180 < span style = { { display : 'flex' , alignItems : 'center' , gap : '0.25rem' } } >
99- < span style = { { width : 10 , height : 10 , backgroundColor : '#EA4335' , display : 'inline-block' } } /> Actual
181+ < span
182+ style = { { width : 10 , height : 10 , backgroundColor : '#EA4335' , display : 'inline-block' } }
183+ /> { ' ' }
184+ Actual
100185 </ span >
101186 </ div >
102187
103188 < div style = { { width : '100%' , height : '240px' } } >
104189 < ResponsiveContainer width = "100%" height = "100%" >
105- < BarChart
106- data = { data }
107- margin = { { top : 10 , right : 10 , left : 35 , bottom : 35 } }
108- >
109- < XAxis dataKey = "project" tick = { { fontSize : 10 } } interval = { 0 } angle = { - 15 } textAnchor = "end" label = { { value : 'Project Name' , position : 'insideBottom' , dy : 25 , fontSize : 10 } } />
110- < YAxis tick = { { fontSize : 10 } } axisLine = { true } tickLine = { true } />
190+ < BarChart data = { data } margin = { { top : 10 , right : 10 , left : 35 , bottom : 35 } } >
191+ < XAxis
192+ dataKey = "project"
193+ tick = { { fontSize : 10 } }
194+ interval = { 0 }
195+ angle = { - 15 }
196+ textAnchor = "end"
197+ label = { { value : 'Project Name' , position : 'insideBottom' , dy : 25 , fontSize : 10 } }
198+ />
199+ < YAxis tick = { { fontSize : 10 } } axisLine tickLine />
111200 < Bar dataKey = "planned" fill = "#4285F4" name = "Planned" >
112201 < LabelList dataKey = "planned" position = "top" style = { { fontSize : 8 } } />
113202 </ Bar >
0 commit comments