Skip to content

Commit c2f7d52

Browse files
Merge pull request #4589 from OneCommunityGlobal/kristin-fix-todays-tag-for-community-portal-events
Sai Sandeep taking over for Kristin Add Today's Tag Dynamically for Events on Community Portal
2 parents 98930dc + 5a6dfd9 commit c2f7d52

8 files changed

Lines changed: 383 additions & 355 deletions

File tree

src/components/CommunityPortal/Reports/Participation/DropOffTracking.jsx

Lines changed: 25 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useSelector } from 'react-redux';
33
import styles from './Participation.module.css';
44
import { ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react';
55
import mockEvents from './mockData';
6+
import { filterEventsByDate } from './FilterByDate';
67

78
function DropOffTracking() {
89
const [selectedEvent, setSelectedEvent] = useState('All Events');
@@ -16,43 +17,12 @@ function DropOffTracking() {
1617

1718
const darkMode = useSelector(state => state.theme.darkMode);
1819

19-
const getDateRange = () => {
20-
const today = new Date();
21-
let startDate, endDate;
20+
const filteredEvents = filterEventsByDate(mockEvents, selectedTime);
2221

23-
if (selectedTime === 'Today') {
24-
startDate = new Date(today);
25-
startDate.setHours(0, 0, 0, 0);
26-
endDate = new Date(today);
27-
endDate.setHours(23, 59, 59, 999);
28-
} else if (selectedTime === 'This Week') {
29-
startDate = new Date(today);
30-
startDate.setDate(today.getDate() - today.getDay());
31-
startDate.setHours(0, 0, 0, 0);
32-
endDate = new Date(startDate);
33-
endDate.setDate(startDate.getDate() + 6);
34-
endDate.setHours(23, 59, 59, 999);
35-
} else if (selectedTime === 'This Month') {
36-
startDate = new Date(today.getFullYear(), today.getMonth(), 1);
37-
endDate = new Date(today.getFullYear(), today.getMonth() + 1, 0);
38-
endDate.setHours(23, 59, 59, 999);
39-
}
40-
41-
return { startDate, endDate };
42-
};
43-
44-
const filteredEvents = mockEvents.filter(event => {
45-
if (selectedEvent !== 'All Events' && event.eventType !== selectedEvent) {
46-
return false;
47-
}
48-
if (selectedTime !== 'All Time') {
49-
const { startDate, endDate } = getDateRange();
50-
const eventDate = new Date(event.eventDate);
51-
return eventDate >= startDate && eventDate <= endDate;
52-
}
53-
return true;
22+
const filteredEventsByEventType = filteredEvents.filter(event => {
23+
if (selectedEvent === 'All Events') return true;
24+
return event.eventType === selectedEvent;
5425
});
55-
5626
const handleOpenList = event => {
5727
setActiveEvent(event);
5828
setSelectedUsers([]);
@@ -74,24 +44,6 @@ function DropOffTracking() {
7444
}
7545
};
7646

77-
const parseRate = val => Number.parseFloat(val);
78-
79-
const sortedEvents = [...filteredEvents].sort((a, b) => {
80-
if (!sortColumn) return 0;
81-
let aVal = a[sortColumn];
82-
let bVal = b[sortColumn];
83-
if (sortColumn === 'noShowRate' || sortColumn === 'dropOffRate') {
84-
aVal = parseRate(aVal);
85-
bVal = parseRate(bVal);
86-
} else {
87-
aVal = aVal?.toLowerCase() ?? '';
88-
bVal = bVal?.toLowerCase() ?? '';
89-
}
90-
if (aVal < bVal) return sortDirection === 'asc' ? -1 : 1;
91-
if (aVal > bVal) return sortDirection === 'asc' ? 1 : -1;
92-
return 0;
93-
});
94-
9547
const sortIndicator = column => {
9648
if (sortColumn !== column) return <ArrowUpDown size={14} />;
9749
return sortDirection === 'asc' ? <ArrowUp size={14} /> : <ArrowDown size={14} />;
@@ -105,15 +57,23 @@ function DropOffTracking() {
10557
>
10658
<div className={`${styles.trackingHeader} ${darkMode ? styles.trackingHeaderDark : ''}`}>
10759
<h3>Drop-off and no-show rate tracking</h3>
108-
<div className={`${styles.trackingFilters} ${darkMode ? styles.trackingFiltersDark : ''}`}>
109-
<select value={selectedEvent} onChange={e => setSelectedEvent(e.target.value)}>
60+
<div className={styles.trackingFilters}>
61+
<select
62+
className={styles.filterDropdown}
63+
value={selectedEvent}
64+
onChange={e => setSelectedEvent(e.target.value)}
65+
>
11066
<option value="All Events">All Events</option>
11167
<option value="Yoga Class">Yoga Class</option>
11268
<option value="Cooking Workshop">Cooking Workshop</option>
11369
<option value="Dance Class">Dance Class</option>
11470
<option value="Fitness Bootcamp">Fitness Bootcamp</option>
11571
</select>
116-
<select value={selectedTime} onChange={e => setSelectedTime(e.target.value)}>
72+
<select
73+
className={styles.filterDropdown}
74+
value={selectedTime}
75+
onChange={e => setSelectedTime(e.target.value)}
76+
>
11777
<option value="All Time">All Time</option>
11878
<option value="Today">Today</option>
11979
<option value="This Week">This Week</option>
@@ -124,6 +84,10 @@ function DropOffTracking() {
12484

12585
<div className={styles.trackingSummary}>
12686
<div className={`${styles.trackingRate} ${darkMode ? styles.trackingRateDark : ''}`}>
87+
<p className={styles.trackingRateValue}>
88+
+5% <span>Last week</span>
89+
{/* People who signed up but did not show up */}
90+
</p>
12791
<p className={styles.trackingRateSubheading}>
12892
<span>
12993
<b>Drop-off rate</b>
@@ -135,6 +99,10 @@ function DropOffTracking() {
13599
</p>
136100
</div>
137101
<div className={`${styles.trackingRate} ${darkMode ? styles.trackingRateDark : ''}`}>
102+
<p className={styles.trackingRateValue}>
103+
+5% <span>Last week</span>
104+
{/* People who did not show up */}
105+
</p>
138106
<p className={styles.trackingRateSubheading}>
139107
<span>
140108
<b>No-show rate</b>
@@ -181,7 +149,7 @@ function DropOffTracking() {
181149
</thead>
182150

183151
<tbody>
184-
{sortedEvents.map(event => (
152+
{filteredEventsByEventType.map(event => (
185153
<tr key={event.id}>
186154
<td>{event.eventName}</td>
187155
<td className={styles.trackingRateGreen} style={{ color: 'green' }}>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Reusable filter for event lists based on date ranges.
3+
* @param {Array} events - Array of event objects containing an 'eventDate' property.
4+
* @param {string} filterType - 'Today', 'This Week', 'This Month', or 'All Time'.
5+
* @returns {Array} - The filtered subset of events.
6+
*/
7+
export const filterEventsByDate = (events, filterType) => {
8+
if (!events || !Array.isArray(events)) return [];
9+
10+
const today = new Date();
11+
// Normalize today to midnight for consistent range comparisons
12+
const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate());
13+
14+
const newEvents = events.toSorted(
15+
(a, b) => new Date(a.eventDate).getTime() - new Date(b.eventDate).getTime(),
16+
);
17+
18+
return newEvents.filter(event => {
19+
// Ensure we have a valid date object to compare
20+
const eventDate = new Date(event.eventDate);
21+
if (Number.isNaN(eventDate.getTime())) return false;
22+
23+
switch (filterType) {
24+
case 'Today':
25+
return eventDate.toDateString() === today.toDateString();
26+
27+
case 'This Week': {
28+
// Find Sunday of the current week
29+
const startOfWeek = new Date(startOfToday);
30+
startOfWeek.setDate(startOfToday.getDate() - today.getDay());
31+
startOfWeek.setHours(0, 0, 0, 0);
32+
33+
// Find Saturday of the current week
34+
const endOfWeek = new Date(startOfWeek);
35+
endOfWeek.setDate(startOfWeek.getDate() + 6);
36+
endOfWeek.setHours(23, 59, 59, 999);
37+
38+
return eventDate >= startOfWeek && eventDate <= endOfWeek;
39+
}
40+
41+
case 'This Month':
42+
return (
43+
eventDate.getMonth() === today.getMonth() &&
44+
eventDate.getFullYear() === today.getFullYear()
45+
);
46+
47+
case 'All Time':
48+
default:
49+
return true;
50+
}
51+
});
52+
};

0 commit comments

Comments
 (0)