Просмотр исходного кода

Sessieafsluiting: TASKS.md opgeschoond (afgeronde items ingekort tot restwerk), CLAUDE.md aangevuld (Insert Widget-patroon, Set Variable-icoontje, API-cache-architectuur, adb-devices-check)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
bob 1 месяц назад
Родитель
Сommit
eeb3d3736c
2 измененных файлов с 117 добавлено и 212 удалено
  1. 57 0
      CLAUDE.md
  2. 60 212
      TASKS.md

+ 57 - 0
CLAUDE.md

@@ -118,6 +118,19 @@ export PATH="/home/bob/fvm/bin:$HOME/.pub-cache/bin:$PATH" && /home/bob/Projects
   `run_in_background: true`. Volg tot minimaal "All done!" én
   `run_in_background: true`. Volg tot minimaal "All done!" én
   idealiter een succesvolle app-launch (`Launching lib/main.dart...`,
   idealiter een succesvolle app-launch (`Launching lib/main.dart...`,
   geen nieuwe `EXCEPTION CAUGHT BY RENDERING LIBRARY`).
   geen nieuwe `EXCEPTION CAUGHT BY RENDERING LIBRARY`).
+- **Check altijd eerst met `adb devices` of er een device begint met
+  `emulator*`** vóórdat je het script start — Bob's emulator staat niet
+  altijd aan, en er kan een ander (fysiek) device aangesloten zijn dat
+  niet bedoeld is om op te draaien. Ontbreekt `emulator-5554`: navragen
+  bij Bob i.p.v. blind op het eerste beschikbare device te draaien.
+- Een `EXCEPTION CAUGHT BY RENDERING LIBRARY`/crash tijdens de run is
+  niet per se een regressie van je eigen wijziging — check eerst de
+  stack trace op bestandsnaam. `lib/kanweg/` is Bob's eigen
+  scratch-testgebied (zie Opschonen hieronder) en kan legitiem crashen
+  zonder dat dat iets met de huidige taak te maken heeft; de app kan
+  daar staan door een eerdere hot-restart die Bob's laatst bezochte
+  route onthield, niet per se doordat het de echte `initialLocation` is
+  (check `nav.dart`).
 
 
 Daarna automatisch:
 Daarna automatisch:
 1. `git status --short`, dan `git add` — **niet blind `-A`**. Alleen
 1. `git status --short`, dan `git add` — **niet blind `-A`**. Alleen
@@ -287,6 +300,37 @@ styling nodig. Werkt niet op iconen embedded als `suffixIcon` van een
 `TextFormField` (bv. Login-pagina wis-/toon-wachtwoord-iconen — geen
 `TextFormField` (bv. Login-pagina wis-/toon-wachtwoord-iconen — geen
 losse wrapbare tree-node).
 losse wrapbare tree-node).
 
 
+**Widget toevoegen: gebruik de kleine inline "Insert Widget", niet de
+grote centrale "Insert"-modal.** Rechtsklik op een Widget Tree-rij →
+**"Insert Widget"** (of het kleine "+"-icoon naast een tree-node) opent
+een compacte dropdown die betrouwbaar werkt: klik op een widget-kaart
+voegt 'm meteen toe. De grote centrale Insert-modal (bv. via de
+"+"-knop bovenaan het linkerpaneel) opent wél, en widget-kaarten lijken
+klikbaar/highlighten bij hover, maar een klik **registreert niet** —
+geen insertie, dialoog blijft open, geen foutmelding. Bevestigd
+2026-08-05 op `EventCurrent` (Button toevoegen na
+`EvenementHorecagelegenheid`): pas de inline-variant via rechtsklik
+werkte. Sluit aan bij een eerdere observatie (2026-08-04, op
+`HorecagelegenheidCurrent`): een widget toevoegen in een AppBar-Row
+faalde herhaaldelijk stil via beide insert-varianten, terwijl exact
+dezelfde inline-picker op een gewone body-`Column` wél meteen werkte —
+mogelijk is een AppBar-Row specifiek een moeilijkere insertie-plek,
+sowieso eerst de inline-variant op een `Column` proberen vóór de grote
+modal.
+
+**Set-Variable/parameter-waarde koppelen aan App State: klein
+icoontje naast het "Value"-label, niet de tekstinvoer zelf.** Bij een
+actie-parameter (bv. Navigate To met page-parameters) toont het
+"Value"-veld standaard een tekstinvoer (voor een letterlijke waarde).
+Om aan een variabele (App State, Page Parameter, …) te binden: klik op
+het kleine icoontje vlak vóór/naast het woord "Value" (niet in het
+invoerveld zelf) — dat opent een **"Set Variable"-dialoog** met een
+zoekbalk en een "Source"-lijst (Page Parameters/App State/Global
+Properties/…) om uit te klappen en te doorzoeken. Dit icoontje is
+makkelijk te missen/verkeerd te klikken (kleiner dan de rest van het
+paneel) — bij twijfel `zoom` gebruiken op de regio rond "Value" om de
+exacte pixelpositie te bepalen vóór je klikt.
+
 **API-call headers: check op hardcoded literals i.p.v. `[varname]`
 **API-call headers: check op hardcoded literals i.p.v. `[varname]`
 templates.** Werkt een call via curl wél maar vanuit de app/Response &
 templates.** Werkt een call via curl wél maar vanuit de app/Response &
 Test-panel niet: check het Headers-tabblad — een handmatig ingeplakte
 Test-panel niet: check het Headers-tabblad — een handmatig ingeplakte
@@ -336,6 +380,19 @@ letterlijke `[varname]`-tekst meegestuurd i.p.v. de testwaarde.
   `itemCount: 0` op, niet per se de `null`-jsonBody-crash die hier de
   `itemCount: 0` op, niet per se de `null`-jsonBody-crash die hier de
   kern van het probleem was.
   kern van het probleem was.
 
 
+- **API-call `cache: true` werkt functioneel correct** — `ApiCallOptions`
+  (`lib/backend/api_requests/api_manager.dart`) `extends Equatable` met
+  `params`/`headers` in de `props`-lijst, dus de in-memory `_apiCache`
+  vergelijkt op echte parameterwaarden (deep equality), niet op
+  object-referentie. Geen reference-equality-bug om je zorgen over te
+  maken — `cache: true` is een veilige, lichte performance-fix voor
+  calls met effectief statische data binnen een sessie (referentie-
+  lijsten zoals provincies/gemeenten, categorieën). Lost wél alleen
+  *herhaalde* identieke calls op (bv. bij een rebuild), niet een
+  eerste gelijktijdige burst van meerdere verschillende calls (bv. een
+  eager `TabBarView` met 6+ tabs die elk hun eigen data ophalen bij
+  page-load, zie `TASKS.md` P1-10).
+
 ## Samenwerken met Bob
 ## Samenwerken met Bob
 
 
 - Bob is de enige developer/eigenaar, werkt vaak **zelf gelijktijdig**
 - Bob is de enige developer/eigenaar, werkt vaak **zelf gelijktijdig**

+ 60 - 212
TASKS.md

@@ -1,6 +1,6 @@
 # Uitgaanskrant — takenlijst
 # Uitgaanskrant — takenlijst
 
 
-Bijgewerkt: 2026-08-04. Zie `CLAUDE.md` voor werkinstructies/conventies.
+Bijgewerkt: 2026-08-05. Zie `CLAUDE.md` voor werkinstructies/conventies.
 Elke openstaande taak hieronder is zelfstandig te begrijpen zonder de
 Elke openstaande taak hieronder is zelfstandig te begrijpen zonder de
 chat gelezen te hebben waarin hij ontstond.
 chat gelezen te hebben waarin hij ontstond.
 
 
@@ -66,95 +66,32 @@ zichzelf al genoeg bewijs dat de configuratie niet compleet is. **Bob:
 graag opnieuw instellen en dit keer een Widget Type kiezen (niet alleen
 graag opnieuw instellen en dit keer een Widget Type kiezen (niet alleen
 de checkbox).**
 de checkbox).**
 
 
-**P0-3 · Eigenaar: gesplitst — zie onder.** Hartje-icoon op gemeente.
-**2026-08-05: hartje-tap-actie (favoriet maken) verplaatst naar P2**
-(Bob: te veel voor de eerste release, wacht toch op de
-FavorietenAgenda-403-fix) — voor nu alleen **naam tonen**, geen
-hartje-functie. Bob akkoord met bouwplan:
-1. App State opschonen/uitbreiden: dode dubbele `provincieSelectNaam`
-   verwijderen (nergens gebruikt), `provincieSelectName` hergebruiken,
-   `gemeenteSelectNaam` (bestond al, ook dood) hergebruiken voor
-   gemeente — **inconsistente spelling Name/Naam is bewust
-   geaccepteerd** (hergebruik bestaande var i.p.v. nieuwe duplicaat
-   aanmaken).
-2. `SelectStateDropDownComponent`, dropdown-onChanged-acties zetten
-   naast Id ook de Naam (opzoeken in de al-geladen lijst, via
-   `provincieNaamById`/`gemeenteNaamById`).
-   - **Provincie-dropdown: Claude, klaar en bevestigd opgeslagen**
-     (2026-08-05) — Action 3 op `DropDownProvincie` → On Selected zet
-     `provincieSelectName = provincieNaamById(provincielijst,
-     provincieSelectId)`.
-   - **Gemeente-dropdown: Claude, klaar en bevestigd opgeslagen
-     (2026-08-05, na computer-restart).** Op `DropDownGemeente` →
-     Actions → On Selected → Action 1 → Set Fields → veld
-     `gemeenteSelectNaam` = `gemeenteNaamById(gemeentelijst,
-     gemeenteSelectId)`. Eerdere 3x freeze bij het 2e argument bleek
-     inderdaad omgevingsinstabiliteit i.p.v. een harde blocker — na
-     computer-herstart in één poging gelukt. Bevestigd via
-     Issues-paneel: errors 2 → 1.
-   - Component-load default-toewijzing (eerste app-start, id
-     `28666`/`28694`) krijgt **nog geen** bijbehorende naam mee — apart
-     punt, laag risico (viel al terug op lege naam tot iemand
-     handmatig een provincie/gemeente kiest), niet blokkerend voor
-     livegang.
-3. **Grotendeels gedaan (2026-08-05, Claude):** `HeaderButtonsComponent`
-   (propageert naar Home, PUitgaanPage,
-   HorecagelegenhedenOverzicht+varianten, HorecagelegenheidCurrent,
-   SelectProvincieGemeente, Login) heeft nu een Text-widget na de twee
-   knoppen met If/Then/Else: toont `gemeenteSelectNaam` als die
-   gezet/niet-leeg is, anders `provincieSelectName`. **Restpunt —
-   Eigenaar: Bob (kleine polish, clipping-blokkade voor Claude):** de
-   Text-widget heeft nog **Expansion: None** (zou **Flexible** moeten
-   zijn) — de rechterpaneel-Expansion-control was niet bereikbaar
-   (zelfde bekende clipping, zie `CLAUDE.md`). Zonder Flexible kan een
-   lange gemeente/provincienaam in combinatie met de twee knoppen een
-   `RenderFlex overflowed`-fout geven op smalle schermen. Component
-   `HeaderButtonsComponent` → Widget Tree → node "Text" (3e kind van de
-   Row, na de twee Tooltips) → rechterpaneel → **Expansion → Flexible**.
-   **Restpunt — Eigenaar: Bob, losse toevoeging aan `EventCurrent`**
-   (heeft geen gedeeld header-component, AppBar → Row met
-   IconButtonBack/IconButtonDrawer). **Claude heeft dit nu in totaal 5x
-   geprobeerd** (2x vóór, 2x ná de computer-restart, en nog 1x na de
-   restart als laatste poging) — steeds bevroren bij het Confirm-en
-   van de If/Then/Else-conditie (soms al bij de binnenste
-   Single-Condition-Confirm), reload verliest de voortgang. In
-   tegenstelling tot de Gemeente-dropdown hierboven (die na de restart
-   wél in één keer lukte) blijft dit specifieke widget/actie-type
-   stabiel blokkerend — **niet meer opnieuw proberen door Claude,
-   definitief bij Bob.** Laatste stand vóór het laatste freeze: IF
-   `gemeenteSelectNaam` Is Set and Not Empty was al succesvol
-   opgebouwd, alleen de outer Confirm-klik faalde. **Exacte stappen
-   (bevestigd werkend patroon van `HeaderButtonsComponent`, hier
-   alleen de laatste Confirm-klik lukt niet):**
-   1. `EventCurrent` → Widget Tree → `AppBar` → `Row` (kind van AppBar,
-      bevat al IconButtonBack + IconButtonDrawer) → rechterpaneel
-      insert-icoon → **Text** toevoegen als 3e kind.
-   2. Nieuwe Text-widget → **Text**-property → bind-icoontje →
-      **Conditional Value (If/Then/Else)** (evt. eerst zoeken op
-      "conditional" als 'ie niet direct in de lijst staat).
-   3. **IF**: Single Condition → First Value = App State
-      `gemeenteSelectNaam` → operator **Is Set and Not Empty** (geen
-      Second Value nodig).
-   4. **THEN**: App State `gemeenteSelectNaam`.
-   5. **ELSE**: App State `provincieSelectName`.
-   6. Confirm. Optioneel: Expansion → Flexible (zelfde clipping-risico
-      als bij `HeaderButtonsComponent`, zie daarboven).
-4. Hartje-tap-actie (favoriete plaats) als losse taak vastgelegd —
-   zie **P2-8**.
-- Blocker die dit voorstel moet oplossen: **geen enkele pagina toont de
-  geselecteerde gemeente-náám als tekst** — alleen het numerieke ID
-  (`FFAppState().gemeenteSelectId`) wordt doorgegeven als filter (bv.
-  `plaats`/`townid` param op `PUitgaanPageWidget`). `GemeentenCall.
-  gemeenteName()` in `lib/backend/api_requests/api_calls.dart` bestaat
-  al maar is ongebruikt.
-- Bekende valkuil als dit gebouwd wordt: bind de naam niet live via
-  een `List<CustomDataType>`-typed lookup function-argument (bv.
-  `provincieNaamById`/`gemeenteNaamById` in
-  `lib/flutter_flow/custom_functions.dart`, al gebouwd, compileert,
-  nog niet gekoppeld) — dat argument-bindingsdialoog loopt vast op de
-  geneste Set Variable-bug (zie `CLAUDE.md`). Simpeler: naam
-  vastleggen in een plain String App State-variabele op moment van
-  selectie i.p.v. 'm live op te zoeken.
+**P0-3 · Eigenaar: Bob (2 restpunten, allebei clipping/freeze-geblokkeerd
+voor Claude).** Gemeente-/provincienaam tonen i.p.v. alleen het ID —
+basis is af (naam wordt al getoond via `HeaderButtonsComponent` op
+Home/PUitgaanPage/HorecagelegenhedenOverzicht+varianten/
+HorecagelegenheidCurrent/SelectProvincieGemeente/Login, gevuld door
+`provincieNaamById`/`gemeenteNaamById` in de dropdown-acties). Hartje-
+tap-actie is losgekoppeld naar **P2-8**. Nog open:
+1. `HeaderButtonsComponent` → Widget Tree → node "Text" (3e kind van
+   de Row, na de twee Tooltips) → rechterpaneel → **Expansion →
+   Flexible** (staat nu op None — rechterpaneel-Expansion-control was
+   niet bereikbaar voor Claude, clipping). Zonder Flexible kan een
+   lange gemeente/provincienaam een `RenderFlex overflowed`-fout geven
+   op smalle schermen.
+2. `EventCurrent` heeft geen gedeeld header-component (AppBar → Row
+   met IconButtonBack/IconButtonDrawer, geen naam-Text). Toevoegen:
+   nieuwe Text-widget als 3e kind van die Row → Conditional Value
+   (If/Then/Else) → IF App State `gemeenteSelectNaam` Is Set and Not
+   Empty → THEN `gemeenteSelectNaam` → ELSE `provincieSelectName` →
+   Expansion → Flexible. **Definitief bij Bob** — Claude liep hier 5x
+   vast op een bevroren Confirm-klik van de If/Then/Else-conditie
+   (reproduceerbaar specifiek op dit widget/actie-type, zie
+   `CLAUDE.md`).
+- Laag risico, niet blokkerend: de component-load default-toewijzing
+  (eerste app-start, id `28666`/`28694`) krijgt nog geen bijbehorende
+  naam mee — valt terug op lege naam tot iemand handmatig een
+  provincie/gemeente kiest.
 
 
 **P0-4 · Eigenaar: Bob.** Werkende login + favorieten — resterende
 **P0-4 · Eigenaar: Bob.** Werkende login + favorieten — resterende
 deeltjes. Basis is af: login gekoppeld, wachtwoord-vergeten-flow,
 deeltjes. Basis is af: login gekoppeld, wachtwoord-vergeten-flow,
@@ -273,140 +210,51 @@ gezien de omvang hieronder (~45 treffers); pak het file-voor-file op.
 uitloggen, account verwijderen). Bovenop de login/favorieten-P0-basis.
 uitloggen, account verwijderen). Bovenop de login/favorieten-P0-basis.
 Account verwijderen heeft mogelijk AVG-implicaties aan Drupal-kant.
 Account verwijderen heeft mogelijk AVG-implicaties aan Drupal-kant.
 
 
-**P1-8 · Eigenaar: Onbepaald (2 losse restpunten, zie onder).**
-Toegankelijkheid & navigatie, restpunten:
+**P1-8 · Eigenaar: Onbepaald.** Toegankelijkheid, restpunt:
 - Login-pagina: 2 icon-only knoppen zonder tooltip (veld wissen +
 - Login-pagina: 2 icon-only knoppen zonder tooltip (veld wissen +
   wachtwoord tonen/verbergen) — `login_widget.dart` (suffixIcon van
   wachtwoord tonen/verbergen) — `login_widget.dart` (suffixIcon van
   een `TextFormField` — standaard Tooltip-wrap werkt daar niet op, zie
   een `TextFormField` — standaard Tooltip-wrap werkt daar niet op, zie
   `CLAUDE.md`; bevestigd nog open, geen fix geprobeerd — vraagt een
   `CLAUDE.md`; bevestigd nog open, geen fix geprobeerd — vraagt een
   andere aanpak dan Wrap Widget, bv. het hele veld i.p.v. alleen het
   andere aanpak dan Wrap Widget, bv. het hele veld i.p.v. alleen het
   icoon wrappen).
   icoon wrappen).
-- ~~Overige icon-only knoppen buiten de header van tooltip
-  voorzien~~ — **gecheckt 2026-08-04: al gedekt.** Hartje op kaarten
-  en drawer-menu-items hebben al `AlignedTooltip`. De per-pagina
-  AppBar-knoppen (hamburger/terug) zijn qua functie ook "header",
-  zowel via de gedeelde `HeaderButtonsComponent` (heeft al tooltips)
-  als de losstaande inline kopieën op sommige pagina's (bv.
-  `home_widget.dart`, `event_current_widget.dart`) — buiten scope van
-  dit punt.
-- ~~Bevestig-stap toevoegen aan de provincie/gemeente-kiezer~~ —
-  **gedaan 2026-08-04.** `SelectStateDropDownComponent` → Column
-  onder de twee dropdowns → nieuwe **Button "Toepassen"** → actie
-  **Navigate To → home**. Relevant: dit scherm is niet alleen via het
-  drawer-menu bereikbaar, het is ook het **allereerste scherm na
-  inloggen** (`nav.dart:117/124`) — stond zonder deze knop zonder
-  duidelijke vervolgstap. "Replace Route"-toggle (voorkomt dat Home
-  bovenop dit scherm gestapeld wordt i.p.v. het te vervangen) kon niet
-  aangezet worden door rechterpaneel-clipping — functioneel geen
-  probleem (back-knop vanaf Home gaat dan terug naar dit scherm i.p.v.
-  waar de gebruiker vandaan kwam), maar Bob kan 'm zelf aanzetten:
-  component `SelectStateDropDownComponent` → Button "Toepassen" →
-  Actions → "Navigate To home" → **Replace Route** aanvinken.
-- ~~Vaste "terug naar hoofdlijst"-snelkoppeling op detailpagina's~~ —
-  **`HorecagelegenheidCurrent` gedaan 2026-08-04.** Nieuwe Button "Alle
-  horecagelegenheden" onderaan de pagina-Column (na `TabBar`) → actie
-  **Navigate To → HorecagelegenhedenOverzicht**, parameter `plaats` =
-  App State `gemeenteSelectId`. Plek is bewust onderaan i.p.v. in de
-  AppBar: het invoegen van een widget in de AppBar-Row (naast
-  `HeaderButtonsComponent`) faalde herhaaldelijk stil (geen foutmelding,
-  gewoon geen insertie) — zowel via de kleine inline widget-picker als
-  via de grote centrale "Insert"-modal; de kleine inline-picker op een
-  gewone body-`Column` werkte wel meteen. Builder-observatie, geen
-  bevestigde bug — als Bob de knop liever in de AppBar wil, eerst dat
-  invoegen zelf proberen.
-  ~~`EventCurrent`~~ — **gedaan 2026-08-05 (Claude).** Nieuwe Button
-  "Alle evenementen" onderaan de body-Column (na `EvenementHorecagelegenheid`
-  component) → **Navigate To → PUitgaanPage**, parameter `plaats` =
-  App State `gemeenteSelectId`, parameter `services` = `services_1`
-  (letterlijke tekst — zelfde conventie als de algemene "Uitgaan"-link
-  op de loginpagina, `login_widget.dart:694`, voor "geen
-  categoriefilter"; `services` is verplicht — `PUitgaanPageWidget`
-  gebruikt `widget!.services!` met force-unwrap, dus oningevuld laten
-  had een null-crash gegeven). Bevestigd opgeslagen ("Synced").
-  Insert-widget-dialoog werkte hier via de kleine inline widget-picker
-  op de Widget Tree-rij (rechtsklik component → "Insert Widget", of
-  het "+"-icoon naast een tree-node) i.p.v. de grote centrale
-  "Insert"-modal (die opende wel maar liet geen klik op een widget-kaart
-  doorkomen) — zelfde inline-picker-voorkeur als hierboven bij
-  `HorecagelegenheidCurrent` genoteerd.
-- Deep-link/query-param robuustheid checken (ongeldig/verlopen `nid`)
-  — **grotendeels gecheckt 2026-08-04, code-niveau, geruststellend.**
-  `HorecagelegenheidCurrentWidget` en `EventCurrentWidget` gebruiken
-  consequent `?.toList() ?? []` en `valueOrDefault<...>` rond
-  `jsonBody`-velden (i.t.t. de `HorecagelegenhedenOverzicht`-lijstpagina's
-  die wél crashten, zie P1-1) — bij een ongeldige/lege `nid` toont dit
-  fallback-tekst (`'title'`, `'logo'`, letterlijke veldnaam — het
-  bekende P1-6-patroon) i.p.v. een crash. `EventCurrent` heeft zelfs al
-  een correcte `if (getJsonField(...) != null)`-guard vóór een
-  `CachedNetworkImage` (regel 621-626) — het juiste patroon uit
-  `CLAUDE.md`. **Niet getest:** het live gedrag in de emulator/app zelf
-  (alleen code gelezen, geen `flutter run` gedaan) — als iemand dit
-  ooit live wil verifiëren, `horecagelegenheidCurrent`/`eventCurrent`
-  openen met een bewust niet-bestaand `nid` in de deep-link.
+- Optioneel, laag risico: live in de emulator/app verifiëren dat een
+  ongeldige/verlopen `nid` op `horecagelegenheidCurrent`/`eventCurrent`
+  geen crash geeft — code-niveau al gecheckt en geruststellend
+  (consequent `?.toList() ?? []`/`valueOrDefault<...>` rond
+  `jsonBody`-velden, i.t.t. de lijstpagina's uit P1-1), alleen nog niet
+  live getest.
 
 
 **P1-9 · Eigenaar: Onbepaald.** Visuele polish (los, per pagina):
 **P1-9 · Eigenaar: Onbepaald.** Visuele polish (los, per pagina):
 Uitgaan-pagina (typografie/contrast/spacing), Event-pagina,
 Uitgaan-pagina (typografie/contrast/spacing), Event-pagina,
 HorecagelegenhedenOverzicht, tabel-kaartje-afstemming met
 HorecagelegenhedenOverzicht, tabel-kaartje-afstemming met
 slider-kaartje, categorie-tag mag titel/datum niet overstemmen.
 slider-kaartje, categorie-tag mag titel/datum niet overstemmen.
 
 
-**P1-10 · Eigenaar: Onbepaald.** Performance. **2026-08-05: audit
-afgerond (Claude, code-niveau), concrete bevindingen:**
-1. **Eager-TabBarView bevestigd op 4 pagina's, niet alleen de 3 al
-   genoemde:** Flutter's `TabBarView` bouwt altijd alle tabs meteen
-   (geen lazy-tabs), dus bij page-load vuren alle tabs hun eigen
-   `FutureBuilder`-API-call tegelijk af, ook de 5-6 tabs die de
-   gebruiker nog niet ziet:
-   - `horecagelegenheden_overzicht_widget.dart`: 6 tabs, elk
-     `EstablishmentsCall.call(horcat: '<id>', ...)` met een eigen
-     categorie-id (17969/17963/34/17965/17967/17968 — echt
-     verschillende calls, geen letterlijke duplicaten).
-   - `horecagelegenheden_overzicht_sort_page_widget.dart`: 7 tabs,
-     zelfde patroon.
-   - `horecagelegenheden_overzicht_page_data_type_widget.dart`: 6
-     tabs, zelfde patroon.
-   - **Nieuw gevonden, stond nog niet in de vorige documentatie:**
-     `home_widget.dart` heeft hetzelfde patroon — 6 tabs, elk met een
-     eigen `HomeUitgaantabelKaartComponentWidget` → eigen
-     `HomeTabelCall`-aanroep, dus ook hier 6 gelijktijdige requests bij
-     het openen van Home (plus 1 losse `HomeUitgaanSliderComponent`
-     bovenaan, buiten de tabs, geen probleem).
-2. **`EstablishmentsCall` heeft al `cache: true`** (`api_calls.dart:1458`)
-   en `ApiCallOptions extends Equatable` met `params`/`headers` in de
-   `props`-lijst (`api_manager.dart:124-138`) — caching werkt dus
-   functioneel correct op basis van echte parameterwaarden (geen
-   reference-equality-bug). Dit voorkomt herhaalde netwerkcalls bij
-   een **rebuild** van dezelfde tab (bv. na een `setState` elders op de
-   pagina), maar lost de **initiële burst** van 6-7 gelijktijdige calls
-   bij eerste page-load niet op — caching helpt pas ná de eerste keer.
-3. **Nieuwe bevinding: `HomeTabelCall` heeft `cache: false`**
-   (`api_calls.dart:465`) — in tegenstelling tot de Establishments-
-   pagina's vuurt Home dus bij *elke* rebuild opnieuw alle 6
-   tab-requests af, niet alleen bij de eerste page-load. Fix: `cache:
-   true` zetten in de FlutterFlow API-call-config (Response &
-   Test-tabblad) — geen codewijziging nodig, low-risk (resultaten zijn
-   read-only lijstdata, geen sessie-afhankelijke content).
-4. **Nieuwe bevinding: `GemeentenCall`/`ProvinciesCall` hebben `cache:
-   false`** (`api_calls.dart:1274/1306`), aangeroepen vanuit
-   `select_state_drop_down_component_widget.dart`. Dit scherm is het
-   verplichte eerste scherm na inloggen (`nav.dart:117/124`) én apart
-   bereikbaar via het drawer-menu (2x, zie het "dubbele blok"-punt bij
-   P2-7) — elke keer dat het scherm opent, worden beide
-   provincie/gemeente-lijsten opnieuw over het netwerk opgehaald,
-   terwijl deze data binnen een sessie feitelijk statisch is. Zelfde
-   low-risk fix: `cache: true` in de builder, geen codewijziging.
-5. **Bijvangst, geen performance-impact maar wel opschoon-kandidaat:**
-   `EstablishmentsNewCall` (`api_calls.dart:845`, `cache: false`) wordt
-   nergens meer aangeroepen — dode API-call-definitie, toevoegen aan de
-   P2-7-opschoonlijst.
-- **Niet opgelost, apart punt voor Bob om te beoordelen:** de
-  eager-TabBarView-burst zelf (punt 1) is in de FlutterFlow-builder-UI
-  niet direct te fixen — `cache: true` helpt alleen bij herhaling, niet
-  bij de eerste gelijktijdige burst. Echte fix vraagt lazy tab-content
-  (bv. een `IndexedStack` met on-demand `FutureBuilder` per tab-
-  activatie i.p.v. `TabBarView`), wat een structurele herbouw is —
-  vermoedelijk custom code nodig, buiten scope van deze audit. Geen
-  bekend rate-limit-probleem op de Drupal-API, dus mogelijk lage
-  prioriteit ondanks de N×-overhead.
+**P1-10 · Eigenaar: Onbepaald.** Performance — resterend werk (audit
+afgerond 2026-08-05, Claude, code-niveau):
+1. **Low-risk quick win, builder-only (geen codewijziging):** zet
+   `cache: true` op `HomeTabelCall` (`api_calls.dart:465`) en op
+   `GemeentenCall`/`ProvinciesCall` (`api_calls.dart:1274/1306`,
+   gebruikt in `select_state_drop_down_component_widget.dart`) — nu
+   `cache: false`, terwijl de onderliggende data (categorielijst per
+   Home-tab resp. provincie/gemeente-referentielijst) binnen een sessie
+   feitelijk statisch is. `EstablishmentsCall` heeft dit al goed staan
+   (`cache: true`, werkt functioneel correct — `ApiCallOptions extends
+   Equatable` met `params`/`headers` in de `props`, dus geen
+   reference-equality-bug) en is het te volgen voorbeeld.
+2. **Groter/structureel, nog te beoordelen:** 4 pagina's (`Home`,
+   `horecagelegenheden_overzicht(_sort_page/_page_data_type)_widget.dart`)
+   hebben een `TabBarView` met 6-7 tabs die **allemaal gelijktijdig**
+   hun eigen API-call vuren bij page-load (Flutter bouwt alle tabs
+   eager, geen lazy-tabs) — ook de tabs die de gebruiker nog niet ziet.
+   `cache: true` (punt 1) verhelpt dit niet — dat voorkomt alleen
+   herhaling bij een latere rebuild, niet de eerste gelijktijdige
+   burst. Echte fix vraagt een structurele herbouw (bv. `IndexedStack`
+   met on-demand `FutureBuilder` per tab-activatie i.p.v.
+   `TabBarView`) — vermoedelijk custom code. Geen bekend
+   rate-limit-probleem op de Drupal-API, dus mogelijk lage prioriteit
+   ondanks de N×-overhead.
+- Bijvangst tijdens de audit: dode `EstablishmentsNewCall` verplaatst
+  naar de P2-7-opschoonlijst.
 
 
 **P1-11 · Eigenaar: Onbepaald.** Responsive/screensize. **2026-08-05:
 **P1-11 · Eigenaar: Onbepaald.** Responsive/screensize. **2026-08-05:
 venue-event-grid-bug uitgezocht (Claude, code-niveau) — root cause
 venue-event-grid-bug uitgezocht (Claude, code-niveau) — root cause