Skip to content

Commit 92fe266

Browse files
committed
Add dark mode, add Provider to tests
1 parent 3fdc27d commit 92fe266

3 files changed

Lines changed: 112 additions & 38 deletions

File tree

src/components/BMDashboard/WeeklyProjectSummary/TotalMaterialCostPerProject/TotalMaterialCostPerProject.css

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,35 @@
2929

3030
.total-material-cost-per-project .select__menu {
3131
font-size: 12px;
32+
}
33+
34+
/* Dark mode for the Select Dropdown */
35+
.dark-mode .material-cost-per-project-dropdown .select__control {
36+
background-color: var(--section-bg) !important;
37+
border-color: var(--section-title-bg) !important;
38+
color: var(--text-color) !important;
39+
}
40+
41+
.dark-mode .material-cost-per-project-dropdown .select__menu {
42+
background-color: var(--section-bg) !important;
43+
}
44+
45+
.dark-mode .material-cost-per-project-dropdown .select__option:hover {
46+
background-color: #0d55b3;
47+
}
48+
49+
.dark-mode .material-cost-per-project-dropdown .select__option--is-focused{
50+
background-color: #0d55b3;
51+
}
52+
53+
.dark-mode .material-cost-per-project-dropdown .select__multi-value {
54+
background-color: #375071;
55+
}
56+
57+
.dark-mode .material-cost-per-project-dropdown .select__multi-value__label {
58+
color: white;
59+
}
60+
61+
.dark-mode .material-cost-per-project-dropdown .css-tj5bde-Svg:hover {
62+
fill: white;
3263
}

src/components/BMDashboard/WeeklyProjectSummary/TotalMaterialCostPerProject/TotalMaterialCostPerProject.jsx

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { useState } from 'react';
1+
import { useState, useEffect, useMemo } from 'react';
2+
import { useSelector } from 'react-redux';
23
import Select from 'react-select';
34
import {
45
Chart as ChartJS,
@@ -13,8 +14,6 @@ import { Bar } from 'react-chartjs-2';
1314
import { toast } from 'react-toastify';
1415
import axios from 'axios';
1516
import './TotalMaterialCostPerProject.css';
16-
import { useEffect } from 'react';
17-
import { useMemo } from 'react';
1817
import { ENDPOINTS } from 'utils/URL';
1918
import Loading from 'components/common/Loading';
2019

@@ -43,37 +42,49 @@ const projectDemoCosts = {
4342
'8': 876,
4443
};
4544

46-
const options = {
47-
responsive: true,
48-
maintainAspectRatio: false,
49-
plugins: {
50-
legend: {
51-
position: 'top',
52-
},
53-
title: {
54-
display: false,
55-
},
56-
},
57-
scales: {
58-
x: {
59-
ticks: {
60-
font: {
61-
size: 11,
62-
},
63-
callback(val) {
64-
const label = this.getLabelForValue(val);
65-
return label.length > 20 ? `${label.slice(0, 20)}…` : label;
66-
},
67-
},
68-
},
69-
},
70-
};
71-
7245
function TotalMaterialCostPerProject() {
7346
const [dataLoaded, setDataLoaded] = useState(false);
7447
const [allProjects, setAllProjects] = useState([]);
7548
const [projectCosts, setProjectCosts] = useState({});
7649
const [selectedProjects, setSelectedProjects] = useState([]);
50+
const darkMode = useSelector(state => state.theme.darkMode);
51+
const textColor = darkMode ? '#ffffff' : '#666';
52+
53+
const options = {
54+
responsive: true,
55+
maintainAspectRatio: false,
56+
plugins: {
57+
legend: {
58+
position: 'top',
59+
labels: { color: textColor },
60+
},
61+
title: {
62+
display: false,
63+
},
64+
},
65+
scales: {
66+
x: {
67+
grid: { display: false },
68+
ticks: {
69+
color: textColor,
70+
font: {
71+
size: 11,
72+
},
73+
callback(val) {
74+
// eslint-disable-next-line react/no-this-in-sfc
75+
const label = this.getLabelForValue(val);
76+
return label.length > 20 ? `${label.slice(0, 20)}…` : label;
77+
},
78+
},
79+
},
80+
y: {
81+
grid: { color: '#ccc' },
82+
ticks: {
83+
color: textColor,
84+
},
85+
},
86+
},
87+
};
7788

7889
useEffect(() => {
7990
const fetchData = async () => {
@@ -124,15 +135,15 @@ function TotalMaterialCostPerProject() {
124135
{
125136
label: 'Total Material Cost (*1000$)',
126137
data: selectedProjects.map(p => projectCosts[p.value]),
127-
backgroundColor: 'rgba(20, 137, 175, 1)',
138+
backgroundColor: 'rgb(23, 154, 197)',
128139
borderRadius: 10,
129140
},
130141
],
131142
};
132143
}, [selectedProjects, projectCosts]);
133144

134145
return (
135-
<div className="total-material-cost-per-project">
146+
<div className={`total-material-cost-per-project ${darkMode ? 'dark-mode' : ''}`}>
136147
<h2 className="total-material-cost-per-project-chart-title">
137148
Total Material Cost Per Project
138149
</h2>
@@ -145,7 +156,7 @@ function TotalMaterialCostPerProject() {
145156
options={allProjects}
146157
value={selectedProjects}
147158
onChange={setSelectedProjects}
148-
className="basic-multi-select"
159+
className="material-cost-per-project-dropdown basic-multi-select"
149160
classNamePrefix="select"
150161
defaultValue={allProjects}
151162
placeholder="Select Projects"

src/components/BMDashboard/WeeklyProjectSummary/TotalMaterialCostPerProject/__tests__/TotalMaterialCostPerProject.test.js

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { render, screen, waitFor, within, fireEvent } from '@testing-library/rea
22
import axios from 'axios';
33
import { toast } from 'react-toastify';
44
import userEvent from '@testing-library/user-event';
5+
import { Provider } from 'react-redux';
6+
import configureStore from 'redux-mock-store';
57
import TotalMaterialCostPerProject from '../TotalMaterialCostPerProject';
68

79
// Mocks
@@ -22,6 +24,12 @@ jest.mock('react-chartjs-2', () => ({
2224
),
2325
}));
2426

27+
const mockStore = configureStore([]);
28+
const store = mockStore({
29+
theme: { darkMode: false }, // Mock dark mode value
30+
// Include other necessary mock slices if needed
31+
});
32+
2533
const mockProjects = [
2634
{ projectId: 1, projectName: 'Project A' },
2735
{ projectId: 2, projectName: 'Project B' },
@@ -46,23 +54,35 @@ describe('TotalMaterialCostPerProject', () => {
4654
});
4755

4856
it('shows loading spinner on initial render and hide the spinner when data loads', async () => {
49-
const { getByTestId } = render(<TotalMaterialCostPerProject />);
57+
const { getByTestId } = render(
58+
<Provider store={store}>
59+
<TotalMaterialCostPerProject />
60+
</Provider>,
61+
);
5062
const loadingSpinner = getByTestId('loading');
5163
expect(loadingSpinner).toBeInTheDocument();
5264

5365
await waitFor(() => expect(loadingSpinner).not.toBeInTheDocument());
5466
});
5567

5668
it('renders bar chart when data loads successfully', async () => {
57-
render(<TotalMaterialCostPerProject />);
69+
render(
70+
<Provider store={store}>
71+
<TotalMaterialCostPerProject />
72+
</Provider>,
73+
);
5874
await waitFor(() => {
5975
// The slash help test partial content
6076
expect(screen.getByText(/Project A,Project B/)).toBeInTheDocument();
6177
});
6278
});
6379

6480
it('render selector when data loads successfully', async () => {
65-
render(<TotalMaterialCostPerProject />);
81+
render(
82+
<Provider store={store}>
83+
<TotalMaterialCostPerProject />
84+
</Provider>,
85+
);
6686
await waitFor(() => {
6787
expect(screen.getByText('Project A')).toBeInTheDocument();
6888
});
@@ -74,7 +94,11 @@ describe('TotalMaterialCostPerProject', () => {
7494
});
7595

7696
it('when select or deselect items in selector, the bar chart updates too', async () => {
77-
render(<TotalMaterialCostPerProject />);
97+
render(
98+
<Provider store={store}>
99+
<TotalMaterialCostPerProject />
100+
</Provider>,
101+
);
78102
await waitFor(() => {
79103
expect(screen.getByText('Project A')).toBeInTheDocument();
80104
});
@@ -109,7 +133,11 @@ describe('TotalMaterialCostPerProject', () => {
109133
}
110134
return Promise.reject(new Error('not found'));
111135
});
112-
render(<TotalMaterialCostPerProject />);
136+
render(
137+
<Provider store={store}>
138+
<TotalMaterialCostPerProject />
139+
</Provider>,
140+
);
113141
await waitFor(() => expect(toast.error).toHaveBeenCalled());
114142
});
115143

@@ -123,7 +151,11 @@ describe('TotalMaterialCostPerProject', () => {
123151
}
124152
return Promise.reject(new Error('not found'));
125153
});
126-
render(<TotalMaterialCostPerProject />);
154+
render(
155+
<Provider store={store}>
156+
<TotalMaterialCostPerProject />
157+
</Provider>,
158+
);
127159
await waitFor(() => expect(toast.error).toHaveBeenCalled());
128160
});
129161
});

0 commit comments

Comments
 (0)