feat: zlepšení šablon, přidány osobní údaje a spánkový režim

This commit is contained in:
Ondřej Anděl committed 2026-09-15 14:16:42 +02:00
1 parent a5711f3e1e
commit 21b01528e9
51 files changed
+3739 -504

No files matched your search

+64 -4
View File
@@ -182,14 +182,74 @@ export function formatQuantity(quantity: number, unitShort: string): string {
return `${quantity.toLocaleString('cs-CZ')} ${unitShort}`;
}
/** Dopočte spálené kalorie z množství a sazby na 100 jednotek. */
export function deriveActivityCalories(quantity?: number, caloriesPer100Units?: number): number | undefined {
/**
* Dopočte spálené kalorie z množství, počtu sérií a sazby na 100 jednotek.
* Musí dávat stejné výsledky jako `deriveActivityCalories` na serveru.
*/
export const deriveActivityCalories = (
quantity?: number,
caloriesPer100Units?: number,
sets?: number,
): number | undefined => {
if (quantity == null || !caloriesPer100Units) return undefined;
return Math.round(quantity / 100 * caloriesPer100Units);
}
return Math.round(quantity * Math.max(sets ?? 1, 1) / 100 * caloriesPer100Units);
};
/** Naformátuje bilanci se znaménkem, např. "−320 kcal" nebo "+150 kcal". */
export function formatBalance(kcal: number): string {
const sign = kcal < 0 ? '−' : '+';
return `${sign}${Math.abs(kcal).toLocaleString('cs-CZ')} kcal`;
}
/** Naformátuje délku spánku z minut, např. 450 → "7 h 30 min". */
export const formatSleep = (minutes?: number): string => {
if (!minutes) return '—';
const hours = Math.floor(minutes / 60);
const rest = minutes % 60;
return rest ? `${hours} h ${rest} min` : `${hours} h`;
};
/** Převede minuty na hodiny s jedním desetinným místem pro editační pole. */
export const formatSleepInput = (minutes?: number): string =>
minutes ? (minutes / 60).toFixed(1).replace('.', ',') : '';
/** Převede hodiny zadané uživatelem (i s desetinnou čárkou) na minuty. */
export const parseSleepInput = (value: string): number | undefined => {
const trimmed = value.trim().replace(',', '.');
if (!trimmed.length) return undefined;
const parsed = Number(trimmed);
return Number.isFinite(parsed) && parsed >= 0 ? Math.round(parsed * 60) : undefined;
};
/** Naformátuje hmotnost z gramů na kilogramy, např. 90000 → "90,0 kg". */
export const formatWeightKg = (grams?: number): string =>
grams == null ? '—' : `${(grams / 1000).toFixed(1).replace('.', ',')} kg`;
/** Převede kilogramy zadané uživatelem na gramy. */
export const parseWeightKgInput = (value: string): number | undefined => {
const trimmed = value.trim().replace(',', '.');
if (!trimmed.length) return undefined;
const parsed = Number(trimmed);
return Number.isFinite(parsed) && parsed > 0 ? Math.round(parsed * 1000) : undefined;
};
/** Převede gramy na kilogramy pro editační pole. */
export const formatWeightKgInput = (grams?: number): string =>
grams == null ? '' : (grams / 1000).toFixed(1).replace('.', ',');
/**
* Naformátuje množství aktivity i se sériemi.
*
* Bez sérií vrací "40 opak.", se sériemi "3 × 40 opak. (120)" — celkové množství
* v závorce, protože z něj vychází spálené kalorie, ale rozpad na série je to,
* co odlišuje tři série s pauzami od jedné dlouhé.
*/
export const formatQuantityWithSets = (quantity: number, unitShort: string, sets?: number): string => {
const one = formatQuantity(quantity, unitShort);
if (!sets || sets <= 1) return one;
return `${sets} × ${one} (${(quantity * sets).toLocaleString('cs-CZ')})`;
};
/** Vrátí celkové množství aktivity — počet sérií krát množství v jedné. */
export const getTotalQuantity = (quantity?: number, sets?: number): number | undefined =>
quantity == null ? undefined : quantity * Math.max(sets ?? 1, 1);