Skip to content

Commit 9ecb141

Browse files
Merge pull request #4588 from OneCommunityGlobal/fix/event-stats-number-alignment
Namitha: Fixed number alignment in Most Popular Event chart and convert to CSS modules
2 parents 0700b7e + 4d82267 commit 9ecb141

2 files changed

Lines changed: 171 additions & 89 deletions

File tree

src/components/CommunityPortal/EventPersonalization/EventStats.jsx

Lines changed: 58 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ export default function PopularEvents() {
5858
const [timeFilter, setTimeFilter] = useState('All day');
5959
const [typeFilter, setTypeFilter] = useState('All');
6060

61-
const calculatePercentage = (attended, enrolled) => Math.round((attended / enrolled) * 100);
61+
const calculatePercentage = (attended, enrolled) =>
62+
enrolled === 0 ? 0 : Math.round((attended / enrolled) * 100);
6263

6364
const getBarColor = percentage => {
6465
if (percentage > 60) return 'green';
@@ -72,39 +73,37 @@ export default function PopularEvents() {
7273
return timeMatch && typeMatch;
7374
});
7475

75-
const mostPopularEvent = filteredData.reduce(
76-
(max, event) =>
77-
calculatePercentage(event.attended, event.enrolled) >
78-
calculatePercentage(max.attended, max.enrolled)
79-
? event
80-
: max,
81-
filteredData[0] || {},
82-
);
76+
const mostPopularEvent =
77+
filteredData.length > 0
78+
? filteredData.reduce(
79+
(max, event) =>
80+
calculatePercentage(event.attended, event.enrolled) >
81+
calculatePercentage(max.attended, max.enrolled)
82+
? event
83+
: max,
84+
filteredData[0],
85+
)
86+
: null;
8387

84-
const leastPopularEvent = filteredData.reduce(
85-
(min, event) =>
86-
calculatePercentage(event.attended, event.enrolled) <
87-
calculatePercentage(min.attended, min.enrolled)
88-
? event
89-
: min,
90-
filteredData[0] || {},
91-
);
88+
const leastPopularEvent =
89+
filteredData.length > 0
90+
? filteredData.reduce(
91+
(min, event) =>
92+
calculatePercentage(event.attended, event.enrolled) <
93+
calculatePercentage(min.attended, min.enrolled)
94+
? event
95+
: min,
96+
filteredData[0],
97+
)
98+
: null;
9299
const darkMode = useSelector(state => state.theme.darkMode);
93100
return (
94-
<div
95-
className={`${styles.popularEventsContainer} ${
96-
darkMode ? styles.popularEventsContainerDark : ''
97-
}`}
98-
>
99-
<div className={`${styles.headerContainer} ${darkMode ? styles.headerContainerDark : ''}`}>
100-
<h2
101-
className={`${styles.popularEventsHeader} ${
102-
darkMode ? styles.popularEventsHeaderDark : ''
103-
}`}
104-
>
101+
<div className={darkMode ? styles.popularEventsContainerDark : styles.popularEventsContainer}>
102+
<div className={darkMode ? styles.headerContainerDark : styles.headerContainer}>
103+
<h2 className={darkMode ? styles.popularEventsHeaderDark : styles.popularEventsHeader}>
105104
Most Popular Event
106105
</h2>
107-
<div className={`${styles.filters} ${darkMode ? styles.filtersDark : ''}`}>
106+
<div className={darkMode ? styles.filtersDark : styles.filters}>
108107
<select value={timeFilter} onChange={e => setTimeFilter(e.target.value)}>
109108
<option value="All day">All day</option>
110109
<option value="Morning">Morning</option>
@@ -118,60 +117,58 @@ export default function PopularEvents() {
118117
</select>
119118
</div>
120119
</div>
121-
<div className={`${styles.stats} ${darkMode ? styles.statsDark : ''}`}>
122-
{filteredData.map(event => (
123-
<div key={event.id} className={styles.statItem}>
124-
<div className={`${styles.statLabel} ${darkMode ? styles.statLabelDark : ''}`}>
125-
{event.type}
126-
</div>
127-
<div className={styles.statBar}>
128-
<div
129-
className={`${styles.bar} ${
130-
styles[getBarColor(calculatePercentage(event.attended, event.enrolled))]
131-
}`}
132-
style={{ width: `${calculatePercentage(event.attended, event.enrolled)}%` }}
133-
/>
134-
</div>
135-
<div className={`${styles.statValue} ${darkMode ? styles.statValueDark : ''}`}>
136-
{`${calculatePercentage(event.attended, event.enrolled)}% (${event.attended}/${
137-
event.enrolled
138-
})`}
120+
121+
<div className={darkMode ? styles.statsDark : styles.stats}>
122+
{filteredData.map(event => {
123+
const percentage = calculatePercentage(event.attended, event.enrolled);
124+
return (
125+
<div key={event.id} className={styles.statItem}>
126+
<div className={darkMode ? styles.statLabelDark : styles.statLabel}>{event.type}</div>
127+
<div className={styles.statBar}>
128+
<div
129+
className={`${styles.bar} ${styles[getBarColor(percentage)]}`}
130+
style={{ width: `${percentage}%` }}
131+
/>
132+
</div>
133+
<div className={darkMode ? styles.statValueDark : styles.statValue}>
134+
{`${percentage}% (${event.attended}/${event.enrolled})`}
135+
</div>
139136
</div>
140-
</div>
141-
))}
137+
);
138+
})}
142139
</div>
143140
<div className={styles.eventSummary}>
144-
<div className={`${styles.summaryItem} ${darkMode ? styles.summaryItemDark : ''}`}>
145-
<div className={`${styles.summaryTitle} ${darkMode ? styles.summaryTitleDark : ''}`}>
141+
<div className={darkMode ? styles.summaryItemDark : styles.summaryItem}>
142+
<div className={darkMode ? styles.summaryTitleDark : styles.summaryTitle}>
146143
Total Number of Events
147144
</div>
148-
<div className={`${styles.summaryValue} ${darkMode ? styles.summaryValueDark : ''}`}>
145+
<div className={darkMode ? styles.summaryValueDark : styles.summaryValue}>
149146
{filteredData.length}
150147
</div>
151148
</div>
152-
<div className={`${styles.summaryItem} ${darkMode ? styles.summaryItemDark : ''}`}>
153-
<div className={`${styles.summaryTitle} ${darkMode ? styles.summaryTitleDark : ''}`}>
149+
<div className={darkMode ? styles.summaryItemDark : styles.summaryItem}>
150+
<div className={darkMode ? styles.summaryTitleDark : styles.summaryTitle}>
154151
Total Number of Event Enrollments
155152
</div>
156-
<div className={`${styles.summaryValue} ${darkMode ? styles.summaryValueDark : ''}`}>
153+
<div className={darkMode ? styles.summaryValueDark : styles.summaryValue}>
157154
{filteredData.reduce((acc, event) => acc + event.enrolled, 0)}
158155
</div>
159156
</div>
160157
{filteredData.length > 0 && (
161158
<>
162-
<div className={`${styles.summaryItem} ${darkMode ? styles.summaryItemDark : ''}`}>
163-
<div className={`${styles.summaryTitle} ${darkMode ? styles.summaryTitleDark : ''}`}>
159+
<div className={darkMode ? styles.summaryItemDark : styles.summaryItem}>
160+
<div className={darkMode ? styles.summaryTitleDark : styles.summaryTitle}>
164161
Most Popular Event
165162
</div>
166-
<div className={`${styles.summaryValue} ${darkMode ? styles.summaryValueDark : ''}`}>
163+
<div className={darkMode ? styles.summaryValueDark : styles.summaryValue}>
167164
{mostPopularEvent.type || 'N/A'}
168165
</div>
169166
</div>
170-
<div className={`${styles.summaryItem} ${darkMode ? styles.summaryItemDark : ''}`}>
171-
<div className={`${styles.summaryTitle} ${darkMode ? styles.summaryTitleDark : ''}`}>
167+
<div className={darkMode ? styles.summaryItemDark : styles.summaryItem}>
168+
<div className={darkMode ? styles.summaryTitleDark : styles.summaryTitle}>
172169
Least Popular Event
173170
</div>
174-
<div className={`${styles.summaryValue} ${darkMode ? styles.summaryValueDark : ''}`}>
171+
<div className={darkMode ? styles.summaryValueDark : styles.summaryValue}>
175172
{leastPopularEvent.type || 'N/A'}
176173
</div>
177174
</div>

src/components/CommunityPortal/EventPersonalization/EventStats.module.css

Lines changed: 113 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
.popularEventsContainer {
2-
32
max-height: 100%;
43
margin: 0 auto;
54
padding: 20px;
@@ -8,7 +7,6 @@
87
}
98

109
.popularEventsContainerDark {
11-
1210
margin: 0 auto;
1311
padding: 20px;
1412
font-family: Arial, sans-serif;
@@ -33,15 +31,13 @@
3331
font-size: 1.5rem;
3432
color: #000000;
3533
margin: 0;
36-
font-weight: 700;
3734
}
3835

3936
.popularEventsHeaderDark {
4037
font-size: 1.5rem;
4138
color: #ffffff;
4239
margin: 0;
4340
background-color: #1C2541;
44-
font-weight: 700;
4541
}
4642

4743
.filters {
@@ -55,17 +51,6 @@
5551
background-color: #1C2541;
5652
}
5753

58-
.filtersDark select {
59-
background-color: #2d3748;
60-
border-color: #4a5568;
61-
color: #fff;
62-
}
63-
64-
.filtersDark select option {
65-
background-color: #2d3748;
66-
color: #fff;
67-
}
68-
6954
.filters select {
7055
padding: 6px;
7156
font-size: 14px;
@@ -94,33 +79,29 @@
9479
}
9580

9681
.statItem {
97-
display: flex;
82+
display: grid;
83+
grid-template-columns: 140px 1fr auto;
9884
align-items: center;
99-
justify-content: space-between;
85+
gap: 15px;
10086
}
10187

102-
103-
10488
.statLabel {
105-
flex: 1;
10689
font-size: 14px;
10790
font-weight: bold;
10891
color: #333;
10992
}
11093

11194
.statLabelDark {
112-
flex: 1;
11395
font-size: 14px;
11496
font-weight: bold;
11597
color: #ffffff;
11698
}
11799

118100
.statBar {
119-
flex: 3;
101+
width: 100%;
120102
background: #f0f0f0;
121103
height: 8px;
122104
border-radius: 5px;
123-
margin: 0 10px;
124105
position: relative;
125106
overflow: hidden;
126107
}
@@ -144,26 +125,27 @@
144125
}
145126

146127
.statValue {
147-
flex: 1;
148-
text-align: right;
149128
font-size: 14px;
150129
font-weight: bold;
151130
color: #333;
131+
white-space: nowrap;
132+
text-align: right;
133+
min-width: 110px;
152134
}
153135

154136
.statValueDark {
155-
flex: 1;
156-
text-align: right;
157137
font-size: 14px;
158138
font-weight: bold;
159139
color: #ffffff;
140+
white-space: nowrap;
141+
text-align: right;
142+
min-width: 110px;
160143
}
161144

162145
.eventSummary {
163146
display: grid;
164147
grid-template-columns: repeat(4, 1fr);
165148
gap: 10px;
166-
max-height: 80px;
167149
margin-top: 20px;
168150
border-radius: 8px;
169151
text-align: center;
@@ -232,4 +214,107 @@
232214
font-weight: bold;
233215
color: #ffffff;
234216
margin-top: 4px;
217+
}
218+
219+
/* ── Responsive: tablets and below ── */
220+
@media (max-width: 768px) {
221+
.popularEventsContainer,
222+
.popularEventsContainerDark {
223+
padding: 14px;
224+
}
225+
226+
.headerContainer,
227+
.headerContainerDark {
228+
flex-direction: column;
229+
align-items: flex-start;
230+
gap: 10px;
231+
}
232+
233+
.popularEventsHeader,
234+
.popularEventsHeaderDark {
235+
font-size: 1.2rem;
236+
}
237+
238+
.filters,
239+
.filtersDark {
240+
width: 100%;
241+
flex-wrap: wrap;
242+
}
243+
244+
.filters select,
245+
.filtersDark select {
246+
flex: 1;
247+
min-width: 100px;
248+
}
249+
250+
.stats,
251+
.statsDark {
252+
padding: 16px;
253+
gap: 14px;
254+
}
255+
256+
.statItem {
257+
grid-template-columns: 1fr auto;
258+
grid-template-rows: auto auto;
259+
gap: 6px 10px;
260+
}
261+
262+
.statLabel,
263+
.statLabelDark {
264+
grid-column: 1 / -1;
265+
font-size: 13px;
266+
}
267+
268+
.statBar {
269+
grid-column: 1;
270+
grid-row: 2;
271+
}
272+
273+
.statValue,
274+
.statValueDark {
275+
grid-column: 2;
276+
grid-row: 2;
277+
font-size: 13px;
278+
min-width: unset;
279+
}
280+
281+
.eventSummary {
282+
grid-template-columns: repeat(2, 1fr);
283+
gap: 10px;
284+
padding-bottom: 14px;
285+
}
286+
287+
.summaryItem,
288+
.summaryItemDark {
289+
min-height: 70px;
290+
padding: 10px;
291+
}
292+
293+
.summaryTitle,
294+
.summaryTitleDark {
295+
font-size: 12px;
296+
}
297+
298+
.summaryValue,
299+
.summaryValueDark {
300+
font-size: 13px;
301+
}
302+
}
303+
304+
/* ── Responsive: small phones ── */
305+
@media (max-width: 480px) {
306+
.popularEventsHeader,
307+
.popularEventsHeaderDark {
308+
font-size: 1.1rem;
309+
}
310+
311+
.statLabel,
312+
.statLabelDark {
313+
font-size: 12px;
314+
}
315+
316+
.statValue,
317+
.statValueDark {
318+
font-size: 12px;
319+
}
235320
}

0 commit comments

Comments
 (0)