83 lines
2.9 KiB
TypeScript
83 lines
2.9 KiB
TypeScript
import type { DailySummary, DecimalMacroRemaining, MacroRemaining } from '@/src/types/diet';
|
|
|
|
const EMPTY_INT_MACRO: MacroRemaining = {
|
|
consumed: 0,
|
|
goal: null,
|
|
remaining: null,
|
|
progressPercent: null,
|
|
};
|
|
|
|
const EMPTY_DECIMAL_MACRO: DecimalMacroRemaining = {
|
|
consumed: 0,
|
|
goal: null,
|
|
remaining: null,
|
|
progressPercent: null,
|
|
};
|
|
|
|
function pick<T>(raw: Record<string, unknown>, camel: string, pascal: string): T | undefined {
|
|
return (raw[camel] ?? raw[pascal]) as T | undefined;
|
|
}
|
|
|
|
function normalizeIntMacro(raw: unknown): MacroRemaining {
|
|
if (!raw || typeof raw !== 'object') return { ...EMPTY_INT_MACRO };
|
|
const obj = raw as Record<string, unknown>;
|
|
return {
|
|
goal: (pick<number | null>(obj, 'goal', 'Goal') ?? null) as number | null,
|
|
consumed: Number(pick<number>(obj, 'consumed', 'Consumed') ?? 0),
|
|
remaining: (pick<number | null>(obj, 'remaining', 'Remaining') ?? null) as number | null,
|
|
progressPercent: (pick<number | null>(obj, 'progressPercent', 'ProgressPercent') ?? null) as
|
|
| number
|
|
| null,
|
|
};
|
|
}
|
|
|
|
function normalizeDecimalMacro(raw: unknown): DecimalMacroRemaining {
|
|
if (!raw || typeof raw !== 'object') return { ...EMPTY_DECIMAL_MACRO };
|
|
const obj = raw as Record<string, unknown>;
|
|
return {
|
|
goal: (pick<number | null>(obj, 'goal', 'Goal') ?? null) as number | null,
|
|
consumed: Number(pick<number>(obj, 'consumed', 'Consumed') ?? 0),
|
|
remaining: (pick<number | null>(obj, 'remaining', 'Remaining') ?? null) as number | null,
|
|
progressPercent: (pick<number | null>(obj, 'progressPercent', 'ProgressPercent') ?? null) as
|
|
| number
|
|
| null,
|
|
};
|
|
}
|
|
|
|
export function normalizeDailySummary(raw: unknown): DailySummary {
|
|
if (!raw || typeof raw !== 'object') {
|
|
return {
|
|
date: '',
|
|
goals: null,
|
|
calories: { ...EMPTY_INT_MACRO },
|
|
proteinG: { ...EMPTY_DECIMAL_MACRO },
|
|
fatG: { ...EMPTY_DECIMAL_MACRO },
|
|
carbsG: { ...EMPTY_DECIMAL_MACRO },
|
|
waterMl: { ...EMPTY_INT_MACRO },
|
|
meals: [],
|
|
drinks: [],
|
|
};
|
|
}
|
|
|
|
const obj = raw as Record<string, unknown>;
|
|
const meals = pick<unknown[]>(obj, 'meals', 'Meals');
|
|
const drinks = pick<unknown[]>(obj, 'drinks', 'Drinks');
|
|
|
|
return {
|
|
date: String(pick<string>(obj, 'date', 'Date') ?? ''),
|
|
goals: (pick(obj, 'goals', 'Goals') as DailySummary['goals']) ?? null,
|
|
calories: normalizeIntMacro(pick(obj, 'calories', 'Calories')),
|
|
proteinG: normalizeDecimalMacro(pick(obj, 'proteinG', 'ProteinG')),
|
|
fatG: normalizeDecimalMacro(pick(obj, 'fatG', 'FatG')),
|
|
carbsG: normalizeDecimalMacro(pick(obj, 'carbsG', 'CarbsG')),
|
|
waterMl: normalizeIntMacro(pick(obj, 'waterMl', 'WaterMl')),
|
|
meals: Array.isArray(meals) ? (meals as DailySummary['meals']) : [],
|
|
drinks: Array.isArray(drinks) ? (drinks as DailySummary['drinks']) : [],
|
|
};
|
|
}
|
|
|
|
export function formatReminderTime(value: string | null | undefined): string {
|
|
if (!value) return '';
|
|
return value.length >= 5 ? value.slice(0, 5) : value;
|
|
}
|