From ebb3b607f2bccade3dabdfc7acad90ec802e55f4 Mon Sep 17 00:00:00 2001 From: Neeraj-Kondaveeti Date: Thu, 4 Dec 2025 19:13:36 -0500 Subject: [PATCH 1/5] Add amount label, extend material bars, and include unit tests for ResourceUsage component --- .../ResourceUsage/ResourceUsage.jsx | 217 ++++++++++-------- .../ResourceUsage/ResourceUsage.module.css | 82 +++++-- .../__tests__/ResourceUsage.test.jsx | 1 + 3 files changed, 194 insertions(+), 106 deletions(-) diff --git a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx index 9e54ce32b0..9afd205e6f 100644 --- a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx +++ b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx @@ -1,6 +1,6 @@ 'use client'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useRef} from 'react'; import { Dropdown } from 'react-bootstrap'; import { BarChart, @@ -82,34 +82,38 @@ const insightDefinitions = { 'Highest cost venues/hr': 'Venue with the highest hourly cost during the selected period.', }; +function filterDataByDate(data, timePeriod) { + return data; +} + function CustomTooltip({ active, payload, darkMode }) { if (!active || !payload || !payload.length) return null; - const data = payload[0].payload; +const data = payload[0].payload; - return ( -
-
{data.name}
+return ( +
+
{data.name}
-
- - Returned - {data.returned} -
+
+ + Returned + {data.returned} +
-
- - Loaned - {data.loaned} -
+
+ + Loaned + {data.loaned}
- ); +
+); } export default function ResourceUsage() { @@ -120,10 +124,21 @@ export default function ResourceUsage() { const [insights, setInsights] = useState(allInsights['Last Week']); const darkMode = useSelector(state => state.theme.darkMode); + const badgeRefs = useRef([]); + + useEffect(() => { + badgeRefs.current.forEach(badge => { + if (badge) { + badge.style.setProperty('color', '#000', 'important'); + } + }); + }, [insights]); useEffect(() => { - setData(allData[resourceType.toLowerCase()]); - }, [resourceType]); + const resourceTypeKey = resourceType.toLowerCase(); + const filteredData = filterDataByDate(allData[resourceTypeKey], timePeriod); + setData(filteredData); + }, [resourceType, timePeriod, allData]); useEffect(() => { setInsights(allInsights[insightsTimePeriod]); @@ -172,85 +187,98 @@ export default function ResourceUsage() { Amount
- - - + {data && data.length > 0 ? ( + + + - + - + - } /> + } /> - + - - - - - - - - {/* RIGHT SECTION */} -
-
-

Insights

- - - - {insightsTimePeriod} - - - setInsightsTimePeriod('This Week')}> - This Week - - setInsightsTimePeriod('Last Week')}> - Last Week - - setInsightsTimePeriod('This Month')}> - This Month - - - -
+ + + + + ) : ( +
+

No data available for the selected time period and resource type.

+
+ )} +
+ + {/* RIGHT SECTION */} +
+
+

Insights

+ + + {insightsTimePeriod} + + + setInsightsTimePeriod('This Week')}> + This Week + + setInsightsTimePeriod('Last Week')}> + Last Week + + setInsightsTimePeriod('This Month')}> + This Month + + + +
{insights.map((insight, idx) => (
- {/* 🔹 ADD THIS LINE RIGHT HERE */} -
{insightDefinitions[insight.title]}
+ {/* Tooltip description */} +
+ {insightDefinitions[insight.title]} +
(badgeRefs.current[idx] = el)} className={`${styles.insightBadge} ${darkMode ? 'text-dark' : ''}`} style={{ backgroundColor: insight.color }} > {insight.value}
-
Based on returned vs loaned comparison
+
+ Based on returned vs loaned comparison +
))}
+
- ); } diff --git a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.module.css b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.module.css index ac172e0314..879b271849 100644 --- a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.module.css +++ b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.module.css @@ -1,7 +1,6 @@ .resourceUsageContainer { display: flex; min-height: 100vh; - background-color: #fff; } .darkContainer { @@ -13,6 +12,10 @@ padding: 1.5rem; } +.darkChartSection { + background: #2b3e59; +} + .headerSection { margin-bottom: 2rem; } @@ -27,6 +30,22 @@ padding: 0.5rem 1rem !important; border-radius: 0.375rem !important; font-size: 0.875rem !important; + + /* Your enhancements */ + box-shadow: none !important; + display: flex !important; + align-items: center !important; + gap: 0.5rem !important; +} + +.customDropdown:hover, +.customDropdown:focus { + background-color: #b7b7b8 !important; + border-color: #e5e7eb !important; +} + +.customDropdown::after { + margin-left: 0.5rem !important; } .chartContainer { @@ -43,6 +62,15 @@ z-index: 5; } +.yAxisLabel { + position: absolute; + top: -8px; + left: 35px; + font-size: 13px; + font-weight: 700; + z-index: 5; +} + /* ---------------- INSIGHTS ---------------- */ .insightsSection { @@ -134,6 +162,7 @@ font-weight: 600; margin: 0; color: #111827; + border-left: 1px solid #e5e7eb; } .darkInsightsSection .insightsHeader h2 { @@ -147,6 +176,21 @@ } /* BADGE */ + +.insightCard { + padding: 1rem; + border-radius: 0.75rem; +} + +.darkInsightCard { + background: #2b3e59; +} + +.insightTitle { + margin-bottom: 0.75rem; + font-size: 0.875rem; +} + .insightBadge { padding: 0.25rem 0.75rem; border-radius: 1rem; @@ -155,11 +199,17 @@ color: #111827; } - .insightCard .insightBadge { color: #111827 !important; } +/* Tooltip */ +.customTooltip { + padding: 0.75rem; + border-radius: 0.375rem; + border: 1px solid #e5e7eb; +} + .insightCard:hover .insightTooltip { opacity: 1; transform: translateX(-50%) translateY(0); @@ -176,6 +226,7 @@ line-height: 1.3; } +/* Tooltip styles */ .tooltipTitle { font-weight: 600; font-size: 0.8rem; @@ -201,31 +252,35 @@ font-weight: 600; } -/* ---------------- DARK MODE DROPDOWNS ---------------- */ - +/* DARK MODE DROPDOWN */ .dark-mode .customDropdown, .dark-mode .dropdown-toggle.customDropdown { - background-color: #1c2541 !important; - color: #fff !important; - border-color: #3a506b !important; + background-color: #1C2541 !important; + color: #ffffff !important; + border-color: #3A506B !important; } .dark-mode .dropdown-toggle.customDropdown.show, .dark-mode .show > .customDropdown.dropdown-toggle { - background-color: #243b5a !important; + background-color: #243B5A !important; } .dark-mode .dropdown-menu { - background-color: #1c2541 !important; - border-color: #3a506b !important; + background-color: #1C2541 !important; + border-color: #3A506B !important; } .dark-mode .dropdown-item { - color: #fff !important; + color: #ffffff !important; } .dark-mode .dropdown-item:hover { - background-color: #3a506b !important; + background-color: #3A506B !important; +} + +/* Badge visibility in dark mode */ +.dark-mode .insightBadge { + color: #111827 !important; } /* Chart ticks */ @@ -233,4 +288,5 @@ font-size: 12px; font-weight: 700; fill: #666; -} + font-weight: 700; +} \ No newline at end of file diff --git a/src/components/CommunityPortal/ResourceUsage/__tests__/ResourceUsage.test.jsx b/src/components/CommunityPortal/ResourceUsage/__tests__/ResourceUsage.test.jsx index d5a0174143..556dc4e765 100644 --- a/src/components/CommunityPortal/ResourceUsage/__tests__/ResourceUsage.test.jsx +++ b/src/components/CommunityPortal/ResourceUsage/__tests__/ResourceUsage.test.jsx @@ -39,6 +39,7 @@ describe('ResourceUsage Component', () => { // Find ALL "Venue" buttons const venueButtons = screen.getAllByRole('button', { name: 'Venue' }); + // The LAST one is the dropdown menu option const menuOption = venueButtons[venueButtons.length - 1]; fireEvent.click(menuOption); From 065f7aa3cd0edc525f09c722b438637415753f00 Mon Sep 17 00:00:00 2001 From: Neeraj-Kondaveeti Date: Sun, 22 Mar 2026 22:37:53 -0400 Subject: [PATCH 2/5] Fix:lint issues --- .../ResourceUsage/ResourceUsage.jsx | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx index 9afd205e6f..f4e14c69ee 100644 --- a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx +++ b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx @@ -252,33 +252,34 @@ export default function ResourceUsage() {

Insights

- - - {insightsTimePeriod} - - - setInsightsTimePeriod('This Week')}> - This Week - - setInsightsTimePeriod('Last Week')}> - Last Week - - setInsightsTimePeriod('This Month')}> - This Month - - - + + + {insightsTimePeriod} + + + setInsightsTimePeriod('This Week')}> + This Week + + setInsightsTimePeriod('Last Week')}> + Last Week + + setInsightsTimePeriod('This Month')}> + This Month + + + +
+ +
+ {insights.map((insight, idx) => ( +
+ {/* Tooltip description */} +
+ {insightDefinitions[insight.title]}
-
- {insights.map((insight, idx) => ( -
- {/* Tooltip description */} -
- {insightDefinitions[insight.title]} -
Date: Thu, 16 Apr 2026 19:57:55 -0400 Subject: [PATCH 3/5] fix: correct dark mode contrast --- .../ResourceUsage/ResourceUsage.jsx | 142 +++++++++--------- .../ResourceUsage/ResourceUsage.module.css | 64 ++------ 2 files changed, 83 insertions(+), 123 deletions(-) diff --git a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx index f4e14c69ee..7498c31b6b 100644 --- a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx +++ b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx @@ -1,6 +1,6 @@ 'use client'; -import { useState, useEffect, useRef} from 'react'; +import { useState, useEffect, useRef } from 'react'; import { Dropdown } from 'react-bootstrap'; import { BarChart, @@ -89,31 +89,31 @@ function filterDataByDate(data, timePeriod) { function CustomTooltip({ active, payload, darkMode }) { if (!active || !payload || !payload.length) return null; -const data = payload[0].payload; + const data = payload[0].payload; -return ( -
-
{data.name}
+ return ( +
+
{data.name}
-
- - Returned - {data.returned} -
+
+ + Returned + {data.returned} +
-
- - Loaned - {data.loaned} +
+ + Loaned + {data.loaned} +
-
-); + ); } export default function ResourceUsage() { @@ -129,10 +129,10 @@ export default function ResourceUsage() { useEffect(() => { badgeRefs.current.forEach(badge => { if (badge) { - badge.style.setProperty('color', '#000', 'important'); + badge.style.setProperty('color', darkMode ? '#000' : '#000'); } }); - }, [insights]); + }, [insights, darkMode]); useEffect(() => { const resourceTypeKey = resourceType.toLowerCase(); @@ -245,65 +245,63 @@ export default function ResourceUsage() {

No data available for the selected time period and resource type.

)} -
-
+
+
- {/* RIGHT SECTION */} -
-
-

Insights

- - - {insightsTimePeriod} - - - setInsightsTimePeriod('This Week')}> - This Week - - setInsightsTimePeriod('Last Week')}> - Last Week - - setInsightsTimePeriod('This Month')}> - This Month - - - -
+ {/* RIGHT SECTION */} +
+
+

Insights

+ + + {insightsTimePeriod} + + + setInsightsTimePeriod('This Week')}> + This Week + + setInsightsTimePeriod('Last Week')}> + Last Week + + setInsightsTimePeriod('This Month')}> + This Month + + + +
-
- {insights.map((insight, idx) => ( +
+ {insights.map((insight, idx) => ( +
+
- {/* Tooltip description */} -
- {insightDefinitions[insight.title]} -
+ {insight.title} +
-
- {insight.title} -
+
(badgeRefs.current[idx] = el)} + className={`${styles.insightBadge} ${darkMode ? 'text-dark' : ''}`} + style={{ backgroundColor: insight.color }} + > + {insight.value} +
-
(badgeRefs.current[idx] = el)} - className={`${styles.insightBadge} ${darkMode ? 'text-dark' : ''}`} - style={{ backgroundColor: insight.color }} - > - {insight.value} +
Based on returned vs loaned comparison
-
- Based on returned vs loaned comparison -
+ {/* Tooltip */} +
{insightDefinitions[insight.title]}
))}
-
+
); } diff --git a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.module.css b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.module.css index 879b271849..4efee66921 100644 --- a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.module.css +++ b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.module.css @@ -62,15 +62,6 @@ z-index: 5; } -.yAxisLabel { - position: absolute; - top: -8px; - left: 35px; - font-size: 13px; - font-weight: 700; - z-index: 5; -} - /* ---------------- INSIGHTS ---------------- */ .insightsSection { @@ -79,10 +70,6 @@ border-left: 1px solid #e5e7eb; } -.darkInsightsSection { - background: #1b2a41; -} - .insightCard { position: relative; padding: 1rem; @@ -111,27 +98,22 @@ /* Tooltip */ .insightTooltip { position: absolute; - bottom: 3.25rem; + bottom: 100%; left: 50%; - transform: translateX(-50%) translateY(6px); - max-width: 140px; - width: max-content; - padding: 0.6rem 0.75rem; - background-color: #374151; - color: #fff; - font-size: 0.75rem; - line-height: 1.35; - border-radius: 0.5rem; - white-space: normal; - text-align: left; - box-shadow: 0 8px 20px rgb(0 0 0 / 18%); + transform: translateX(-50%); + background: #374151; + color: white; + padding: 8px 10px; + border-radius: 6px; + font-size: 12px; opacity: 0; + visibility: hidden; + transition: all 0.2s ease; pointer-events: none; - transition: opacity 0.15s ease, transform 0.15s ease; - z-index: 5; + z-index: 10; } -/* 🔥 FIX: Apply dark styles INSIDE insights section */ +/* FIX: Apply dark styles INSIDE insights section */ .darkInsightsSection .insightCard { background-color: #1e293b; border: 1px solid #334155; @@ -177,20 +159,6 @@ /* BADGE */ -.insightCard { - padding: 1rem; - border-radius: 0.75rem; -} - -.darkInsightCard { - background: #2b3e59; -} - -.insightTitle { - margin-bottom: 0.75rem; - font-size: 0.875rem; -} - .insightBadge { padding: 0.25rem 0.75rem; border-radius: 1rem; @@ -256,7 +224,7 @@ .dark-mode .customDropdown, .dark-mode .dropdown-toggle.customDropdown { background-color: #1C2541 !important; - color: #ffffff !important; + color: #fff !important; border-color: #3A506B !important; } @@ -271,22 +239,16 @@ } .dark-mode .dropdown-item { - color: #ffffff !important; + color: #fff !important; } .dark-mode .dropdown-item:hover { background-color: #3A506B !important; } -/* Badge visibility in dark mode */ -.dark-mode .insightBadge { - color: #111827 !important; -} - /* Chart ticks */ .recharts-cartesian-axis-tick-value { font-size: 12px; font-weight: 700; fill: #666; - font-weight: 700; } \ No newline at end of file From 98a5bb21d8bdd02ace01141af50f50d76cf79acb Mon Sep 17 00:00:00 2001 From: Neeraj-Kondaveeti Date: Thu, 16 Apr 2026 20:11:28 -0400 Subject: [PATCH 4/5] fix: remove redundant conditional class causing sonar issue --- src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx index 7498c31b6b..e3495e7372 100644 --- a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx +++ b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx @@ -287,7 +287,7 @@ export default function ResourceUsage() {
(badgeRefs.current[idx] = el)} - className={`${styles.insightBadge} ${darkMode ? 'text-dark' : ''}`} + className={styles.insightBadge} style={{ backgroundColor: insight.color }} > {insight.value} From 4c9d26338d501f6055bd326ba033d3378567f52c Mon Sep 17 00:00:00 2001 From: Neeraj-Kondaveeti Date: Thu, 16 Apr 2026 20:24:39 -0400 Subject: [PATCH 5/5] fix: remove redundant conditional in badge color to solve sonar issue --- src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx index e3495e7372..a1b4e57dd5 100644 --- a/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx +++ b/src/components/CommunityPortal/ResourceUsage/ResourceUsage.jsx @@ -129,7 +129,7 @@ export default function ResourceUsage() { useEffect(() => { badgeRefs.current.forEach(badge => { if (badge) { - badge.style.setProperty('color', darkMode ? '#000' : '#000'); + badge.style.setProperty('color', '#000'); } }); }, [insights, darkMode]);