Jelajahi Sumber

P1-7 Tab 3 'Favoriete Gelegenheden' volledig gebouwd (builder, FavorietenAgendaCall + Generate Dynamic Children); CLAUDE.md: Actions-tab en Generate Dynamic Children-mechanisme gedocumenteerd (eerder gemist/foutief 'niet gevonden')

bob 1 bulan lalu
induk
melakukan
bed1d68d18
2 mengubah file dengan 135 tambahan dan 74 penghapusan
  1. 60 18
      CLAUDE.md
  2. 75 56
      TASKS.md

+ 60 - 18
CLAUDE.md

@@ -869,24 +869,66 @@ voor selectie, gebruik single-click + verificatie.
   reboot nodig — dit is de snellere/betrouwbaardere manier om
   P1-17-achtige locale-afhankelijke bugs te reproduceren/verifiëren.
 
-**Actions-paneel voor een Button-widget (onPressed/If-Then na een
-custom action) — niet gevonden in deze sessie, ondanks uitgebreid
-zoeken.** De 2 extra tab-iconen naast de standaard Widget Styling-tab
-bleken **Animations** en **Accessibility** te zijn — geen "Actions"-tab
-ertussen. Ook niet gevonden: via rechtsklik (canvas of tree, beide
-andere contextmenu's, geen "Edit Actions"-optie), via het
-"Search properties…"-veld (geen match op "action"/"tap"), via de losse
-tree-rij-iconen (leken niets te doen), via de globale "24"-badge
-rechtsboven (Action Blocks-teller, opent geen paneel bij klikken). Het
-`⌘+K`-commandpalet vindt wel "Custom Action: `<naam>`" maar dat
-springt naar de **Custom Code-editor van de actie zelf** (functie-body),
-niet naar de knop's eigen Actions-configuratie. **Nog niet uitgeprobeerd:**
-uiBuilder-canvasmodus met een expliciete hover (i.p.v. click) op de
-rand van de knop, of Bob zelf vragen waar dit paneel in zijn versie
-zit. Bij een volgende taak die een knop-actie/conditie moet wijzigen:
-eerst hier verder zoeken vóór blind te herhalen wat hierboven al niet
-werkte, en anders vroeg overdragen aan Bob i.p.v. tijd te verliezen
-(kostte deze sessie ~1,5 uur zonder resultaat).
+**Actions-paneel: bestaat wél, gevonden op 2026-08-14 (`ListTile`,
+niet op een Button geprobeerd, vermoedelijk hetzelfde) — eerdere
+notitie hieronder ("niet gevonden ondanks uitgebreid zoeken") was
+onvolledig zoeken, niet een echte afwezigheid.** Selecteer het widget
+→ kijk naar de kleine **iconenrij direct onder de widgetnaam** bovenin
+het rechterpaneel (naast de paint-brush/Styling-icoon): het **2e
+icoontje** (een vertakkings-/node-icoon) opent de **Actions**-tab
+(kop "Define Action", een "On Tap"-trigger-dropdown + "+ Add Action").
+Daar: **Add Action → Navigation → Navigate To** → doelpagina kiezen →
+**Parameters → klik expliciet op "Pass"** (niet op "+ Define" — dat
+opent per ongeluk de doelpagina's eigen **parameterschema-editor**,
+geen waarde-invoer voor déze actie) → per parameter verschijnt dan een
+rij met een Value-veld → normale **Set from Variable**-flow (zie
+elders in dit bestand) om de waarde te binden. **Deze hele
+Actions-tab was het ontbrekende stuk voor P1-9/P1-15's knop-condities**
+— bij een volgende poging op die taken eerst hier proberen i.p.v. de
+Insert-Widget/Wrap-Widget-routes.
+
+**Generate Dynamic Children — hoe je een `ListView`/`GridView`/
+`StaggeredView` een rij per API-response-item laat tonen (gevonden
+2026-08-14, bevestigd werkend via P1-7 Tab 3).** Dit is **niet**
+hetzelfde als de "Backend Query" database-icoon-optie (die haalt alleen
+de data op via een `FutureBuilder`, genereert geen herhaalde
+kinderen) — het is een **apart, makkelijk over het hoofd te ziene 4e
+icoontje** in dezelfde kleine iconenrij als hierboven (paint-brush,
+Actions-node, database, **dít 4e icoontje = sliders/kolommen-symbool**,
+play, save-as-template) — hover toont tooltip "Generate Dynamic
+Children" ter bevestiging. Volledige flow:
+1. Voeg eerst een **Backend Query** (database-icoon) toe aan de
+   ListView/GridView zelf, type "API Call" → kies de call.
+2. Voeg een item-template-widget toe als kind (bv. `ListTile`, of een
+   `Row`/`Container` naar smaak) via Insert Widget.
+3. Selecteer de ListView/GridView zelf opnieuw → klik het **4e icoontje
+   (Generate Dynamic Children)** → **Variable Name** (vrije naam, wordt
+   de loop-itemvariabele) → **Value** → klik het icoontje naast
+   "Value" → Set from Variable → kies de API-call-response als bron →
+   **Available Options → "No Further Changes"** (géén Predefined
+   Path/JSON Path hier — je wil de **rauwe array**, niet één
+   geëxtraheerd veld) → Confirm → **Save**. Een bevestigingsdialoog
+   volgt ("This widget will now generate its children dynamically...
+   edit the first child to set how every child should look") → Ok. De
+   canvas toont meteen N herhaalde design-time placeholder-rijen.
+4. **Cruciaal restpunt:** de velden die je vóór stap 3 al op het
+   item-template gebonden had (bv. via de Backend Query direct) wijzen
+   nog naar de **hele respons**, niet naar het loop-item — moeten
+   **opnieuw** gebonden worden: Set from Variable → bron is nu de
+   nieuwe **loop-itemvariabele** (naam uit stap 3, verschijnt als eigen
+   Source-regel) → Available Options → **"JSON Path"** → pad **relatief
+   aan het item** (dus `$.veldnaam`, **niet** `$[:].veldnaam` zoals de
+   al bestaande `establishmentX`-getters in `api_calls.dart` gebruiken
+   — die zijn geschreven voor de hele array, niet voor een los item).
+5. Voor een tap-actie per item (bv. navigeren met het item's ID): zie
+   de Actions-tab-notitie hierboven — Value van de Navigate-To-parameter
+   ook via Set from Variable → loop-itemvariabele → JSON Path.
+Geverifieerd via verse export: genereert een correcte
+`ListView.builder(itemCount: ..., itemBuilder: (context, index) {
+final xItem = xList[index]; ...})`-structuur, identiek aan het
+patroon dat al elders in dit project draait
+(`MasonryGridView.builder`/`StaggeredView` op
+`HorecagelegenhedenOverzicht`).
 
 **"+ Add App State Variable"/"+ Add App Constant"-knop reageert niet
 op Claude's klikken (2026-08-09).** Op zowel `?tab=appValues&appValuesTab=state`

+ 75 - 56
TASKS.md

@@ -33,6 +33,20 @@ elders in dit bestand, maar nu voor het eerst ook op het (verder
 betrouwbare) API Calls-paneel i.p.v. alleen de widget-tree/canvas. Zie
 de nieuwe blocker-notitie bij P2-7. Niet verder geprobeerd (staande
 regel: na 1-2 pogingen overdragen aan Bob), geen schade aangericht.
+**Vervolgens, op Bob's aanmoediging ("pak nog een paar taken op"), P1-7
+Tab 3 "Favoriete Gelegenheden" alsnog volledig gebouwd** in de builder
+(los tabblad, Bob's eigen tabblad met rust gelaten): `ListView` +
+`ListTile`-itemtemplate + `FavorietenAgendaCall`-Backend Query +
+**"Generate Dynamic Children"** (een tot nu toe onbekend/gemist
+icoontje, zie nieuw gedocumenteerd in `CLAUDE.md`) + tap-navigatie naar
+`HorecagelegenheidCurrent`. Onderweg **twee eerder als "niet gevonden"
+gedocumenteerde builder-mechanismes alsnog gevonden en gecorrigeerd in
+CLAUDE.md**: het Actions-tab-icoontje (P1-9 had dit "niet gevonden"
+genoteerd) en de "Generate Dynamic Children"-flow zelf (nergens eerder
+gedocumenteerd, waarschijnlijk de ontbrekende schakel voor alle
+toekomstige API-gebonden lijst-taken). Bevestigd via verse export +
+`flutter analyze` (geen nieuwe treffers). Zie bijgewerkte P1-7
+hieronder voor de volledige stappen (herbruikbaar recept).
 
 **Vorige sessie (2026-08-14, eerste ronde, code-only — geen builder-UI
 gebruikt omdat Bob meldde gelijktijdig zelf in een andere sessie aan de
@@ -336,25 +350,20 @@ bevat. Het laag-risico restpunt (default-locatie 28666/28694 toont nog
 geen naam bij allereerste app-start) staat als bijvangst bij P2-7
 hieronder. Uit deze lijst verwijderd.)*
 
-**P0-4 · Eigenaar: Bob.** Werkende login + favorieten — resterende
-deeltjes. Basis is af: login gekoppeld, wachtwoord-vergeten-flow,
-favorieten drawer-link + 3-tabblad-pagina, hartje op horeca-kaart +
--detailpagina. Nog open:
-- Lege-lijst empty-state op de favorietenpagina (nu kale/lege
-  Container als er nog geen favorieten zijn).
-  `lib/favorieten/favorieten_widget.dart`.
-- ~~Bevestigen dat favorieten écht syncen via Drupal bij inloggen~~ —
-  **root cause gevonden + gefixed (Claude, 2026-08-09), zie P1-18.**
-  De eerder aan Cloudflare Bot Management toegeschreven
-  "FavorietenAgenda 403-fout" (lege Cookie-header bij FlutterFlow-
-  requests) bleek gewoon het gevolg van de login-sessie die nooit
-  werd opgeslagen — niets met Cloudflare/IP-reputatie te maken. Live
-  bevestigd met testaccount `bobcity` op emulator: na de fix geeft
-  `flutterfavorietenagenda.json` **status 200 + geldige
-  `Cookie`/`X-CSRF-Token`-headers + echte data** i.p.v. de eerdere
-  lege/anonieme 403. Kan hiermee als afgerond beschouwd worden zodra
-  Bob dit ook zelf in de FavorietenAgenda-flow (niet alleen de
-  `kanweg`-testpagina) bevestigt.
+*(P0-4 afgerond 2026-08-14 — live pair-sessie, Bob builder, bevestigd
+via verse export: `favorieten_widget.dart` Tab 3 ("Favoriete
+Gelegenheden") toont nu
+`if (favorieteGelegenheidItem.isEmpty) { return Image.asset('assets/images/logo800px.png'); }`
+vóór de `ListView.builder` gebouwd wordt — zelfde empty-state-patroon
+als P0-1/P1-1. Bob zet er later nog begeleidende tekst bij (cosmetisch
+restpunt, geen blocker). **Correctie tijdens uitzoekwerk:** Tab 1
+("Persoonlijke agenda") en Tab 2 ("Favoriete gemeenten") bleken bij
+inspectie nog helemaal niet gebouwd (kale placeholder-tekst, geen
+lijst) — die empty-state-vraag is dus alleen op Tab 3 van toepassing,
+zie P1-7 voor het bouwplan van tab 1/2. Bevestigd dat favorieten al
+syncen via Drupal bij inloggen (root cause gefixed 2026-08-09, zie
+P1-18) — Tab 3 haalt live data op via `FavorietenAgendaCall`. Uit deze
+lijst verwijderd.)*
 
 **P0-5 · Eigenaar: Bob.** Drupal: anonieme leestoegang onderzoeken
 voor browse-endpoints. Drupal-niveau, geen Claude-taak. **Bijvangst
@@ -450,39 +459,10 @@ toch al wachten op ander Drupal-werk hier verzamelen i.p.v. los oppakken
   en Fill Color staat op `Color(0x0AFFFFFF)` i.p.v. wit (zoals de
   Else-tak). Functioneel al correct (Remove/Add-acties kloppen, bevestigd
   via export 2026-08-13) — puur cosmetisch restpunt.
-- **P1-7 Tab 3 "Favoriete Gelegenheden" — blokkering op P0-7 is stale,
-  taak is nu ontgrendeld (2026-08-14, Claude, code-audit).** Deze regel
-  ging ervan uit dat `EstablishmentInfoCall` nog HTTP 500 gaf — maar
-  P0-7 is inmiddels gefixt (zie boven, live bevestigd 2026-08-13) en
-  `EstablishmentInfoCall` werkt weer gewoon per `nid`. Bovendien bleek
-  bij het herlezen van `api_calls.dart` een **kant-en-klare, nog
-  efficiëntere route die niet eerder overwogen was:**
-  `FavorietenAgendaCall` (endpoint
-  `flutterfavorietenagenda.json?display_id=services_1`, sessie-cookie-
-  geauthenticeerd — dus server-side al gefilterd op de ingelogde
-  gebruiker, geen client-side nid-lijst nodig) geeft in **1 call**
-  precies `establishmentTitle`/`establishmentLogo`/`establishmentNid`
-  terug voor alle favoriete gelegenheden van de ingelogde gebruiker.
-  Bevestigd functioneel via P0-4/P1-18 (status 200 + echte data met
-  testaccount `bobcity`), en bevestigd **nergens in `lib/` aangeroepen**
-  (`grep` op `FavorietenAgendaCall` buiten `api_calls.dart`: 0
-  treffers) — dus volledig vrij om nu aan te sluiten. **Twee
-  realistische opties, geen van beide nog Drupal-werk nodig:**
-  1. **Simpelste/efficiëntste:** `FavorietenAgendaCall` rechtstreeks in
-     een `ListView`/`GridView` tonen (titel + logo, tik → navigeer naar
-     `HorecagelegenheidCurrent(nid: ...)` voor de rest van de details).
-     1 API-call ongeacht het aantal favorieten, geen client-side
-     nid-lijst-afhankelijkheid (werkt zelfs op een nieuw toestel vóór
-     `favorieteHorecaNids` lokaal gevuld is).
-  2. **Meer werk, herbruikt de bestaande kaart-widget:** loop over de al
-     bestaande client-side `favorieteHorecaNids` (App State) en roep
-     `EstablishmentInfoCall` per nid aan — geeft alle velden die
-     `HorecagelegenheidoverzichtKaartWidget` nodig heeft (`adres`/
-     `plaats`/`categorie`, niet alleen titel/logo), dus visueel
-     consistent met de rest van de app, maar N calls i.p.v. 1.
-  **Claude: builder-stappen voor Tab 3 kunnen nu gewoon gegeven worden**
-  (optie 1 is de aanbevolen eerste keus qua efficiëntie) — dit hoeft niet
-  langer te wachten op een Drupal-sessie met Bob.
+- ~~P1-7 Tab 3 "Favoriete Gelegenheden"~~ — **afgerond (2026-08-14,
+  Claude, builder), zie P1-7 hieronder.** Was hier vermeld als
+  Drupal-geblokkeerd; bleek stale en is dezelfde sessie alsnog
+  gloednieuw gebouwd (nooit door Bob opgepakt) — geen actie meer nodig.
 
 ## P1 — snel na livegang
 
@@ -799,12 +779,51 @@ lokale/UI-kant + look&feel oppakken zolang die niet op Drupal wacht.
   restpunt** (icoon/kleur If-tak nog niet aangepast) verplaatst naar de
   "Drupal dingen"-lijst hierboven — Bob wil dit batchen met een latere
   Drupal-sessie.
+- **Tab 3 "Favoriete Gelegenheden" — volledig gebouwd en werkend
+  (2026-08-14, Claude, builder, bevestigd via verse export +
+  `flutter analyze`).** Gebruikt `FavorietenAgendaCall` (1 sessie-
+  geauthenticeerde call, geen client-side nid-lijst nodig). Bouwstappen
+  (herbruikbaar patroon, zie ook de nieuwe "Generate Dynamic Children"-
+  sectie in `CLAUDE.md`):
+  1. `ListView` ingevoegd op Tab 3's lege Column (Insert Widget → Layout
+     Elements → ListView), placeholder-Text verwijderd.
+  2. Backend Query (database-icoon) → API Call → `FavorietenAgenda`
+     toegevoegd aan de ListView.
+  3. `ListTile` als item-template ingevoegd in de ListView.
+  4. **Generate Dynamic Children** (4e icoon in de widget-iconenrij,
+     tooltip bevestigt de naam) op de ListView aangezet: Variable Name
+     `favorieteGelegenheidItem`, Value → Set from Variable →
+     `FavorietenAgenda Response` → Available Options **"No Further
+     Changes"** (rauwe JSON-array, geen predefined-path-extractie) →
+     Save → bevestigingsdialoog ("generate its children dynamically...
+     edit the first child to set how every child should look") → Ok.
+     Canvas toont meteen 4 herhaalde design-time placeholder-rijen.
+  5. ListTile's **Title** opnieuw gebonden (was per ongeluk nog aan de
+     hele API-respons gebonden i.p.v. het loop-item): Set from Variable
+     → bron **`favorieteGelegenheidItem`** (nieuw beschikbaar ná stap 4)
+     → Available Options **"JSON Path"** → `$.node_title`.
+  6. **Subtitle** leeggemaakt (triple-click veld → Delete) — geen
+     bruikbaar 2e veld in deze call, anders bleef de letterlijke
+     placeholder-tekst "Subtitle" op elke rij staan (zelfde
+     P1-6-patroon).
+  7. **On Tap-actie** (Actions-tab, 2e icoon — ja, deze tab bestaat wel,
+     zie de gecorrigeerde P1-9-notitie): Navigate To →
+     `horecagelegenheidCurrent` → Parameters → **Pass** (niet "Define" —
+     dat opent per ongeluk de doelpagina's eigen parameterschema-editor)
+     → parameter `nid` → Value → Set from Variable → bron
+     `favorieteGelegenheidItem` → JSON Path `$.nid`.
+  Gegenereerde code geverifieerd (`ListView.builder` +
+  `getJsonField(favorieteGelegenheidItemItem, r'''$.node_title''')` +
+  `context.pushNamed(HorecagelegenheidCurrentWidget.routeName,
+  queryParameters: {'nid': ...$.nid...})`), `flutter analyze` toont geen
+  nieuwe treffers voor `favorieten_widget.dart`. **Bekend restpunt, geen
+  blocker:** geen leading-logo-afbeelding (ListTile's "Leading"-sectie
+  biedt alleen een Icon-property, geen Image-slot — zou een aparte
+  widget-vervanging vergen) en geen "geen favorieten"-lege-lijst-state
+  (zelfde open punt als P0-4's "Lege-lijst empty-state op de
+  favorietenpagina", nu ook hier van toepassing).
 
 **Nog open:**
-- **Tab 3 "Favoriete Gelegenheden" vullen met echte data — geblokkeerd,
-  zie "Drupal dingen"-lijst hierboven (hangt aan P0-7).** Niet proberen
-  met de bestaande `EstablishmentInfoCall` (geeft HTTP 500) of
-  `EstablishmentsCall` (geen nid-filter) vóór dat is opgelost.
 - **Tab 2 "Favoriete gemeenten" vullen** — geen Drupal-blocker bekend:
   `gemeenteNaamById` (custom function) + `favorieteGemeenteIds` kunnen in
   principe al een lijst van gemeentenamen tonen, zodra er ooit iets in