fix: resolve stash conflict and update roadmap to v2
Resolved merge conflict in exercise_card.html (kept suggested reps/weight pre-population logic) and updated roadmap.md with the new v2 improvement plan. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,13 @@
|
|||||||
<!-- Inline logging (Phase 4) -->
|
<!-- Inline logging (Phase 4) -->
|
||||||
{% if active_profile %}
|
{% if active_profile %}
|
||||||
<div id="logs-exercise-{{ exercise.id }}">
|
<div id="logs-exercise-{{ exercise.id }}">
|
||||||
|
{% if existing_logs and existing_logs[exercise.id] %}
|
||||||
|
{% set suggested_reps = existing_logs[exercise.id][-1].reps_completed %}
|
||||||
|
{% set suggested_weight = existing_logs[exercise.id][-1].weight_used %}
|
||||||
|
{% elif suggestions and suggestions[exercise.id] %}
|
||||||
|
{% set suggested_reps = suggestions[exercise.id].suggested_reps %}
|
||||||
|
{% set suggested_weight = suggestions[exercise.id].suggested_weight %}
|
||||||
|
{% endif %}
|
||||||
{% if existing_logs and existing_logs[exercise.id] %}
|
{% if existing_logs and existing_logs[exercise.id] %}
|
||||||
{% set logs = existing_logs[exercise.id] %}
|
{% set logs = existing_logs[exercise.id] %}
|
||||||
{% set exercise_id = exercise.id %}
|
{% set exercise_id = exercise.id %}
|
||||||
|
|||||||
131
docs/roadmap.md
131
docs/roadmap.md
@@ -1,30 +1,127 @@
|
|||||||
# SneakySwole Roadmap
|
# SneakySwole Roadmap
|
||||||
|
|
||||||
## Completed
|
## V2 Improvements
|
||||||
|
|
||||||
### Phase 1: Scaffold & Infrastructure
|
Each improvement is implemented as a separate branch/PR. Implementation order matters — auth removal goes first since other features depend on the simplified profile flow.
|
||||||
FastAPI project structure, Dockerfile + docker-compose.yaml, Pico CSS dark theme base template, `.env` config, structlog logging, health check endpoint.
|
|
||||||
|
|
||||||
### Phase 2: Data Layer & Seeding
|
---
|
||||||
8-table SQLite schema via SQLModel + Alembic migrations. YAML-driven seed script (`config/exercises.yaml`, `config/user_programs.yaml`). Service layer for all DB access. Admin user auto-created from `.env` with bcrypt.
|
|
||||||
|
|
||||||
### Phase 3: Workout UI
|
### 1. Easier Profile Selection
|
||||||
Admin login (bcrypt + signed session cookies), profile switcher, workout day viewer with warmups and exercise cards, HTMX-powered exercise browser with search/filter. NavContextMiddleware for automatic template context.
|
**Branch:** `feature/remove-auth`
|
||||||
|
|
||||||
### Phase 4: Logging & Tracking
|
Strip all authentication entirely — this is a homelab app, no need for login. When the app opens, the landing page (`/`) shows a profile picker with cards for each user. Selecting a profile sets an `active_profile_id` cookie that persists across sessions (per-device, until the user switches profiles or clears cookies).
|
||||||
Inline set logging from the workout day view via HTMX. Auto-created workout sessions. Log history with per-session detail view. Edit and delete log entries.
|
|
||||||
|
|
||||||
### Phase 5: Progression & Analytics
|
**What gets removed:**
|
||||||
Auto-progression engine (+reps/+weight/deload rules), 4-week schedule calendar, progress dashboard with Chart.js charts, per-exercise progress pages with suggestions.
|
- Admin login flow (login page, bcrypt password verification, session tokens)
|
||||||
|
- `is_admin` and `password_hash` fields from the users table
|
||||||
|
- `auth_service.py`, `auth.py` routes, `login.html` template
|
||||||
|
- `bcrypt` and `itsdangerous` dependencies
|
||||||
|
- Auth dependency (`get_current_admin_user`) from all route handlers
|
||||||
|
|
||||||
|
**What gets added/changed:**
|
||||||
|
- `/` becomes the profile picker page (cards with name, height, weight, and "Select" button)
|
||||||
|
- `require_active_profile()` dependency replaces auth — just checks for the cookie
|
||||||
|
- `NoProfileSelectedError` handler redirects to `/` if no profile is set
|
||||||
|
- `NavContextMiddleware` simplified to only read the `active_profile_id` cookie
|
||||||
|
- Nav bar always shows profile switcher dropdown (no admin gating)
|
||||||
|
|
||||||
|
**Edge cases:**
|
||||||
|
- No profiles exist → show "Create Profile" link
|
||||||
|
- Cookie references a deleted profile → middleware returns None, redirect to picker
|
||||||
|
- Existing DB with admin row → migration deletes it
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Schedule Adjustment — "Workout Now" Flow
|
||||||
|
**Branch:** `feature/workout-now` | **Depends on:** #1 merged
|
||||||
|
|
||||||
|
Replace the `/workouts` page (static list of all 4 days) with a smart "Workout Now" page that auto-recommends the next workout in the Push → Pull → Lower → Full Body cycle based on the user's last completed session.
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
1. User selects profile → navigates to `/workouts`
|
||||||
|
2. App queries the most recent `workout_session` for that profile
|
||||||
|
3. Determines next day in cycle (e.g., last did Push → recommend Pull). No history defaults to Push.
|
||||||
|
4. Page shows all 4 workout types as cards, with the recommended one visually highlighted (`<mark>Recommended Next</mark>`, primary button vs outline for others)
|
||||||
|
5. User clicks "Start Workout" on any card → goes to that workout's exercise page
|
||||||
|
6. Once on a workout, a "Change Workout" button is visible to switch types (soft lock — not hard-locked, but the UI keeps you focused on the chosen workout)
|
||||||
|
|
||||||
|
**Card-based approach (no JS):** The recommendation is shown via highlighted cards rather than a dropdown/select. This follows the project's HTMX-first principle — no JavaScript needed.
|
||||||
|
|
||||||
|
**Display context:** Show "Last workout: Pull on Mar 10" message on the page so the user understands the recommendation.
|
||||||
|
|
||||||
|
**Edge cases:**
|
||||||
|
- Same-day multiple workout types → creates separate sessions (existing behavior, correct)
|
||||||
|
- No profile selected → show "pick a profile first" message with link to `/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Automatic Scaled Workout Reps / Sets / Weights — 6→12 Rep Ladder
|
||||||
|
**Branch:** `feature/rep-ladder-progression` | **Depends on:** #1 merged
|
||||||
|
|
||||||
|
Replace the current wk1/wk4 target system with a fixed, universal rep ladder progression. Every exercise follows the same pattern:
|
||||||
|
|
||||||
|
**Progression model:**
|
||||||
|
- **Rep ladder:** 6 → 8 → 10 → 12 reps at current weight
|
||||||
|
- **Weight increase:** At 12 reps with all sets marked "felt easy" → +5 lbs, reset to 6 reps
|
||||||
|
- **Hold:** If not all sets felt easy at current reps → stay at current reps/weight
|
||||||
|
- **Climb:** If all sets felt easy but below 12 reps → move to next step in ladder
|
||||||
|
- **Deload:** After 4+ consecutive sessions struggling (none felt easy) → reduce weight by 20%, reset to 6 reps
|
||||||
|
- **Always 3 sets** per exercise
|
||||||
|
|
||||||
|
**Schema change:** Simplify `user_exercise_programs` table — keep only `starting_weight` per user/exercise (migrated from existing `wk1_weight` data). Drop `wk1_reps`, `wk4_reps`, `wk4_weight` columns. The existing 40 rows of programming data (20 exercises × 2 users) are preserved as starting weights.
|
||||||
|
|
||||||
|
**Starting weight behavior:**
|
||||||
|
- Exercise with no log history → suggest starting_weight at 6 reps, 3 sets
|
||||||
|
- Exercise with log history → progression engine picks up from last logged values
|
||||||
|
|
||||||
|
**UI change:** Replace the Week 1/Week 4 target display on exercise cards with a rep ladder progress bar showing the 4 steps (6, 8, 10, 12) with the current position filled in.
|
||||||
|
|
||||||
|
**Bodyweight exercises** (weight = "BW"): Weight increase is skipped. User climbs the rep ladder and holds at 12 reps.
|
||||||
|
|
||||||
|
**Data continuity:** The 55 existing workout log entries are unchanged and feed directly into the new progression engine. The progression_service.py gets a full rewrite of `get_suggestion()` with the new ladder logic.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Export Workout History as CSV
|
||||||
|
**Branch:** `feature/csv-export` | **Depends on:** #1 merged
|
||||||
|
|
||||||
|
Add a CSV export section to the dashboard page with a date range picker (default: last 30 days) and a "Download CSV" button.
|
||||||
|
|
||||||
|
**CSV format — one row per set:**
|
||||||
|
| Column | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| date | Workout session date (ISO format) |
|
||||||
|
| workout_type | Push / Pull / Lower / Full Body |
|
||||||
|
| exercise | Exercise name |
|
||||||
|
| set_number | Set number within that exercise |
|
||||||
|
| reps | Reps completed |
|
||||||
|
| weight | Weight used |
|
||||||
|
| felt_easy | Yes / No |
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
- `GET /dashboard/export?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD` returns a CSV file download
|
||||||
|
- Uses standard HTML form GET (not HTMX — HTMX can't trigger file downloads)
|
||||||
|
- `StreamingResponse` with `Content-Disposition: attachment` header
|
||||||
|
- Filename: `sneakyswole_{profile_name}_{start}_to_{end}.csv`
|
||||||
|
- Date range defaults: start = 30 days ago, end = today. Invalid dates fall back to defaults.
|
||||||
|
|
||||||
|
**Edge cases:**
|
||||||
|
- No data in range → CSV with headers only (valid empty CSV)
|
||||||
|
- No profile selected → redirect to dashboard
|
||||||
|
- Large date ranges are fine — even a year of heavy use is ~3,000 rows
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Order
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Remove Auth ──┬──> 2. Workout Now
|
||||||
|
├──> 3. Rep Ladder Progression (can be parallel with 4)
|
||||||
|
└──> 4. CSV Export (can be parallel with 3)
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Future Ideas
|
## Future Ideas
|
||||||
|
|
||||||
- Multi-user login (replace profile switcher with individual logins)
|
|
||||||
- REST API for mobile clients
|
|
||||||
- Exercise video/image attachments
|
- Exercise video/image attachments
|
||||||
- Custom workout program builder
|
- Custom workout program builder
|
||||||
- Export/import workout data (CSV/JSON)
|
|
||||||
- Notifications/reminders
|
|
||||||
- Social features (sharing workouts)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user