@@ -26,8 +26,22 @@ export default function ProjectRiskProfileOverview() {
2626 const [ showDateDropdown , setShowDateDropdown ] = useState ( false ) ;
2727 const darkMode = useSelector ( state => state . theme . darkMode ) ;
2828
29- const allSpanRef = useRef ( null ) ;
30- const dateSpanRef = useRef ( null ) ;
29+ const projectWrapperRef = useRef ( null ) ;
30+ const dateWrapperRef = useRef ( null ) ;
31+
32+ useEffect ( ( ) => {
33+ const handleClickOutside = event => {
34+ if ( projectWrapperRef . current && ! projectWrapperRef . current . contains ( event . target ) ) {
35+ setShowProjectDropdown ( false ) ;
36+ }
37+ if ( dateWrapperRef . current && ! dateWrapperRef . current . contains ( event . target ) ) {
38+ setShowDateDropdown ( false ) ;
39+ }
40+ } ;
41+
42+ document . addEventListener ( 'mousedown' , handleClickOutside ) ;
43+ return ( ) => document . removeEventListener ( 'mousedown' , handleClickOutside ) ;
44+ } , [ ] ) ;
3145
3246 useEffect ( ( ) => {
3347 async function fetchData ( ) {
@@ -72,8 +86,90 @@ export default function ProjectRiskProfileOverview() {
7286 return `${ selectedDates . length } selected` ;
7387 } ;
7488
75- if ( loading ) return < div className = { `${ styles . loading } ` } > Loading project risk profiles...</ div > ;
76- if ( error ) return < div className = { `${ styles . error } ` } > { error } </ div > ;
89+ const chartTheme = {
90+ grid : darkMode ? '#3f4652' : '#e8e8e8' ,
91+ axisText : darkMode ? '#d7dbe2' : '#666' ,
92+ axisLine : darkMode ? '#6b7280' : '#d5d5d5' ,
93+ tooltipBg : darkMode ? '#1f2937' : '#fff' ,
94+ tooltipBorder : darkMode ? '#4b5563' : '#e0e0e0' ,
95+ tooltipText : darkMode ? '#f3f4f6' : '#333' ,
96+ hover : darkMode ? 'rgba(66, 133, 244, 0.16)' : 'rgba(66, 133, 244, 0.08)' ,
97+ } ;
98+
99+ const customSelectStyles = {
100+ control : base => ( {
101+ ...base ,
102+ fontSize : 12 ,
103+ minHeight : 34 ,
104+ backgroundColor : darkMode ? '#2c2c2c' : '#fff' ,
105+ borderColor : darkMode ? '#555' : '#d5d5d5' ,
106+ boxShadow : 'none' ,
107+ } ) ,
108+ valueContainer : base => ( {
109+ ...base ,
110+ padding : '2px 6px' ,
111+ } ) ,
112+ multiValue : base => ( {
113+ ...base ,
114+ background : darkMode ? '#444' : '#e8f0fe' ,
115+ fontSize : 11 ,
116+ } ) ,
117+ multiValueLabel : base => ( {
118+ ...base ,
119+ color : darkMode ? '#eee' : '#333' ,
120+ } ) ,
121+ multiValueRemove : base => ( {
122+ ...base ,
123+ color : darkMode ? '#eee' : '#333' ,
124+ ':hover' : {
125+ backgroundColor : darkMode ? '#555' : '#dbe7ff' ,
126+ color : darkMode ? '#fff' : '#111' ,
127+ } ,
128+ } ) ,
129+ input : base => ( {
130+ ...base ,
131+ color : darkMode ? '#eee' : '#333' ,
132+ } ) ,
133+ placeholder : base => ( {
134+ ...base ,
135+ color : darkMode ? '#c7c7c7' : '#666' ,
136+ } ) ,
137+ menu : base => ( {
138+ ...base ,
139+ zIndex : 9999 ,
140+ backgroundColor : darkMode ? '#2c2c2c' : '#fff' ,
141+ border : darkMode ? '1px solid #555' : '1px solid #e2e2e2' ,
142+ boxShadow : darkMode ? '0 4px 16px rgba(0, 0, 0, 0.45)' : '0 4px 16px rgba(0,0,0,0.12)' ,
143+ } ) ,
144+ option : ( base , state ) => ( {
145+ ...base ,
146+ color : darkMode ? '#eee' : '#333' ,
147+ backgroundColor : state . isSelected
148+ ? darkMode
149+ ? '#4a4a4a'
150+ : '#dbe7ff'
151+ : state . isFocused
152+ ? darkMode
153+ ? '#3a3a3a'
154+ : '#f5f5f5'
155+ : darkMode
156+ ? '#2c2c2c'
157+ : '#fff' ,
158+ } ) ,
159+ } ;
160+
161+ if ( loading )
162+ return (
163+ < div className = { `${ styles . statusCard } ${ darkMode ? styles . darkMode : '' } ` } >
164+ < div className = { `${ styles . loading } ` } > Loading project risk profiles...</ div >
165+ </ div >
166+ ) ;
167+ if ( error )
168+ return (
169+ < div className = { `${ styles . statusCard } ${ darkMode ? styles . darkMode : '' } ` } >
170+ < div className = { `${ styles . error } ` } > { error } </ div >
171+ </ div >
172+ ) ;
77173
78174 return (
79175 < div className = { `${ styles . wrapper } ${ darkMode ? styles . darkMode : '' } ` } >
@@ -83,10 +179,9 @@ export default function ProjectRiskProfileOverview() {
83179
84180 < div className = { `${ styles . filterRow } ` } >
85181 { /* Project Dropdown */ }
86- < div className = { `${ styles . dropdownWrapper } ` } >
182+ < div ref = { projectWrapperRef } className = { `${ styles . dropdownWrapper } ` } >
87183 < span className = { `${ styles . dropdownLabel } ` } > Project</ span >
88184 < button
89- ref = { allSpanRef }
90185 type = "button"
91186 className = { `${ styles . dropdownButton } ` }
92187 onClick = { ( ) => setShowProjectDropdown ( prev => ! prev ) }
@@ -105,16 +200,17 @@ export default function ProjectRiskProfileOverview() {
105200 closeMenuOnSelect = { false }
106201 hideSelectedOptions = { false }
107202 components = { { IndicatorSeparator : ( ) => null , ClearIndicator : ( ) => null } }
203+ styles = { customSelectStyles }
204+ placeholder = "Select projects"
108205 />
109206 </ div >
110207 ) }
111208 </ div >
112209
113210 { /* Date Dropdown */ }
114- < div className = { `${ styles . dropdownWrapper } ` } >
211+ < div ref = { dateWrapperRef } className = { `${ styles . dropdownWrapper } ` } >
115212 < span className = { `${ styles . dropdownLabel } ` } > Dates</ span >
116213 < button
117- ref = { dateSpanRef }
118214 type = "button"
119215 className = { `${ styles . dropdownButton } ` }
120216 onClick = { ( ) => setShowDateDropdown ( prev => ! prev ) }
@@ -133,6 +229,8 @@ export default function ProjectRiskProfileOverview() {
133229 closeMenuOnSelect = { false }
134230 hideSelectedOptions = { false }
135231 components = { { IndicatorSeparator : ( ) => null , ClearIndicator : ( ) => null } }
232+ styles = { customSelectStyles }
233+ placeholder = "Select dates"
136234 />
137235 </ div >
138236 ) }
@@ -173,7 +271,7 @@ export default function ProjectRiskProfileOverview() {
173271 >
174272 < CartesianGrid
175273 strokeDasharray = "5 5"
176- stroke = { darkMode ? '#3a3a3a' : '#e8e8e8' }
274+ stroke = { chartTheme . grid }
177275 horizontal = { true }
178276 vertical = { false }
179277 />
@@ -182,27 +280,29 @@ export default function ProjectRiskProfileOverview() {
182280 angle = { - 45 }
183281 textAnchor = "end"
184282 height = { 110 }
185- tick = { { fontSize : 13 , fill : darkMode ? '#888' : '#666' , fontWeight : 500 } }
186- axisLine = { { stroke : darkMode ? '#555' : '#d5d5d5' , strokeWidth : 1.5 } }
187- tickLine = { { stroke : darkMode ? '#555' : '#d5d5d5' } }
283+ tick = { { fontSize : 13 , fill : chartTheme . axisText , fontWeight : 500 } }
284+ axisLine = { { stroke : chartTheme . axisLine , strokeWidth : 1.5 } }
285+ tickLine = { { stroke : chartTheme . axisLine } }
188286 />
189287 < YAxis
190- tick = { { fontSize : 12 , fill : darkMode ? '#888' : '#666' , fontWeight : 500 } }
191- axisLine = { { stroke : darkMode ? '#555' : '#d5d5d5' , strokeWidth : 1.5 } }
192- tickLine = { { stroke : darkMode ? '#555' : '#d5d5d5' } }
288+ tick = { { fontSize : 12 , fill : chartTheme . axisText , fontWeight : 500 } }
289+ axisLine = { { stroke : chartTheme . axisLine , strokeWidth : 1.5 } }
290+ tickLine = { { stroke : chartTheme . axisLine } }
193291 />
194292 < Tooltip
195293 contentStyle = { {
196- backgroundColor : darkMode ? '#333' : '#fff' ,
197- border : `2px solid ${ darkMode ? '#666' : '#e0e0e0' } ` ,
294+ backgroundColor : chartTheme . tooltipBg ,
295+ border : `2px solid ${ chartTheme . tooltipBorder } ` ,
198296 borderRadius : '8px' ,
199297 padding : '14px' ,
200- color : darkMode ? '#fff' : '#333' ,
298+ color : chartTheme . tooltipText ,
201299 fontSize : '13px' ,
202300 fontWeight : 500 ,
203301 boxShadow : '0 4px 12px rgba(0, 0, 0, 0.15)' ,
204302 } }
205- cursor = { { fill : 'rgba(66, 133, 244, 0.08)' } }
303+ labelStyle = { { color : chartTheme . tooltipText } }
304+ itemStyle = { { color : chartTheme . tooltipText } }
305+ cursor = { { fill : chartTheme . hover } }
206306 />
207307 < Bar
208308 dataKey = "predictedCostOverrun"
@@ -219,6 +319,10 @@ export default function ProjectRiskProfileOverview() {
219319 />
220320 </ BarChart >
221321 </ ResponsiveContainer >
322+
323+ { filteredData . length === 0 && (
324+ < div className = { styles . emptyState } > No risk profile data for selected filters.</ div >
325+ ) }
222326 </ div >
223327 </ div >
224328 </ div >
0 commit comments