feat(fitness/body-parts): "Same as last" button + larger Copy L→R pill
- New "Same as last" pill below each step's stepper. Clicking fills the input(s) with the prior recorded value(s) — for paired steps in split mode, both L and R — and advances to the next step. Only rendered when a previous measurement exists; the placeholder already surfaces the exact number so the button text stays terse. - Copy L→R button resized to match the same-as-last pill (0.88 rem text, 0.55 × 1.1 rem padding) and given top margin. Unicode → swapped for a proper ArrowRight icon between L and R. - i18n: added `same_as_last` and split `copy_l_to_r` into `copy_l_to_r_before` / `copy_l_to_r_after` so each language keeps its natural wrapping around the arrow (EN "Copy L / R", DE "L / R übernehmen").
This commit is contained in:
@@ -4,9 +4,10 @@
|
||||
[x] on /fitness/measure, fill "Past measurements" in SSR only for the last 10 measurements. anything further should be fetched client side on mount to decreae initial page load time. use a "show more" button and paginate measurments.
|
||||
[x] on /fitness/measure (resp. their associated logging API routes), consolidate measurements by day. If we want to log another measurement, overwriting an old one, show a warning to indicate this. disparate measurements (e.g., weight and bodyfat) should not show this warning but simply be merged into one log entry for that day.
|
||||
[x] on /fitness/measure in the past measurments tab, show more than "Body measurements only" if we don't have Bodyweight logged. we can be a bit more elaborate in our syntax here tbh.
|
||||
[ ] add a button on /fitness/measure/body-parts for each measurement directly below to say "Same value", instead of having to hit +, then - to lock in same number
|
||||
[x] add a button on /fitness/measure/body-parts for each measurement directly below to say "Same value", instead of having to hit +, then - to lock in same number
|
||||
[ ] BF graph (with trend line like weight graph) on /fitness/stats page. Emphasize relative changes, not absolute numbers in design (as we cannot trust those) (e.g., use start day of overview as 0% and then show +/- x % on the graph)
|
||||
[ ] Workshop better names than "Measure" for the /fitness/measure route. It's about body data points (i.e., non-food related). What's a better, short name than "Measure" to capture the logging of weight, body composition, body part measurements, and period tracking?
|
||||
[ ] on /fitness/stats/histoy/<part> for body measurement graphs, make the range reasonable. e.g., if we have 1 cm change, do not fill the entire y-height with 1 cm. Use reasonable padding for low ranges (i think we do something like htis already on the weight graph?)
|
||||
|
||||
## Refactor Recipe Search Component
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homepage",
|
||||
"version": "1.46.5",
|
||||
"version": "1.46.6",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -292,6 +292,8 @@ const translations: Translations = {
|
||||
exit: { en: 'Exit', de: 'Schlie\u00dfen' },
|
||||
same_both_sides: { en: 'Same on both sides', de: 'Auf beiden Seiten gleich' },
|
||||
copy_l_to_r: { en: 'Copy L \u2192 R', de: 'L \u2192 R \u00fcbernehmen' },
|
||||
copy_l_to_r_before: { en: 'Copy L', de: 'L' },
|
||||
copy_l_to_r_after: { en: 'R', de: 'R \u00fcbernehmen' },
|
||||
kbd_nav: { en: 'nav', de: 'Navigation' },
|
||||
kbd_next: { en: 'next', de: 'weiter' },
|
||||
kbd_skip: { en: 'skip', de: 'auslassen' },
|
||||
@@ -319,6 +321,7 @@ const translations: Translations = {
|
||||
de: 'Für dieses Datum sind bereits Werte erfasst: {fields}. Überschreiben?'
|
||||
},
|
||||
overwrite_confirm: { en: 'Overwrite', de: 'Überschreiben' },
|
||||
same_as_last: { en: 'Same as last', de: 'Wie zuletzt' },
|
||||
|
||||
// SetTable
|
||||
set_header: { en: 'SET', de: 'SATZ' },
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script>
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Minus, Plus, X, ArrowLeft, ArrowRight, Check, Ruler, CopyPlus, TrendingUp } from '@lucide/svelte';
|
||||
import { Minus, Plus, X, ArrowLeft, ArrowRight, Check, Ruler, CopyPlus, TrendingUp, History } from '@lucide/svelte';
|
||||
import { fly, fade } from 'svelte/transition';
|
||||
import { cubicOut } from 'svelte/easing';
|
||||
import { detectFitnessLang, t } from '$lib/js/fitnessI18n';
|
||||
@@ -119,6 +119,20 @@
|
||||
}
|
||||
/** @param {string} key */
|
||||
function copyLtoR(key) { values[key].right = values[key].left; }
|
||||
|
||||
/** @param {string} key */
|
||||
function useLastValue(key) {
|
||||
const s = steps.find((x) => x.key === key);
|
||||
if (!s) return;
|
||||
const last = historyFor(s).at(-1);
|
||||
if (!last) return;
|
||||
if (s.paired) {
|
||||
if (last.left != null) values[key].left = String(last.left);
|
||||
if (!values[key].same && last.right != null) values[key].right = String(last.right);
|
||||
} else if (last.value != null) {
|
||||
values[key] = String(last.value);
|
||||
}
|
||||
}
|
||||
/** @param {number} i */
|
||||
function jumpTo(i) {
|
||||
direction = i > idx ? 1 : -1;
|
||||
@@ -463,10 +477,19 @@
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="copy-btn" onclick={() => copyLtoR(step.key)} disabled={!pv.left}>
|
||||
<CopyPlus size={13} /> {t('copy_l_to_r', lang)}
|
||||
<CopyPlus size={15} />
|
||||
<span>{t('copy_l_to_r_before', lang)}</span>
|
||||
<ArrowRight size={14} />
|
||||
<span>{t('copy_l_to_r_after', lang)}</span>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{#if lastForStep?.left != null || lastForStep?.right != null}
|
||||
<button type="button" class="same-value-btn" onclick={() => { useLastValue(step.key); next(); }}>
|
||||
<History size={15} />
|
||||
<span>{t('same_as_last', lang)}</span>
|
||||
</button>
|
||||
{/if}
|
||||
<div class="same-toggle">
|
||||
<Toggle bind:checked={pv.same} label={t('same_both_sides', lang)} />
|
||||
</div>
|
||||
@@ -483,6 +506,12 @@
|
||||
<Plus size={20} />
|
||||
</button>
|
||||
</div>
|
||||
{#if lastForStep?.value != null}
|
||||
<button type="button" class="same-value-btn" onclick={() => { useLastValue(step.key); next(); }}>
|
||||
<History size={15} />
|
||||
<span>{t('same_as_last', lang)}</span>
|
||||
</button>
|
||||
{/if}
|
||||
{/if}
|
||||
</section>
|
||||
{/key}
|
||||
@@ -876,13 +905,15 @@
|
||||
align-self: center;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
padding: 0.25rem 0.7rem;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.55rem 1.1rem;
|
||||
border: 1px dashed var(--color-border);
|
||||
border-radius: var(--radius-pill);
|
||||
background: transparent;
|
||||
font-size: 0.7rem;
|
||||
color: var(--color-text-tertiary);
|
||||
font-size: 0.88rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: all 150ms;
|
||||
}
|
||||
@@ -893,6 +924,28 @@
|
||||
}
|
||||
.copy-btn:disabled { opacity: 0.45; cursor: not-allowed; }
|
||||
|
||||
.same-value-btn {
|
||||
align-self: center;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.55rem 1.1rem;
|
||||
border: 1px dashed color-mix(in oklab, var(--color-primary) 40%, transparent);
|
||||
border-radius: var(--radius-pill);
|
||||
background: color-mix(in oklab, var(--color-primary) 5%, transparent);
|
||||
font-size: 0.88rem;
|
||||
font-weight: 600;
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: border-color var(--transition-fast, 120ms), background var(--transition-fast, 120ms), color var(--transition-fast, 120ms);
|
||||
}
|
||||
.same-value-btn:hover {
|
||||
border-style: solid;
|
||||
border-color: var(--color-primary);
|
||||
background: color-mix(in oklab, var(--color-primary) 12%, transparent);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.same-toggle {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user