trackWork 0.15.0

A terminal-based time tracking application for managing work sessions
# Weekly Summary Architecture

## Overview

Full-screen mode (`InputMode::WeekSummary { anchor, selected_day, selected_field, editing }`)
that overlays the whole app and renders all 7 weekday timelines (Mon–Sun) side by side on
one shared vertical time scale, plus a per-day stats footer and an **editable section** for
the highlighted day. Distinct from the right-side `week_overview` panel, which only
aggregates time per Jira issue.

Files mirror the `tasks/` layout:
- `state.rs``DaySummary` + `build_week()` (data only, no rendering)
- `ui.rs``draw_week_summary()` (rendering only)
- `input.rs``handle_week_summary_input()` (key handling)
- `mod.rs` — re-exports

## Entry / exit

Opened from the Operations menu (`m` → "Weekly summary"). The week is derived from `anchor`
via `week_start_of`. `selected_day` (0..=6) is the highlighted column; `selected_field`
(0=Workday Start, 1=Workday End, 2=Lunch) the row in the edit panel. `Esc`/`q` → Normal.

## Navigation & editing (state lives in the `InputMode::WeekSummary` variant)

Browse (`editing == None`):
- ``/`` — move highlighted day; rolls into the adjacent week at the Mon/Sun edge
  (`App::week_select_day`).
- `Shift+←`/`Shift+→` — page a whole week, keep weekday (`App::week_change_week`).
- ``/`` — cycle Workday Start / End / Lunch (`App::week_move_field`).
- `Enter``App::week_open_day` leaves the summary and opens the highlighted day in the
  normal dashboard (sets `current_date`, `refresh_entries`, `InputMode::Normal`, entry 0).
- `e`/`E``App::week_begin_edit` builds a `DayEditDraft` for the highlighted field (inline edit).

Edit (`editing == Some`): `↑`/`↓` nudge the active time (`adjust_time_string`), digits/`:`
type, `Tab` toggles lunch start/end, `Enter` saves (`week_edit_save`), `Esc` cancels.

`week_edit_save` writes **Workday Start/End** as per-day overrides
(`db.set_day_overrides`, preserving the untouched side) and **Lunch** as an `off_work`
`TimeEntry` — updating the day's first off-work entry if present, else `create_entry` +
`toggle_off_work`. Edits to `current_date` trigger `refresh_entries` so the dashboard
cache stays correct. App methods are all named `week_*`, mirroring the `tasks_*` family.

## Data: `build_week(app, anchor) -> Vec<DaySummary>`

For each of Mon–Sun (`week_start_of` = Monday of anchor's ISO week) it queries the DB
fresh every frame (`db.get_entries_for_date`, `db.get_day_overrides`) — cheap indexed
reads, and running timers stay live. Span uses the shared `app::at_work_span_of(entries,
start_ov, end_ov, now)` free fn (same logic as the dashboard "At Work" row).

Per-day metrics (running entries counted up to `now`):
- `logged_min` = Σ duration where `logged && !off_work`
- `unlogged_min` = Σ duration where `!logged && !off_work`
- `workday_min` = span length − Σ off_work duration (clamped ≥ 0)
- `missing_lunch` = has ≥1 work entry but **zero** off_work entries

## Rendering: shared vertical scale

The key to side-by-side comparison: one time window for all columns.
1. `window_start` = earliest span start across the week, floored to the hour.
2. `window_end` = latest span end, ceiled to the hour.
3. `minutes_per_row` via `dashboard::utils::calculate_minutes_per_row` (shared with the
   day timeline) sized to the day-column inner height minus the stats footer (`STAT_LINES`).
4. Every column iterates the same rows, so equal times line up horizontally.

`ui.rs` splits `inner` vertically into the **grid** (`draw_grid`, `Min(3)`) and the
**edit panel** (`draw_edit_panel`, `Length(8)`).

Grid: a 6-wide time-axis gutter (hour labels) + 7 equal day columns. Each day column is a
bordered block titled `Mon 05-26`; the `selected_day` column's border/title is Cyan,
today's title Green. Bars use config palette colors (`string_to_color`); `off_work` slices
render Magenta. Empty rows show faint `─`/`╌`/`┄` guides. Footer per column: Start, End,
Logged, Unlog, Work, and a red `⚠ no lunch` when flagged.

Edit panel: bordered block titled with the selected day, three rows (Workday Start / End /
Lunch). The `selected_field` row is highlighted (`bg DarkGray`); while editing it shows the
`DayEditDraft` buffer(s) bracketed (`bg White`), the active lunch sub-field marked. A hint
line at the bottom switches between browse and edit keymaps.

## Lunch suggestion

`suggest_lunch_gap` (app.rs) scans the day's non-off-work, ended entries (sorted by start)
and returns the bounds of the largest positive gap between consecutive tasks, falling back
to `11:30–12:00`. Used to prefill the Lunch draft when the day has no off-work entry yet.

## Extension points

- New per-day metric: add field in `DaySummary` + compute in `build_week`, render in
  `render_day_lines`'s footer (bump `STAT_LINES` to keep bars from overflowing).
- Different bar styling: edit the covering-entry branch in `render_day_lines`.