Files
babymonitor/frontend/src/components/stats/BedtimePlot.tsx
T

94 lines
3.0 KiB
TypeScript

import { useEffect, useState } from 'react';
import { useStats } from '../../hooks/useStats';
import { formatMinutesAfter, getToday, getLocalOffsetFromReference } from '../../utils/time';
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from 'recharts';
interface WakeupBedtimeProps {
from_date: string;
to_date: string;
wakeup_ref: string;
bedtime_ref: string;
}
const BedtimePlot: React.FC<WakeupBedtimeProps> = ({ from_date, to_date, wakeup_ref, bedtime_ref }) => {
const { wakeupBedtime, isLoading } = useStats(from_date, to_date, '07:00', '20:00', wakeup_ref, bedtime_ref);
const [chartData, setChartData] = useState<{ date: string; minutes: number; time: string }[]>([]);
useEffect(() => {
if (!wakeupBedtime?.days) {
setChartData([]);
return;
}
const data = wakeupBedtime.days.map((day) => {
const daysAgo = Math.floor(
(new Date(getToday()).getTime() - new Date(day.date).getTime()) / (1000 * 60 * 60 * 24)
);
const offsetFromRef = day.bedtime_minutes !== null ? getLocalOffsetFromReference(day.bedtime_minutes, bedtime_ref) : 0;
return {
date: daysAgo === 0 ? 'Today' : `${daysAgo}d ago`,
minutes: offsetFromRef,
time:
day.bedtime_minutes !== null
? formatMinutesAfter(offsetFromRef, bedtime_ref)
: 'N/A',
};
}).reverse();
setChartData(data);
}, [wakeupBedtime, bedtime_ref]);
if (isLoading) return <div className="text-center p-4">Loading plot...</div>;
if (!chartData.length) {
return <div className="text-center p-4 text-gray-500">No data available for this period.</div>;
}
return (
<div className="bg-white p-4 rounded-xl shadow-sm border border-gray-200">
<h3 className="text-lg font-semibold mb-4 text-gray-800">Bedtime</h3>
<ResponsiveContainer width="100%" height={200}>
<LineChart data={chartData} margin={{ top: 5, right: 20, left: 0, bottom: 5 }}>
<CartesianGrid strokeDasharray="3 3" stroke="#e5e7eb" />
<XAxis
dataKey="date"
tick={{ fontSize: 12 }}
tickLine={false}
axisLine={{ stroke: '#e5e7eb' }}
/>
<YAxis
tick={{ fontSize: 12 }}
tickLine={false}
axisLine={{ stroke: '#e5e7eb' }}
tickFormatter={(value) => formatMinutesAfter(value, bedtime_ref)}
domain={['dataMin - 30', 'dataMax + 30']}
/>
<Tooltip
formatter={(value: any) => [
value !== undefined ? formatMinutesAfter(value, bedtime_ref) : '',
'Bedtime',
] as any}
labelFormatter={(label) => label}
/>
<Line
type="monotone"
dataKey="minutes"
stroke="#8b5cf6"
strokeWidth={2}
dot={{ fill: '#8b5cf6', r: 4 }}
connectNulls={false}
/>
</LineChart>
</ResponsiveContainer>
</div>
);
};
export default BedtimePlot;