Skip to content

Dashboard improvements, CSV import dedupe, and remote-DB performance - #1

Merged
shim369 merged 9 commits into
mainfrom
dashboard-improvements-and-csv-import-feedback
Sep 23, 2026
Merged

shim369 merged 9 commits into
mainfrom
dashboard-improvements-and-csv-import-feedback

Conversation

@shim369

@shim369 shim369 commented Sep 23, 2026

Copy link
Copy Markdown
Owner

Summary

Dashboard improvements, CSV import feedback/dedupe, and a large speed-up of every page against the remote Neon DB (≈110 ms per round trip).

Performance

  • CSV import: rows are saved in one transaction via new record_*_logs(list) service methods instead of one commit per row (140 rows: ~50 s → 0.85 s)
  • Read cache (app/services.py): read-only service calls (list_/get_/compute_) are cached in-process (TTL 10 min). A write invalidates the written service plus services reading the same tables (_DEPENDENTS); a generation counter prevents storing stale values loaded during a concurrent write
  • Parallel prefetch (prefetch()): independent page-load reads on dashboard/today/goals/recipe run in a thread pool (dashboard cold load 3.05 s → 1.50 s; cached reruns ≈ 0 DB round trips). ScriptRunContext is propagated to worker threads
  • N+1 removal: recipe ingredient names and goal task progress now use single IN queries (IngredientRepository.list_by_ids, DailyTaskLogRepository.list_by_tasks)

Dashboard

  • Period selector (7 / 30 / 90 days)
  • Workout section: removed "workout sessions"; added max weight per strength exercise (top 5 by recorded days, gaps connected) and cardio time stacked by exercise (y max 90 min)
  • Fixed y-axis maxima (calories, PFC, cardio, …) now expand when a day exceeds them instead of drawing bars outside the plot
  • Fixed pandas FutureWarning on all-NA line series

CSV import

  • Success message shown under the uploader after import
  • Rows whose content matches an existing log are skipped (split_new_logs), so importing the same file twice no longer multiplies dashboard totals

Other

  • Sidebar label "Recipe" → "AI Recipes" (matches the page title)
  • Claude Code tooling: PreToolUse hook blocking pytest without .env.test (test_migrations.py drops every table in the configured DB), /check (lint, format, mypy, i18n duplicate keys, safe unit tests) and /db-health (read-only production DB check) skills
  • Docs (README en/ja, architecture 7.4 / 18 / 20, requirements 17.6 / 18) synced

Data note

Existing duplicate rows in production (meals ×4, workouts ×3 from repeated CSV imports) were already removed with the user's approval (meals 880 → 220, workouts 153 → 51); /db-health now reports 0 duplicates.

Test plan

  • .claude/skills/check/check.sh: ruff, format, mypy, i18n keys, 112 unit tests pass
  • New unit tests for split_new_logs and workout aggregations
  • Dashboard rendered via Streamlit AppTest against real data (ja/en × 7/30/90 days): no exceptions or warnings
  • Bulk insert verified on the real DB inside a rolled-back transaction
  • Manual browser check: dashboard workout charts (legend/readability), CSV import of an already-imported file shows the skip message
  • CI (migration + integration tests on the Postgres service container)

🤖 Generated with Claude Code

shim369 and others added 9 commits September 22, 2026 18:44
Previously the success st.success() was shown right before st.rerun(),
so the message was cleared before the user could ever see it. The
imported count is now stashed in session_state and rendered under the
file uploader on the next render, right below the "Upload" control.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Add a 7/30/90-day period selector so historical CSV-imported logs
  (older than 7 days) are actually visible on the dashboard instead of
  being silently dropped by the previously hardcoded 7-day window.
- Compute the reference date from JST instead of UTC, matching the
  rest of the app's date-boundary convention (avoids a 1-day window
  shift during 00:00-08:59 JST).
- Fix an N+1 query pattern: the study/work-time and household-expense
  sections looped list_task_logs/get_journal once per displayed day
  (up to ~180 DB round trips at the 90-day setting). Added
  list_by_date_range to DailyTaskLogRepository/DailyJournalRepository
  (protocol + SQLAlchemy + fake test impls) and corresponding
  DailyJournalService methods to fetch each range in a single query.
- Fix chart readability: integer-only y-axis ticks for session count
  and condition score, angled date labels for longer periods, and
  fixed y-axis ranges tuned to this user's typical values (calories
  0-3500, PFC 0-500g, weight 60-75kg, study/work time 0-600min,
  workout sessions 0-10, cardio time 0-360min).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Dashboard period selector (7/30/90 days, JST day boundaries)
- CI now runs migrations and integration tests against a Postgres service
- Weight ML pipeline real-data readiness check and weekly workflow
- Browser-based initial locale for new users; login screen fixed to English
- Recipe history accordions with delete

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- CSV import: add record_*_logs bulk methods and save all rows in a
  single transaction instead of one commit per row (~50s -> <1s for 140 rows)
- app/services.py: cache read-only service calls (list_/get_/compute_),
  invalidating the written service and its dependents on every write
- prefetch(): run independent page-load reads in parallel on
  dashboard/today/goals/recipe
- Remove N+1 queries in recipe ingredient names and goal task progress

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- CSV import: skip rows whose content matches an existing log
  (split_new_logs), so importing the same file twice no longer
  multiplies dashboard totals
- Dashboard: expand the fixed y-axis max (calories/PFC etc.) when a
  day exceeds it instead of drawing bars outside the plot
- prefetch(): propagate ScriptRunContext to worker threads to silence
  "missing ScriptRunContext" warnings
- Dashboard line charts: build long-form DataFrame directly to avoid
  pandas FutureWarning on all-NA series

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…harts

- Remove the "workout sessions" chart
- Add max weight per exercise (top 5 by recorded days) line chart,
  connecting gaps between sparse training days
- Add daily strength volume (weight x reps, bodyweight excluded)
- Cardio time is now stacked by exercise, y-axis max 90 min
  (expands when exceeded)
- Rename sidebar "Recipe" label to "AI Recipes" to match the page title

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Workout section now shows max weight per exercise and cardio time by
exercise, both full width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PreToolUse hook blocks pytest unless .env.test exists or DATABASE_URL
  is overridden to localhost (test_migrations.py wipes the configured DB)
- /check: ruff, format, mypy, i18n duplicate keys, safe unit tests
- /db-health: read-only production DB check (counts, content duplicates,
  latest record date, orphaned workout rows)
- Expose csv_import.content_key for reuse by /db-health
- Ignore .claude/settings.local.json

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- README (en/ja): describe new dashboard workout charts and CSV
  duplicate-row skipping; fix the testing section (tests/unit includes
  the DB-destroying test_migrations.py) to use check.sh / /check, add
  /db-health usage, the pytest DB guard hook, the 10-minute read cache
  limitation, and .claude/ in the project structure
- architecture.md: add 7.4 remote-DB performance design (read cache and
  invalidation, parallel prefetch, bulk CSV insert, N+1 avoidance),
  test DB protection layers in ch.18, and .claude/ in ch.20
- requirements.md: update dashboard chart list and y-axis auto-expand,
  CSV import dedupe/bulk save, "AI Recipes" page name, and add 17.6
  performance requirements

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@shim369
shim369 merged commit d547a20 into main Sep 23, 2026
2 checks passed
@shim369
shim369 deleted the dashboard-improvements-and-csv-import-feedback branch September 23, 2026 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant