diff --git a/src/components/BMDashboard/RentalChart/RentalChart.jsx b/src/components/BMDashboard/RentalChart/RentalChart.jsx index 3542862037..c78ec3302a 100644 --- a/src/components/BMDashboard/RentalChart/RentalChart.jsx +++ b/src/components/BMDashboard/RentalChart/RentalChart.jsx @@ -238,50 +238,47 @@ export default function RentalChart() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [chartType, selectedProject, selectedTool, dateRange, groupBy, rawData]); - const options = useMemo( - () => ({ + const options = useMemo(() => { + const textColor = darkMode ? '#ffffff' : '#000000'; + const bgColor = darkMode ? '#1b2a41' : '#ffffff'; + const tooltipBorder = darkMode ? '#ffffff' : '#000000'; + const tooltipBg = darkMode ? '#343a40' : '#f8f9fa'; + const titleColor = darkMode ? '#ffffff' : '#000000'; + const gridXColor = darkMode ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)'; + const gridYColor = darkMode ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)'; + + return { responsive: true, maintainAspectRatio: false, - backgroundColor: darkMode ? '#1b2a41' : '#ffffff', + backgroundColor: bgColor, plugins: { legend: { position: 'top', - labels: { - color: darkMode ? '#e0e0e0' : '#333333', - }, + labels: { color: textColor, font: { size: 16 } }, }, title: { display: true, text: generateChartTitle(), - font: { - size: 14, - }, - color: darkMode ? '#ffffff' : '#1b2a41', - padding: { - bottom: 20, - }, + font: { size: 25 }, + color: titleColor, }, tooltip: { callbacks: { - label(context) { - let label = context.dataset.label || ''; - if (label) { - label += ': '; - } - if (context.parsed.y !== null) { - label += - chartType === 'percentage' - ? `${context.parsed.y.toFixed(1)}%` - : `$${context.parsed.y.toFixed(2)}`; + label({ dataset, parsed }) { + let label = dataset.label ? `${dataset.label}: ` : ''; + if (parsed.y !== null) { + label += chartType === 'percentage' ? `${parsed.y}%` : `$${parsed.y.toFixed(2)}`; } return label; }, }, - backgroundColor: darkMode ? '#1b2a41' : 'rgba(255,255,255,0.8)', - titleColor: darkMode ? '#ffffff' : '#1b2a41', - bodyColor: darkMode ? '#ffffff' : '#333333', - borderColor: darkMode ? 'rgba(255,255,255, 0.2)' : '#1b2a41', - borderWidth: 1, + backgroundColor: tooltipBg, + titleColor, + bodyColor: textColor, + borderColor: tooltipBorder, + borderWidth: 2, + titleFont: { size: 18 }, + bodyFont: { size: 16 }, }, datalabels: { color: darkMode ? '#e0e0e0' : '#333333', @@ -319,17 +316,9 @@ export default function RentalChart() { }, scales: { x: { - title: { - display: true, - text: 'Month/Year', - color: darkMode ? '#e0e0e0' : '#333333', - }, - ticks: { - color: darkMode ? '#e0e0e0' : '#333333', - }, - grid: { - color: darkMode ? '#e0e0e0' : '#333333', - }, + title: { display: true, text: 'Month/Year', color: textColor, font: { size: 18 } }, + ticks: { color: textColor }, + grid: { color: gridXColor }, }, y: { beginAtZero: true, @@ -339,22 +328,18 @@ export default function RentalChart() { chartType === 'percentage' ? 'Percentage of Total Materials Cost (%)' : 'Total Rental Cost ($)', - color: darkMode ? '#e0e0e0' : '#333333', + color: textColor, + font: { size: 18 }, }, ticks: { - callback(value) { - return chartType === 'percentage' ? `${value}%` : `$${value}`; - }, - color: darkMode ? '#e0e0e0' : '#333333', - }, - grid: { - color: darkMode ? 'rgba(255,255,255,0.1)' : '#1b2a41', + callback: value => (chartType === 'percentage' ? `${value}%` : `$${value}`), + color: textColor, }, + grid: { color: gridYColor }, }, }, - }), - [darkMode, chartType, dateRange, selectedProject, selectedTool], - ); + }; + }, [darkMode, chartType, dateRange, selectedProject, selectedTool]); const handleTypeChange = e => { setChartType(e.target.value); @@ -392,131 +377,105 @@ export default function RentalChart() { const renderChartContent = () => { if (loading) { - return ( -
- Loading Chart Data.... -
- ); + return
Loading Chart Data....
; } if (error) { - return
{error}
; + return
{error}
; } if (chartData.datasets.length === 0) { - return ( -
- No data available for the selected filters -
- ); + return
No data available for the selected filters
; } return ; }; return ( -
-

Rental Cost Over Time

- -
-
-
- - -
- -
- - +
+
+

Rental Cost Over Time

+
+
+
+ + +
+ +
+ + +
+ +
+ + +
-
- - +
+
+ + +
+ +
+ + +
-
-
- - -
- -
- - -
-
-
- -
- {renderChartContent()} +
{renderChartContent()}
); diff --git a/src/components/BMDashboard/RentalChart/RentalChart.module.css b/src/components/BMDashboard/RentalChart/RentalChart.module.css index aa28f6ad79..bceaacc7d8 100644 --- a/src/components/BMDashboard/RentalChart/RentalChart.module.css +++ b/src/components/BMDashboard/RentalChart/RentalChart.module.css @@ -1,56 +1,31 @@ -/* stylelint-disable */ -/* Dark mode on body has to stay global */ -:global(body.dark-mode) { - background-color: #1b2a41; - color: #e0e0e0; -} - +/* ====================== + Light Mode Base + ====================== */ .rentalContainer { position: relative; width: 100%; margin: 0 auto; padding: 20px; - border-radius: 8px; - min-height: 100vh; - margin-top: -20px; -} - -.darkMode { - background-color: #1b2a41; - color: #e0e0e0; -} - -.chartFilters { - display: flex; - flex-direction: column; - align-items: center; - gap: 10px; - margin-bottom: 20px; } +/* General text */ .textLight { color: #e0e0e0; } -.darkSelect { - background-color: #333; - color: #e0e0e0; - border: 1px solid #555; -} - -.darkDatePicker { - background-color: #333; - color: #e0e0e0; - border: 1px solid #555; -} - -.darkChart { - background-color: #1b2a41; +/* Chart wrapper (applies in dark + light mode) */ +.chartWrapper { + height: 600px; + width: 100%; + margin: 0 auto; + padding: 40px; + box-sizing: border-box; border-radius: 8px; - padding: 16px; - border: 1px solid #333; + background-color: #fff; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05); } +/* Chart controls + filters */ .chartControls { display: flex; flex-direction: column; @@ -63,9 +38,9 @@ display: flex; flex-wrap: wrap; gap: 20px; - margin-top: 20px; - align-items: center; - justify-content: center; + margin-top: 40px; + align-items: flex-start; + justify-content: flex-end; } .topFilters { @@ -79,46 +54,42 @@ .filterGroup { display: flex; - align-items: center; - white-space: nowrap; -} - -.filterText { - margin-right: 8px; - white-space: nowrap; + flex-direction: column; + align-items: flex-start; + gap: 6px; + min-width: 150px; } -.chartWrapper { - min-height: 500px; - width: 100%; - margin: 0 auto; - padding: 15px; - box-sizing: border-box; - border-radius: 8px; - box-shadow: 0 2px 10px rgb(0 0 0 / 5%); +.filterGroup label { + font-size: 18px; + font-weight: 500; + margin-bottom: 2px; + color: inherit; } -.lightChart { - background-color: #fff; - border: 1px solid #ddd; +.filterText { + margin-right: 0; + white-space: nowrap; } +/* Date picker input */ .datePicker { padding: 6px 10px; border: 1px solid #ccc; - border-radius: 4px; + border-radius: 6px; /* rounded */ font-size: 14px; width: 120px; } +select, .rentalChartSelect { - padding: 6px 10px; + background-color: #fff; + color: #333; border: 1px solid #ccc; - border-radius: 4px; - font-size: 14px; - min-width: 150px; + border-radius: 6px; + cursor: pointer; } - +/* States */ .loading, .error, .noData { @@ -134,42 +105,133 @@ color: #d32f2f; } -/* DatePicker needs global selectors, otherwise its classNames won’t match */ +/* React DatePicker overrides (light mode base) */ +.reactDatepicker { + background-color: #fff; + color: #333; + border: 1px solid #ccc; + border-radius: 6px; +} + +.reactDatepicker__header { + background-color: #f5f5f5; + border-bottom: 1px solid #ccc; + border-radius: 6px 6px 0 0; +} + +.reactDatepicker__current-month, +.reactDatepicker__day-name, +.reactDatepicker__day, +.reactDatepicker__month-text, +.reactDatepicker__year-text { + color: #333; +} + +.reactDatepicker__day:hover, +.reactDatepicker__month-text:hover, +.reactDatepicker__year-text:hover { + background-color: #eee; +} + +.reactDatepicker__day--selected, +.reactDatepicker__day--in-selecting-range, +.reactDatepicker__day--in-range { + background-color: #0078d7; + color: white; + border-radius: 50%; +} + +.reactDatepickerPopper { + z-index: 999 !important; + max-width: 100vw; + border-radius: 6px; +} -/* Only apply dark datepicker when app is in dark mode so other pages (e.g. UtilizationChart) stay light */ -:global(body.dark-mode) :global(.react-datepicker) { +/* ====================== + Dark Mode Overrides + ====================== */ +.darkMode { + background-color: #1b2a41; + color: #e0e0e0; +} + +.darkMode .rentalContainer { + background-color: #1b2a41; + color: #e0e0e0; +} + +.darkMode select, +.darkMode .rentalChartSelect { background-color: #333; color: #e0e0e0; border: 1px solid #555; } -:global(body.dark-mode) :global(.react-datepicker__header) { - background-color: #444; +/* DatePicker input & popper */ +.darkMode .DatePickerInput, +.darkMode .DatePicker, +.darkMode .DatePickerPopper, +.darkMode .DatePickerCalendar { + background-color: #333; + color: #e0e0e0; + border: 1px solid #555; + border-radius: 6px; + z-index: 9999; +} + +/* Calendar header */ +.darkMode .DatePickerCalendar .react-datepicker__header { + background-color: #333; border-bottom: 1px solid #555; + color: #e0e0e0; + border-radius: 6px 6px 0 0; } -:global(body.dark-mode) :global(.react-datepicker__current-month), -:global(body.dark-mode) :global(.react-datepicker__day-name), -:global(body.dark-mode) :global(.react-datepicker__day), -:global(body.dark-mode) :global(.react-datepicker__month-text), -:global(body.dark-mode) :global(.react-datepicker__year-text) { +/* Days, months, years */ +.darkMode .DatePickerCalendar .react-datepicker__day, +.darkMode .DatePickerCalendar .react-datepicker__day-name, +.darkMode .DatePickerCalendar .react-datepicker__month-text, +.darkMode .DatePickerCalendar .react-datepicker__year-text { color: #e0e0e0; + background-color: #333; + border-radius: 4px; } -:global(body.dark-mode) :global(.react-datepicker__day:hover), -:global(body.dark-mode) :global(.react-datepicker__month-text:hover), -:global(body.dark-mode) :global(.react-datepicker__year-text:hover) { - background-color: #555; +/* Dark mode DatePicker root */ +.darkMode .react-datepicker { + background-color: #000 !important; /* match your select */ + color: #e0e0e0 !important; + border: 1px solid #444 !important; + border-radius: 6px; +} + +/* Header inside */ +.darkMode .react-datepicker__header { + background-color: #111 !important; + border-bottom: 1px solid #444 !important; + color: #e0e0e0 !important; } -:global(body.dark-mode) :global(.react-datepicker__day--selected), -:global(body.dark-mode) :global(.react-datepicker__day--in-selecting-range), -:global(body.dark-mode) :global(.react-datepicker__day--in-range) { - background-color: #0050a8; +/* Hover effect */ +.darkMode .DatePickerCalendar .react-datepicker__day:hover, +.darkMode .DatePickerCalendar .react-datepicker__month-text:hover, +.darkMode .DatePickerCalendar .react-datepicker__year-text:hover { + background-color: #444; color: #fff; } -:global(.react-datepicker-popper) { - z-index: 999 !important; - max-width: 100vw; +/* Selected and in-range */ +.darkMode .DatePickerCalendar .react-datepicker__day--selected, +.darkMode .DatePickerCalendar .react-datepicker__day--in-range, +.darkMode .DatePickerCalendar .react-datepicker__day--in-selecting-range { + background-color: #555; + color: #fff; + border-radius: 50%; +} + +/* Chart wrapper */ +.darkMode .chartWrapper { + background-color: #1b2a41; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(255, 255, 255, 0.05); }