feat: implement Sleepy sleep diary
This commit is contained in:
58
lib/sleep.ts
Normal file
58
lib/sleep.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
export type AlarmType = 'alarm' | 'natural' | 'awakened';
|
||||
|
||||
export interface SleepEntry {
|
||||
date: string;
|
||||
napped: boolean;
|
||||
napStart: string | null;
|
||||
napDurationMinutes: number | null;
|
||||
bedtime: string;
|
||||
sleepLatencyMinutes: number;
|
||||
awakenings: number;
|
||||
wasoMinutes: number;
|
||||
riseTime: string;
|
||||
alarmType: AlarmType;
|
||||
rating: number;
|
||||
notes: string;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
export interface SleepMetrics {
|
||||
timeInBedMinutes: number;
|
||||
totalSleepMinutes: number;
|
||||
efficiency: number;
|
||||
}
|
||||
|
||||
export function calculateMetrics(entry: Pick<SleepEntry, 'bedtime' | 'riseTime' | 'sleepLatencyMinutes' | 'wasoMinutes'>): SleepMetrics {
|
||||
const [bedHours, bedMinutes] = entry.bedtime.split(':').map(Number);
|
||||
const [riseHours, riseMinutes] = entry.riseTime.split(':').map(Number);
|
||||
let timeInBedMinutes = riseHours * 60 + riseMinutes - (bedHours * 60 + bedMinutes);
|
||||
|
||||
if (timeInBedMinutes <= 0) timeInBedMinutes += 24 * 60;
|
||||
|
||||
const totalSleepMinutes = Math.max(0, timeInBedMinutes - entry.sleepLatencyMinutes - entry.wasoMinutes);
|
||||
const efficiency = timeInBedMinutes === 0 ? 0 : Math.round((totalSleepMinutes / timeInBedMinutes) * 100);
|
||||
|
||||
return { timeInBedMinutes, totalSleepMinutes, efficiency };
|
||||
}
|
||||
|
||||
export function formatDuration(minutes: number): string {
|
||||
const hours = Math.floor(minutes / 60);
|
||||
const remainder = minutes % 60;
|
||||
return hours > 0 ? `${hours} ч ${remainder.toString().padStart(2, '0')} мин` : `${remainder} мин`;
|
||||
}
|
||||
|
||||
export const defaultEntry = (date: string): SleepEntry => ({
|
||||
date,
|
||||
napped: false,
|
||||
napStart: null,
|
||||
napDurationMinutes: null,
|
||||
bedtime: '23:30',
|
||||
sleepLatencyMinutes: 20,
|
||||
awakenings: 0,
|
||||
wasoMinutes: 0,
|
||||
riseTime: '07:00',
|
||||
alarmType: 'natural',
|
||||
rating: 3,
|
||||
notes: '',
|
||||
});
|
||||
Reference in New Issue
Block a user