59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
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: '',
|
|
});
|