10 KiB
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<number | null>(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) returnNo sessions recorded.;
@@ -55,7 +69,7 @@ export function SessionList() {
Sleep Sessions
-
{sessions.map((s) => (
-
{paginatedSessions.map((s) => ( <div key={s.id} className="border-b border-gray-100 last:border-0 py-3 sm:py-2"> {editingId === s.id ? ( <div className="flex flex-col space-y-3 py-1">
@@ -140,6 +154,13 @@ export function SessionList() {
-
{sessions.length > sessionsPerPage && ( -
<Pagination -
currentPage={clampedPage} -
totalPages={totalPages} -
onPageChange={setCurrentPage} -
/> -
);)}
} 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
<div className="space-y-3"> <div>
-Day starts (HH:MM) -<input
- id="day-start"
- type="time"
- value={localDayStart}
- onChange={(e) => setLocalDayStart(e.target.value)}
- className="w-full p-2 border rounded-md text-sm" -/>
-
<label htmlFor="day-start" className="block text-xs text-gray-500 mb-1">Day starts (HH:MM)</label> -
<input -
id="day-start" -
type="time" -
value={localDayStart} -
onChange={(e) => setLocalDayStart(e.target.value)} -
className="w-full p-2 border rounded-md text-sm" -
/> </div> <div>
-Day ends (HH:MM) -<input
- id="day-end"
- type="time"
- value={localDayEnd}
- onChange={(e) => setLocalDayEnd(e.target.value)}
- className="w-full p-2 border rounded-md text-sm" -/>
-
<label htmlFor="day-end" className="block text-xs text-gray-500 mb-1">Day ends (HH:MM)</label> -
<input -
id="day-end" -
type="time" -
value={localDayEnd} -
onChange={(e) => setLocalDayEnd(e.target.value)} -
className="w-full p-2 border rounded-md text-sm" -
/> </div> <div>
-Wakeup ref (HH:MM) -<input
- id="wakeup-ref"
- type="time"
- value={localWakeupRef}
- onChange={(e) => setLocalWakeupRef(e.target.value)}
- className="w-full p-2 border rounded-md text-sm" -/>
-
<label htmlFor="wakeup-ref" className="block text-xs text-gray-500 mb-1">Wakeup ref (HH:MM)</label> -
<input -
id="wakeup-ref" -
type="time" -
value={localWakeupRef} -
onChange={(e) => setLocalWakeupRef(e.target.value)} -
className="w-full p-2 border rounded-md text-sm" -
/> </div> <div>
-Bedtime ref (HH:MM) -<input
- id="bedtime-ref"
- type="time"
- value={localBedtimeRef}
- onChange={(e) => setLocalBedtimeRef(e.target.value)}
- className="w-full p-2 border rounded-md text-sm" -/>
-
<label htmlFor="bedtime-ref" className="block text-xs text-gray-500 mb-1">Bedtime ref (HH:MM)</label> -
<input -
id="bedtime-ref" -
type="time" -
value={localBedtimeRef} -
onChange={(e) => setLocalBedtimeRef(e.target.value)} -
className="w-full p-2 border rounded-md text-sm" -
/> -
</div> -
<div> -
<label htmlFor="sessions-per-page" className="block text-xs text-gray-500 mb-1">Results per page</label> -
<select -
id="sessions-per-page" -
value={localSessionsPerPage} -
onChange={(e) => setLocalSessionsPerPage(Number(e.target.value))} -
className="w-full p-2 border rounded-md text-sm" -
> -
<option value={5}>5</option> -
<option value={10}>10</option> -
<option value={25}>25</option> -
<option value={50}>50</option> -
</select> </div> </div>
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
-
<SettingsPopover -
dayStart={settings.dayStart} -
dayEnd={settings.dayEnd} -
wakeupRef={settings.wakeupRef} -
bedtimeRef={settings.bedtimeRef} -
onSave={(s) => { -
update('dayStart', s.dayStart); -
update('dayEnd', s.dayEnd); -
update('wakeupRef', s.wakeupRef); -
update('bedtimeRef', s.bedtimeRef); -
}} -
/>
-
<SettingsPopover -
dayStart={settings.dayStart} -
dayEnd={settings.dayEnd} -
wakeupRef={settings.wakeupRef} -
bedtimeRef={settings.bedtimeRef} -
sessionsPerPage={settings.sessionsPerPage} -
onSave={(s) => { -
update('dayStart', s.dayStart); -
update('dayEnd', s.dayEnd); -
update('wakeupRef', s.wakeupRef); -
update('bedtimeRef', s.bedtimeRef); -
update('sessionsPerPage', s.sessionsPerPage); -
}} -
/> </div> <div className="bg-white p-6 rounded-[2rem] shadow-md border border-gray-100">
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() {