diff --git a/frontend/src/components/stats/SessionList.tsx b/frontend/src/components/stats/SessionList.tsx index 374e41c..2bd6ea7 100644 --- a/frontend/src/components/stats/SessionList.tsx +++ b/frontend/src/components/stats/SessionList.tsx @@ -1,15 +1,29 @@ import React, { useState } from 'react'; import { useSessions } from '../../hooks/useSleepSession'; +import { useSettings } from '../../hooks/useSettings'; +import { Pagination } from './Pagination'; import { Edit2, Check, X, Trash2 } from 'lucide-react'; import type { SleepSessionRead } from '../../types'; import { formatDateTime, toLocalDatetimeInputValue, getDurationMinutes, formatMinutes } from '../../utils/time'; export function SessionList() { const { sessions, isLoading, updateSession, deleteSession, isDeleting } = useSessions(); + const { settings } = useSettings(); + const sessionsPerPage = settings.sessionsPerPage; + + const [currentPage, setCurrentPage] = useState(1); const [editingId, setEditingId] = useState(null); const [editStart, setEditStart] = useState(''); const [editEnd, setEditEnd] = useState(''); + const totalPages = Math.ceil(sessions.length / sessionsPerPage); + const clampedPage = Math.max(1, Math.min(currentPage, totalPages || 1)); + + const paginatedSessions = sessions.slice( + (clampedPage - 1) * sessionsPerPage, + clampedPage * sessionsPerPage + ); + if (isLoading) return
Loading sessions...
; if (!sessions.length) return
No sessions recorded.
; @@ -55,7 +69,7 @@ export function SessionList() {

Sleep Sessions

- {sessions.map((s) => ( + {paginatedSessions.map((s) => (
{editingId === s.id ? (
@@ -140,6 +154,13 @@ export function SessionList() {
))}
+ {sessions.length > sessionsPerPage && ( + + )}
); } diff --git a/frontend/src/components/stats/SettingsPopover.tsx b/frontend/src/components/stats/SettingsPopover.tsx index 005a302..8031392 100644 --- a/frontend/src/components/stats/SettingsPopover.tsx +++ b/frontend/src/components/stats/SettingsPopover.tsx @@ -6,15 +6,17 @@ interface SettingsPopoverProps { dayEnd: string; wakeupRef: string; bedtimeRef: string; - onSave: (settings: { dayStart: string; dayEnd: string; wakeupRef: string; bedtimeRef: string }) => void; + sessionsPerPage: number; + onSave: (settings: { dayStart: string; dayEnd: string; wakeupRef: string; bedtimeRef: string; sessionsPerPage: number }) => void; } -export function SettingsPopover({ dayStart, dayEnd, wakeupRef, bedtimeRef, onSave }: SettingsPopoverProps) { +export function SettingsPopover({ dayStart, dayEnd, wakeupRef, bedtimeRef, sessionsPerPage, onSave }: SettingsPopoverProps) { const [isOpen, setIsOpen] = useState(false); const [localDayStart, setLocalDayStart] = useState(dayStart); const [localDayEnd, setLocalDayEnd] = useState(dayEnd); const [localWakeupRef, setLocalWakeupRef] = useState(wakeupRef); const [localBedtimeRef, setLocalBedtimeRef] = useState(bedtimeRef); + const [localSessionsPerPage, setLocalSessionsPerPage] = useState(sessionsPerPage); const popoverRef = useRef(null); useEffect(() => { @@ -22,7 +24,8 @@ export function SettingsPopover({ dayStart, dayEnd, wakeupRef, bedtimeRef, onSav setLocalDayEnd(dayEnd); setLocalWakeupRef(wakeupRef); setLocalBedtimeRef(bedtimeRef); - }, [dayStart, dayEnd, wakeupRef, bedtimeRef]); + setLocalSessionsPerPage(sessionsPerPage); + }, [dayStart, dayEnd, wakeupRef, bedtimeRef, sessionsPerPage]); useEffect(() => { const handleClickOutside = (e: MouseEvent) => { @@ -42,6 +45,7 @@ export function SettingsPopover({ dayStart, dayEnd, wakeupRef, bedtimeRef, onSav dayEnd: localDayEnd, wakeupRef: localWakeupRef, bedtimeRef: localBedtimeRef, + sessionsPerPage: localSessionsPerPage, }); setIsOpen(false); }; @@ -65,44 +69,58 @@ export function SettingsPopover({ dayStart, dayEnd, wakeupRef, bedtimeRef, onSav
- - setLocalDayStart(e.target.value)} - className="w-full p-2 border rounded-md text-sm" -/> + + setLocalDayStart(e.target.value)} + className="w-full p-2 border rounded-md text-sm" + />
- - setLocalDayEnd(e.target.value)} - className="w-full p-2 border rounded-md text-sm" -/> + + setLocalDayEnd(e.target.value)} + className="w-full p-2 border rounded-md text-sm" + />
- - setLocalWakeupRef(e.target.value)} - className="w-full p-2 border rounded-md text-sm" -/> + + setLocalWakeupRef(e.target.value)} + className="w-full p-2 border rounded-md text-sm" + />
- - setLocalBedtimeRef(e.target.value)} - className="w-full p-2 border rounded-md text-sm" -/> + + setLocalBedtimeRef(e.target.value)} + className="w-full p-2 border rounded-md text-sm" + /> +
+
+ +
diff --git a/frontend/src/components/stats/StatsPage.tsx b/frontend/src/components/stats/StatsPage.tsx index 2516d55..e3518c8 100644 --- a/frontend/src/components/stats/StatsPage.tsx +++ b/frontend/src/components/stats/StatsPage.tsx @@ -27,18 +27,20 @@ const StatsPage: React.FC = () => {

Statistics

Overview of sleep patterns and trends

- { - update('dayStart', s.dayStart); - update('dayEnd', s.dayEnd); - update('wakeupRef', s.wakeupRef); - update('bedtimeRef', s.bedtimeRef); - }} - /> + { + update('dayStart', s.dayStart); + update('dayEnd', s.dayEnd); + update('wakeupRef', s.wakeupRef); + update('bedtimeRef', s.bedtimeRef); + update('sessionsPerPage', s.sessionsPerPage); + }} + />
diff --git a/frontend/src/hooks/useSettings.ts b/frontend/src/hooks/useSettings.ts index c587fb3..d95899b 100644 --- a/frontend/src/hooks/useSettings.ts +++ b/frontend/src/hooks/useSettings.ts @@ -8,6 +8,7 @@ interface Settings { wakeupRef: string; bedtimeRef: string; statsInterval: number; + sessionsPerPage: number; } const DEFAULT_SETTINGS: Settings = { @@ -16,6 +17,7 @@ const DEFAULT_SETTINGS: Settings = { wakeupRef: '04:00', bedtimeRef: '19:00', statsInterval: 7, + sessionsPerPage: 10, }; export function useSettings() {