feat: předělání historie a profilu

This commit is contained in:
Ondřej Anděl committed 2026-10-07 14:48:21 +02:00
1 parent 9e72f431a1
commit 8fa7f601f2
97 files changed
+7502 -1034

No files matched your search

+13 -3
View File
@@ -24,6 +24,12 @@ paths:
$ref: "./paths/meals/delete.yml"
/meals/multiplier:
$ref: "./paths/meals/multiplier.yml"
/meals/history:
$ref: "./paths/meals/history.yml"
/meals/sources:
$ref: "./paths/meals/sources.yml"
/meals/fillSameName:
$ref: "./paths/meals/fillSameName.yml"
# Statistiky (/api/stats)
/stats/summary:
@@ -36,6 +42,10 @@ paths:
$ref: "./paths/day/overview.yml"
/day/sleep:
$ref: "./paths/day/sleep.yml"
/day/weight:
$ref: "./paths/day/weight.yml"
/day/weights:
$ref: "./paths/day/weights.yml"
# Pohyb (/api/activities)
/activities/add:
@@ -59,7 +69,7 @@ paths:
/workouts/fromActivities:
$ref: "./paths/workouts/fromActivities.yml"
# Šablony jídel (/api/mealTemplates)
# Recepty (/api/mealTemplates)
/mealTemplates:
$ref: "./paths/mealTemplates/list.yml"
/mealTemplates/save:
@@ -68,8 +78,6 @@ paths:
$ref: "./paths/mealTemplates/delete.yml"
/mealTemplates/apply:
$ref: "./paths/mealTemplates/apply.yml"
/mealTemplates/fromMeal:
$ref: "./paths/mealTemplates/fromMeal.yml"
# Kalorie (/api/calories)
/calories/search:
@@ -82,6 +90,8 @@ paths:
$ref: "./paths/settings/basal.yml"
/settings/profile:
$ref: "./paths/settings/profile.yml"
/settings/goals:
$ref: "./paths/settings/goals.yml"
# Importy (/api/import)
/import/luncher:
+28
View File
@@ -0,0 +1,28 @@
post:
operationId: saveWeight
summary: Zapíše vážení k zvolenému dni.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [date]
properties:
date:
type: string
format: date
weightGrams:
description: Hmotnost v gramech. Bez hodnoty (nebo 0) se vážení dne smaže.
type: integer
responses:
"200":
description: Aktualizovaný přehled dne
content:
application/json:
schema:
$ref: "../../schemas/_index.yml#/DayOverview"
"400":
description: Neplatná data
"401":
description: Neautentizovaný uživatel
+14
View File
@@ -0,0 +1,14 @@
get:
operationId: getWeights
summary: Vrátí všechna vážení přihlášeného uživatele seřazená podle data.
responses:
"200":
description: Vážení od nejstaršího
content:
application/json:
schema:
type: array
items:
$ref: "../../schemas/_index.yml#/WeightEntry"
"401":
description: Neautentizovaný uživatel
+5 -5
View File
@@ -1,6 +1,6 @@
post:
operationId: applyMealTemplate
summary: Založí jídlo ze šablony do zvoleného dne.
summary: Založí jednu porci receptu jako jídlo do zvoleného dne.
requestBody:
required: true
content:
@@ -10,18 +10,18 @@ post:
required: [id, date]
properties:
id:
description: Identifikátor šablony
description: Identifikátor receptu
type: string
date:
description: Den, do kterého se jídlo založí
type: string
format: date
mealType:
description: Chod. Bez něj se použije chod ze šablony, jinak oběd.
description: Chod. Bez něj se použije chod receptu, jinak oběd.
allOf:
- $ref: "../../schemas/_index.yml#/MealType"
multiplier:
description: Násobek porce, třeba 2 za dvě stejné sušenky. Bez něj 1.
description: Násobek porce, třeba 2 za dvě porce. Bez něj 1.
type: number
responses:
"200":
@@ -35,4 +35,4 @@ post:
"401":
description: Neautentizovaný uživatel
"404":
description: Šablona neexistuje
description: Recept neexistuje
+2 -2
View File
@@ -1,6 +1,6 @@
post:
operationId: deleteMealTemplate
summary: Smaže šablonu jídla.
summary: Smaže recept.
requestBody:
required: true
content:
@@ -13,7 +13,7 @@ post:
type: string
responses:
"200":
description: Aktualizovaný seznam šablon
description: Aktualizovaný seznam receptů
content:
application/json:
schema:
-33
View File
@@ -1,33 +0,0 @@
post:
operationId: createMealTemplateFromMeal
summary: Vytvoří šablonu jídla z existujícího záznamu v přehledu dne.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [id, date]
properties:
id:
description: Identifikátor jídla, ze kterého se šablona vytvoří
type: string
date:
description: Den, ve kterém jídlo je
type: string
format: date
responses:
"200":
description: Aktualizovaný seznam šablon
content:
application/json:
schema:
type: array
items:
$ref: "../../schemas/_index.yml#/MealTemplate"
"400":
description: Neplatná data
"401":
description: Neautentizovaný uživatel
"404":
description: Jídlo neexistuje
+2 -2
View File
@@ -1,9 +1,9 @@
get:
operationId: getMealTemplates
summary: Vrátí šablony jídel přihlášeného uživatele.
summary: Vrátí recepty přihlášeného uživatele.
responses:
"200":
description: Šablony seřazené podle názvu
description: Recepty seřazené podle názvu
content:
application/json:
schema:
+2 -2
View File
@@ -1,6 +1,6 @@
post:
operationId: saveMealTemplate
summary: Založí novou šablonu jídla, nebo upraví existující.
summary: Založí nový recept, nebo upraví existující.
requestBody:
required: true
content:
@@ -9,7 +9,7 @@ post:
$ref: "../../schemas/_index.yml#/MealTemplateInput"
responses:
"200":
description: Aktualizovaný seznam šablon
description: Aktualizovaný seznam receptů
content:
application/json:
schema:
+39
View File
@@ -0,0 +1,39 @@
post:
operationId: fillSameNameMeals
summary: |
Doplní energii a živiny jídla do ostatních jídel stejného názvu, která je nemají.
description: |
Typicky po doplnění kalorií jednomu naimportovanému jídlu — ostatní jídla
téhož jména mají stejné složení. Jídla, která energii nebo živiny už mají,
se nemění. S `dryRun` jen spočítá, kterých jídel by se to týkalo.
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [id, date]
properties:
id:
description: Identifikátor jídla, ze kterého se hodnoty převezmou
type: string
date:
description: Datum jídla (YYYY-MM-DD)
type: string
format: date
dryRun:
description: Jen spočítat, nic neměnit
type: boolean
responses:
"200":
description: Jídla, kterých se doplnění týká
content:
application/json:
schema:
$ref: "../../schemas/_index.yml#/FillSameNameResult"
"400":
description: Neplatná data
"401":
description: Neautentizovaný uživatel
"404":
description: Jídlo neexistuje
+17
View File
@@ -0,0 +1,17 @@
get:
operationId: getMealHistory
summary: Vrátí jídla z historie přihlášeného uživatele, každý název jednou.
description: |
Slouží k našeptávání při zakládání jídla. Seřazeno od nejčastěji jedených,
při shodě od naposledy jedených.
responses:
"200":
description: Jídla z historie
content:
application/json:
schema:
type: array
items:
$ref: "../../schemas/_index.yml#/MealSuggestion"
"401":
description: Neautentizovaný uživatel
+17
View File
@@ -0,0 +1,17 @@
get:
operationId: getMealSources
summary: Vrátí zdroje jídel (podniky, obchody), které uživatel už použil.
description: |
Slouží jako nabídka při zadávání zdroje. Každý zdroj je jednou, seřazené
od nejčastěji použitých; zápis je z posledního použití.
responses:
"200":
description: Použité zdroje
content:
application/json:
schema:
type: array
items:
type: string
"401":
description: Neautentizovaný uživatel
+21
View File
@@ -0,0 +1,21 @@
post:
operationId: saveGoals
summary: Uloží cíle uživatele — tempo změny hmotnosti, cílovou hmotnost a bílkoviny.
description: Nevyplněné hodnoty se odstraní.
requestBody:
required: true
content:
application/json:
schema:
$ref: "../../schemas/_index.yml#/Goals"
responses:
"200":
description: Aktualizované nastavení
content:
application/json:
schema:
$ref: "../../schemas/_index.yml#/UserSettings"
"400":
description: Neplatná data
"401":
description: Neautentizovaný uživatel
+243 -56
View File
@@ -57,6 +57,8 @@ MealEntry:
caloriesPer100g:
description: Energetická hodnota na 100 g v kcal. Slouží k dopočtu kalorií z gramáže.
type: integer
nutrientsPer100g:
$ref: "#/Nutrients"
note:
description: Poznámka uživatele k jídlu
type: string
@@ -130,6 +132,8 @@ MealInput:
description: Energetická hodnota na 100 g v kcal
type: integer
nullable: true
nutrientsPer100g:
$ref: "#/Nutrients"
note:
description: Poznámka uživatele k jídlu
type: string
@@ -138,6 +142,100 @@ MealInput:
description: Násobek porce; nevyplněno znamená 1
type: number
Nutrients:
description: |
Nutriční hodnoty v gramech, ve stejném členění jako na etiketě potravin.
U jídla jsou vztažené na 100 g; hodnoty porce se dopočtou z gramáže,
takže jídlo bez gramáže do součtů živin nevstupuje. Na rozdíl od ostatních
hodnot nejsou celočíselné — etikety uvádějí desetiny gramu a u soli
nebo vlákniny by zaokrouhlení na celé gramy smazalo celou hodnotu.
Ukládají se zaokrouhlené na jedno desetinné místo.
type: object
additionalProperties: false
properties:
protein:
description: Bílkoviny
type: number
carbohydrates:
description: Sacharidy
type: number
sugars:
description: Z toho cukry
type: number
fat:
description: Tuky
type: number
saturatedFat:
description: Z toho nasycené mastné kyseliny
type: number
fiber:
description: Vláknina
type: number
salt:
description: Sůl
type: number
FillSameNameResult:
description: Jídla stejného názvu, do kterých se doplní (nebo doplnily) energie a živiny
type: object
additionalProperties: false
required:
- count
- dates
properties:
count:
description: Počet jídel
type: integer
dates:
description: Dny, ve kterých ta jídla jsou (YYYY-MM-DD), seřazené
type: array
items:
type: string
format: date
MealSuggestion:
description: |
Jídlo z historie uživatele nabízené při zakládání nového. Každý název je
v návrzích jen jednou; hodnoty jsou z posledního záznamu toho jména.
Chod, datum, násobek ani poznámka se nepřenášejí — patří ke konkrétnímu dni.
type: object
additionalProperties: false
required:
- name
- lastDate
- count
properties:
name:
description: Název jídla tak, jak byl zapsán naposledy
type: string
source:
type: string
price:
description: Cena v haléřích
type: integer
pricePer100g:
description: Cena za 100 g v haléřích
type: integer
weight:
description: |
Gramáž zadaná ručně. Chybí, pokud se gramáž dopočetla z ceny —
v novém záznamu se pak dopočte znovu.
type: integer
caloriesPer100g:
type: integer
calories:
description: Kalorie porce, jen pokud nejdou dopočítat z gramáže a energie na 100 g
type: integer
nutrientsPer100g:
$ref: "#/Nutrients"
lastDate:
description: Den, kdy uživatel jídlo jedl naposledy
type: string
format: date
count:
description: Kolikrát se jídlo v historii vyskytuje
type: integer
DayRecord:
description: Přehled jídel jednoho dne včetně součtů
type: object
@@ -163,6 +261,12 @@ DayRecord:
totalCalories:
description: Součet kalorií jídel dne v kcal (jídla bez kalorií se nezapočítávají)
type: integer
totalNutrients:
description: |
Součet živin jídel dne po započtení násobku. Započítávají se jen jídla
s gramáží a nutričními hodnotami; chybí, pokud takové jídlo v dni není.
allOf:
- $ref: "#/Nutrients"
PeriodTotal:
description: Součty za jedno období (den, měsíc nebo rok)
@@ -506,6 +610,102 @@ UserSettings:
Klidový výdej, který se reálně použije v bilanci dne — ručně zadaný,
jinak spočítaný z profilu. Doplňuje server.
type: integer
goals:
$ref: "#/Goals"
bodyMetrics:
$ref: "#/BodyMetrics"
Goals:
description: Cíle uživatele — tempo změny hmotnosti, cílová hmotnost a příjem bílkovin
type: object
additionalProperties: false
properties:
weeklyChangeGrams:
description: |
Plánovaná změna hmotnosti za týden v gramech, záporná při hubnutí
(−500 = půl kila týdně dolů). Určuje cílovou denní bilanci.
type: integer
targetWeightGrams:
description: Cílová hmotnost v gramech
type: integer
proteinPerKg:
description: |
Cílový příjem bílkovin v gramech na kilogram hmotnosti, s přesností
na desetiny (1,6). Desetinné číslo, protože doporučení se tak udávají.
type: number
BmiKategorie:
description: |
Pásmo BMI podle WHO — PODVAHA pod 18,5, NORMA do 25, NADVAHA do 30,
OBEZITA od 30.
type: string
enum:
- PODVAHA
- NORMA
- NADVAHA
- OBEZITA
BodyMetrics:
description: |
Ukazatele spočítané z tělesných údajů, posledního vážení a cílů.
Doplňuje server, nic z toho se neukládá. Každý chybí, když pro něj
nejsou údaje.
type: object
additionalProperties: false
properties:
weightGrams:
description: |
Aktuální hmotnost — z posledního vážení, bez vážení hmotnost zadaná
v profilu
type: integer
weightDate:
description: Den posledního vážení; chybí, pokud jde o hmotnost z profilu
type: string
format: date
bmi:
description: Body mass index, kg / m², zaokrouhlený na desetiny
type: number
bmiCategory:
$ref: "#/BmiKategorie"
healthyWeightMinGrams:
description: Hmotnost odpovídající BMI 18,5 při zadané výšce
type: integer
healthyWeightMaxGrams:
description: Hmotnost odpovídající BMI 25 při zadané výšce
type: integer
bodyFatPercent:
description: |
Odhad podílu tuku v procentech metodou US Navy z výšky a obvodů
(muž pas a krk, žena navíc boky), zaokrouhlený na desetiny
type: number
targetDailyBalance:
description: |
Cílová denní bilance v kcal podle týdenního tempa
(1 kg tělesné hmotnosti ≈ 7 700 kcal)
type: integer
proteinTargetGrams:
description: Cílový denní příjem bílkovin v gramech podle aktuální hmotnosti
type: integer
weeksToTarget:
description: |
Za kolik týdnů se při zvoleném tempu dosáhne cílové hmotnosti.
Chybí, pokud tempo nevede k cíli (nulové nebo opačným směrem).
type: integer
WeightEntry:
description: Jedno vážení
type: object
additionalProperties: false
required:
- date
- weightGrams
properties:
date:
type: string
format: date
weightGrams:
description: Hmotnost v gramech
type: integer
ActivityUnit:
description: Jednotka, ve které se aktivita měří
@@ -756,6 +956,11 @@ EnergyBalance:
False, pokud uživatel nemá nastavený klidový výdej. Bilance pak
porovnává jen jídlo proti pohybu a není to skutečný deficit.
type: boolean
targetBalance:
description: |
Cílová bilance dne podle týdenního tempa změny hmotnosti. Chybí,
pokud si uživatel tempo nenastavil.
type: integer
DayOverview:
description: Kompletní přehled dne — jídlo, pohyb a jejich bilance
@@ -782,6 +987,14 @@ DayOverview:
bilance nevstupuje, protože klidový výdej už pokrývá celých 24 hodin
včetně spánku a žádná standardní rovnice délku spánku nezohledňuje.
type: integer
weightGrams:
description: Vážení zapsané k tomuto dni v gramech
type: integer
proteinTargetGrams:
description: |
Cílový příjem bílkovin dne v gramech — podle hmotnosti platné k tomuto
dni. Chybí bez nastaveného cíle.
type: integer
Pohlavi:
description: Pohlaví — vstupuje do výpočtu bazálního metabolismu
@@ -793,7 +1006,7 @@ Pohlavi:
PersonalProfile:
description: |
Tělesné údaje uživatele. Slouží k výpočtu bazálního metabolismu
(klidového výdeje) rovnicí Mifflin–St Jeor.
(klidového výdeje) rovnicí Mifflin–St Jeor, BMI a odhadu podílu tuku.
type: object
additionalProperties: false
properties:
@@ -806,7 +1019,18 @@ PersonalProfile:
description: Výška v centimetrech
type: integer
weightGrams:
description: Hmotnost v gramech. Celé číslo, aby se počítalo bez desetinných chyb.
description: |
Hmotnost v gramech zadaná dřív, než přibylo vážení po dnech. Použije se,
jen dokud uživatel žádné vážení nezapsal.
type: integer
waistCm:
description: Obvod pasu v cm — u mužů v úrovni pupku, u žen v nejužším místě
type: integer
neckCm:
description: Obvod krku v cm, pod ohryzkem
type: integer
hipCm:
description: Obvod boků v cm v nejširším místě; do odhadu tuku vstupuje jen u žen
type: integer
WorkoutItemKind:
@@ -820,52 +1044,46 @@ WorkoutItemKind:
MealTemplate:
description: |
Předpřipravené jídlo. Použitím se založí do zvoleného dne, takže opakovaně
jedené jídlo není potřeba zadávat znovu. Na rozdíl od šablon tréninků se
šablony jídel neskládají z jiných — jsou to ploché záznamy.
Recept — vařené jídlo se surovinami a postupem. Hodnoty jedné porce
(gramáž, energie, cena) dopočte server ze surovin při uložení a použitím
receptu se z nich založí běžný záznam jídla. Opakovaně jedená hotová jídla
šablony nemají, nabízejí se z historie (MealSuggestion).
type: object
additionalProperties: false
required:
- id
- kind
- name
- ingredients
properties:
id:
type: string
kind:
$ref: "#/MealTemplateKind"
name:
description: Název jídla
type: string
source:
description: Zdroj jídla (podnik, obchod, "doma", ...)
description: Zdroj jídla, typicky "doma"
type: string
mealType:
description: Chod, pod kterým se jídlo zakládá. Bez něj se použije oběd.
allOf:
- $ref: "#/MealType"
calories:
description: |
Energetická hodnota celé porce v kcal. Použije se, když jídlo nemá
vyplněnou gramáž a energii na 100 g.
description: Energetická hodnota jedné porce v kcal
type: integer
caloriesPer100g:
description: Energetická hodnota na 100 g v kcal
description: Energetická hodnota hotového jídla na 100 g v kcal
type: integer
weight:
description: Obvyklá gramáž porce v gramech
description: Gramáž jedné porce v gramech
type: integer
price:
description: Obvyklá cena v haléřích
type: integer
pricePer100g:
description: Cena za 100 g v haléřích
description: Cena jedné porce v haléřích
type: integer
note:
description: Poznámka, u receptu postup přípravy
description: Postup přípravy
type: string
ingredients:
description: Suroviny receptu. U hotového jídla chybí.
description: Suroviny receptu
type: array
items:
$ref: "#/RecipeIngredient"
@@ -880,46 +1098,27 @@ MealTemplate:
MealTemplateInput:
description: |
Data pro založení nebo úpravu šablony jídla. Oproti {@link MealTemplate} je
`id` volitelné — bez něj se šablona založí jako nová.
Data pro založení nebo úpravu receptu. Oproti {@link MealTemplate} je
`id` volitelné — bez něj se recept založí jako nový — a hodnoty porce
chybí, protože je server dopočte ze surovin.
type: object
additionalProperties: false
required:
- name
- ingredients
properties:
id:
description: Identifikátor upravované šablony. Bez něj se založí nová.
description: Identifikátor upravovaného receptu. Bez něj se založí nový.
type: string
kind:
description: Druh šablony. Bez něj se založí hotové jídlo.
allOf:
- $ref: "#/MealTemplateKind"
name:
type: string
source:
type: string
nullable: true
mealType:
allOf:
- $ref: "#/MealType"
calories:
type: integer
nullable: true
caloriesPer100g:
type: integer
nullable: true
weight:
type: integer
nullable: true
price:
type: integer
nullable: true
pricePer100g:
type: integer
nullable: true
note:
type: string
nullable: true
ingredients:
type: array
items:
@@ -947,18 +1146,6 @@ ImportMode:
- PRIDAT
- NAHRADIT
MealTemplateKind:
description: |
Druh šablony jídla.
HOTOVE — objednané nebo koupené jídlo; stačí si pamatovat výsledné
hodnoty porce (kcal, cenu), aby se nemusely dohledávat znovu.
RECEPT — vařené jídlo; eviduje se, z čeho a jak vzniklo, a hodnoty
porce se dopočítají ze surovin.
type: string
enum:
- HOTOVE
- RECEPT
RecipeIngredient:
description: Jedna surovina receptu
type: object