mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 15:02:04 +00:00
feat: add the timeline page, its readiness inventory and life-event entry
The opt-in timeline module gets its page (#613). At 768 px and up the record's lanes (life, conditions, allergies, medications, vaccinations, doctor and procedures, labs, documents) are drawn in one SVG on a shared time axis, with a year, month or week grid, open periods ending in an arrow, a dashed lead-in where a start is unknown, dose marks and pauses on the medication they belong to, a Today line and a selection line. Up to three neutral value lines run below as monthly means, chosen in a menu. Recharts stays for every value chart; this surface is plain SVG like the heatmaps. All geometry is pure (timeline-geometry.ts): window, scale, row packing and label placement through one occupancy map, so no label overlaps another label or a bar, none runs past the card edge, and labels that do not fit are left out rather than squeezed. The width comes from a ResizeObserver, so a docked day panel re-runs the layout. The bar under the chart names the selected month's entries as chips, the month's means and "Open 3 Jan.", which puts ?day= in the URL for the day layer. The chart is one tab stop: arrows move the selection by a day, a month or a year with the zoom, Home and End jump to the ends, Enter opens the day. A visually hidden table lists every entry for screen readers. The legend says once that stacked means at the same time, not cause and effect. Below 768 px the timeline is a chronicle, newest first by month or year, with an Ongoing block for what has no meaningful start, rails beside the rows an episode or course spans, and empty stretches named as such. Switching the module on in Settings opens the readiness inventory: each lane carries, is thin or is empty, with one link per gap and the verdict as a count. The same inventory sits as a dismissible card on the timeline while a gap is open, and under Layers as "Data coverage". Life events are entered in a sheet (title, kind, a date to the day, month or year, an optional end, an optional note) from the timeline, the capture picker and the dashboard's add menu; one surface line maps the capture kind to the timeline module, and it is offered in one's own record only. Deleting asks first. Server routes are built in parallel; the e2e journey answers them with the contract's shapes. Copy in all seven locales; the timeline and lifeEvents release-pending prefixes are gone.
This commit is contained in:
1 parent
b8f6372963
commit
32258bc5ab
50 files changed
+8277
-54
No files matched your search
+161
-7
@@ -427,7 +427,9 @@
|
||||
"workout": "Trening",
|
||||
"workoutDescription": "Sesja, której nie zapisały twoje urządzenia",
|
||||
"symptom": "Objaw",
|
||||
"symptomDescription": "Jeden z twoich objawów, z nasileniem"
|
||||
"symptomDescription": "Jeden z twoich objawów, z nasileniem",
|
||||
"lifeEventDescription": "Przeprowadzka, narodziny, nowa praca",
|
||||
"lifeEvent": "Wydarzenie życiowe"
|
||||
},
|
||||
"cycle": "Cykl",
|
||||
"labs": "Wyniki badań",
|
||||
@@ -578,6 +580,7 @@
|
||||
"quickAddMood": "Zarejestruj nastrój",
|
||||
"quickAddMedicationIntake": "Zarejestruj przyjęcie",
|
||||
"quickAddWorkout": "Zarejestruj trening",
|
||||
"quickAddLifeEvent": "Zapisz wydarzenie życiowe",
|
||||
"customizeDashboard": "Dostosuj pulpit",
|
||||
"medicationIntakeQuickAdd": {
|
||||
"sheetTitle": "Zarejestruj przyjęcie leku",
|
||||
@@ -12214,8 +12217,8 @@
|
||||
},
|
||||
"timeline": {
|
||||
"title": "Oś czasu",
|
||||
"subtitle": "Lata w jednym widoku.",
|
||||
"legend": "Pokazane obok siebie, nie jako przyczyna i skutek.",
|
||||
"subtitle": "Co i kiedy się działo, obok Twoich wartości.",
|
||||
"legend": "Jedno pod drugim oznacza ten sam czas, nie przyczynę i skutek.",
|
||||
"standing": "Stałe",
|
||||
"startMissing": "Brak daty rozpoczęcia",
|
||||
"openDay": "Otwórz {date}",
|
||||
@@ -12254,16 +12257,151 @@
|
||||
"lanes": {
|
||||
"values": "Wartości",
|
||||
"mood": "Nastrój",
|
||||
"environment": "Otoczenie"
|
||||
"environment": "Otoczenie",
|
||||
"life": "Wydarzenia życiowe"
|
||||
},
|
||||
"meter": "{carrying} z {total} ścieżek ma treść",
|
||||
"carriesDetail": "{carrying} z {total} ścieżek daje przegląd od {since}.",
|
||||
"loadFailed": "Nie udało się wczytać przeglądu.",
|
||||
"card": {
|
||||
"title": "Co już zawiera oś czasu",
|
||||
"summary": "Sięga do {since}; {carrying} z {total} ścieżek ma już treść.",
|
||||
"dismiss": "Ukryj"
|
||||
},
|
||||
"detail": {
|
||||
"valuesOne": "{count} pomiar od {since}",
|
||||
"valuesFew": "{count} pomiary od {since}",
|
||||
"valuesOther": "{count} pomiarów od {since}",
|
||||
"illnessOne": "{count} epizod; przewlekłe: {chronic}",
|
||||
"illnessFew": "{count} epizody; przewlekłe: {chronic}",
|
||||
"illnessOther": "{count} epizodów; przewlekłe: {chronic}",
|
||||
"allergiesOne": "{count} alergia",
|
||||
"allergiesFew": "{count} alergie",
|
||||
"allergiesOther": "{count} alergii",
|
||||
"medicationsOne": "{count} lek; bez daty rozpoczęcia: {missingStart}",
|
||||
"medicationsFew": "{count} leki; bez daty rozpoczęcia: {missingStart}",
|
||||
"medicationsOther": "{count} leków; bez daty rozpoczęcia: {missingStart}",
|
||||
"medicationsDatedOne": "{count} lek z datą rozpoczęcia",
|
||||
"medicationsDatedFew": "{count} leki z datą rozpoczęcia",
|
||||
"medicationsDatedOther": "{count} leków z datą rozpoczęcia",
|
||||
"vaccinationsOne": "{count} szczepienie",
|
||||
"vaccinationsFew": "{count} szczepienia",
|
||||
"vaccinationsOther": "{count} szczepień",
|
||||
"visitsOne": "{count} wizyta · z zabiegiem: {procedures}",
|
||||
"visitsFew": "{count} wizyty · z zabiegiem: {procedures}",
|
||||
"visitsOther": "{count} wizyt · z zabiegiem: {procedures}",
|
||||
"visitsPlannedOne": "{count} wizyta, tylko zaplanowana",
|
||||
"visitsPlannedFew": "{count} wizyty, tylko zaplanowane",
|
||||
"visitsPlannedOther": "{count} wizyt, tylko zaplanowane",
|
||||
"labsOne": "{count} dzień z wynikami",
|
||||
"labsFew": "{count} dni z wynikami",
|
||||
"labsOther": "{count} dni z wynikami",
|
||||
"documentsOne": "{count} dokument z datą",
|
||||
"documentsFew": "{count} dokumenty z datą",
|
||||
"documentsOther": "{count} dokumentów z datą",
|
||||
"lifeOne": "{count} wydarzenie życiowe",
|
||||
"lifeFew": "{count} wydarzenia życiowe",
|
||||
"lifeOther": "{count} wydarzeń życiowych",
|
||||
"cycleOne": "{count} cykl",
|
||||
"cycleFew": "{count} cykle",
|
||||
"cycleOther": "{count} cykli",
|
||||
"moodOne": "{count} wpis od {since}",
|
||||
"moodFew": "{count} wpisy od {since}",
|
||||
"moodOther": "{count} wpisów od {since}",
|
||||
"environmentOne": "{count} dzień z danymi o środowisku",
|
||||
"environmentFew": "{count} dni z danymi o środowisku",
|
||||
"environmentOther": "{count} dni z danymi o środowisku",
|
||||
"empty": "Jeszcze brak"
|
||||
},
|
||||
"gap": {
|
||||
"valuesEmpty": "Połącz źródła",
|
||||
"illnessEmpty": "Dodaj epizod",
|
||||
"medicationsWithoutStart": "Uzupełnij",
|
||||
"visitsEmpty": "Dodaj wizytę",
|
||||
"documentsUndated": "Przejrzyj",
|
||||
"labsEmpty": "Dodaj wynik",
|
||||
"vaccinationsEmpty": "Dodaj szczepienia",
|
||||
"lifeEventsEmpty": "Dodaj"
|
||||
},
|
||||
"gapLine": {
|
||||
"medicationsWithoutStartOne": "{count} lek bez daty rozpoczęcia",
|
||||
"medicationsWithoutStartFew": "{count} leki bez daty rozpoczęcia",
|
||||
"medicationsWithoutStartOther": "{count} leków bez daty rozpoczęcia",
|
||||
"documentsUndatedOne": "{count} dokument bez daty",
|
||||
"documentsUndatedFew": "{count} dokumenty bez daty",
|
||||
"documentsUndatedOther": "{count} dokumentów bez daty",
|
||||
"valuesEmpty": "Jeszcze brak wartości z dłuższego okresu",
|
||||
"illnessEmpty": "Jeszcze brak chorób z datą początku",
|
||||
"visitsEmpty": "Jeszcze brak odbytych wizyt",
|
||||
"labsEmpty": "Jeszcze brak wyników badań",
|
||||
"vaccinationsEmpty": "Jeszcze brak szczepień",
|
||||
"lifeEventsEmpty": "Brak wydarzeń życiowych"
|
||||
}
|
||||
}
|
||||
},
|
||||
"legendSpan": "Okres",
|
||||
"legendEvent": "Zdarzenie",
|
||||
"legendMean": "Średnia miesięczna",
|
||||
"today": "Dziś",
|
||||
"noDataYet": "Jeszcze brak danych",
|
||||
"layers": "Warstwy",
|
||||
"layersLanes": "Ścieżki",
|
||||
"zoomLabel": "Zakres widoku",
|
||||
"chartLabel": "Oś czasu od {from} do {to}",
|
||||
"keyboardHint": "Strzałki przesuwają wybór, Home i End przeskakują na krańce, Enter otwiera dzień.",
|
||||
"loadFailed": "Nie udało się wczytać osi czasu.",
|
||||
"empty": {
|
||||
"title": "Na osi czasu jeszcze nic nie ma",
|
||||
"description": "Wpisy z datą pojawią się tutaj, gdy tylko jakieś będą."
|
||||
},
|
||||
"values": {
|
||||
"menuLabel": "Do trzech wartości",
|
||||
"none": "Brak wartości",
|
||||
"noneInWindow": "Brak wartości w tym okresie",
|
||||
"series": {
|
||||
"BLOOD_PRESSURE_SYS": "Ciśnienie skurczowe",
|
||||
"BLOOD_PRESSURE_DIA": "Ciśnienie rozkurczowe"
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"caption": "Wpisy na osi czasu",
|
||||
"lane": "Ścieżka",
|
||||
"entry": "Wpis",
|
||||
"start": "Początek",
|
||||
"end": "Koniec"
|
||||
},
|
||||
"selection": {
|
||||
"empty": "Brak wpisów w tym miesiącu",
|
||||
"ongoing": "trwa",
|
||||
"range": "od {from} do {to}",
|
||||
"mean": "Ø {values}"
|
||||
},
|
||||
"chronicle": {
|
||||
"months": "Miesiące",
|
||||
"years": "Lata",
|
||||
"groupingLabel": "Grupowanie",
|
||||
"gap": "Od {from} do {to} · brak wpisów",
|
||||
"gapSingle": "{period} · brak wpisów",
|
||||
"ended": "Koniec: {label}",
|
||||
"afterDaysOne": "po 1 dniu",
|
||||
"afterDaysFew": "po {count} dniach",
|
||||
"afterDaysOther": "po {count} dniach",
|
||||
"notable": {
|
||||
"extremeHigh": "Najwyższa wartość od dawna",
|
||||
"extremeLow": "Najniższa wartość od dawna",
|
||||
"firstValue": "Pierwsza wartość pomiaru",
|
||||
"gap": "Dłuższa przerwa w wartościach"
|
||||
},
|
||||
"notableMeta": "Otwórz dzień, aby zobaczyć szczegóły"
|
||||
},
|
||||
"standingAllergiesOne": "{count} alergia",
|
||||
"standingAllergiesFew": "{count} alergie",
|
||||
"standingAllergiesOther": "{count} alergii"
|
||||
},
|
||||
"lifeEvents": {
|
||||
"title": "Wydarzenie życiowe",
|
||||
"add": "Wydarzenie życiowe",
|
||||
"subtitle": "Punkt odniesienia na osi czasu, nie pomiar.",
|
||||
"privacy": "Tytuł i notatka są zapisywane w postaci zaszyfrowanej. Nie trafiają do żadnej AI.",
|
||||
"empty": "Brak wydarzeń życiowych",
|
||||
"emptyHint": "Przeprowadzka, narodziny dziecka czy nowa praca dają latom punkt odniesienia.",
|
||||
"save": "Zapisz",
|
||||
"cancel": "Anuluj",
|
||||
@@ -12279,7 +12417,8 @@
|
||||
"endDate": "Do",
|
||||
"note": "Notatka",
|
||||
"optionalTag": "opcjonalnie",
|
||||
"notePlaceholder": "Coś, co zechcesz wiedzieć później"
|
||||
"notePlaceholder": "Coś, co zechcesz wiedzieć później",
|
||||
"removeEnd": "Usuń datę zakończenia"
|
||||
},
|
||||
"category": {
|
||||
"FAMILY": "Rodzina",
|
||||
@@ -12292,6 +12431,21 @@
|
||||
"DAY": "Dzień",
|
||||
"MONTH": "Miesiąc",
|
||||
"YEAR": "Rok"
|
||||
},
|
||||
"edit": "Edytuj wydarzenie życiowe",
|
||||
"errors": {
|
||||
"titleRequired": "Nadaj wydarzeniu nazwę.",
|
||||
"titleTooLong": "Najwyżej 120 znaków.",
|
||||
"categoryRequired": "Wybierz rodzaj.",
|
||||
"dateRequired": "Podaj prawidłową datę.",
|
||||
"endBeforeStart": "Koniec jest przed początkiem.",
|
||||
"noteTooLong": "Najwyżej 2000 znaków."
|
||||
},
|
||||
"saveFailed": "Nie udało się zapisać.",
|
||||
"deleteFailed": "Nie udało się usunąć.",
|
||||
"deleteConfirm": {
|
||||
"title": "Usunąć to wydarzenie życiowe?",
|
||||
"body": "Tytuł i notatka znikną."
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user