Skip to content

Commit e3f8d98

Browse files
committed
feat(ui): add dark mode support for filters, tiles, and chart
1 parent ad9088f commit e3f8d98

2 files changed

Lines changed: 194 additions & 81 deletions

File tree

src/components/BMDashboard/Issues/IssueGraph.jsx

Lines changed: 88 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -61,93 +61,103 @@ function IssueGraph() {
6161
};
6262

6363
return (
64-
<div className={styles.issueGraphEventContainer}>
65-
<div className={styles.filterRow}>
66-
<div className={styles.filterGroup}>
67-
<label htmlFor="start-date">Start Date:</label>
68-
<input
69-
id="start-date"
70-
type="date"
71-
value={startDate}
72-
onChange={e => setStartDate(e.target.value)}
73-
min={minStartDate}
74-
max={maxStartDate}
75-
/>
76-
</div>
77-
78-
<div className={styles.filterGroup}>
79-
<label htmlFor="end-date">End Date:</label>
80-
<div className={styles.inputWithButton}>
64+
<div className={`${styles.issueGraphPage} ${darkMode ? styles.darkMode : ''}`}>
65+
<div className={styles.issueGraphEventContainer}>
66+
<div className={styles.filterRow}>
67+
<div className={styles.filterGroup}>
68+
<label htmlFor="start-date">Start Date:</label>
8169
<input
82-
id="end-date"
70+
id="start-date"
8371
type="date"
84-
value={endDate}
85-
onChange={e => setEndDate(e.target.value)}
86-
min={minEndDate}
87-
max={maxEndDate}
72+
value={startDate}
73+
onChange={e => setStartDate(e.target.value)}
74+
min={minStartDate}
75+
max={maxStartDate}
8876
/>
89-
<button className={styles.goButton} onClick={handleGoClick}>
90-
Go
91-
</button>
9277
</div>
93-
</div>
9478

95-
<div className={styles.filterGroup}>
96-
<label htmlFor="weeks-select">Weeks:</label>
97-
<select id="weeks-select" value={weeks} onChange={handleWeeksChange}>
98-
<option value={4}>Last 4 Weeks</option>
99-
<option value={8}>Last 8 Weeks</option>
100-
<option value={12}>Last 12 Weeks</option>
101-
</select>
102-
</div>
103-
</div>
104-
105-
{startDate && endDate && new Date(startDate) > new Date(endDate) && (
106-
<p style={{ color: 'red' }}>Start date cannot be after end date.</p>
107-
)}
108-
{/* issue tiles */}
109-
{issueSummary && (
110-
<div className={styles.tileRow}>
111-
<div className={styles.tile}>
112-
<h3>Total Issues</h3>
113-
<p>{issueSummary.total}</p>
114-
</div>
115-
<div className={styles.tile}>
116-
<h3>New Issues This Week</h3>
117-
<p>{issueSummary.newThisWeek}</p>
79+
<div className={styles.filterGroup}>
80+
<label htmlFor="end-date">End Date:</label>
81+
<div className={styles.inputWithButton}>
82+
<input
83+
id="end-date"
84+
type="date"
85+
value={endDate}
86+
onChange={e => setEndDate(e.target.value)}
87+
min={minEndDate}
88+
max={maxEndDate}
89+
/>
90+
<button className={styles.goButton} onClick={handleGoClick}>
91+
Go
92+
</button>
93+
</div>
11894
</div>
119-
<div className={styles.tile}>
120-
<h3>Resolved Issues</h3>
121-
<p>{issueSummary.resolved}</p>
122-
</div>
123-
<div className={styles.tile}>
124-
<h3>Avg. Resolution Time</h3>
125-
<p>{issueSummary.avgResolution} days</p>
95+
96+
<div className={styles.filterGroup}>
97+
<label htmlFor="weeks-select">Weeks:</label>
98+
<select id="weeks-select" value={weeks} onChange={handleWeeksChange}>
99+
<option value={4}>Last 4 Weeks</option>
100+
<option value={8}>Last 8 Weeks</option>
101+
<option value={12}>Last 12 Weeks</option>
102+
</select>
126103
</div>
127104
</div>
128-
)}
129-
{/* charts */}
130-
<div className={styles.graphWrapper}>
131-
<h2>Issues Created vs. Resolved</h2>
132-
{loading && <p>Loading...</p>}
133-
{error && <p style={{ color: 'red' }}>{error}</p>}
134-
{graphData.length > 0 && (
135-
<ResponsiveContainer width="100%" height={400}>
136-
<BarChart data={graphData} margin={{ top: 20, right: 20, left: 0, bottom: 30 }}>
137-
<CartesianGrid strokeDasharray="3 3" />
138-
<XAxis dataKey="week" />
139-
<YAxis />
140-
<Tooltip />
141-
<Legend verticalAlign="bottom" height={36} />
142-
<Bar dataKey="created" fill="#007bff" name="Created Issues">
143-
<LabelList dataKey="created" position="top" />
144-
</Bar>
145-
<Bar dataKey="resolved" fill="#28a745" name="Resolved Issues">
146-
<LabelList dataKey="resolved" position="top" />
147-
</Bar>
148-
</BarChart>
149-
</ResponsiveContainer>
105+
106+
{startDate && endDate && new Date(startDate) > new Date(endDate) && (
107+
<p style={{ color: 'red' }}>Start date cannot be after end date.</p>
150108
)}
109+
{/* issue tiles */}
110+
{issueSummary && (
111+
<div className={styles.tileRow}>
112+
<div className={styles.tile}>
113+
<h3>Total Issues</h3>
114+
<p>{issueSummary.total}</p>
115+
</div>
116+
<div className={styles.tile}>
117+
<h3>New Issues This Week</h3>
118+
<p>{issueSummary.newThisWeek}</p>
119+
</div>
120+
<div className={styles.tile}>
121+
<h3>Resolved Issues</h3>
122+
<p>{issueSummary.resolved}</p>
123+
</div>
124+
<div className={styles.tile}>
125+
<h3>Avg. Resolution Time</h3>
126+
<p>{issueSummary.avgResolution} days</p>
127+
</div>
128+
</div>
129+
)}
130+
{/* charts */}
131+
<div className={styles.graphWrapper}>
132+
<h2>Issues Created vs. Resolved</h2>
133+
{loading && <p>Loading...</p>}
134+
{error && <p style={{ color: 'red' }}>{error}</p>}
135+
{graphData.length > 0 && (
136+
<ResponsiveContainer width="100%" height="100%">
137+
<BarChart data={graphData} margin={{ top: 20, right: 20, left: 0, bottom: 30 }}>
138+
<CartesianGrid strokeDasharray="3 3" />
139+
<XAxis dataKey="week" />
140+
<YAxis />
141+
<Tooltip />
142+
<Legend verticalAlign="bottom" height={36} />
143+
<Bar
144+
dataKey="created"
145+
fill={darkMode ? '#4fc3f7' : '#007bff'}
146+
name="Created Issues"
147+
>
148+
<LabelList dataKey="created" position="top" />
149+
</Bar>
150+
<Bar
151+
dataKey="resolved"
152+
fill={darkMode ? '#81c784' : '#28a745'}
153+
name="Resolved Issues"
154+
>
155+
<LabelList dataKey="resolved" position="top" />
156+
</Bar>
157+
</BarChart>
158+
</ResponsiveContainer>
159+
)}
160+
</div>
151161
</div>
152162
</div>
153163
);

src/components/BMDashboard/Issues/IssueGraph.module.css

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,48 @@
1+
.issueGraphPage {
2+
min-height: 100vh;
3+
width: 100%;
4+
background-color: #f0f4f8;
5+
display: flex;
6+
justify-content: center;
7+
align-items: flex-start;
8+
padding: 40px 0;
9+
box-sizing: border-box;
10+
overflow-y: auto;
11+
}
12+
113
.issueGraphEventContainer {
214
max-width: 1200px;
3-
margin: 0 auto;
15+
width: 100%;
16+
margin: 0 24px;
417
padding: 24px 24px 40px 24px;
518
background: #f9f9f9;
619
border-radius: 8px;
20+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
21+
22+
display: flex;
23+
flex-direction: column;
24+
gap: 20px;
25+
box-sizing: border-box;
26+
max-height: calc(100vh - 80px);
27+
overflow: auto;
728
}
29+
30+
.graphWrapper {
31+
display: flex;
32+
flex-direction: column;
33+
justify-content: center;
34+
align-items: stretch;
35+
height: 420px;
36+
min-height: 300px;
37+
padding: 20px;
38+
}
39+
40+
.graphWrapper .recharts-responsive-container {
41+
width: 100%;
42+
height: 100%;
43+
}
44+
45+
846
.filterRow {
947
display: flex;
1048
justify-content: space-between;
@@ -13,7 +51,7 @@
1351
padding: 16px 20px;
1452
border-radius: 8px;
1553
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
16-
margin-bottom: 20px;
54+
margin-bottom: 5px;
1755
flex-wrap: wrap;
1856
gap: 20px;
1957
}
@@ -71,8 +109,9 @@
71109
justify-content: space-between;
72110
align-items: stretch;
73111
gap: 20px;
74-
margin-bottom: 20px;
112+
margin-bottom: 5px;
75113
flex-wrap: nowrap;
114+
padding: 15px 30px;
76115
}
77116

78117
.tile {
@@ -109,3 +148,67 @@
109148
}
110149
}
111150

151+
/* dark mode */
152+
.darkMode {
153+
background-color: #1b2a41;
154+
color: #f5f5f5;
155+
}
156+
.darkMode .issueGraphPage {
157+
background-color: #1b2a41;
158+
color: #f5f5f5;
159+
}
160+
.darkMode .issueGraphEventContainer {
161+
background: #253342;
162+
color: #f5f5f5;
163+
}
164+
.darkMode .filterRow,
165+
.darkMode .tileRow,
166+
.darkMode .graphWrapper {
167+
background-color: #1b2a41;
168+
color: #f5f5f5;
169+
}
170+
171+
/* Filter groups */
172+
.darkMode .filterGroup label {
173+
color: #f5f5f5;
174+
}
175+
.darkMode .filterRow label {
176+
background-color: transparent;
177+
color: #f5f5f5;
178+
border: none;
179+
}
180+
.darkMode input[type='date'],
181+
.darkMode select,
182+
.darkMode .goButton {
183+
background-color: #253342;
184+
color: #f5f5f5;
185+
border: 1px solid #555;
186+
}
187+
188+
/* Tiles */
189+
.darkMode .tile {
190+
background-color: #2b3e59;
191+
color: #f5f5f5;
192+
border: 1px solid #30b8f8;
193+
}
194+
.darkMode .tile h3 {
195+
color: #ffffff;
196+
}
197+
.darkMode .graphWrapper h2 {
198+
color: #ffffff;
199+
}
200+
201+
.darkMode .recharts-cartesian-axis-tick-value {
202+
fill: #ffffff;
203+
}
204+
.darkMode .recharts-legend-item-text {
205+
fill: #ffffff;
206+
}
207+
208+
.darkMode .goButton :hover {
209+
background-color: #1a73e8;
210+
}
211+
.darkMode .goButton :focus {
212+
outline: 2px solid #1a73e8;
213+
outline-offset: 2px;
214+
}

0 commit comments

Comments
 (0)