Kaynağa Gözat

P1-44/P1-45: Home-tab-bug gevonden, fix gebouwd en bewust teruggedraaid

- P1-44: HomeUitgaantabelKaartComponent gebruikt zijn displayid-parameter
  nergens, waardoor alle vijf Home-tabs services_2 tonen. Fix gebouwd
  (display_id-variabele op homeTabel + binding in de Backend Query),
  op toestel geverifieerd, daarna teruggedraaid.
- P1-45: reden van het terugdraaien. categorie is een lijst in
  services_1/2/3 en een komma-string in services_4/5/6/7; de kaart doet
  .toList() op dat veld en crasht daar stil op (Films-tab bleef leeg).
  Nette fix zit in de view, samen met P1-42.
- CLAUDE.md: Generate Dynamic Children accepteert geen custom function
  (dood spoor), stille .toList()-crash in profile-builds, en het
  categorie-vormverschil als domeinfeit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bob 1 hafta önce
ebeveyn
işleme
21b3c9e4cd
2 değiştirilmiş dosya ile 142 ekleme ve 31 silme
  1. 72 0
      CLAUDE.md
  2. 70 31
      TASKS.md

+ 72 - 0
CLAUDE.md

@@ -1750,6 +1750,70 @@ op een wegwerp-duplicaat):
   variabele hoogtes aankan. Dat is ook het patroon dat op
   `HorecagelegenhedenOverzicht` al draait.
 
+**Een component-parameter die wél gedeclareerd is maar nergens gelezen
+wordt, is een stille bug — en de builder waarschuwt er niet voor.**
+Gevonden 2026-09-06 (P1-44): `HomeUitgaantabelKaartComponent` kreeg per
+Home-tab een eigen `displayid` mee, maar gebruikte 'm nergens; alle vijf
+de tabs toonden daardoor dezelfde lijst. Geen foutmelding, geen
+analyse-waarschuwing, en op een toestel volstrekt geloofwaardig (elke
+tab vult zich netjes met kaarten). **Snelle audit in de export:** voor
+elke component-parameter `x`
+`grep -n "widget!\.x" <component>_widget.dart` — komt hij alleen in de
+declaratie voor, dan wordt hij weggegooid.
+
+**Een API Call een extra query-variabele geven (bv. om een hardcoded
+`display_id` overrulebaar te maken) — werkend recept, 2026-09-06.**
+API Calls-paneel (⌘+K → "api" → "Tabs: API Calls") → call kiezen →
+tab **Variables** → "+ Add Variable" (naam + Type + Default Value) →
+**Save** → tab **Query Parameters** → "+ Add Query Parameter" → naam →
+Value Source **"From Variable"** → Select Variable → de zojuist gemaakte
+variabele → **Save**. Twee keer opslaan dus; de variabele moet bestaan
+vóór de query-parameter 'm kan kiezen.
+- **Een dubbele query-parameter is geen probleem: de laatste wint.**
+  De URL van zo'n call houdt vaak zijn eigen `?display_id=services_2`,
+  en de nieuwe parameter komt daar áchter. Geverifieerd tegen Drupal:
+  `?display_id=services_2&display_id=services_4` levert exact hetzelfde
+  als alleen `services_4`. Je hoeft de URL dus niet te herschrijven —
+  dat is ook precies hoe `Uitgaanstabel` het al deed.
+- Geef de nieuwe variabele als **Default Value de waarde die nu
+  hardcoded in de URL staat**, dan verandert er niets voor aanroepers
+  die 'm niet binden.
+
+**Een variabele binden in een Backend Query mét Infinite Scroll: de
+`page`-binding overleeft dat gewoon.** Recept: node selecteren →
+Backend Query (3e icoontje) → **Edit** (reken op twee klikken, de eerste
+opent 'm vaak niet) → **sleep de onderrand van de dialoog omlaag** (de
+"———" onderaan; anders valt de nieuwe rij eronder weg) →
+"+ Set Additional Variable" → Parameter Name kiezen → het icoontje naast
+**Value** → Set Variable → bron kiezen → **Confirm**. Klap daarna de
+`page`-rij open om te zien dat die nog op *"Pagination - Next Page
+Number"* staat vóór je Confirm drukt — dat is het enige echte risico van
+deze ingreep, en in dit geval bleef hij intact.
+
+**"Generate Dynamic Children" accepteert GEEN custom function als
+waarde — dood spoor, niet opnieuw proberen.** Bevestigd 2026-09-06: de
+waardekiezer toont in zijn bronnenlijst wél "Custom Functions" (zodra je
+op de functienaam zoekt), maar de sectie klapt **leeg** open — geen
+enkele functie is selecteerbaar voor het verwachte type
+`List < Anything >`. Ook niet na het return-type van de functie op
+**JSON + Is List** te zetten (dat levert `List<dynamic>?` op, wat precies
+zou moeten passen). Vier pogingen, met en zonder de bekende hover-truc;
+de sectie toggelt alleen tussen leeg-open en dicht. Wil je een lijst
+normaliseren vóór hij de loop in gaat: dat moet dus **aan de databron**
+gebeuren (de view/het endpoint), niet in de builder.
+
+**Een `Text`/`Wrap`-loop over een JSON-veld dat soms een lijst en soms
+een string is, crasht STIL in een profile-build.** Bevestigd 2026-09-06:
+`getJsonField(item, r'$.veld').toList()` op een String gooit
+`NoSuchMethodError: Class 'String' has no instance method 'toList'`. Op
+het toestel zie je geen rood scherm en geen overflow-streep — alleen een
+leeg vlak (of een grijs blok waar het widget hoorde), en `dart analyze`
+zegt niets, want `getJsonField` levert `dynamic`. **Vind het terug in
+`adb logcat`/de run-log op de letterlijke tekst `has no instance
+method`** — dat is het snelste bewijs. Reken er bij elk nieuw
+lijst-achtig veld op dat je de vorm eerst even met `curl` controleert
+vóór je erop bouwt.
+
 **Breekpunten en het huispatroon voor responsieve waarden.** De
 constanten staan in `lib/flutter_flow/flutter_flow_util.dart`:
 `kBreakpointSmall` 479, `kBreakpointMedium` 767, `kBreakpointLarge` 991
@@ -2501,6 +2565,14 @@ maakte dat er geen exposed datumfilter bestond.
   `copymethartje`, `kanweg/*`) en wacht op P2-7's opruimactie.
 
 
+- **`flutterflowmobiel1` levert `categorie` NIET in één vorm: displays
+  services_1/2/3 geven een **lijst** (`["Kindvriendelijk","Theater"]`),
+  services_4/5/6/7 een **komma-string** (`"Kindvriendelijk, Theater"`).**
+  Gemeten 2026-09-06 op pagina 0 van alle zeven displays. Alles wat over
+  dit veld itereert werkt daardoor op de ene tab wel en op de andere
+  niet. Zie `TASKS.md` P1-45; de nette oplossing zit in de view, niet in
+  de app.
+
 - **Firebase App Check beschermt alleen Firebase-diensten zelf
   (Firestore/Cloud Functions/Storage), niet de eigen Drupal-backend van
   dit project.** Besproken 2026-08-25 (Bob's vraag n.a.v. FlutterFlow's

+ 70 - 31
TASKS.md

@@ -30,10 +30,14 @@ bij P1-42. Kort: het raakt **alle zeven** displays van
 horeca-overzicht sorteert op nieuwste-inschrijving-eerst i.p.v.
 alfabetisch. Eén Drupal-ronde lost het hele rijtje op.
 
-**Nieuw gevonden en belangrijker dan de rest: P1-44** — alle vijf
-Home-tabs tonen dezelfde lijst, omdat `HomeUitgaantabelKaartComponent`
-zijn `displayid`-parameter nergens gebruikt. Builder-fix, staat bij
-P1-42/P1-43 verderop beschreven.
+**Nieuw gevonden: P1-44 en P1-45, en ze hangen aan elkaar.** Alle vijf
+Home-tabs tonen dezelfde lijst (P1-44). De fix daarvoor is gebouwd en op
+een toestel bewezen, maar **teruggedraaid**, omdat hij een tweede,
+sluimerende bug blootlegt: `categorie` komt in services_4 t/m 7 als
+komma-string binnen in plaats van als lijst, en daar crasht de kaart
+stil op (P1-45) — de Films-tab werd volledig leeg. **Volgorde: eerst
+P1-45 (één veldinstelling in dezelfde views als P1-42), dan de laatste
+handeling van P1-44.** De app staat nu weer precies zoals vanochtend.
 
 ---
 
@@ -2285,34 +2289,69 @@ horeca-overzicht niet gewoon alfabetisch moet.
 P1-42 is afgemaakt; de uitkomst staat hierboven bij P1-42 als tabel. Deze
 taak kan weg zodra Bob de view-ronde in Drupal gedaan heeft.
 
-**P1-44 · Eigenaar: Bob (FlutterFlow-builder) — ALLE VIJF HOME-TABS
-TONEN DEZELFDE LIJST.** Gevonden 2026-09-06 tijdens P1-43, hard
-aantoonbaar in de code, nog niet op een toestel nagekeken.
-- `home_widget.dart` geeft elke tab een eigen display mee
-  (`displayid: 'services_3'` t/m `'services_7'`, regels 303/328/365/402/439)
-  aan `HomeUitgaantabelKaartComponentWidget`.
-- Dat component **gebruikt die parameter nergens**: `displayid` komt in
+**P1-44 · Eigenaar: Bob — alle vijf Home-tabs tonen dezelfde lijst.
+Fix is gebouwd, getest, en daarna BEWUST TERUGGEDRAAID; er ligt nog één
+blokkade, zie P1-45.** Gevonden en uitgezocht 2026-09-06 door Claude.
+- **Wat er mis is:** `home_widget.dart` geeft elke tab een eigen display
+  mee (`displayid: 'services_3'` t/m `'services_7'`, regels
+  303/328/365/402/439) aan `HomeUitgaantabelKaartComponentWidget`, maar
+  dat component gebruikt de parameter nergens: hij komt in
   `home_uitgaantabel_kaart_component_widget.dart` alleen voor in de
-  declaratie (regels 25 en 28), en de enige API-aanroep is
-  `HomeTabelCall.call(page: ...)` (regel 135) — zonder display-argument.
-- `HomeTabelCall` heeft ook helemaal geen `displayId`-parameter en heeft
-  `display_id=services_2` **hardcoded in zijn URL**
-  (`api_calls.dart` regel ~252).
-- Gevolg: Uitgaan / Activiteiten / Cultuur & Info / Films / Jeugd tonen
-  alle vijf de inhoud van `services_2`. Alleen "Cultuur & Info" klopt bij
-  toeval — `services_2` en `services_5` leveren op de API exact dezelfde
-  nids (geverifieerd op pagina 0).
-- Ter vergelijking: de slider ernaast doet het wél goed
-  (`HomeSliderCall.call(displayId: widget!.displayid)`), en
-  `UitgaanstabelCall` heeft de parameter ook gewoon.
-- **Fix (builder):** `homeTabel` API Call een `displayId`-variabele geven
-  (net als `Uitgaanstabel`), en in de Backend Query van
-  `HomeUitgaantabelKaartComponent` binden aan de component-parameter
-  `displayid`. Let op de bekende paginerings-valkuil: bij het bewerken van
-  een Backend Query met Infinite Scroll moet de `page`-binding daarna terug
-  op "Next Page Index (StaggeredView)".
-- ⚠️ Doe dit **vóór** P1-42's view-ingreep opgeleverd wordt, anders wordt
-  daar per tab iets gemeten dat de gebruiker helemaal niet ziet.
+  declaratie (regels 25/28), en de enige aanroep is
+  `HomeTabelCall.call(page: ...)`. `HomeTabelCall` heeft
+  `display_id=services_2` hardcoded in de URL. Uitgaan / Activiteiten /
+  Cultuur & Info / Films / Jeugd tonen dus alle vijf `services_2`.
+  ("Cultuur & Info" klopt bij toeval — `services_2` en `services_5`
+  leveren dezelfde nids.)
+- **Wat er nu al klaarstaat in de builder (blijft staan, verandert niets
+  aan het gedrag):** de API Call `homeTabel` heeft een variabele
+  `display_id` (String, default `services_2`) plus een query-parameter
+  `display_id` die daaraan hangt. De hardcoded `?display_id=services_2`
+  in de URL mag blijven — de láátste query-parameter wint, los tegen
+  Drupal nagemeten.
+- **De enige resterende handeling:** Backend Query van de
+  `StaggeredView` in `HomeUitgaantabelKaartComponent` → "Set Additional
+  Variable" → Parameter Name `display_id` → Value = component-parameter
+  `displayid`. Dat is precies wat Claude gebouwd, geëxporteerd én op een
+  toestel geverifieerd heeft (Uitgaan toonde daarna services_3,
+  Activiteiten services_4 — allebei nagelegd tegen de API).
+- **Waarom het toch teruggedraaid is:** met de fix erin lopen vier van de
+  vijf tabs stuk op P1-45 hieronder (Films werd volledig leeg). De app
+  stond daarmee er zichtbaar slechter voor dan ervoor, en dat wilde ik
+  niet een nacht laten staan. **Doe P1-45 eerst, dan deze handeling.**
+
+**P1-45 · Eigenaar: Bob (Drupal/views) — `categorie` komt in de ene
+display als lijst en in de andere als komma-string, en daar crasht de
+Home-kaart op.** Gevonden 2026-09-06 tijdens P1-44.
+- Gemeten op `flutterflowmobiel1`, pagina 0 van elke display:
+  - **lijst** (goed): services_1, services_2, services_3 —
+    `"categorie": ["Kindvriendelijk", "Theater"]`
+  - **string** (fout): services_4, services_5, services_6, services_7 —
+    `"categorie": "Kindvriendelijk, Theater"`
+- `HomeUitgaantabelKaartComponent` bouwt zijn groene categorielabels met
+  Generate Dynamic Children over `$.categorie`, wat in de export
+  `getJsonField(item, r'$.categorie').toList()` oplevert. Op een String
+  gooit dat `NoSuchMethodError: Class 'String' has no instance method
+  'toList'` — letterlijk zo in `logcat` gezien tijdens de P1-44-test.
+- In een **profile**-build is dat volledig stil: geen rood scherm, geen
+  overflow-streep, niets in `dart analyze`. De Films-tab was gewoon een
+  leeg wit vlak; Activiteiten toonde wél kaarten maar met een grijs blok
+  waar de labels horen.
+- **Beste fix, en meteen de goedkoopste: laat services_4 t/m services_7
+  hetzelfde lijstformaat teruggeven als services_1/2/3.** Dat is dezelfde
+  view, dus het is een veldinstelling per display — geen app-wijziging
+  nodig, en het lost het in één keer op voor élke plek die deze data
+  toont. Pak het mee in dezelfde ronde als P1-42.
+- **App-side alternatief is geprobeerd en loopt vast:** er staat nu een
+  custom function `categorieAlsLijst(dynamic categorie)` in het project
+  (geeft `List<dynamic>` terug, slikt zowel een lijst als een
+  komma-string). Die werkt, maar is **niet te binden**: de
+  "Generate Dynamic Children"-waardekiezer toont de bron "Custom
+  Functions" wel, maar klapt leeg open — geen enkele functie is
+  selecteerbaar voor het verwachte type `List<Anything>`. Vier pogingen,
+  ook na het return-type naar JSON+Is List te hebben gezet. De functie
+  mag blijven staan (kost niets) voor het geval jij 'm in jouw browser
+  wél gebonden krijgt.
 
 **P2-2 · Eigenaar: Onbepaald, bewust v2 (herbevestigd 2026-08-25 door
 Bob).** Google Maps-**overzichtsweergave** (kaart met meerdere markers)