diff --git a/src/actions/bmdashboard/issueChartActions.js b/src/actions/bmdashboard/issueChartActions.js index 12f8b4ad4f8..6a0f34a503a 100644 --- a/src/actions/bmdashboard/issueChartActions.js +++ b/src/actions/bmdashboard/issueChartActions.js @@ -53,10 +53,8 @@ const formatFilters = ({ projectIds, startDate, endDate } = {}) => { ) { formatted.projectIds = Array.isArray(projectIds) ? projectIds.join(',') : projectIds.trim(); } - if (startDate !== undefined && startDate !== '') { + if (startDate !== undefined && startDate !== '' && endDate !== undefined && endDate !== '') { formatted.startDate = startDate; - } - if (endDate !== undefined && endDate !== '') { formatted.endDate = endDate; } return formatted; @@ -69,7 +67,7 @@ export const fetchLongestOpenIssues = filters => async dispatch => { const response = await axios.get(ENDPOINTS.BM_LONGEST_OPEN_ISSUES, { params: formattedFilters, }); - dispatch({ type: FETCH_LONGEST_OPEN_ISSUES_SUCCESS, payload: response.data }); + dispatch({ type: FETCH_LONGEST_OPEN_ISSUES_SUCCESS, payload: response.data.data }); } catch (error) { dispatch({ type: FETCH_LONGEST_OPEN_ISSUES_FAILURE, @@ -85,7 +83,7 @@ export const fetchMostExpensiveIssues = filters => async dispatch => { const response = await axios.get(ENDPOINTS.BM_MOST_EXPENSIVE_ISSUES, { params: formattedFilters, }); - dispatch({ type: FETCH_MOST_EXPENSIVE_ISSUES_SUCCESS, payload: response.data }); + dispatch({ type: FETCH_MOST_EXPENSIVE_ISSUES_SUCCESS, payload: response.data.data }); } catch (error) { dispatch({ type: FETCH_MOST_EXPENSIVE_ISSUES_FAILURE, diff --git a/src/components/BMDashboard/InteractiveMap/InteractiveMap.jsx b/src/components/BMDashboard/InteractiveMap/InteractiveMap.jsx index 6163c0f3d4e..5cae710a9b2 100644 --- a/src/components/BMDashboard/InteractiveMap/InteractiveMap.jsx +++ b/src/components/BMDashboard/InteractiveMap/InteractiveMap.jsx @@ -541,17 +541,17 @@ export default function InteractiveMap() {
Status:{' '} {org.status} diff --git a/src/components/BMDashboard/InteractiveMap/InteractiveMap.module.css b/src/components/BMDashboard/InteractiveMap/InteractiveMap.module.css index af3cb9d025b..bdf14385fc1 100644 --- a/src/components/BMDashboard/InteractiveMap/InteractiveMap.module.css +++ b/src/components/BMDashboard/InteractiveMap/InteractiveMap.module.css @@ -376,6 +376,10 @@ filter: invert(1) hue-rotate(180deg) brightness(0.95) contrast(0.9) saturate(0.6); } +.darkMap :global(.leaflet-tile-pane) { + filter: invert(1) hue-rotate(180deg) brightness(0.9) contrast(0.9); +} + /* ---------------------------------- POPUPS ---------------------------------- */ @@ -487,6 +491,48 @@ margin-right: 8px; } +/* ---------------------------------- + POPUP STATUS TEXT +---------------------------------- */ +.statusActive, +.statusDelayed, +.statusCompleted, +.statusDefault { + font-weight: 700; +} + +.statusActive { + color: #b84040; +} + +.statusDelayed { + color: #8a6d00; +} + +.statusCompleted { + color: #1a8fa0; +} + +.statusDefault { + color: #666; +} + +.darkPage .statusActive { + color: #ff8a80; +} + +.darkPage .statusDelayed { + color: #ffd166; +} + +.darkPage .statusCompleted { + color: #5ee2f0; +} + +.darkPage .statusDefault { + color: #ccc; +} + /* ---------------------------------- POPUP BUTTON ---------------------------------- */ diff --git a/src/components/BMDashboard/Issues/LongestOpenIssuesChart.jsx b/src/components/BMDashboard/Issues/LongestOpenIssuesChart.jsx index 9507e4b8ce1..dce86123b9f 100644 --- a/src/components/BMDashboard/Issues/LongestOpenIssuesChart.jsx +++ b/src/components/BMDashboard/Issues/LongestOpenIssuesChart.jsx @@ -22,9 +22,7 @@ function IssuesCharts({ bmProjects = [] }) { const [selectedProjects, setSelectedProjects] = useState([]); const [dateRange, setDateRange] = useState({ start: null, end: null }); - const { longestOpenIssues = [], mostExpensiveIssues = [] } = useSelector( - state => state.issue || {}, - ); + const { longestOpenIssues, mostExpensiveIssues } = useSelector(state => state.issue || {}); const darkMode = useSelector(state => state.theme.darkMode); useEffect(() => { @@ -41,7 +39,8 @@ function IssuesCharts({ bmProjects = [] }) { } }, [graphType, selectedProjects, dateRange.start, dateRange.end, dispatch]); - const chartData = graphType === 'Longest Open' ? longestOpenIssues : mostExpensiveIssues; + const rawChartData = graphType === 'Longest Open' ? longestOpenIssues : mostExpensiveIssues; + const chartData = Array.isArray(rawChartData) ? rawChartData : []; const data = { labels: chartData.map(issue => truncateLabel(issue.title || String(issue.issueId))), diff --git a/src/components/BMDashboard/WeeklyProjectSummary/ActualVsPlannedCost/ActualVsPlannedCost.module.css b/src/components/BMDashboard/WeeklyProjectSummary/ActualVsPlannedCost/ActualVsPlannedCost.module.css index 8be87dad0d1..123a7282405 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/ActualVsPlannedCost/ActualVsPlannedCost.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/ActualVsPlannedCost/ActualVsPlannedCost.module.css @@ -28,14 +28,26 @@ width: 100%; max-height: 200px; overflow-y: auto; - background-color: var(--card-bg); - color: var(--text-color); + background-color: #fff; + color: #000; border: 1px solid var(--button-hover); border-radius: 4px; padding: 4px 8px; box-sizing: border-box; } +.darkMode .selectorGroup select { + background-color: #253342; + color: #fff; + border-color: #4a5a77; + color-scheme: dark; +} + +.darkMode .selectorGroup select option { + background-color: #253342; + color: #fff; +} + .chartCaption { text-align: center; font-size: medium; diff --git a/src/components/BMDashboard/WeeklyProjectSummary/DistributionLaborHours/DistributionLaborHours.jsx b/src/components/BMDashboard/WeeklyProjectSummary/DistributionLaborHours/DistributionLaborHours.jsx index a5fddea041a..b82d7c3d3b2 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/DistributionLaborHours/DistributionLaborHours.jsx +++ b/src/components/BMDashboard/WeeklyProjectSummary/DistributionLaborHours/DistributionLaborHours.jsx @@ -6,20 +6,22 @@ import styles from './DistributionLaborHours.module.css'; const COLORS = ['#4f8fa8', '#3fa4b8', '#ffab91', '#ffccbb', '#c7c7c7', '#f9f3e3']; +const SWATCH_CLASSES = [ + styles.swatch0, + styles.swatch1, + styles.swatch2, + styles.swatch3, + styles.swatch4, + styles.swatch5, +]; + const CustomTooltip = ({ active, payload, total, darkMode }) => { if (active && payload && payload.length) { const { name, value } = payload[0]; const percent = total > 0 ? ((value / total) * 100).toFixed(1) : '0.0'; return ( -
+

{name}

{`Hours: ${value} hrs`}

{`Percentage: ${percent}%`}

@@ -298,17 +300,13 @@ export default function DistributionLaborHours() { {filteredData.map((entry, index) => (
{entry.name}: {entry.value} hrs diff --git a/src/components/BMDashboard/WeeklyProjectSummary/DistributionLaborHours/DistributionLaborHours.module.css b/src/components/BMDashboard/WeeklyProjectSummary/DistributionLaborHours/DistributionLaborHours.module.css index f793516ffd3..9685b3655f9 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/DistributionLaborHours/DistributionLaborHours.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/DistributionLaborHours/DistributionLaborHours.module.css @@ -381,6 +381,11 @@ min-width: 0; overflow-wrap: anywhere; line-height: 1.3; + color: #000; +} + +.legendTextDark { + color: #f5f5f5; } .colorBox { @@ -394,6 +399,30 @@ flex-shrink: 0; } +.swatch0 { + background-color: #4f8fa8; +} + +.swatch1 { + background-color: #3fa4b8; +} + +.swatch2 { + background-color: #ffab91; +} + +.swatch3 { + background-color: #ffccbb; +} + +.swatch4 { + background-color: #c7c7c7; +} + +.swatch5 { + background-color: #f9f3e3; +} + /* ========================= PIE ========================= */ @@ -428,6 +457,20 @@ margin: 2px 0; } +.tooltipLight { + border: 1px solid #ccc; + + background-color: #fff; + color: #000; +} + +.tooltipDark { + border: 1px solid #64748b; + + background-color: #2e3e5a; + color: #fff; +} + :global(.dark) .tooltip, :global(.dark-mode) .tooltip, :global(.bm-dashboard-dark) .tooltip, diff --git a/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostBreakDown/CostBreakDown.module.css b/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostBreakDown/CostBreakDown.module.css index 7f1a0490e4e..f7b9c5bf4d7 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostBreakDown/CostBreakDown.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostBreakDown/CostBreakDown.module.css @@ -344,6 +344,14 @@ .wrapperDark .filterSelect, .wrapperDark .filterInput { color-scheme: dark; + background: #2b3e59; + color: #fff; + border-color: #4a5a77; +} + +.wrapperDark .filterInput[type='date']::-webkit-datetime-edit, +.wrapperDark .filterInput[type='date']::-webkit-datetime-edit-fields-wrapper { + color: #fff; } .wrapperDark .filterInput[type='date']::-webkit-calendar-picker-indicator { diff --git a/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostVarianceTrendGraph.jsx b/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostVarianceTrendGraph.jsx index 82a9133a236..476e96b047d 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostVarianceTrendGraph.jsx +++ b/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostVarianceTrendGraph.jsx @@ -253,7 +253,7 @@ export default function CostVarianceTrendGraph() { const containerClass = `${styles.varianceContainer} ${darkMode ? styles.darkMode : ''}`; const dateInputClass = `${styles.dateInput} ${darkMode ? styles.darkDateInput : ''}`; - const calendarClass = darkMode ? 'paid-labor-cost-dark-calendar' : ''; + const calendarClass = darkMode ? 'cost-variance-dark-calendar' : ''; const tooltipCursorFill = darkMode ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)'; if (initialLoading) { diff --git a/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostVarianceTrendGraph.module.css b/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostVarianceTrendGraph.module.css index d7f4d28260c..d82b1db2943 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostVarianceTrendGraph.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/Financials/CostVarianceTrendGraph.module.css @@ -35,7 +35,7 @@ width: 100%; } -@media (max-width: 900px) { +@media (width <= 900px) { .filtersGrid { grid-template-columns: 1fr; } @@ -90,14 +90,18 @@ border-color: #4285F4; } -.darkDateInput { +.dateInput.darkDateInput { background-color: #253342; color: #fff; border-color: #2d4059; color-scheme: dark; } -.darkDateInput:focus { +.dateInput.darkDateInput::placeholder { + color: #94a3b8; +} + +.dateInput.darkDateInput:focus { border-color: #3a506b; } @@ -173,8 +177,61 @@ display: inline-block; } -.varianceOverLight { color: #e74c3c !important; } -.varianceOverDark { color: #ff4444 !important; } +.varianceOverLight { color: #e74c3c; } +.varianceOverDark { color: #f44; } + +.varianceUnderLight { color: #2ecc71; } +.varianceUnderDark { color: #4ade80; } + +:global(.cost-variance-dark-calendar.react-datepicker) { + background-color: #253342; + border-color: #2d4059; + color: #fff; +} + +:global(.cost-variance-dark-calendar .react-datepicker__header) { + background-color: #2d4059; + border-bottom-color: #3a506b; +} + +:global(.cost-variance-dark-calendar .react-datepicker__current-month), +:global(.cost-variance-dark-calendar .react-datepicker__day-name) { + color: #fff; +} + +:global(.cost-variance-dark-calendar .react-datepicker__day) { + color: #e0e0e0; +} + +:global(.cost-variance-dark-calendar .react-datepicker__day:hover) { + background-color: #3a506b; + color: #fff; +} + +:global(.cost-variance-dark-calendar .react-datepicker__day--outside-month) { + color: #8a94a3; +} + +:global(.cost-variance-dark-calendar .react-datepicker__day--disabled) { + color: #5a6472; +} + +:global(.cost-variance-dark-calendar .react-datepicker__day--selected), +:global(.cost-variance-dark-calendar .react-datepicker__day--keyboard-selected), +:global(.cost-variance-dark-calendar .react-datepicker__day--range-start), +:global(.cost-variance-dark-calendar .react-datepicker__day--range-end) { + background-color: #e8a71c; + color: #000; + font-weight: 600; +} + +/* stylelint-disable-next-line no-duplicate-selectors -- repeated class raises specificity to beat + react-datepicker's own :not() compound selector for --in-selecting-range without !important */ +:global(.cost-variance-dark-calendar.cost-variance-dark-calendar .react-datepicker__day--in-selecting-range) { + background-color: rgb(232 167 28 / 55%); + color: #1a1a1a; +} -.varianceUnderLight { color: #2ecc71 !important; } -.varianceUnderDark { color: #4ade80 !important; } \ No newline at end of file +:global(.cost-variance-dark-calendar .react-datepicker__navigation-icon::before) { + border-color: #fff; +} \ No newline at end of file diff --git a/src/components/BMDashboard/WeeklyProjectSummary/IssueBreakdownChart.module.css b/src/components/BMDashboard/WeeklyProjectSummary/IssueBreakdownChart.module.css index e8f3ce674fd..08b415c7322 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/IssueBreakdownChart.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/IssueBreakdownChart.module.css @@ -64,6 +64,12 @@ text-shadow: none; } +/* Dark mode heading (fixes #888 fallback which is near-invisible on dark bg) */ +:global(.dark-mode) .heading, +:global(.bm-dashboard-dark) .heading { + color: #e5e7eb; +} + /* Dark mode legend label */ :global(.dark-mode) .legendLabel { color: #fff; @@ -131,9 +137,9 @@ /* Dark mode specific styling for better visibility */ :global(.dark-mode) .datePicker { - background-color: #2c3344 !important; - border-color: #364156 !important; - color: #e0e0e0 !important; + background-color: #2c3344; + border-color: #364156; + color: #e0e0e0; color-scheme: dark; } @@ -173,7 +179,7 @@ } :global(.dark-mode) .datePicker:hover { - border-color: #4a5568 !important; + border-color: #4a5568; } .datePicker:focus { @@ -183,8 +189,8 @@ } :global(.dark-mode) .datePicker:focus { - border-color: #0d55b3 !important; - box-shadow: 0 0 0 2px rgb(13 85 179 / 30%) !important; + border-color: #0d55b3; + box-shadow: 0 0 0 2px rgb(13 85 179 / 30%); } .dateSeparator { @@ -194,7 +200,7 @@ } :global(.dark-mode) .dateSeparator { - color: #e0e0e0 !important; + color: #e0e0e0; } .resetButtonContainer { @@ -212,7 +218,7 @@ cursor: pointer; font-weight: 500; font-size: 14px; - transition: all 0.3s ease; + transition: background-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease; box-shadow: 0 2px 4px rgb(0 0 0 / 10%); } @@ -263,10 +269,15 @@ background: var(--section-bg, #fff); border-radius: 12px; display: flex; - align-items: center; + align-items: stretch; justify-content: center; } +.chartContainer > * { + flex: 1; + min-width: 0; +} + :global(.dark-mode) .chartContainer { background: #253342; } @@ -518,12 +529,6 @@ Responsive adjustments =========================== */ -/* Responsive design */ -@media (width <= 768px) { - .container { - padding: 20px; - } - /* Tablets */ @media (width <= 1024px) { .heading { @@ -554,8 +559,12 @@ } } -/* Mobile */ +/* Responsive design */ @media (width <= 768px) { + .container { + padding: 20px; + } + .heading { font-size: 22px; } @@ -575,7 +584,7 @@ /* Increase label contrast and adjust stroke width */ :global(.recharts-label-list text) { font-size: 9px; - fill: var(--chart-label-color, #111827) !important; + fill: var(--chart-label-color, #111827); stroke-width: 1px; opacity: 1; } @@ -598,49 +607,23 @@ .legendBox { border: 1px solid currentcolor; + } /* Reduce label size and opacity instead of hiding */ :global(.recharts-label-list text) { font-size: 8px; opacity: 0.85; - fill: var(--chart-label-color, #111827) !important; + fill: var(--chart-label-color, #111827); stroke-width: 1px; } } - -:global(.recharts-cartesian-axis-tick-value) { - fill: var(--chart-axis-color, #374151) !important; /* strong contrast */ +.container :global(.recharts-cartesian-axis-tick-value) { + fill: var(--chart-axis-color, #374151); /* strong contrast */ font-weight: 600; font-size: 12px; } -/* Selected value text — DARK MODE (keep text black) */ -:global(.darkMode .injurySelect__single-value) { - color: #000 !important; -} - -:global(.darkMode .injurySelect__multi-value__label) { - color: #000 !important; -} - -/* Ensure input text while typing is also black */ -:global(.darkMode .injurySelect__input-container), -:global(.darkMode .injurySelect__input) { - color: #000 !important; -} - -/* Ensure clear (×) and dropdown arrow are black in dark mode */ -:global(.darkMode .injurySelect__clear-indicator), -:global(.darkMode .injurySelect__dropdown-indicator) { - color: #000 !important; -} - -:global(.darkMode .injurySelect__clear-indicator:hover), -:global(.darkMode .injurySelect__dropdown-indicator:hover) { - color: #000 !important; -} - :global(.filter label) { margin-bottom: 4px; } @@ -665,4 +648,4 @@ :global(.filter .injurySelect__control) { width: 100%; -}}} \ No newline at end of file +} \ No newline at end of file diff --git a/src/components/BMDashboard/WeeklyProjectSummary/IssuesBreakdownChart.jsx b/src/components/BMDashboard/WeeklyProjectSummary/IssuesBreakdownChart.jsx index 336e038c03f..8b423b0a437 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/IssuesBreakdownChart.jsx +++ b/src/components/BMDashboard/WeeklyProjectSummary/IssuesBreakdownChart.jsx @@ -82,6 +82,20 @@ const getSelectStyles = darkMode => { ...baseStyles, color: '#aaaaaa', }), + clearIndicator: baseStyles => ({ + ...baseStyles, + color: '#e0e0e0', + ':hover': { + color: '#fff', + }, + }), + dropdownIndicator: baseStyles => ({ + ...baseStyles, + color: '#e0e0e0', + ':hover': { + color: '#fff', + }, + }), }; } @@ -566,12 +580,13 @@ export default function IssuesBreakdownChart() {
) : ( - + ({ }), }); +const LaborCostSummary = ({ + hasData, + darkMode, + textColor, + displayTotalBudget, + displayTotalCost, + absoluteVariance, + variancePercentage, + varianceClass, + componentStyles, +}) => { + if (!hasData) { + return ( +
No data available for the selected filters.
+ ); + } + + return ( +
+
+ Total Budget + + $ + {displayTotalBudget.toLocaleString('en-US', { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + })} + +
+
+ Total Actual + + $ + {displayTotalCost.toLocaleString('en-US', { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + })} + +
+
+ Variance + + $ + {absoluteVariance.toLocaleString('en-US', { + minimumFractionDigits: 2, + maximumFractionDigits: 2, + })}{' '} + ({variancePercentage > 0 ? '+' : ''} + {variancePercentage.toFixed(1)}%) + +
+
+ ); +}; + +LaborCostSummary.propTypes = { + hasData: PropTypes.bool.isRequired, + darkMode: PropTypes.bool.isRequired, + textColor: PropTypes.string.isRequired, + displayTotalBudget: PropTypes.number.isRequired, + displayTotalCost: PropTypes.number.isRequired, + absoluteVariance: PropTypes.number.isRequired, + variancePercentage: PropTypes.number.isRequired, + varianceClass: PropTypes.string.isRequired, + // eslint-disable-next-line react/forbid-prop-types + componentStyles: PropTypes.object.isRequired, +}; + const MultiValue = () => null; const ValueContainer = ({ children, ...props }) => { @@ -409,7 +481,13 @@ const buildChartOptions = (textColor, darkMode) => ({ scales: { x: { grid: { display: false }, - ticks: { font: { size: 12 }, color: textColor }, + ticks: { + font: { size: 12 }, + color: textColor, + autoSkip: false, + maxRotation: 45, + minRotation: 0, + }, offset: true, }, y: { @@ -661,40 +739,17 @@ export default function PaidLaborCost() { )}
-
-
- Total Budget - - $ - {displayTotalBudget.toLocaleString('en-US', { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - })} - -
-
- Total Actual - - $ - {displayTotalCost.toLocaleString('en-US', { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - })} - -
-
- Variance - - $ - {absoluteVariance.toLocaleString('en-US', { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - })}{' '} - ({variancePercentage > 0 ? '+' : ''} - {variancePercentage.toFixed(1)}%) - -
-
+ 0} + darkMode={darkMode} + textColor={textColor} + displayTotalBudget={displayTotalBudget} + displayTotalCost={displayTotalCost} + absoluteVariance={absoluteVariance} + variancePercentage={variancePercentage} + varianceClass={varianceClass} + componentStyles={styles} + />
); } diff --git a/src/components/BMDashboard/WeeklyProjectSummary/PaidLaborCost/PaidLaborCost.module.css b/src/components/BMDashboard/WeeklyProjectSummary/PaidLaborCost/PaidLaborCost.module.css index e6b46f81628..6b84995c747 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/PaidLaborCost/PaidLaborCost.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/PaidLaborCost/PaidLaborCost.module.css @@ -15,54 +15,32 @@ color: #1e293b; } +/* Filters row (Tasks, Project, Date Range) */ +.filtersGrid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 16px; + margin-bottom: 20px; +} + /* Each filter group (Tasks, Project, Date Range) */ -.paidLaborCostFilterGroup { +.filterGroup { display: flex; - flex-direction: row; - - /* side by side */ - align-items: center; - - /* align vertically */ - gap: 8px; - - /* space between label and select */ - width: fit-content; - - /* shrink-wrap to contents instead of 100% */ - padding: 4px 8px; - - /* optional padding */ + flex-direction: column; + gap: 6px; } -.paidLaborCostFilterLabel { +.filterLabel { margin: 0; - - /* reset margin so it doesn't push things apart */ - font-size: 15px; - color: var(--text-color); - white-space: nowrap; - - /* keep label text on one line */ + font-size: 13px; + font-weight: 600; + color: #334155; } -.paidLaborCostFilterSelect { - font-size: 14px; - padding: 4px 8px; - height: 28px; - box-sizing: border-box; - width: auto; - - /* let it size naturally */ - min-width: 80px; - - /* optional minimum width */ - border: 1px solid #ccc; - border-radius: 4px; - background-color: white; +.darkMode .filterLabel { + color: #e2e8f0; } - /* Chart container */ .paid-labor-cost-chart-container { width: 100%; @@ -75,15 +53,6 @@ } } -.filterGroup { - display: flex; - justify-content: center; - align-items: center; - height: 200px; - color: #666; - font-size: 12px; -} - /* Date picker container styles */ .paidLaborCostDaterangeRow { width: 100%; @@ -98,7 +67,7 @@ width: 100%; overflow: visible; max-width: 300px; - transition: all 0.3s ease-in-out; + transition: max-width 0.3s ease-in-out; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; } @@ -124,10 +93,18 @@ font-size: 0.9rem; } +.dateRangeFlex { + display: flex; + align-items: center; + gap: 8px; + width: 100%; + flex-wrap: wrap; +} + .datePickerWrapper { flex: 1; width: 100%; - min-width: 0; + min-width: 140px; } .datePickerWrapper > div { @@ -151,21 +128,43 @@ outline: none; } +.dateInput { + flex: 1; + width: 100%; + padding: 8px 30px 8px 12px; + border: 1px solid #ccc; + border-radius: 6px; + background-color: #fff; + color: #000; + font-size: 13px; + box-sizing: border-box; + height: 38px; +} + .dateInput:focus { border-color: #4285F4; } -.darkDateInput { +.dateInput.darkDateInput { background-color: #253342; color: #fff; border-color: #2d4059; color-scheme: dark; } -.darkDateInput:focus { +.dateInput.darkDateInput:focus { border-color: #3a506b; } +.dateInput.darkDateInput::placeholder { + color: #94a3b8; +} + +.datePickerWrapper :global(.react-datepicker-wrapper) { + width: 100%; + display: block; +} + .dateSeparator { flex: 0 0 auto; font-size: 13px; @@ -383,19 +382,19 @@ min-height: 30px; } -.varianceOver { color: #e74c3c !important; } -.darkSummaryContainer .varianceOver { color: #ff5252 !important; } +.varianceOver { color: #e74c3c; } +.darkSummaryContainer .varianceOver { color: #ff5252; } -.varianceUnder { color: #2ecc71 !important; } -.darkSummaryContainer .varianceUnder { color: #4ade80 !important; } +.varianceUnder { color: #2ecc71; } +.darkSummaryContainer .varianceUnder { color: #4ade80; } -.varianceNeutral { color: #666 !important; } -.darkSummaryContainer .varianceNeutral { color: #fff !important; } +.varianceNeutral { color: #666; } +.darkSummaryContainer .varianceNeutral { color: #fff; } -:global(.paid-labor-cost-calendar.react-datepicker) { - background-color: #fff !important; - border-color: #aeaeae !important; - color: #000 !important; +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar.react-datepicker) { + background-color: #fff; + border-color: #aeaeae; + color: #000; } .dark-mode .paid-labor-cost-day { @@ -406,54 +405,71 @@ background-color: #f0f0f0; } -:global(.paid-labor-cost-calendar .react-datepicker__current-month), -:global(.paid-labor-cost-calendar .react-datepicker__day-name) { - color: #000 !important; +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__current-month), +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__day-name) { + color: #000; } -:global(.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day) { - color: #000 !important; +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day) { + color: #000; } -:global(.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day:hover) { - background-color: #f0f0f0 !important; - color: #000 !important; +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day:hover) { + background-color: #f0f0f0; + color: #000; } -:global(.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day--selected), -:global(.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day--keyboard-selected) { - background-color: #216ba5 !important; - color: #fff !important; +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day--selected), +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day--keyboard-selected) { + background-color: #216ba5; + color: #fff; +} + +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day--in-range), +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day--in-selecting-range) { + background-color: #badcf6; + color: #000; +} + +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__navigation-icon::before) { + border-color: #ccc; +} + +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar.react-datepicker) { + background-color: #253342; + border-color: #2d4059; + color: #fff; } -:global(.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day--in-range), -:global(.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day--in-selecting-range) { - background-color: #badcf6 !important; - color: #000 !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__header) { + background-color: #2d4059; + border-bottom-color: #3a506b; } -:global(.paid-labor-cost-calendar .react-datepicker__navigation-icon::before) { - border-color: #ccc !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__header__dropdown) { + background-color: #2d4059; } -:global(.paid-labor-cost-dark-calendar.react-datepicker) { - background-color: #253342 !important; - border-color: #2d4059 !important; - color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__current-month), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__day-name) { + color: #fff; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__header) { - background-color: #2d4059 !important; - border-bottom-color: #3a506b !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__day) { + color: #e0e0e0; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__header__dropdown) { - background-color: #2d4059 !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__day:hover) { + background-color: #3a506b; + color: #fff; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__current-month), -:global(.paid-labor-cost-dark-calendar .react-datepicker__day-name) { - color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__day--outside-month) { + color: #8a94a3; +} + +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__day--disabled) { + color: #5a6472; } @media screen and (width <=1130px) { @@ -477,10 +493,10 @@ box-shadow: 0 1px 3px var(--card-shadow); } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--selected), -:global(.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--keyboard-selected) { - background-color: #e8a71c !important; - color: #000 !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--selected), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--keyboard-selected) { + background-color: #e8a71c; + color: #000; font-weight: 600; } @@ -488,25 +504,27 @@ background-color: rgb(232 167 28 / 20%); } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--in-selecting-range) { - background-color: rgb(232 167 28 / 55%) !important; - color: #1a1a1a !important; +/* stylelint-disable-next-line no-duplicate-selectors -- repeated class raises specificity to beat + react-datepicker's own :not() compound selector for --in-selecting-range without !important */ +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--in-selecting-range) { + background-color: rgb(232 167 28 / 55%); + color: #1a1a1a; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--range-start), -:global(.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--range-end) { - background-color: #e8a71c !important; - color: #000 !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--range-start), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--range-end) { + background-color: #e8a71c; + color: #000; font-weight: 600; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__navigation-icon::before) { - border-color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__navigation-icon::before) { + border-color: #fff; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__year-read-view--down-arrow), -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-read-view--down-arrow) { - border-top-color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__year-read-view--down-arrow), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-read-view--down-arrow) { + border-top-color: #fff; } .dark-mode .paid-labor-cost-date-range-calendar { @@ -514,71 +532,71 @@ box-shadow: 0 4px 12px rgb(0 0 0 / 30%); } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-option), -:global(.paid-labor-cost-dark-calendar .react-datepicker__year-option) { - background-color: #253342 !important; - color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-option), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__year-option) { + background-color: #253342; + color: #fff; padding: 8px 12px; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-option:hover), -:global(.paid-labor-cost-dark-calendar .react-datepicker__year-option:hover) { - background-color: #3a506b !important; - color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-option:hover), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__year-option:hover) { + background-color: #3a506b; + color: #fff; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-option--selected), -:global(.paid-labor-cost-dark-calendar .react-datepicker__year-option--selected) { - background-color: #e8a71c !important; - color: #000 !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-option--selected), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__year-option--selected) { + background-color: #e8a71c; + color: #000; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__year-read-view), -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-read-view) { - color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__year-read-view), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-read-view) { + color: #fff; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-dropdown-container), -:global(.paid-labor-cost-dark-calendar .react-datepicker__year-dropdown-container), -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-year-dropdown-container) { - background-color: transparent !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-dropdown-container), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__year-dropdown-container), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-year-dropdown-container) { + background-color: transparent; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-select), -:global(.paid-labor-cost-dark-calendar .react-datepicker__year-select) { - background-color: #253342 !important; - border: 1px solid #2d4059 !important; - color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-select), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__year-select) { + background-color: #253342; + border: 1px solid #2d4059; + color: #fff; padding: 4px 8px; border-radius: 4px; font-size: 14px; cursor: pointer; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-select:focus), -:global(.paid-labor-cost-dark-calendar .react-datepicker__year-select:focus) { +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-select:focus), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__year-select:focus) { outline: none; - border-color: #e8a71c !important; + border-color: #e8a71c; box-shadow: 0 0 0 2px rgb(232 167 28 / 20%); } -:global(.paid-labor-cost-dark-calendar .react-datepicker__month-select option), -:global(.paid-labor-cost-dark-calendar .react-datepicker__year-select option) { - background-color: #253342 !important; - color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__month-select option), +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__year-select option) { + background-color: #253342; + color: #fff; padding: 8px; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__time-container) { - border-left-color: #2d4059 !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__time-container) { + border-left-color: #2d4059; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__time) { - background-color: #253342 !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__time) { + background-color: #253342; } -:global(.paid-labor-cost-dark-calendar .react-datepicker__time-list-item) { - color: #fff !important; +:global(.paid-labor-cost-dark-calendar.paid-labor-cost-dark-calendar .react-datepicker__time-list-item) { + color: #fff; } .dark-mode .paid-labor-cost-day.in-range { @@ -623,9 +641,9 @@ align-items: center; } -:global(.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--disabled:hover) { - color: #ccc !important; - background-color: transparent !important; +:global(.paid-labor-cost-calendar.paid-labor-cost-calendar .react-datepicker__month .react-datepicker__day.react-datepicker__day--disabled:hover) { + color: #ccc; + background-color: transparent; } .paid-labor-cost-info-button:hover, @@ -718,30 +736,3 @@ border-width: 4px; } } - -.paidLaborCostChartScrollWrapper { - width: 100%; - overflow-x: auto; - background-color: var(--bg-color); - scrollbar-width: thin; - scrollbar-color: var(--button-bg) var(--card-shadow); - -} - -.paidLaborCostChartScrollWrapper::-webkit-scrollbar { - height: 6px; -} - -.paidLaborCostChartScrollWrapper::-webkit-scrollbar-track { - background: var(--bg-color); -} - -.paidLaborCostChartScrollWrapper::-webkit-scrollbar-thumb { - background: var(--button-bg); - border-radius: 3px; -} - -/* .paidLaborCostChartScrollWrapper { - scrollbar-width: thin; - scrollbar-color: var(--button-bg) var(--card-shadow); -} */ diff --git a/src/components/BMDashboard/WeeklyProjectSummary/ProjectRiskProfileOverview.jsx b/src/components/BMDashboard/WeeklyProjectSummary/ProjectRiskProfileOverview.jsx index 84852526444..b6c5d9744a9 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/ProjectRiskProfileOverview.jsx +++ b/src/components/BMDashboard/WeeklyProjectSummary/ProjectRiskProfileOverview.jsx @@ -309,6 +309,9 @@ export default function ProjectRiskProfileOverview() { }, labelStyle: { color: darkMode ? '#eee' : '#222' }, itemStyle: { color: darkMode ? '#eee' : '#222' }, + allowEscapeViewBox: { x: true, y: true }, + wrapperStyle: { zIndex: 2000, pointerEvents: 'none' }, + position: { y: -60 }, }), [darkMode], ); diff --git a/src/components/BMDashboard/WeeklyProjectSummary/ProjectRiskProfileOverview.module.css b/src/components/BMDashboard/WeeklyProjectSummary/ProjectRiskProfileOverview.module.css index ca2e1448179..75469e8126f 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/ProjectRiskProfileOverview.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/ProjectRiskProfileOverview.module.css @@ -116,10 +116,13 @@ padding: 8px 12px; border-radius: 5px; transition: all 0.25s ease; + box-sizing: border-box; } .dateInput { - min-width: 150px; + display: block; + width: 100%; + min-width: 170px; } .dropdownButton:hover, .dateInput:hover { @@ -192,6 +195,8 @@ .trendSection { margin-top: 28px; padding: 24px; + min-width: 0; + box-sizing: border-box; background: #fafafa; border-radius: 8px; border: 1px solid #e8e8e8; @@ -215,7 +220,7 @@ .trendGrid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 16px; } @@ -225,6 +230,8 @@ border-radius: 6px; padding: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.04); + min-width: 0; + box-sizing: border-box; } .darkMode .trendCard { @@ -239,6 +246,7 @@ margin-bottom: 12px; border-bottom: 1px solid #eee; padding-bottom: 8px; + overflow-wrap: break-word; } .darkMode .projectName { @@ -254,9 +262,9 @@ margin-bottom: 8px; } -.trendRow span:first-child { flex: 1; color: #666; font-weight: 500; } +.trendRow span:first-child { flex: 1; min-width: 0; overflow-wrap: anywhere; color: #666; font-weight: 500; } .darkMode .trendRow span:first-child { color: #aaa; } -.trendRow span:last-child { font-weight: 600; color: #1a1a1a; min-width: 50px; text-align: right; } +.trendRow span:last-child { font-weight: 600; color: #1a1a1a; min-width: 50px; text-align: right; flex-shrink: 0; } .darkMode .trendRow span:last-child { color: #ddd; } .trendIndicator { font-size: 16px; font-weight: 700; display: inline-block; width: 24px; text-align: center; } @@ -280,7 +288,7 @@ padding-top: 0; } -.attributeRow .label { flex: 1; color: #666; font-weight: 500; } +.attributeRow .label { flex: 1; min-width: 0; overflow-wrap: anywhere; color: #666; font-weight: 500; } .darkMode .attributeRow .label { color: #aaa; } .attributeRow .value { font-weight: 600; color: #1a1a1a; text-align: right; } .darkMode .attributeRow .value { color: #ddd; } @@ -288,6 +296,8 @@ .tableScroll { width: 100%; overflow-x: auto; + overflow-y: visible; + padding-bottom: 4px; } .table { @@ -304,6 +314,28 @@ background: #2b2b2b; } +.table tbody tr:hover { + background-color: #e8f0fe; +} + +.table tbody tr:hover .td, +.table tbody tr:hover .tdProject, +.table tbody tr:hover .deltaText, +.table tbody tr:hover .indicatorSub { + color: #1a1a1a; +} + +.darkMode .table tbody tr:hover { + background-color: #3a506b; +} + +.darkMode .table tbody tr:hover .td, +.darkMode .table tbody tr:hover .tdProject, +.darkMode .table tbody tr:hover .deltaText, +.darkMode .table tbody tr:hover .indicatorSub { + color: #fff; +} + .th { padding: 12px; text-align: left; @@ -320,10 +352,12 @@ .td { padding: 12px; border-bottom: 1px solid #eee; + color: #1a1a1a; } .darkMode .td { border-bottom: 1px solid #404040; + color: #e5e7eb; } .tdProject { @@ -331,10 +365,12 @@ border-bottom: 1px solid #eee; white-space: nowrap; font-weight: 500; + color: #1a1a1a; } .darkMode .tdProject { border-bottom: 1px solid #404040; + color: #e5e7eb; } .sparkRow { diff --git a/src/components/BMDashboard/WeeklyProjectSummary/QuantityOfMaterialsUsed/QuantityOfMaterialsUsed.jsx b/src/components/BMDashboard/WeeklyProjectSummary/QuantityOfMaterialsUsed/QuantityOfMaterialsUsed.jsx index 576773e590b..b214cf61b37 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/QuantityOfMaterialsUsed/QuantityOfMaterialsUsed.jsx +++ b/src/components/BMDashboard/WeeklyProjectSummary/QuantityOfMaterialsUsed/QuantityOfMaterialsUsed.jsx @@ -20,6 +20,7 @@ import { useDispatch, useSelector } from 'react-redux'; import ReactTooltip from 'react-tooltip'; import { Info, Repeat } from 'lucide-react'; import { v4 as uuidv4 } from 'uuid'; +import PropTypes from 'prop-types'; import { fetchBMProjects } from '../../../../actions/bmdashboard/projectActions'; import styles from './QuantityOfMaterialsUsed.module.css'; @@ -68,6 +69,88 @@ function getRandomColor() { return `#${Math.floor(Math.random() * 16777215).toString(16)}`; } +const getOptionBackground = (darkMode, state) => { + if (state.isSelected || state.isFocused) return '#0d55b3'; + return darkMode ? '#22272e' : '#fff'; +}; + +const getOptionColor = (darkMode, state) => { + if (state.isSelected || darkMode) return '#fff'; + return '#232323'; +}; + +const createSelectStyles = darkMode => ({ + control: base => ({ + ...base, + backgroundColor: darkMode ? '#22272e' : '#fff', + borderColor: darkMode ? '#375071' : '#ccc', + color: darkMode ? '#fff' : '#232323', + minHeight: 38, + boxShadow: 'none', + borderRadius: 8, + }), + menu: base => ({ + ...base, + backgroundColor: darkMode ? '#22272e' : '#fff', + fontSize: 12, + zIndex: 10001, + borderRadius: 8, + marginTop: 2, + color: darkMode ? '#fff' : '#232323', + }), + menuList: base => ({ + ...base, + maxHeight: 400, + overflowY: 'auto', + backgroundColor: darkMode ? '#22272e' : '#fff', + color: darkMode ? '#fff' : '#232323', + padding: 0, + }), + option: (base, state) => ({ + ...base, + backgroundColor: getOptionBackground(darkMode, state), + color: getOptionColor(darkMode, state), + fontSize: 13, + padding: '10px 16px', + cursor: 'pointer', + }), + multiValue: base => ({ + ...base, + backgroundColor: darkMode ? '#375071' : '#e2e7ee', + borderRadius: 6, + fontSize: 12, + marginRight: 4, + }), + multiValueLabel: base => ({ + ...base, + color: darkMode ? '#fff' : '#333', + fontSize: 12, + padding: '2px 6px', + }), + multiValueRemove: base => ({ + ...base, + color: darkMode ? '#fff' : '#333', + ':hover': { + backgroundColor: darkMode ? '#0d55b3' : '#e2e7ee', + color: '#fff', + }, + borderRadius: 4, + padding: 2, + }), + singleValue: base => ({ + ...base, + color: darkMode ? '#fff' : base.color, + }), + input: base => ({ + ...base, + color: darkMode ? '#fff' : base.color, + }), + placeholder: base => ({ + ...base, + color: darkMode ? '#fff' : base.color, + }), +}); + function QuantityOfMaterialsUsed({ data, comparisonMode = 'No Comparison', @@ -96,86 +179,7 @@ function QuantityOfMaterialsUsed({ dispatch(fetchBMProjects()); }, [dispatch]); - const selectStyles = useMemo( - () => ({ - control: base => ({ - ...base, - backgroundColor: darkMode ? '#22272e' : '#fff', - borderColor: darkMode ? '#375071' : '#ccc', - color: darkMode ? '#fff' : '#232323', - minHeight: 38, - boxShadow: 'none', - borderRadius: 8, - }), - menu: base => ({ - ...base, - backgroundColor: darkMode ? '#22272e' : '#fff', - fontSize: 12, - zIndex: 10001, - borderRadius: 8, - marginTop: 2, - color: darkMode ? '#fff' : '#232323', - }), - menuList: base => ({ - ...base, - maxHeight: 400, - overflowY: 'auto', - backgroundColor: darkMode ? '#22272e' : '#fff', - color: darkMode ? '#fff' : '#232323', - padding: 0, - }), - option: (base, state) => ({ - ...base, - backgroundColor: state.isSelected - ? '#0d55b3' - : state.isFocused - ? '#0d55b3' - : darkMode - ? '#22272e' - : '#fff', - color: state.isSelected ? '#fff' : darkMode ? '#fff' : '#232323', - fontSize: 13, - padding: '10px 16px', - cursor: 'pointer', - }), - multiValue: base => ({ - ...base, - backgroundColor: darkMode ? '#375071' : '#e2e7ee', - borderRadius: 6, - fontSize: 12, - marginRight: 4, - }), - multiValueLabel: base => ({ - ...base, - color: darkMode ? '#fff' : '#333', - fontSize: 12, - padding: '2px 6px', - }), - multiValueRemove: base => ({ - ...base, - color: darkMode ? '#fff' : '#333', - ':hover': { - backgroundColor: darkMode ? '#0d55b3' : '#e2e7ee', - color: '#fff', - }, - borderRadius: 4, - padding: 2, - }), - singleValue: base => ({ - ...base, - color: darkMode ? '#fff' : base.color, - }), - input: base => ({ - ...base, - color: darkMode ? '#fff' : base.color, - }), - placeholder: base => ({ - ...base, - color: darkMode ? '#fff' : base.color, - }), - }), - [darkMode], - ); + const selectStyles = useMemo(() => createSelectStyles(darkMode), [darkMode]); useEffect(() => { const handleResize = () => { @@ -841,7 +845,10 @@ function QuantityOfMaterialsUsed({ maxDate={new Date()} dateFormat="MM/dd/yy - MM/dd/yy" placeholderText="Select Date Range one" - className={`${styles.quantityOfMaterialUsedCustomDatePicker}`} + className={`${styles.quantityOfMaterialUsedCustomDatePicker}${ + darkMode ? ` ${styles.quantityOfMaterialUsedCustomDatePickerDark}` : '' + }`} + calendarClassName={darkMode ? 'paid-labor-cost-dark-calendar' : ''} disabledKeyboardNavigation calendarStartDay={1} shouldCloseOnSelect={false} @@ -886,7 +893,10 @@ function QuantityOfMaterialsUsed({ maxDate={new Date()} dateFormat="MM/dd/yy - MM/dd/yy" placeholderText="Select Date Range two" - className={`${styles.quantityOfMaterialUsedCustomDatePicker}`} + className={`${styles.quantityOfMaterialUsedCustomDatePicker}${ + darkMode ? ` ${styles.quantityOfMaterialUsedCustomDatePickerDark}` : '' + }`} + calendarClassName={darkMode ? 'paid-labor-cost-dark-calendar' : ''} disabledKeyboardNavigation calendarStartDay={1} shouldCloseOnSelect={false} @@ -1101,4 +1111,8 @@ function QuantityOfMaterialsUsed({ ); } +QuantityOfMaterialsUsed.propTypes = { + data: PropTypes.array.isRequired, +}; + export default QuantityOfMaterialsUsed; diff --git a/src/components/BMDashboard/WeeklyProjectSummary/QuantityOfMaterialsUsed/QuantityOfMaterialsUsed.module.css b/src/components/BMDashboard/WeeklyProjectSummary/QuantityOfMaterialsUsed/QuantityOfMaterialsUsed.module.css index b23a46a65c4..1d30cf67a24 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/QuantityOfMaterialsUsed/QuantityOfMaterialsUsed.module.css +++ b/src/components/BMDashboard/WeeklyProjectSummary/QuantityOfMaterialsUsed/QuantityOfMaterialsUsed.module.css @@ -211,11 +211,15 @@ div.weeklyProjectSummaryCard.normalCard .dropdownItem { border-radius: 4px; text-align: center; padding: 2px 6px; - background-color: var(--card-bg); - color: var(--text-color); + background-color: var(--card-bg) !important; + color: var(--text-color) !important; transition: border-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out; } +.quantityOfMaterialUsedCustomDatePickerDark { + color-scheme: dark; +} + .quantityOfMaterialsUsedCard .customSelect_singleValue { color: var(--text-color) !important; } diff --git a/src/components/BMDashboard/WeeklyProjectSummary/SupplierPerformanceGraph.jsx b/src/components/BMDashboard/WeeklyProjectSummary/SupplierPerformanceGraph.jsx index e743f113752..99042456eec 100644 --- a/src/components/BMDashboard/WeeklyProjectSummary/SupplierPerformanceGraph.jsx +++ b/src/components/BMDashboard/WeeklyProjectSummary/SupplierPerformanceGraph.jsx @@ -11,9 +11,10 @@ import { Label, } from 'recharts'; import { useDispatch, useSelector } from 'react-redux'; -import { Input } from 'reactstrap'; +import Select from 'react-select'; import { fetchSupplierProjects, fetchSupplierPerformance } from '../../../actions/summaryDashboard'; import styles from './SupplierPerformanceGraph.module.css'; +import { buildChartSelectStyles } from './sharedSelectStyles'; const getDateRangeOptions = () => { const today = new Date(); @@ -72,12 +73,13 @@ const SupplierPerformanceDashboard = function({ height = 420, onDataLoaded }) { const chartTheme = { textColor: darkMode ? '#e0e0e0' : '#333', axisColor: darkMode ? '#a0a0a0' : '#666', - // UPDATE: Set a lighter grey for dark mode so grid lines are clearly visible gridColor: darkMode ? '#9CA3AF' : '#E2E8F0', barColor: '#4CAF50', labelFill: darkMode ? '#ffffff' : '#333', }; + const selectStyles = buildChartSelectStyles(darkMode); + useEffect(() => { const loadProjects = async () => { try { @@ -124,6 +126,18 @@ const SupplierPerformanceDashboard = function({ height = 420, onDataLoaded }) { fetchData(); }, [dispatch, selectedDateRange, selectedProject, onDataLoaded]); + // Build react-select options + const dateOptions = getDateRangeOptions().map(opt => ({ value: opt.value, label: opt.label })); + const selectedDateOption = + dateOptions.find(opt => opt.value === selectedDateRange) || dateOptions[0]; + + const projectOptions = [ + { value: 'all', label: 'ALL Projects' }, + ...projects.map(p => ({ value: p._id, label: p.projectName })), + ]; + const selectedProjectOption = + projectOptions.find(opt => opt.value === selectedProject) || projectOptions[0]; + return (
- - setSelectedDateRange(e.target.value)} - className={styles['supplier-performance-select']} - > - {getDateRangeOptions().map(option => ( - - ))} - + + Dates + + setSelectedProject(e.target.value)} - className={styles['supplier-performance-select']} - > - - {projects.map(project => ( - - ))} - + + Project + +