Files

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) return
    No 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() {