Переглянути джерело

P2-24 aangemaakt: restpunten horeca-zoekfilter als eigen taak voor Bob

P2-6 is grotendeels af (zoeken werkt op 5 van 6 tabs, live bevestigd op een
toestel) en niet langer als 'bezig' geclaimd. De punten die Bob nodig hebben
staan nu als zelfstandige taak P2-24 in plaats van verstopt in het P2-6-blok:
tab Verhuur-catering, de categoriedropdown (wacht op ontwerpkeuze), Max Items,
de route-omzetting, de twee overbodige TextField-placeholders, en de
Drupal-duplicaten. Het technische recept blijft bij P2-6 staan.

CLAUDE.md: twee herbruikbare inzichten - een pagina met page-parameter testen
via profile-build met --route (browserloos, dus ook bruikbaar als Bob weg is),
en dat categorie-velden uit de establishments-view lijsten zijn.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bob 1 тиждень тому
батько
коміт
19cdc62dd1
2 змінених файлів з 109 додано та 49 видалено
  1. 25 0
      CLAUDE.md
  2. 84 49
      TASKS.md

+ 25 - 0
CLAUDE.md

@@ -1160,6 +1160,31 @@ is veel toleranter en draait vaak door terwijl `export-code` weigert —
 "de build doet het toch gewoon" is dus geen bewijs dat de teller
 onschuldig is.
 
+**Een pagina die alleen via een page-parameter bereikbaar is, test je zonder
+de builder met een profile-build + `--route`.** Recept dat 2026-09-05 in één
+keer werkte voor `HorecagelegenhedenOverzichtCopy3`:
+```
+cd /tmp/ff-checkN && fvm flutter run --profile -d <device> \
+  --route "/horecagelegenhedenOverzichtCopy3?plaats=25434"
+```
+(25434 = Arnhem, een plaats met content in vrijwel elke categorie.) Vergeet
+niet eerst `.fvmrc`, `.fvm/` en `pubspec.lock` naar de exportmap te kopiëren —
+zonder die drie bouwt hij niet, zie de notitie daarover elders. **Deze route
+is browserloos en dus juist geschikt wanneer Bob niet achter zijn scherm zit.**
+Handig bij het aflezen: `mcp__android__get_ui_tree` geeft de kaarten met hun
+volledige tekst als `desc`, waardoor je het aantal treffers exact kunt tellen
+en tegen de API kunt naleggen — betrouwbaarder dan tellen op een screenshot.
+Let op: het **toetsenbord dekt de lijst af** en `keyevent 111` sluit 'm niet
+als het veld nog focus heeft; **`keyevent 4` (back) werkt wel**.
+
+**Categorievelden uit `flutterflowmobiel_establishments.json` zijn LIJSTEN,
+geen strings.** Bevestigd 2026-09-05: `"categorie": ["Italiaans restaurant",
+"Pizzeria"]`. Elke functie die daarop filtert of er opties uit opbouwt, moet de
+binnenlijst plat slaan; een `.toString()` op het hele veld levert `[Pizzeria]`
+op en matcht dan nergens op. Reken er verder op dat de view **echte duplicaten**
+bevat (zelfde titel, verschillende nid en categorie-set) — dat is data, geen
+app-bug.
+
 **Rechterpaneel-tekstvelden: `triple_click` + typen werkt, `left_click` +
 `ctrl+a` + typen niet — en commit met een klik ergens neutraals, niet met
 Tab.** Bevestigd 2026-09-05 op een TextField's *Hint Text*: `ctrl+a` gevolgd

+ 84 - 49
TASKS.md

@@ -2294,7 +2294,8 @@ overgeslagen, Bob's eigen Sort/Datatype-experiment op die pagina loopt
 nog (zie P2-6); oppakken zodra dat is afgerond, zelfde recept
 (kopieer de AdBanner-node vanaf een van de 3 al werkende pagina's).
 
-**P2-6 · KLAAR OM UIT TE VOEREN — begin hier. Eigenaar: Claude — bezig (sessie 2026-09-04b, builder via Chrome, bouwt op `HorecagelegenhedenOverzichtCopy3`).**
+**P2-6 · Grotendeels afgerond — zoeken werkt op 5 van 6 tabs, live bevestigd.
+Eigenaar: Claude (niet bezig). Restpunten staan als eigen taak bij P2-24.**
 
 > ### Uitvoerplan voor de volgende sessie (opgesteld 2026-09-04, alles hieronder is getest)
 >
@@ -2418,55 +2419,13 @@ nog (zie P2-6); oppakken zodra dat is afgerond, zelfde recept
 >
 > ---
 >
-> ### Openstaande taken
+> ### Openstaande taken → verplaatst naar **P2-24**
 >
-> **A. Tab 6 (Verhuur, catering) koppelen · Eigenaar: Bob**
-> De enige `StaggeredView` die nog op de rauwe API-respons staat. Recept staat
-> hieronder; `items` = **`alleVerhuurCatering`**.
-> ⚠️ **Claude komt hier niet doorheen.** Twee sessies, ~15 pogingen: in de
-> Set-Variable-dialoog van uitgerekend deze ene `StaggeredView` rendert de
-> bron **Custom Functions** zijn optielijst nooit. Uitklappen lukt (chevron
-> slaat om), maar de rij `filterHorecagelegenheden` eronder verschijnt niet —
-> niet na hoveren, niet na blind klikken op de verwachte positie, niet na
-> dialoog sluiten/heropenen, niet na een volledige herlaad van de builder. Op
-> de andere vijf tabs werkte exact dezelfde reeks wél. Niets kapot: de tab
-> staat gewoon nog op zijn oorspronkelijke binding en werkt zoals voorheen.
->
-> **B. Stap 4 — categoriedropdown · Eigenaar: Bob (ontwerpkeuze) → daarna Claude**
-> Er is een custom function nodig die de unieke `categorie`-waarden uit de
-> dataset haalt. **Claude heeft die bewust nog NIET aangemaakt**, want er zit
-> een productkeuze in en een eenmaal aangemaakte custom function kan Claude
-> niet meer verwijderen (staande regel). Twee varianten:
-> - **Tab-bewust (volgt de oorspronkelijke spec):** functie krijgt de zes
->   `alleXxx`-lijsten + `TabBar Current Index` (Widget State) + het pad = **8
->   argumenten**. De dropdown toont dan precies de categorieën van de zichtbare
->   tab. Nadeel: 8 bindingen in juist die dialoog die bij taak A vastliep.
-> - **Samengevoegd (simpeler):** functie krijgt de zes lijsten + het pad = **7
->   argumenten**, en toont alle categorieën over alle tabs heen. Kiest de
->   gebruiker er een die op de actieve tab niet voorkomt, dan is de lijst leeg.
->   Fors minder bindwerk en minder kans op de dialoogblokkade.
-> Zeg welke je wilt, dan bouwt Claude de functie én de dropdown (invoegen in
-> de root-`Column` is bewezen werkend, net als bij het zoekveld).
-> ⚠️ **`categorie` is in de API een LIJST, geen string** — bevestigd 2026-09-05
-> met een curl op Arnhem (`townid=25434`): `"categorie": ["Bioscoop"]`,
-> `["Entertainment Centre"]`. De bestaande `filterHorecagelegenheden` gaat daar
-> al goed mee om (`lijst.any((c) => c.toString()... == catFilter...)`), maar de
-> nieuwe unieke-categorieën-functie moet de binnenlijst **plat slaan** en niet
-> `.toString()` op het hele veld doen — anders krijg je opties als `[Bioscoop]`
-> die nooit matchen. Realistische aantallen per tab in Arnhem: Activiteiten 2
-> items / 2 categorieën, Eetgelegenheden 20 / 19, Uitgaan 4 / 4.
->
-> **C. `Max Items` staat per tab op 25 · Eigenaar: Bob (beslissing)**
-> Bestond al vóór deze taak. Filteren gebeurt vóór het afkappen, dus zoeken
-> werkt correct — maar zónder zoekterm zie je 25 van de volledige dataset die
-> `fetchAlleHorecagelegenheden` juist ophaalt. Limiet weghalen of laten staan?
->
-> **D. Stap 7 — route omzetten · Eigenaar: Bob (bewust uitgesteld)**
-> Pas doen als A en B klaar zijn. Twee `Navigate To`-wijzigingen naar
-> `HorecagelegenhedenOverzichtCopy3`:
-> `lib/shared/drawer_component/drawer_component_widget.dart` en
-> `lib/horecagelegenhedenoverzicht/horecagelegenheid_current/horecagelegenheid_current_widget.dart`.
-> Daarna wordt de oude `HorecagelegenhedenOverzicht` een orphan → naar P2-7.
+> De vier resterende punten (tab Verhuur/catering, de categoriedropdown,
+> `Max Items`, en het omzetten van de route) staan nu als zelfstandige taak
+> **P2-24** verderop in deze lijst, samen met de twee bijvangsten. Het
+> technische recept en de valkuilen blijven hieronder staan — P2-24 verwijst
+> ernaar terug.
 >
 > **Niet oplosbaar, geaccepteerd:** FlutterFlow zet op de `On Change`-trigger
 > zelf een **`EasyDebounce` van 2000 ms**. Er is geen `debounce`-eigenschap op
@@ -2827,6 +2786,82 @@ establishmentPlaats` resp. `EvenementCall.eventAdres/eventPlaats`),
 horeca-blok bij stadsactiviteiten op `EventCurrent`) blijft bewust
 liggen tot Bob erop terugkomt — geen eigen taak-ID.)*
 
+**P2-24 · Restpunten horeca-zoekfilter (vervolg op P2-6) · Eigenaar: Bob.**
+Pagina: **`HorecagelegenhedenOverzichtCopy3`**. P2-6 heeft het zoekveld op 5
+van de 6 tabs werkend en live op een toestel bevestigd (zie het
+✅-blok bij P2-6). Dit zijn de punten die nog over zijn; ze hebben allemaal
+Bob nodig — óf omdat Claude er aantoonbaar niet doorheen komt, óf omdat er een
+keuze in zit. **Het werkende recept per `StaggeredView` en alle valkuilen
+staan bij P2-6; niet opnieuw uitzoeken.**
+
+**A. Tab 6 (Verhuur, catering) alsnog koppelen.** De enige `StaggeredView` die
+nog op de rauwe API-respons staat; alle andere vijf draaien op
+`filterHorecagelegenheden(...)`. Recept staat bij P2-6, met
+`items` = **`alleVerhuurCatering`**.
+⚠️ **Claude komt hier niet doorheen** — twee sessies, ~15 pogingen: in de
+Set-Variable-dialoog van uitgerekend deze ene `StaggeredView` rendert de bron
+**Custom Functions** zijn optielijst nooit. Uitklappen lukt (chevron slaat om),
+maar de rij `filterHorecagelegenheden` eronder verschijnt niet — niet na
+hoveren, niet na blind klikken op de verwachte positie, niet na de dialoog te
+sluiten en te heropenen, en niet na een volledige herlaad van de builder. Op
+de andere vijf tabs werkte exact dezelfde reeks wél. Niets kapot: de tab staat
+gewoon nog op zijn oorspronkelijke binding en werkt zoals voorheen.
+
+**B. Categoriedropdown (was P2-6 stap 4) — eerst een ontwerpkeuze van Bob,
+daarna kan Claude bouwen.** Er is een custom function nodig die de unieke
+`categorie`-waarden uit de dataset haalt. **Claude heeft die bewust nog NIET
+aangemaakt**: er zit een productkeuze in, en een eenmaal aangemaakte custom
+function kan Claude niet meer verwijderen (staande regel). Twee varianten:
+- **Tab-bewust** (volgt de oorspronkelijke spec): zes `alleXxx`-lijsten +
+  `TabBar Current Index` (Widget State) + het pad = **8 argumenten**. De
+  dropdown toont precies de categorieën van de zichtbare tab. Nadeel: 8
+  bindingen in juist die dialoog die bij punt A vastliep.
+- **Samengevoegd** (simpeler): zes lijsten + het pad = **7 argumenten**, toont
+  alle categorieën over alle tabs heen. Kiest de gebruiker er een die op de
+  actieve tab niet voorkomt, dan is de lijst leeg. Fors minder bindwerk.
+Zeg welke, dan bouwt Claude de functie én de dropdown (invoegen in de
+root-`Column` is bewezen werkend, net als bij het zoekveld).
+⚠️ **`categorie` is in de API een LIJST, geen string** — bevestigd 2026-09-05
+met curl op Arnhem (`townid=25434`): `"categorie": ["Bioscoop"]`. De bestaande
+`filterHorecagelegenheden` gaat daar al goed mee om, maar de nieuwe
+unieke-categorieën-functie moet de binnenlijst **plat slaan** en niet
+`.toString()` op het hele veld doen — anders krijg je opties als `[Bioscoop]`
+die nooit matchen. Aantallen in Arnhem: Activiteiten 2 items / 2 categorieën,
+Eetgelegenheden 20 / 19, Uitgaan 4 / 4.
+
+**C. `Max Items` staat per tab op 25 — beslissing Bob.** Bestond al vóór P2-6.
+Filteren gebeurt vóór het afkappen, dus zoeken werkt correct — maar zónder
+zoekterm zie je 25 van de volledige dataset die `fetchAlleHorecagelegenheden`
+juist ophaalt. Limiet weghalen of laten staan?
+
+**D. Route omzetten (was P2-6 stap 7) — bewust uitgesteld tot A en B klaar
+zijn.** Twee `Navigate To`-wijzigingen naar `HorecagelegenhedenOverzichtCopy3`:
+`lib/shared/drawer_component/drawer_component_widget.dart` en
+`lib/horecagelegenhedenoverzicht/horecagelegenheid_current/horecagelegenheid_current_widget.dart`.
+Daarna wordt de oude `HorecagelegenhedenOverzicht` een orphan → toevoegen aan
+P2-7. Ook `Copy3` heet dan nog "Copy3" terwijl het de levende pagina is;
+hernoemen of niet is Bob's keuze.
+
+**E. Twee lege `TextField`-placeholders opruimen.** In tab 0 (Activiteiten) en
+tab 1 (Cultuur) staat nog het oude, ongebonden `TextField` met hint letterlijk
+"TextField". Op een toestel is dat een zwevend wit vak dat half over de
+`TabBar` valt — lelijk en verwarrend naast het echte zoekveld. De eerdere
+afspraak "laten staan tot P2-6 ze van een echte binding voorziet" is hiermee
+afgehandeld: het echte zoekveld staat nu bóven de `TabBar`, dus deze twee zijn
+overbodig. Claude verwijdert niets.
+
+**F. Duplicaten in Drupal (los van de app, eigen afweging).** Voor
+Arnhem/Eetgelegenheden staan dezelfde zaken dubbel in de view, met
+verschillende categorie-sets: nid **53455** en **50584** heten allebei "New
+York Pizza Arnhem Zuid", nid **53454** en **50583** allebei "New York Pizza
+Arnhem Centrum". De app toont ze dus terecht dubbel; het zit in de data.
+
+**Niet oplosbaar, geaccepteerd:** FlutterFlow zet op de `On Change`-trigger
+zelf een **`EasyDebounce` van 2000 ms** en die is nergens instelbaar (geen
+`debounce`-eigenschap op het widget, en de trigger-/actiemenu's bieden 'm
+niet). Live merkbaar: de lijst ververst ~2 s nadat je stopt met typen. Werkt
+correct, voelt traag.
+
 **P2-7 · Eigenaar: Bob — Claude gooit hier niets weg (Bob expliciet,
 2026-09-04).** Claude mag deze lijst wél verifiëren en actueel houden;
 het daadwerkelijke verwijderen doet Bob zelf. Opschonen: