Enhance date handling in RecentMailingStatsChart

- Import additional Dayjs plugins for UTC and timezone support.
- Update start and end dates to reflect the start and end of the day.
- Fetch mailing statistics using formatted date strings in the correct timezone.
- Modify statistics aggregation to include all dates in the range.
- Change aggregation method from `reduce` to `forEach`.
- Update x-axis value formatter to use UTC date formatting.
This commit is contained in:
David Headrick 2025-04-07 21:09:14 -05:00
parent 5e85b9e596
commit c14b33c77b

View File

@ -1,21 +1,28 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Box, Typography } from '@mui/material'; import { Box, Typography } from '@mui/material';
import { BarChart } from '@mui/x-charts/BarChart'; import { BarChart } from '@mui/x-charts/BarChart';
import dayjs from 'dayjs'; import dayjs from 'dayjs'; // Import Dayjs for date handling
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import MailingStatistic from '@/types/mailingStatistic'; import MailingStatistic from '@/types/mailingStatistic';
dayjs.extend(utc);
dayjs.extend(timezone);
export default function RecentMailingStatsChart({ days = 7 }: { days?: number }) { export default function RecentMailingStatsChart({ days = 7 }: { days?: number }) {
const [stats, setStats] = useState<MailingStatistic[]>([]); const [stats, setStats] = useState<MailingStatistic[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const startDate = dayjs().subtract(days, 'day').format('YYYY-MM-DD'); const startDate = dayjs().subtract(days, 'day').startOf('day');
const endDate = dayjs().format('YYYY-MM-DD'); const endDate = dayjs().endOf('day');
const startDateString = dayjs.utc(startDate).tz("America/Chicago").format("YYYY-M-D");
const endDateString = dayjs.utc(endDate).tz("America/Chicago").format("YYYY-M-D")
useEffect(() => {
//startDate = '2025-02-12';
//endDate = '2025-02-26'
const fetchStats = async () => { const fetchStats = async () => {
try { try {
const response = await fetch(`/api/mailings/status/s%2Csd/stats?startDate=${startDate}&endDate=${endDate}`); const response = await fetch(`/api/mailings/status/s%2Csd/stats?startDate=${startDateString}&endDate=${endDateString}`);
const data: MailingStatistic[] = await response.json(); const data: MailingStatistic[] = await response.json();
setStats(data); setStats(data);
} catch (error) { } catch (error) {
@ -25,21 +32,31 @@ export default function RecentMailingStatsChart({ days = 7 }: { days?: number })
} }
}; };
useEffect(() => {
fetchStats(); fetchStats();
const intervalId = setInterval(fetchStats, 5000); const intervalId = setInterval(fetchStats, 5000);
return () => clearInterval(intervalId); return () => clearInterval(intervalId);
}, [days]); }, [days, startDateString, endDateString]);
if (loading) { if (loading) {
return <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>Loading...</Box>; return <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>Loading...</Box>;
} }
// Aggregate stats by date const aggregatedStats: Record<string, {
const aggregatedStats = stats.reduce((acc, stat) => { sentCount: number;
const dateStr = stat.sentDate ? dayjs(stat.sentDate).format('YYYY-MM-DD') : dayjs().format('YYYY-MM-DD'); deliveredCount: number;
if (!acc[dateStr]) { failedCount: number;
acc[dateStr] = { bounceCount: number;
blockedCount: number;
invalidCount: number
}> = {};
let currentDate = startDate;
const endDateFormatted = endDate.format('YYYY-MM-DD');
// Include all dates from startDate to endDate (today)
while (!currentDate.isAfter(endDate, 'day')) {
const dateStr = currentDate.format('YYYY-MM-DD');
aggregatedStats[dateStr] = {
sentCount: 0, sentCount: 0,
deliveredCount: 0, deliveredCount: 0,
failedCount: 0, failedCount: 0,
@ -47,15 +64,21 @@ export default function RecentMailingStatsChart({ days = 7 }: { days?: number })
blockedCount: 0, blockedCount: 0,
invalidCount: 0, invalidCount: 0,
}; };
currentDate = currentDate.add(1, 'day');
} }
acc[dateStr].sentCount += stat.sendCount;
acc[dateStr].deliveredCount += stat.deliveredCount; // Aggregate stats by date
acc[dateStr].failedCount += stat.failedCount; stats.forEach(stat => {
acc[dateStr].bounceCount += stat.bounceCount; const dateStr = stat.sentDate ? dayjs(stat.sentDate).format('YYYY-MM-DD') : endDateFormatted;
acc[dateStr].blockedCount += stat.blockedCount; if (aggregatedStats[dateStr]) {
acc[dateStr].invalidCount += stat.invalidCount; aggregatedStats[dateStr].sentCount += stat.sendCount;
return acc; aggregatedStats[dateStr].deliveredCount += stat.deliveredCount;
}, {} as Record<string, { sentCount: number; deliveredCount: number; failedCount: number; bounceCount: number; blockedCount: number; invalidCount: number }>); aggregatedStats[dateStr].failedCount += stat.failedCount;
aggregatedStats[dateStr].bounceCount += stat.bounceCount;
aggregatedStats[dateStr].blockedCount += stat.blockedCount;
aggregatedStats[dateStr].invalidCount += stat.invalidCount;
}
});
// Prepare chart data, sorted by date ascending // Prepare chart data, sorted by date ascending
const sortedDates = Object.keys(aggregatedStats).sort((a, b) => dayjs(a).isBefore(dayjs(b)) ? -1 : 1); const sortedDates = Object.keys(aggregatedStats).sort((a, b) => dayjs(a).isBefore(dayjs(b)) ? -1 : 1);
@ -103,7 +126,7 @@ export default function RecentMailingStatsChart({ days = 7 }: { days?: number })
{ {
scaleType: 'band', scaleType: 'band',
data: dates, data: dates,
valueFormatter: (value) => dayjs(value).format("MMM DD"), valueFormatter: (value) => dayjs.utc(value).format("MMM DD"),
}, },
]} ]}
/> />