Files
drk-blutspende-orte/docs/overview.md
T
Paddy caecc60c7b UI/UX pass: readability, feedback, safer actions, DRK branding
Items 1–12 of the interface review:

- Larger UI font (UI_FONT_SIZE) across widgets, menus, dialogs, Treeview rows.
- DRK-red header bar; window title shows entry count; runtime-drawn red-cross
  icon (also written to data/icon.png for the launcher).
- Status bar colour-coded by severity; transient messages auto-clear after 8 s,
  queue-count messages stay.
- Tab 1: more form spacing, digits-only PLZ, explicit "Auswahl entfernen" +
  Delete key for queue rows, confirm on "Warteschlange leeren", modal on
  duplicate save.
- Tab 2: raw lat/lon columns replaced by one "Karte" column (checkmark / red
  "fehlt"); ▲/▼ arrow on the active sort column; hint line always shows the
  saved-entry count.
- "Karte öffnen" with no coordinates shows a dialog, not just a status line.
- Window size/position remembered between sessions (data/window.json).

Verified by building and driving the window under Homebrew Python 3.12 / Tk 9;
non-GUI smoke tests still pass. Docs updated (changelog, overview, improvements,
data-model, setup, dev-notes).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 18:51:17 +02:00

97 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Overview what the app does
The app is a single window: a **DRK-red header bar**, two tabs, and a
**colour-coded status bar** at the bottom (grey = neutral, green = success,
orange = warning, red = error; transient messages fade back to neutral after
~8 s). The window title shows the total entry count, and the window remembers
its size and position between sessions (`data/window.json`). The UI font is
enlarged for readability (`UI_FONT_SIZE`).
## Tab 1 "Neuer Eintrag" (new entry)
Workflow: build up a **queue** of entries, let them geocode in the background,
then save the whole batch at once.
1. **Entry form** date (a **calendar picker**, `ttkbootstrap.DateEntry`,
pre-filled with today; typed input is accepted in `JJJJ-MM-TT` or
`TT.MM.JJJJ` and **validated** an invalid date is rejected with a dialog),
city (autocomplete combobox), postal code (optional). Pressing `Return` in any
field, or the **+ Hinzufügen** button, adds the row to the queue.
The PLZ field only accepts digits.
2. **Queue table** shows date, city, PLZ, and a live coordinate column that
updates from `⏳ wird gesucht…` to either `lat / lon` or `⚠ nicht gefunden`
as the background geocoder works through the queue.
- Select a row and press <kbd>Delete</kbd>, use the **"Auswahl entfernen"**
button, or click the `✕` cell.
- Right-click a row for *Löschen* / *Koordinaten erneut suchen*.
3. **Action bar**
- **Alle speichern** appends every queued row to `orte.csv`. If any row
looks like a duplicate (same date + city + PLZ), a **modal** lists them and
asks whether to save anyway.
- **Warteschlange leeren** discards the queue (asks for confirmation).
- **Karte öffnen** regenerates `karte.html` and opens it in the browser.
## Tab 2 "Einträge verwalten" (manage entries)
A table view of everything in `orte.csv`.
- **Columns:** Datum, Ort, PLZ, and **Karte** a status column showing `✓` when
the row has coordinates or a red `fehlt` when it doesn't (the whole row is red
too). The raw lat/lon numbers live in the edit dialog, not this table.
- **Search box** live filter across date, city, and PLZ (substring match).
- **Sortable columns** click a header to sort; clicking again reverses. The
active column shows a ▲/▼ arrow. Default sort is by date, newest first.
Sorting by **Karte** groups the rows without coordinates together.
- **"Nur ohne Koordinaten"** toggle filters to entries that have no
coordinates yet. The hint line always shows the total count, plus how many are
missing coordinates.
- **Edit** double-click a row (or *Bearbeiten*) opens a modal dialog to change
date (calendar picker, validated) / city / PLZ. Two ways to fix coordinates:
a "Koordinaten automatisch neu suchen" toggle re-runs geocoding after saving,
or the **Breitengrad / Längengrad** fields let you type them in by hand
(both empty = no map marker).
- **Right-click → Koordinaten suchen** runs geocoding for that one row
(handy for rows that failed the first time).
- **Delete** *Löschen* removes the selected row(s) after a confirmation
dialog. This is **irreversible**, but a timestamped copy of the file is
written to `data/backups/` before every change (see
[data-model.md](data-model.md#backups)).
- **Karte öffnen** same as on Tab 1.
## The map (`karte.html`)
Generated by `generate_map()`:
- Base layer: `CartoDB positron`, initial view centred on `[49.0, 9.0]`,
zoom 8 (roughly Baden-Württemberg).
- One **`CircleMarker`** per unique `(city, lat, lon)` group. Radius scales
linearly with the visit count for that location
(`5 + count / max_count * 20` px), colour is DRK red (`#CC0000`).
- Popup shows the city and the visit count; tooltip shows the city.
- Rows with missing/blank coordinates are silently excluded.
- If there are no usable coordinates at all, a dialog says so (and the status
bar shows a warning).
> The generated HTML pulls Leaflet, jQuery and Bootstrap from CDNs, so the map
> needs an internet connection to render even though the data is local.
## Geocoding behaviour
`geocode_city(city, postal_code)` tries a series of queries in order and returns
the first hit:
1. `"<PLZ> <city>, Germany"` (only if a PLZ was given)
2. `"<city>, Baden-Württemberg, Germany"`
3. `"<city>, Hessen, Germany"`
4. `"<city>, Germany"`
The regional bias is the `GEOCODE_REGIONS` constant (`Baden-Württemberg`,
`Hessen`) near the top of `app.py`. Results are rounded to five decimal places.
Nominatim's usage policy (max 1 req/s, identifying `user_agent`) is respected by
a manual `time.sleep(1)` in the worker loop.
If the geocoding service is unreachable (no internet), entries still save
without coordinates and after a few consecutive failures a one-time dialog
explains that the coordinates can be added later via *Bearbeiten*. The worker
thread logs failures to `data/app.log` and keeps running.