Dedup Garmin data storage, configurable chart colors, taxonomy fixes, sync/progression fixes

- Remove duplicated Garmin fields from storage; decode display-only fields
  (activity name/type, lap duration/HR, structured workout raw JSON) from
  RawJSON at API-response time instead of storing redundant columns
- Add a fully configurable chart color system (pace/HR main-line colors, 4
  effort-kind colors, tint/darken/brighten intensity knobs) under Profile >
  Chart colors
- Rename training types and fix their display order (Easy, Long, 60'/30'
  Threshold, Tempo, Intervals, MAS Test, Race) everywhere they're listed
- Add an Efficiency Factor progression metric; fix Progression chart axes to
  use tight non-zero-based domains, m:ss/km pace formatting, and rounded
  ticks instead of raw floating-point labels
- Expose the raw get_workout_by_id() payload in the raw-data viewer
  alongside activity/lap/detail JSON; enlarge the modal and shrink array
  indentation for readability
- Fix "last sync" reporting a meaningless activity count: record one
  combined sync run per manual "Sync now" and count genuinely new
  activities instead of re-listing whatever Garmin returned for the queried
  window
- Let a Review Queue activity be manually cleared back to Unclassified, and
  make "Reset all" available even while disconnected from Garmin

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 06:33:47 +02:00
parent 9818d35910
commit 518bccf5ab
56 changed files with 2334 additions and 890 deletions

View File

@@ -9,6 +9,7 @@ const METRICS: { key: ProgressionMetric; label: string }[] = [
{ key: "vo2max", label: "VO2max" },
{ key: "aerobic_te", label: "Aerobic Training Effect" },
{ key: "anaerobic_te", label: "Anaerobic Training Effect" },
{ key: "efficiency_factor", label: "Efficiency Factor" },
];
export function Dashboard() {
@@ -42,17 +43,16 @@ export function Dashboard() {
return (
<div className="page">
<h2>Progression</h2>
{kinds.length === 0 ? (
<p className="empty-state">
No workout kinds defined yet. Create one on the Workout Kinds tab to start seeing progression here.
No training types defined yet. See the Training types card on the Profile page to start seeing progression
here.
</p>
) : (
<>
<div className="controls">
<label>
Workout kind
Training types
<select
value={selectedKindId ?? ""}
onChange={(e) => setSelectedKindId(Number(e.target.value))}