Backend:
- PATCH /api/wahl/:wahlId (isOpen) to open/close a Wahl.
- GET /api/wahl/:wahlId/teilnehmer (LT): participants with their priorities
and any existing Force-Zuteilung.
- Verified against local Postgres: PATCH toggles isOpen, teilnehmer list
returns, CSV export works. (A stale dev server on :3000 masked this at
first — real routes are fine.)
Client (client/app/):
- Wahl detail: open/close switch, participant list with a "Zuteilen"
(Force-Zuteilung) action, CSV export via a browser download
(browser.downloadText).
- files_admin_screen.dart: LT file upload — browser.pickFile() +
visibility picker -> multipart POST /api/files/:kcId; list existing
files. Reachable from KcDetailScreen.
- browser_web.dart gains pickFile()/downloadText() (native <input file> +
Blob), with throwing stubs for the VM.
- Dropped the file_picker package again (heavy transitive deps, and the
native web input is enough); disk on this box is nearly full.
flutter analyze/test/build web green; backend npm test 56.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
New screens (client/app/lib/screens/):
- wahl_admin_screen.dart — per KC: list/create Wahlen; per Wahl: add
workshops, run the assignment (POST /wahl/:id/zuteilung/run), view the
result table.
- teamer_admin_screen.dart — per Gemeinde: list/create local Teamer
accounts, create group-link or per-email invites (shows the token).
- verantwortliche_register_screen.dart — enter a KC invite code
(GET /onboarding/kc/:code), pick a Gemeinde, submit
(POST /onboarding/verantwortliche); shown on the home screen to a
logged-in Authentik user who has no membership yet.
- ui.dart — shared toast / ErrorText / SectionHeader / promptText.
KcDetailScreen now links to Wahl admin and each Gemeinde row opens Teamer
admin.
Backend: widen the wahl + files LT routes to AuthGuard(['authentik','team'])
for consistency with the other LT controllers. Rebrand web/index.html +
manifest from "kc_app" to "KC-App".
Verified against local Postgres with an isLeitungsteam team token: create
KC/Gemeinde/Wahl/Workshop, run Zuteilung, create Teamer + invite, resolve
an invite code. flutter analyze/test/build web green; backend npm test 56.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>