TASKS.md 59 KB

Uitgaanskrant — takenlijst

Bijgewerkt: 2026-08-10 (Claude, builder-sessie). Zie CLAUDE.md voor werkinstructies/conventies. Elke openstaande taak hieronder is zelfstandig te begrijpen zonder de chat gelezen te hebben waarin hij ontstond.

Deze sessie (2026-08-10): twee taken opgepakt. P2-9-bijvangst (dode terug-knop Home) volledig afgerond — Remove Widget-actie, bevestigd via verse export. P1-13: builder-fix uitgevoerd (Expanded+Shrink Wrap uit+Scrollable aan op de StaggeredView-node) maar niet doorgezet naar de export ondanks correcte builder-UI-status ("Synced", geen foutmelding, blijft staan na reload) — bevestigd met 3 onafhankelijke verse flutterflow export-code-runs. Sanity-check bevestigt dat de exportpijplijn zelf werkt (P0-6/P2-9 tonen wél correct) — dit lijkt een specifiek sync-probleem bij deze property-combinatie, zie P1-13 voor het volledige verslag en het verzoek aan Bob om zelf te verifiëren.

Vorige sessie (2026-08-09, avond): twee taken opgepakt. P1-19: builder-fix geprobeerd (Row → Wrap Widget), maar de menu-klik registreerde niet (4 pogingen, geen schade) — teruggegeven aan Bob met exact stappenplan. P1-13: eindelijk de al maanden gezochte volledige stack trace gevangen (nieuwe flutter run --route-truc omzeilt de race met Home's eigen overflow) — root cause nu hard bevestigd (niet-scrollbare MasonryGridView in een kale Column) + concreet fix-voorstel, builder-uitvoering nog open. Bijvangst: een tweede, nog niet eerder gedocumenteerde instantie van P1-19's "kale Row/Column zonder Wrap"-bugfamilie gevonden op PUitgaanSliderKaartComponent:179.

Vorige sessie (2026-08-09, middag): eerste sessie met mcp__android__*- toegang tot beide emulators (i.p.v. alleen losse adb-Bash-commando's) — P0-6 afgerond (5 debug-knoppen op Login verwijderd, builder + export/build + live geverifieerd op telefoon én tablet). Sub-bevinding (hintText-placeholder) blijft open, geblokkeerd op paneel-clipping. P1-17 opnieuw onderzocht en root cause herbevestigd, maar de voorgestelde "Engels weghalen"-fix is door Bob afgewezen — Engels moet beschikbaar blijven; taak blijft open in andere vorm (zie daar).

Deze review-sessie (2026-08-07, middag+avond): volledige doorloop van open taken + code-audit, plus een live "ogen van een gebruiker"-doorloop op de emulator (ná herstart van Bob's desktop/ Android-VM wegens een OOM — app opnieuw opgestart via de standaard ff-run-fvm.sh-workflow, daarna pm clear om een echte eerste-launch-ervaring te simuleren). Concrete live vondsten: zie nieuwe P0-6 (test-navigatieknoppen zichtbaar op de productie- Login-pagina — grootste vondst van de sessie), P1-17 (Engelse locale-fallback + vrijwel geen echte vertalingen), aangevulde P2-9 (onboarding + dode terug-knop op Home, nu live bevestigd i.p.v. ingeschat) en P1-15 (scope groter dan gedacht). Kanttekening: de emulator vertoonde ook wat omgevingsinstabiliteit (kort een "System UI isn't responding"-melding vlak na herstart, en flutter run verloor op een gegeven moment de verbinding met het device) — dat lijkt eerder aan de verse VM-herstart/host-belasting te liggen dan aan de app zelf, dus niet 1-op-1 als app-bug behandelen, maar wel vermeld voor het geval het patroon terugkomt.

Formaat van elke taak: **P0-1 · Eigenaar: ...** als eerste regel — een stabiel nummer (verandert niet als andere taken worden afgerond/verwijderd) + wie 'm oppakt. Volgorde binnen elke prioriteit = geschatte ernst/impact, hoogste eerst.

Eigenaar-waarden:

  • Bob — sneller/simpeler voor hem zelf (meestal builder-UI met een bekend fragiele dialoog, zie CLAUDE.md).
  • Claude — zelfstandig/via browser-automation te doen, nog onbeklaimd.
  • Claude — bezig (sessie ) / Bob — bezig — een sessie/persoon is hier nu actief mee bezig.
  • Onbepaald — nog geen eigenaar gekozen.
  • ⚠️ Voorkom dubbel werk: Bob start elke taak in een nieuwe, aparte chat — er kunnen dus meerdere sessies tegelijk actief zijn op hetzelfde project. Voordat je een taak oppakt: check of de Eigenaar-regel al "— bezig" zegt. Zo ja: niet zelfstandig ook gaan zitten werken aan hetzelfde bestand/component — vraag Bob eerst wie 'm afmaakt (dit gebeurde op 2026-08-04: twee sessies pakten onafhankelijk P0-2 op; Bob moest scheidsrechteren). Zet zelf "— bezig" in de Eigenaar-regel zodra je serieus aan een taak begint, en haal het weer weg (of verwijder de taak, zie hieronder) zodra je stopt.

    Afronden: een volledig afgeronde taak wordt verwijderd uit deze lijst (niet gearchiveerd). Bij gedeeltelijke voortgang: taak laten staan met bijgewerkte inhoud die alleen het resterende werk beschrijft.

    Modelkeuze: Haiku vs Sonnet

    Korte conclusie (2026-08-05, beoordeeld): niet standaard overschakelen op Haiku voor dit project. Bijna elke Claude-taak hier eindigt als een FlutterFlow-builder-interactie (Bob kan zelf geen code bewerken, zie CLAUDE.md), en die builder is canvas-gerenderd Flutter Web zonder normale DOM/accessibility-tree. Dat botst met precies Haiku's zwakke kant: geduldig multi-stap troubleshooten (scroll-pogingen, DOM/shadow-DOM-zoektochten, accessibility geforceerd activeren, herkennen van een "Discard changes?"- dialoog, op tijd stoppen na 1-2 pogingen i.p.v. blijven klikken of per ongeluk een Delete-knop raken). Zelfs taken die er triviaal uitzien (bv. P1-10's cache-toggle: 1 klik + Confirm) bleken pas na 6+ verschillende technieken écht geblokkeerd op een clipping-bug — dat vraagt het uithoudingsvermogen/verstand van Sonnet om zowel de pogingen als het op tijd stoppen goed te doen.

    • Wel Haiku-geschikt — puur lezen/greppen/samenvatten, geen builder-UI, geen destructief risico:
      • De audit-/verificatiestappen die dit bestand al vaak gebruikt om "open" vs "al gefixt" te bevestigen (git log -S"...", gerichte grep) — zie de vuistregel hierboven over verouderde taakstatus.
      • Live emulator-checks (app draaien, deep link/navigatie, scherm/ logs checken) — geen builder-bewerking. Kanttekening (2026-08-05): de eerder als "laag risico, duidelijk slagingscriterium" ingeschatte P1-8-check bleek bij uitvoering juist 2 échte crashes op te leveren (zie P1-1 punt 4 en de nieuwe P1-12) — het navigeren/screenshotten zelf is Haiku-geschikt, maar de opvolging (stacktrace naar exacte broncoderegel herleiden, onderscheid maken tussen "al bekend probleem" en "nieuwe bug", inschatten of normaal gebruik geraakt wordt) vroeg meer redeneerwerk dan verwacht — bij een crash-bevinding op zo'n check de opvolging liever alsnog met Sonnet doen.
    • Niet Haiku-geschikt (Sonnet aanhouden): elke taak die een builder-widget/-property wijzigt (vrijwel alle overige P1/P2-taken), en taken die ontwerpkeuze/afweging vragen zoals P1-9 en de P2-features (P2-2 t/m P2-6, P2-8) — geen mechanisch patroon, dus geen goede Haiku-fit.

    P0 — blokkeert livegang

    (P0-6 volledig afgerond 2026-08-09 avond, incl. hintText-restpunt — door Bob zelf gedaan in de builder, geverifieerd via verse flutterflow export-code: keys d507d3b9/t8h5f8ir in internationalization.dart staan nu op nl: 'E-mailadres'/en: 'Email address' resp. nl: 'Wachtwoord'/en: 'Password'. Uit deze lijst verwijderd.)

    P0-1 · Eigenaar: Bob (10 sec klusje) — bevestigd nog open (2026-08-05). Home-slider crasht (RangeError) bij 0 API-resultaten. Bob koos: bij 0 resultaten component overslaan (niets tonen), geen melding. CarouselSlider.builder met itemCount: 0 crasht. Native fix: Carousel-widget (component HomeUitgaanSliderComponent → Widget Tree → ConditionalBuilder → If → Container → Carousel) → rechterpaneel → "Empty List Widget" → vink "Show Empty List Widget" aan → Widget Type instellen (bv. Image → Asset "logo800px.png", zelfde als het werkende patroon op HorecagelegenhedenOverzicht, zie P1-1). 2026-08-05, read-only gecheckt in de builder (Claude, geen klik op de checkbox zelf i.v.m. clipping-risico): "Widget Type" staat nog op "Unset". Bob dacht dit al ingesteld te hebben ("volgens mij heb ik dat ingesteld, bij geen gegevens dan een plaatje") — dat klopt dus nog niet, of de instelling ging niet door. De checkbox zelf viel niet af te lezen (rechterpaneel- clipping, zie CLAUDE.md), maar "Unset" bij Widget Type is op zichzelf al genoeg bewijs dat de configuratie niet compleet is. Bob: graag opnieuw instellen en dit keer een Widget Type kiezen (niet alleen de checkbox).

    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. Bob dacht dit gedaan te hebben (2026-08-09 avond), maar geverifieerd via verse export: nog steeds niet toegepast — de Text staat nog kaal (geen Flexible/Expanded) in header_buttons_component_widget.dart regel 199-216. Vermoedelijk hetzelfde "edit hield niet vast"-patroon als elders gedocumenteerd in CLAUDE.md (rechterpaneel-clipping) — check na een nieuwe poging opnieuw via een verse export, niet alleen op het rechterpaneel zelf vertrouwen.
    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).
    3. 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 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 inloggenroot 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-5 · Eigenaar: Bob. Drupal: anonieme leestoegang onderzoeken voor browse-endpoints. Drupal-niveau, geen Claude-taak.

    P1 — snel na livegang

    P1-18 · Eigenaar: Bob (1 conditie-edit in de builder — Claude vond het Actions-paneel voor deze knop niet, zie CLAUDE.md). Login-knop (login-pagina, "Inloggen") crasht altijd stil na een druk erop — geen succes-/foutmelding, en (belangrijker) de sessie werd nooit opgeslagen, waardoor elke beveiligde pagina (favorieten, kanweg) zonder sessie-cookie draaide. Root cause (bevestigd via flutter run-log, 2026-08-09): login_widget.dart:534if (_model.resultDrupalLogin!) { — behandelt het resultaat van de custom action drupalLogin (een JSON-map: {success, sessid, session_name, token, uid, name, mail}) alsof het een bool is. Dat crasht altijd met type '_Map<String, dynamic>' is not a subtype of type 'bool', ongeacht of de credentials kloppen — dus ook de regels daarna (FFAppState().userSessionid = ...) draaiden nooit. Functioneel al gefixed (Claude, Custom Code-editor): lib/custom_code/actions/drupal_login.dart zet de sessievelden (userSessionid/userSessionname/userToken/userName/userUid/ userMail) nu zelf al in FFAppState() vóórdat de crashende regel in de knop bereikt wordt — dat gebeurt dus altijd, ook al crasht de knop daarna nog steeds. Live bevestigd (emulator, testaccount bobcity): na inloggen + navigeren naar kanweg komt er nu een Cookie-header mee en status 200 i.p.v. de eerdere lege/403-request. Update 2026-08-09 avond: Bob heeft de conditie zelf aangepast — de crash is inderdaad weg, maar de nieuwe conditie heeft een andere bug en er kwam een tweede probleem aan het licht, allebei bevestigd via verse flutterflow export-code (login_widget.dart:534-538):

    1. De conditie is nu getJsonField(_model.resultDrupalLogin, r'''$.success''') != null — dat staat feitelijk altijd op waar. drupalLogin retourneert namelijk ALTIJD een success-veld, zowel bij een geslaagde login (success: true) als bij een mislukte (success: false, zie drupal_login.dart) — het veld is dus nooit afwezig/null, alleen de waarde verschilt. Een "Is Set"-achtige != null-check ziet dat verschil niet. Gevolg: een fout wachtwoord of netwerkfout wordt nu stil behandeld alsof het inloggen gelukt is — de else-tak met "Inloggen mislukt..." is onbereikbare code geworden, en FFAppState().userSessionid etc. worden gevuld met lege/"null"-strings uit de mislukte respons. Fix: conditie moet de daadwerkelijke boolean-waarde vergelijken (== true), niet alleen of het veld aanwezig is — in de builder dus niet "Is Set" maar een echte gelijkheids-check tegen true.
    2. Nieuw zichtbaar geworden (was eerder gemaskeerd door de crash): ná de if/else staat een onvoorwaardelijke showDialog(...) (regel 577-593) die bij elke inlogpoging een AlertDialog met titel "melding" toont met de rauwe JSON-respons als platte tekst erin — oogt als achtergebleven debug/testcode, vergelijkbaar met de al verwijderde testknoppen van P0-6. Nu de crash weg is, ziet elke gebruiker dit bij elke inlogpoging. Aanbevolen: dit dialoogblok (regel 577-593) verwijderen.

    P1-1 · Eigenaar: Bob (mechanisch, ~10 sec per stuk) — audit compleet, wachtend op Bob. Loading/foutafhandeling-patroon uitrollen naar overige lijst-/detailpagina's. Referentiepatroon bevestigd (2026-08-04, builder): rechterpaneel → "Empty List Widget""Show Empty List Widget" aan → Widget Type: Image → Asset "logo800px.png". Op HorecagelegenhedenOverzicht zelf al op alle 5 tabs aanwezig (geverifieerd via verse export 2026-08-04/05). 2026-08-05: volledige audit afgerond (Claude) van resterende Carousel-widgets zonder deze fix — allemaal read-only bevestigd "Widget Type: Unset"/leeg:

    1. HomeUitgaanSliderComponent → Carousel (= P0-1, zie daar)
    2. PUitgaanSliderComponent → Carousel — ontbreekt zelfs de ConditionalBuilder-wrapper om de Carousel (i.t.t. de andere 3), dus mogelijk P0-ernstig: dezelfde itemCount:0-RangeError-crash als P0-1 kan hier nog optreden zonder enige vangnet.
    3. EvenementComponent → Carousel (foto-carousel van één evenement)
    4. horecagelegenheidCurrent → Carousel (foto-carousel van één horecagelegenheid) — live bevestigd 2026-08-05 (Claude, emulator, deep link ?nid=999999999, niet-bestaand item): exact het verwachte RangeError (length): Invalid value: Valid value range is empty: 0 op-scherm, 3x. Bevestigt dat dit al een échte crash is, niet alleen een theoretisch risico.
    5. Waarom bij Bob i.p.v. Claude: de "Show Empty List Widget"- checkbox is structureel onbereikbaar via Claude's browser-automation-viewport (bevestigd op alle 4 hierboven, zie CLAUDE.md bekende problemen) — geen per-component toeval, dus verder proberen door Claude heeft geen zin. Bob: dezelfde twee klikken (checkbox aan + Widget Type instellen) 4x herhalen op bovenstaand lijstje, kost in eigen browser seconden per stuk.

    P1-3 · Eigenaar: Bob — geblokkeerd op rechterpaneel-clipping. Sliderkaartje: datumregel mist de Flexible-wrap. Bevestigd nog open (2026-08-04: regels 310/351 in p_uitgaan_slider_kaart_component_widget.dart hebben Flexible om de Text, regel 273-281 niet). Fix zit in builder: component PUitgaanSliderKaartComponent → Widget Tree → node "Text-datum" (Text-widget, kind van de Row met Icons.calendar_month, tussen "Text-title" en de horecagelegenheid-Row) → rechterpaneel → property "Expansion" → moet net als bij "Text-horecagelegenheid"/"Text-adres" op Flexible gezet worden i.p.v. None. Geblokkeerd: de 3 Expansion-type-iconen (None/Expanded/Flexible) renderen net buiten het zichtbare/klikbare canvas rechts van het "Flex"-invoerveld — bekend rechterpaneel-clippingprobleem (zie CLAUDE.md). Geprobeerd: directe klik op geschatte positie, paneel-scroll, paneel-drag-resize, "Wrap Widget"-dialoog (geen Flexible-optie daarin, alleen structurele widgets) — geen succes. Kost Bob vermoedelijk seconden op zijn eigen scherm.

    P1-4 · Eigenaar: Bob. EstablishmentsCall crasht zonder categoriefilter. horcat ??= null!; — bevestigd nog aanwezig, regel

    1. Nu geen probleem omdat elke aanroep toevallig altijd een filter meegeeft, wel een landmijn voor de toekomst. lib/backend/api_requests/api_calls.dart. Fix zit vermoedelijk in de FlutterFlow API-call-configuratie (default parameterwaarde), niet in lokale code.

    P1-5 · Eigenaar: Bob. "Thuis bezorgen" koppelen aan een echt leverbaar-veld per horecagelegenheid. Wacht op Bob: eerst het API-endpoint aan Drupal-kant configureren. Daarna tonen/verbergen op basis van het echte veld i.p.v. de huidige dode tap.

    P1-6 · Eigenaar: Bob (mechanisch, maar groot — spreid over sessies). Letterlijke veldnaam i.p.v. nette placeholder bij ontbrekende data. 2026-08-05: audit herhaald (Claude, verse grep) — scope flink groter dan de eerdere 13 treffers van 2026-08-04, met name evenement_horecagelegenheid_widget.dart bleek nog niet meegenomen. Patroon overal hetzelfde: valueOrDefault<String>(<bron>, '<default>') waarbij de default gelijk is aan de veld-/functienaam. Fix is mechanisch (Default Value-tekst aanpassen in de builder op het Text-widget), maar raakt dezelfde "Set from Variable"-property als de Empty-URL-fix — zelfde risico-inschatting als het CachedNetworkImage-patroon. Niet in één sessie proberen af te maken gezien de omvang hieronder (~45 treffers); pak het file-voor-file op.

    • horecagelegenheidoverzicht_kaart_widget.dart:359/383/410 — titel/adres/plaats
    • evenement_info_widget.dart:136/158/213/238/293 — adres/plaats/entreeprijs/entreetoelichting/contact
    • evenement_component_widget.dart:221/242/317/339 — title/eventDate/adres/plaats (317/339 zijn nieuw t.o.v. de 2026-08-04-audit, waren toen nog niet aanwezig of gemist)
    • horecagelegenheid_current_widget.dart:377/500/747 — title/logo/content (volledig nieuw gevonden, stond niet in de vorige audit)
    • event_current_widget.dart:327/418/442 — title/nid/date (327 en 442 zijn nieuw t.o.v. de 2026-08-04-audit, alleen nid stond er al in)
    • evenement_horecagelegenheid_widget.dartgrootste blok, ~30 treffers, volledig nieuw t.o.v. de vorige audit (waarschijnlijk pas zichtbaar geworden na de P1-image-crash-fix-uitbreiding van dit component): regels 178(HorecaNaam), 418(establishmentnid), 445(email), 476(Logo), 499(Plaats), 533(Adres), 577/586/597 (Telefoon, 3x — icoon/tekst/tooltip-varianten), 642(menukaart), 710(entreeprijs), 743(EntreeToelichting), 818/827/843(facebook, 3x), 885/894/910(instagram, 3x), 952/961(twitter, 2x), 1016/1025/1041(Website, 3x), 1083/1092/1108(urluk, 3x), 1194(Openingstijden), 1222(OpeningstijdenUitzondering), 1310(Bezorgtijden), 1337(bezorgkosten), 1364(bestellink).
    • Grensgeval (geen letterlijke veldnaam maar wel technische/zinloze placeholder, zelfde fix-aanpak): p_uitgaan_slider_kaart_component_widget.dart:284 toont 'def' als datum ontbreekt.
    • Niet-verdachte gevallen bewust genegeerd (echte inhoudelijke fallback, geen technische naam): 'Evenement' (kaart_tabel_uitgaan_comp_widget.dart:216, kaart_tabel_uitgaan_s_comp_widget.dart:123) en 'Uitgaan' (tag_categorie_component_widget.dart:113).
    • Let op — voor de Facebook/Instagram/Twitter/Website/urluk-knoppen op evenement_horecagelegenheid_widget.dart is dit géén puur cosmetisch probleem, zie P1-15 hieronder: de Default-Value-tekst aanpassen lost daar de crash niet op, alleen de zichtbare tekst als hij (na de P1-15-fix) wél verborgen wordt.

    P1-15 · Eigenaar: Bob (builder — Claude geblokkeerd, zie hieronder). Kapotte zichtbaarheids-conditie op de social-/ contact-knoppen laat de app crashen bij tikken (niet alleen lelijke tekst) — vermoedelijke verklaring voor de herhaalde Invalid argument(s): No host specified in URI-excepties die 2026-08-07 in de live flutter run-log van de andere sessie verschenen (naast de al bekende P1-13-overflows, niet met elkaar verwarren — twee losse foutmeldingen in dezelfde log).

    • Root cause bevestigd (code-niveau, lib/evenement/evenement_horecagelegenheid/evenement_horecagelegenheid_widget.dart): de Facebook- (r. 812-829), Instagram- (879-896), Twitter- (~946-961), Website- (1010-1027) en urluk-knop (1077-1094) zijn elk gewrapt in if (valueOrDefault<String>(<veld>, '<placeholder>') != null && valueOrDefault<String>(...) != ''). Omdat valueOrDefault bij een lege/ontbrekende bron altijd de placeholder-tekst teruggeeft (nooit null/''), is deze conditie altijd waar — de knop is dus altijd zichtbaar én tikbaar, ook zonder échte link. Bij tikken roept onTap launchURL(valueOrDefault<String>(...)) aan (lib/flutter_flow/flutter_flow_util.dart:61, Uri.parse(url)launchUrl(uri)) met de kale placeholder-string (bv. 'facebook', 'Website', 'urluk') als URL — geen geldig schema/host, vandaar de crash. Hetzelfde broken-guard-patroon staat ook op de Telefoon-tekst (r. 571-588) maar die crasht niet (geen launchURL, alleen Text) — daar is het wél puur het P1-6-cosmetica-probleem.
    • Fix (builder): op elk van de 5 knoppen de Visibility/If-conditie niet tegen de valueOrDefault-uitkomst laten toetsen, maar tegen het rale API-veld zelf (dezelfde JSON Path-expressie als de Image-URL-fix in CLAUDE.md, operator "Is Set" i.p.v. != null && != '') — zelfde patroon als het al gedocumenteerde CachedNetworkImage-fix-recept. Zonder deze fix blijft ook een betere Default-Value-tekst (P1-6) een tikbare crash-knop.
    • Nog te controleren of hetzelfde patroon ook elders voorkomt (bv. horecagelegenheid_current_widget.dart heeft vergelijkbare velden, maar daar is maar 1 losse != null &&-treffer gevonden — niet diep genoeg nagekeken deze sessie om zeker te zijn dat het daar wél goed staat).
    • Scope vermoedelijk groter dan gedacht: 2026-08-07, live op de emulator, verscheen Invalid argument(s): No host specified in URI al herhaaldelijk op/vanaf de Home-pagina zelf, vóór enige navigatie naar een horecagelegenheid-detailpagina. Dat wijst erop dat hetzelfde kapotte-guard-patroon ook in Home-gerelateerde componenten zit (bv. de Home-sliderkaartjes of de "OOK LEUK"-tegels), niet alleen in evenement_horecagelegenheid_widget.dart. Nog niet tot de exacte plek herleid — bij oppakken van deze taak breder zoeken dan alleen het al gevonden bestand.
    • Poging door Claude (2026-08-09 avond), geblokkeerd op Widget-Tree-coördinaten — geen wijziging aangebracht. Component EvenementHorecagelegenheid geopend, maar de 5 knoppen (diep genest onder TabBar → TabBarPageInfo) bleken niet betrouwbaar te bereiken: klik-coördinaten op een zichtbare tree-rij selecteerden herhaaldelijk een andere rij, en de offset was niet constant (eerste meting +42px, twee stappen later +21px) — dus geen vaste correctie toe te passen zoals CLAUDE.md's kalibratietruc suggereert. De "Search for widget..."-zoekbalk in het paneel pakte maar één keer focus (na een klik op het "collapse"-icoontje ernaast), en zelfs toen gaf zoeken op Facebook geen enkel resultaat (wijst erop dat de knoppen intern niet zo genoemd zijn — zoek in de builder dus niet blind op die letterlijke naam). Concreet stappenplan voor Bob (in eigen browser, geen coördinaat-problemen): component EvenementHorecagelegenheid openen → Widget Tree → TabBar → TabBarPageInfo-tak uitklappen tot de Facebook/Instagram/Twitter/Website/urluk-knoppen (rond regel 812-829/879-896/946-961/1010-1027/1077-1094 in de geëxporteerde code, zie hierboven) → op elk van de 5: Visibility/If-conditie open → First Value aanpassen van de valueOrDefault-gebonden expressie naar de rauwe API-veld-expressie (zelfde JSON Path, vóór de Default Value-substitutie) → operator van != null && != '' naar "Is Set". Zelfde recept als de al werkende CachedNetworkImage-fix in CLAUDE.md.

    P1-16 · Eigenaar: Bob (Firebase-koppeling is account-/builder-niveau, geen Claude-taak). Geen crash-reporting/analytics (bv. Firebase Crashlytics) ingesteld. Nu is de enige manier om een crash zoals P1-15 hierboven te zien een handmatige flutter run-log tijdens een actieve sessie — na livegang is dat niet meer haalbaar, dan draai je blind. Aanbeveling: instellen vóór livegang, niet pas erna — FlutterFlow heeft ingebouwde Firebase-integratie (Crashlytics minimaal, Analytics optioneel) die met een paar builder-instellingen aan te zetten is. Zonder dit blijft elke toekomstige crash-bug (nieuwe RenderFlex- overflows, een volgende launchURL-achtige misser) onzichtbaar totdat een gebruiker 'm toevallig meldt.

    P1-17 · Eigenaar: Onbepaald. Live bevestigd 2026-08-07 (Claude, emulator met systeemtaal en-US, verse app-data): de app valt terug op Engels zodra het toestel niet op Nederlands staat (geen opgeslagen taalvoorkeur → MaterialApp.locale is null → Flutter matcht het systeem-en-US tegen de ondersteunde ['nl','en']-lijst en kiest en). Dat zou op zich geen probleem zijn als er een echte Engelse vertaling stond — die is er vrijwel niet: van de 169 sleutels in lib/flutter_flow/internationalization.dart zijn er 50 waar nl/en toevallig identiek zijn (onvertaald), 44 waar beide talen leeg zijn (dus zichtbaar niets, zoals de Login-hinttekst uit P0-6), en slechts 1 sleutel met een bewust andere Engelse tekst — en die ene is fout: key 7pacsyhe (het hartje-menu-item in de drawer) toont nl: 'Favorieten' maar en: 'Home', dus een Engelstalig toestel ziet twee menu-items met de tekst "Home" (huis-icoon én hartje-icoon) — verwarrend, de favorieten zijn zo niet te vinden. Iedere gebruiker met een Engelstalig toestel (niet ongebruikelijk, ook onder Nederlanders) krijgt dus een merkbaar kapotte/lege interface. 2026-08-09, Bob: Engels moet blijven aangeboden (niet weghalen als taal) — de eerder voorgestelde "forceer hard op nl"-fix (Engels uit FFLocalizations.languages() verwijderen) is dus afgewezen, niet uitgevoerd. Resterende optie is de grotere, aparte contentklus: de ontbrekende Engelse vertalingen daadwerkelijk invullen (of een losse taalkeuze-instelling bouwen i.p.v. op systeemlocale te vertrouwen). Nog niet opgepakt. Live herbevestigd 2026-08-09 (Claude, emulator): root cause klopt exact zoals hierboven beschreven — op een device met ro.product.locale=en-US verdween de "Wachtwoord vergeten?"-link op Login volledig (lege en-vertaling voor key utppw2si); na adb shell cmd locale set-app-locales com.uitgaanskrant.app --locales nl-NL (betrouwbaardere per-app-locale-override dan de systeembrede settings put system system_locales + broadcast, die op de emulator niet altijd doorwerkte zonder reboot) kwam de tekst meteen terug — bevestigt dat dit puur een vertaalprobleem is, geen widget-bug.

    P1-7 · Eigenaar: Claude — bezig (2026-08-09). Favorieten-pagina + profielscherm — Bob heeft de scope + designbeslissingen 2026-08-09 gegeven, absorbeert ook het oude P2-8 (gemeente-favoriet). Belangrijke bevinding vooraf (code-audit, niet eerder gedocumenteerd): de 3-tabblad-structuur op FavorietenWidget bestaat al (Persoonlijke agenda/Favoriete gemeenten/Favoriete Gelegenheden), maar alle 3 tabs zijn pure placeholder-tekst — geen enkele API-call/FutureBuilder. Én: het hartje op zowel de horeca-overzichtskaart als de horeca-detailpagina is een kale print('IconButtonFavoriet pressed ...')-stub (horecagelegenheidoverzicht_kaart_widget.dart:334, horecagelegenheid_current_widget.dart:364) — er bestaat nergens in de codebase een POST/toggle-call om een favoriet daadwerkelijk op te slaan, alleen de GET-only FavorietenAgendaCall (ondanks de naam: geeft favoriete horecagelegenheden terug, geen agenda/events). De eerdere P0-4-aantekening "hartje... af" klopte dus alleen voor het zichtbare icoon, niet voor de functionaliteit erachter.

    Bob's beslissingen (2026-08-09):

    1. Favorieten (zowel horeca als gemeenten) worden Drupal-gesynchroniseerd, niet puur lokaal — sync bij app-start én direct na elke toevoegen/verwijderen-actie. Lokale opslag (FFAppState/ secureStorage) blijft daarnaast nodig als cache/snelle UI-state.
    2. "Persoonlijke agenda" (tab 1) = events in de door de gebruiker gefavoriete gemeente(n) (niet de her-toegekende naam "agenda" op de bestaande horeca-GET-call — dat is een aparte, nog te bouwen view).
    3. "Gebruiker"-tab = het oude P1-7-scope (wachtwoord wijzigen, uitloggen, account verwijderen), nu als tab i.p.v. aparte pagina. Account verwijderen heeft mogelijk AVG-implicaties aan Drupal-kant. Let op prioriteit: Apple's App Store Review Guideline 5.1.1(v) eist in-app accountverwijdering voor een app met accountaanmaak — zonder dit scherm blokkeert een iOS-submissie, niet alleen P1.

    Open vraag aan Bob (blokkeert het schrijf-/sync-gedeelte): bestaat er al een Drupal-endpoint om een favoriet (horeca of gemeente) toe te voegen/verwijderen voor een ingelogde gebruiker (bv. Flag-module of een custom Services-resource), of moet dat nog gebouwd worden? Zonder endpoint-naam/-vorm kan Claude alleen de lokale kant (state, UI, hartje-toggle-optimistic-update, logout) bouwen, niet de sync. Onbelemmerd te bouwen, ongeacht antwoord: FFAppState-velden voor lokale favorieten-lijsten (gemeenten + horeca), hartje-toggle die lokaal al werkt (optimistic UI), uitloggen op de Gebruiker-tab (geen backend nodig — alleen FFAppState-sessievelden wissen + terug naar Login).

    Geblokkeerd voor Claude (2026-08-09), klein klusje voor Bob: de "+ Add App State Variable"-knop (?tab=appValues&appValuesTab=state) reageert niet op Claude's klikken — geen dialoog, geen nieuwe rij, 6+ pogingen zonder resultaat (zie CLAUDE.md voor details). Bob: graag deze 2 App State-velden zelf toevoegen (kost seconden in eigen browser):

    1. favorieteGemeenteIds — type List<String> (gemeente-ID's, zelfde ID-vorm als gemeenteSelectId/gemeentelijst), Persisted: true.
    2. favorieteHorecaNids — type List<String> (horeca-nid's, zelfde vorm als FavorietenAgendaCall.establishmentNid), Persisted: true.

    Zodra deze 2 velden bestaan kan Claude verder (hartje-toggle, tab-content vullen) — de rest van de bouw hangt hier niet losstaand van vast.

    P1-12 · Eigenaar: Bob (builder, gegenereerde code niet lokaal te fixen). EventCurrent crasht direct (Null check operator used on a null value) op een deep link met wél nid maar zonder horecaid query-param. Gevonden 2026-08-05 (Claude), live bevestigd op emulator via adb shell am start -d "uitgaanskrant://uitgaanskrant.com/eventCurrent?nid=999999999" (bewust zonder horecaid). Root cause: event_current_widget.dart:808, establishmentID: widget!.horecaid! — geen fallback. Alle in-app navigatie naar EventCurrent stuurt nid+horecaid altijd samen mee (gecheckt, alle pushNamed-aanroepen vullen beide), dus dit raakt geen normaal gebruik — wel elke deep link/gedeelde link/push-notificatie die ooit alleen nid meegeeft (bv. een toekomstige "deel-knop", zie P2-4). Fix: in de builder op EventCurrent → widget-tree → de EvenementHorecagelegenheidWidget-instantie → establishmentID-param een Default Variable Value/valueOrDefault toevoegen i.p.v. de kale !, zelfde patroon als P1-6. (Losstaand: de bekende Carousel- RangeError op deze en de horecagelegenheidCurrent-pagina bij een niet-bestaande nid is al gedekt door P1-1 punt 4 — live bevestigd, zie daar.)

    P1-13 · Eigenaar: Onbepaald — builder-fix toegepast maar NIET bevestigd in de export, zie blocker hieronder vóór verder bouwen. Op HorecagelegenhedenOverzicht → tab "Activiteiten" overflowt de kaartjesgrid. Root cause definitief bevestigd (2026-08-09, Claude, verse volledige stack trace + visuele bevestiging op emulator-5554):

    A RenderFlex overflowed by 5382 pixels on the bottom.
    Column:file:///.../lib/horecagelegenhedenoverzicht/horecagelegenheden_overzicht/horecagelegenheden_overzicht_widget.dart:286:29
    

    horecagelegenheden_overzicht_widget.dart:286-382: de Activiteiten-tab is een kale Column (mainAxisSize: MainAxisSize.max, regel 286) met als enige kind een FutureBuilder die uiteindelijk een MasonryGridView.builder bouwt (regel 354) met shrinkWrap: true + physics: NeverScrollableScrollPhysics() (regel 355-356/382) — dit patroon (shrinkWrapped grid zonder eigen scroll) vereist een scrollbare ouder om te werken, maar die ontbreekt hier: de Column zit direct in de TabBarView's Expanded (regel 282-284), zonder SingleChildScrollView eromheen. Met 25 items (regel 340, .take(25)) × Container(width: 600.0, height: 225.0) (regel 388-390) in 1 kolom op telefoonformaat (crossAxisCount: 1 onder kBreakpointSmall, regel 359-363) wil de grid ≈5625px hoog worden terwijl de tab maar een fractie daarvan aan ruimte heeft — vandaar de 5382px-overflow. Verklaart vermoedelijk ook de eerder waargenomen kleinere "on the right"-overflows elders in eerdere sessies (los bevestigd deze sessie op een ander component: zie P1-19's zustervondst op PUitgaanSliderKaartComponent:179, zelfde "kale-Row/Column-zonder-wrap"-familie maar niet dezelfde plek).

    • Bestandspad-correctie (2026-08-10): de hierboven genoemde horecagelegenheden_overzicht_widget.dart bestaat niet meer als zodanig — Bob's project splitst deze pagina inmiddels in HorecagelegenhedenOverzicht (dunne ConditionalBuilder-wrapper, [If/Then/Else 2 Conditions]) die naar horecagelegenheden_overzicht_page_data_type_widget.dart of ..._sort_page_widget.dart doorschakelt. De Activiteiten-tab-Column zit nu op regel ~277 van het PageDataType-bestand (structuur/getallen overigens identiek: Column(mainAxisSize: MainAxisSize.max)FutureBuilderMasonryGridView.builder(shrinkWrap: true, physics: const NeverScrollableScrollPhysics())). Navigeer in de builder dus naar ?page=HorecagelegenhedenOverzicht (niet naar de PageDataType/SortPage-varianten los) — de widget-tree toont dan gewoon de juiste, actieve tak.
    • Fix uitgevoerd in de builder (2026-08-10, Claude) — mechanisch, bevestigd correct qua stappen, maar NIET bevestigd in de export (zie blocker hieronder): op de Column binnen TabBar Page (kind van TabActiviteiten) bleek de Column zelf al binnen een bestaande Expanded(TabBarView(...)) te zitten (dus al bounded-height) — een losse "Scrollable"-toggle op die Column zelf gaf zelfs een expliciete "Invalid Action"-foutdialoog terug ("You can't set Expanded for a widget if it's in a Column that doesn't have a defined Height. This includes a Scrollable Column.") toen ik daarna ook Expanded op het kind probeerde — nuttige bevestiging dat FlutterFlow deze combinatie zelf detecteert en terugdraait. Werkende combinatie (op de StaggeredView-node zelf, kind van de Column, niet op de Column zelf): rechterpaneel → Expansion → Expanded (rechtse van de 3 iconen: None/Flexible/Expanded, in die volgorde — geen tooltip nodig om te onthouden) + Shrink Wrap → uit + Scrollable → aan. Geen foutdialoog bij deze combinatie, paneel toont "Synced"/"Saved", waarde blijft staan na page-reload binnen dezelfde sessie.
    • ⚠️ BLOCKER — bevestigd niet-doorzettend naar de export (2026-08-10, Claude): ondanks bovenstaande drie toggles zichtbaar correct in de builder (en blijvend zo na reload) én "Synced"-status zonder foutmelding, lieten drie onafhankelijke verse flutterflow export-code --as-debug-runs (over ca. 10 minuten, dezelfde opzet als Bob's eigen ff-run-fvm.sh gebruikt) geen enkele wijziging zien: Column/MasonryGridView in het geëxporteerde bestand staan nog altijd exact zoals vóór de builder-edit (shrinkWrap: true, NeverScrollableScrollPhysics, geen nieuwe Expanded). Sanity-check uitgevoerd: de exportpijplijn zelf werkt wél correct — dezelfde export toonde de al langer bevestigde P0-6-hintText-fix (d507d3b9/t8h5f8ir in internationalization.dart) gewoon goed. Ook een heel andere, eenvoudiger wijziging in dezelfde sessie (P2-9's dode terug-knop op Home, kale "Remove Widget"-actie) wél correct in de export terechtgekomen — dus dit is geen algemene sessie-brede exportstoring, het lijkt specifiek aan deze combinatie van property-toggles (Expansion/Shrink Wrap/Scrollable op een StaggeredView diep genest in een TabBarView) gebonden. Voor Bob: graag zelf in je eigen browser bevestigen of de 3 toggles op HorecagelegenhedenOverzicht → Widget Tree → TabActiviteitenTabBar PageColumnStaggeredView daadwerkelijk staan zoals hierboven beschreven, en zo ja, gewoon een verse ff-run-fvm.sh/export proberen — het kan een eenmalige sync-hik zijn die met een handmatige trigger (of gewoon wat meer tijd) alsnog doorkomt. Zo niet: dit is het eerste bevestigde geval waarbij de builder een wijziging laat zien die structureel niet naar de exportbron doorzet, wat relevant is voor elke toekomstige property-edit-taak, niet alleen deze.
    • Resterend werk zodra de sync bevestigd/opgelost is: dezelfde 3 toggles herhalen op de overige tabs (Cultuur, Eetgelegenheden, Overnachten, en nog 2 verder niet genoemde tabs — 6 in totaal per _model.tabBarController se length: 6) — nu nog niet gedaan, geen zin om te herhalen vóór de sync-blocker opgelost is.
    • Reproductierecept dat de race met Home's eigen overflow (P1-19) vermeed (2026-08-09, definitief werkend — vervangt eerdere R+deep-link-pogingen): flutter run direct starten met --route i.p.v. cold-start via am start ná een losse flutter run/hot-restart. Dit zet Flutter's defaultRouteName al vóór de eerste frame, dus go_router opent meteen de juiste pagina — Home wordt nooit gebouwd, dus zijn eigen overflow (P1-19/P1-3-familie) verbruikt de "één-volledige-dump-per-proces"-slot niet meer eerder:

      export PATH="/home/bob/fvm/bin:$HOME/.pub-cache/bin:$PATH"
      fvm flutter run -d emulator-5554 --route "/horecagelegenhedenOverzicht?plaats=28666"
      

      (geen FIFO/R/deep-link-am-start meer nodig voor dít doel. Voor een pagina die zelf niet los bereikbaar is met de juiste parameters via een directe --route, blijft het FIFO/R-recept uit CLAUDE.md nodig.) Bevestigd geprobeerd en verworpen: R (hot-restart) + de deep-link-am start vlak erna in één Bash-call (minimale sleep) — een hot-restart reset altijd naar de initialLocation/Home, en de daarna verstuurde deep-link-intent wordt door de al herstarte app niet meer verwerkt (adb-warning "Activity not started, intent has been delivered to currently running top-most instance" terwijl de app toch weer op Home landde) — dus dit blijft Home's eigen overflow eerst verbruiken. --route bij het opstarten zelf is de werkende oplossing voor dit specifieke race-probleem.

    • Hypothese uit 2026-08-05 (HorecagelegenheidoverzichtKaartWidget's MediaQuery.sizeOf-breedtekeuze) blijft weerlegd — de daadwerkelijke oorzaak is de ontbrekende scroll-wrapper hierboven, niet de tekstkolom-breedtekeuze.

    P1-19 · Eigenaar: Bob (Wrap Widget-menuklik registreert niet, zie hieronder — Claude geblokkeerd). Nieuwe, nog niet eerder gedocumenteerde RenderFlex overflowed-crash op de Home-pagina, live bevestigd met een volledige, verse stack trace (2026-08-09, via de setsid-interactieve-flutter run-sessie uit CLAUDE.md, 2x identiek reproduceerbaar bij elke fresh app-start/hot-restart):

    A RenderFlex overflowed by 113 pixels on the right.
    Row:file:///.../lib/uitgaanspaginas/home_uitgaantabel_kaart_component/home_uitgaantabel_kaart_component_widget.dart:301:50
    constraints: BoxConstraints(0.0<=w<=111.5, 0.0<=h<=152.0)
    size: Size(111.5, 40.0)
    

    Root cause (code-niveau bevestigd, home_uitgaantabel_kaart_component_widget.dart:299-301): een Row (mainAxisSize: MainAxisSize.max) met children: List.generate(categorieitem.length, ...) — voor elk element in de dynamische categorie-lijst van een evenement wordt een TagCategorieComponentWidget-pilletje in de Row gezet, zonder Wrap, zonder horizontale scroll, zonder Expanded/Flexible per tag. Zodra een evenement 2+ categorieën heeft (of één lange categorienaam), passen de pilletjes niet in de ~111px die de Row van zijn ouder krijgt. Dit is dezelfde soort bug als de al bekende ontbrekende-Flexible-patronen (P1-3/P1-11), maar op een ander component dan beide daar genoemde — niet eerder in dit bestand vermeld. Fix (builder): component HomeUitgaantabelKaartComponent → Widget Tree → de Row met de TagCategorieComponentWidget-kinderen (rond de hierboven genoemde code) → wrappen in een Wrap-widget (i.p.v. Row) zodat tags naar een volgende regel overlopen, of een horizontale SingleChildScrollView eromheen zodat ze scrollen i.p.v. overflowen — zelfde afweging als Bob eerder maakte voor vergelijkbare tag-rijen elders. Nog niet gecheckt of hetzelfde patroon (kale Row van List.generate-tags, geen wrap) ook voorkomt op de niet-Home-varianten van dit component (PUitgaantabelKaartComponent/kaartTabelUitgaanComp/ kaartTabelUitgaanSComp, zie ook de P2-7-opschoonnotitie over die laatste twee) — bij het oppakken van deze taak even meenemen.

    • Bevestigde zustervondst (2026-08-09, Claude, verse stack trace): hetzelfde patroon zit ook op PUitgaanSliderKaartComponent (ánder component dan de drie hierboven genoemde) — categorie-tag- badge rechtsonder op de afbeelding:

      A RenderFlex overflowed by 2.4 pixels on the right.
      Row:file:///.../lib/uitgaanspaginas/p_uitgaan_slider_kaart_component/p_uitgaan_slider_kaart_component_widget.dart:179:38
      

      Zelfde oorzaak (Row met List.generate(categorie.length, ...), regel 178-179, mainAxisSize: MainAxisSize.min, geen Wrap/Expanded). Kleiner overflow (2.4px, minder zichtbaar dan Home's 113px) maar zelfde onderliggende bug — zelfde fix-aanpak (Wrap i.p.v. Row).

    • Poging door Claude (2026-08-09), geblokkeerd — geen wijziging aangebracht. De juiste Row-node (kind tagCategorieComponent, binnen Container → sibling van de image-Stack) was betrouwbaar te selecteren via de Widget Tree (zelfde kalibratietruc als CLAUDE.md beschrijft: klik op nominale y-positie landde structureel 63px lager, dus y-63 gebruikt — dat werkte hier wél consistent, in tegenstelling tot de "niet-constante offset" die P1-15 blokkeerde). Rechtsklik → contextmenu opende betrouwbaar met "Wrap Widget (Ctrl+B)" zichtbaar op exact geverifieerde coördinaten (bevestigd met zoom). Maar de klik op dat menu-item registreert niet — 3x geprobeerd op de exacte tekst-coördinaten (menu's positie verschilt wel steeds licht per keer geopend, maar telkens opnieuw met zoom geverifieerd vóór de klik) + 1x de Ctrl+B-sneltoets direct op de geselecteerde Row — geen van alle opende een wrap-type-dialoog of wijzigde de tree (geen nieuwe parent-node, geen dubbele widget). Een van de pogingen landde net naast het menu en deselecteerde terug naar de root-component (geen schade, gewoon opnieuw moeten selecteren). Nieuw exemplaar van het bekende "menu-actie-klik registreert niet zichtbaar"-patroon, nu ook bevestigd op "Wrap Widget" specifiek (niet eerder in CLAUDE.md genoemd voor dit menu-item). Concreet voor Bob: component HomeUitgaantabelKaartComponent → Widget Tree → ListViewContainerRowContainer (2e kind, na de image-Stack) → Row (bevat tagCategorieComponent als enige kind) → rechtsklik → Wrap Widget (Ctrl+B) → kies Wrap i.p.v. Row.

    P1-9 · Eigenaar: Onbepaald. Visuele polish (los, per pagina) — resterend na sessie 2026-08-06:

    1. Nog niet opgepakt: Event-pagina (typografie/contrast/spacing).
    2. Restpunt PUitgaanSliderKaartComponent-schaduw (builder → Widget Tree → beide Containers binnen de root-Row, rechterpaneel- eigenschappenzoekbalk "offset"): Offset Y staat op beide containers nog op 12 (target: 2, zelfde als PUitgaantabelKaartComponent). Blur (nu 4) en Offset X (nu 0, bevestigd via geëxporteerde code) staan al goed — alleen Offset Y bleek herhaaldelijk niet via Claude's browser-automation in te stellen (rechterveld rendert buiten het klikbare venster, en een Tab-naar-volgend-veld-workaround liet de waarde niet altijd vasthouden). Hoekafronding is al prima opgelost (uniform 24px op de afbeelding-Container, 12px — exact gelijk aan het tabel-kaartje — op de tekst-Container). Bob: Offset Y typen via het gewone rechterpaneel-veld lukt in eigen browser vermoedelijk gewoon (geen bekende clipping bij hem).
    3. Al afgerond sessie 2026-08-06 (Claude, builder): PUitgaanSliderKaartComponent schaduw verzacht (blur 6→4, offsetX 12→0, hoekafronding asymmetrisch→uniform) zodat die minder afwijkt van het tabel-kaartje; PUitgaanPage padding toegevoegd tussen advertentiebanner en tabellijst; HorecagelegenheidoverzichtKaart titel kreeg maxLines: 2 (voorkomt ongelijke kaarthoogtes in de grid); categorie-tag-kleur op datzelfde kaartje gelijkgetrokken naar huisstijlrood #9A141D (was paars-blauw #CC4B39EF, afweek van het gedeelde TagCategorieComponentWidget elders in de app).
    4. Al afgerond sessie 2026-08-07 (Claude, builder), live bevestigd op emulator: HorecagelegenhedenOverzicht — TabBar nu gewrapt in een Container met een zachte onderschaduw (#33000000, blur 4, offsetY 2 — zelfde stijl als de kaartjes) zodat de lijst niet meer direct tegen de tabs plakt bij scrollen. HorecagelegenheidoverzichtKaart — de categorie-tag-pilletjes (bv. "Bioscoop"/"Theater" op "De Beun") overlapten rommelig met logo-afbeeldingen; de omringende Column kreeg een halfdoorzichtige donkere achtergrond (#40000000, geen eigen padding — leunt op de al bestaande 8px Padding eromheen) als zachte "backing" tussen tags en logo-artwork.
    5. Bevinding voor volgende sessies (builder-workflow): de "Search properties..."-zoekbalk bovenaan het rechterpaneel is een betrouwbare workaround voor het bekende clipping/scroll-probleem — filtert eigenschappen op naam (bv. "blur", "offset", "radius", "padding") i.p.v. moeten scrollen door een niet-scrollende paneel- sectie. Voor een enkel numeriek veld: klik veld → Ctrl+A → typen → Tab/Enter werkt niet altijd betrouwbaar (soms blijft de oude waarde staan zonder foutmelding) — controleer na elke edit met een screenshot van het gefilterde veld; bij twijfel triple-click + Delete
      • typen i.p.v. Ctrl+A gebruiken, werkte in deze sessie consistenter. Verificatie via View Code (rechtsboven </>-icoon) is nuttig maar risicovol te bereiken: de icoontjes rechtsboven verschuiven afhankelijk van app-state (commit-icoon verschijnt/verdwijnt) — 3x per ongeluk een ander icoon geraakt (2x "Create Commit"-dialoog, 1x "Make Project Public"-dialoog, 1x app-preview) door te gokken op vaste coördinaten. Veiliger: direct navigeren naar https://app.flutterflow.io/code/uitgaanskrant-1qhvtd?component=<Naam> i.p.v. op het icoon te klikken, en binnen die code-view Ctrl+F gebruiken (werkt als browser-find) i.p.v. handmatig scrollen (scroll- wheel-events op die pagina reageren nauwelijks).

    P1-10 · Eigenaar: Bob (10 sec-klusje, geblokkeerd voor Claude — clipping). 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. **2026-08-05, geprobeerd door Claude op homeTabel (API Calls → Advanced Settings → "Cache API Results"-toggle aanzetten): toggle zet zelf prima aan, maar de "Confirm"-knop van de daaropvolgende opslag-bar (Cancel/Confirm) rendert buiten het browservenster — nieuw bevestigd geval van het bekende rechterpaneel/actiebalk- clippingprobleem uit CLAUDE.md (nu ook horizontaal op de API-Calls-pagina, niet alleen op Widget Tree-panelen). Geprobeerd: directe klik, scroll, DOM/shadow-DOM-doorzoeking op tekst "Confirm"/ "Cancel" (niets gevonden — Flutter Web HTML-renderer, geen standaard-knoppen), Flutter-accessibility-semantics geforceerd geactiveerd (flt-semantics-placeholder, hielp niet), Tab- toetsnavigatie. Geen succes — wijziging veilig teruggedraaid (toggle weer uit, geen halve state). Bob: 3x deze toggle aanzetten (homeTabel, gemeenten, provincies) en de Confirm-knop rechtsonder klikken (in eigen browser wél gewoon zichtbaar/klikbaar).
    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.
    3. Bijvangst tijdens de audit: dode EstablishmentsNewCall verplaatst naar de P2-7-opschoonlijst.

    P1-11 · Eigenaar: Bob — geblokkeerd op rechterpaneel-clipping (zelfde patroon als P1-3). Responsive/screensize. 2026-08-05: venue-event-grid-bug uitgezocht (Claude, code-niveau) — root cause gevonden, mechanische builder-fix, nog niet uitgevoerd:

    • Component: HorecagelegenheidEventTabelComponentCopy (lib/horecagelegenhedenoverzicht/horecagelegenheid_event_tabel_component_copy/...widget.dart), gebruikt op de "Events"-tab van HorecagelegenheidCurrent (enige gebruiksplek — geen niet-"_copy"-variant meer aanwezig om simpel in te wisselen).
    • GridView (regel 165-172): crossAxisCount: 2, childAspectRatio: 3.0 → elke grid-cel wordt ≈ (schermbreedte/2) breed × (celbreedte/3) hoog — op een telefoon van 390px breed dus ≈190×63px per cel.
    • Binnen elke cel (regel 178-315): een Row met twee Containers die beide hardcoded width: 200.0, height: 200.0 hebben (tekst-tegel regel 186-187, afbeeldings-tegel regel 294-295/311-312 incl. de CachedNetworkImage zelf). De tekst-Container zit wel in Expanded (dus de breedte krimpt mee), maar de hoogte (200) nietExpanded in een Row regelt alleen de hoofdas (breedte), niet de dwarsas (hoogte). De afbeeldings-Container zit zelfs helemaal niet in Expanded — noch breedte noch hoogte passen zich aan.
    • Gevolg: content wil 200px hoog zijn in een cel van ≈63px hoog, en de afbeeldings-tegel wil alléén al 200px breed zijn terwijl de hele cel maar ≈190px breed is (gedeeld met de tekst-tegel ernaast) — RenderFlex overflowed-fouten/afgeknipte layout op de Events-tab van elke horecagelegenheid-detailpagina.
    • Voorgestelde fix (mechanisch, builder-property-wijzigingen, geen nieuwe widgets nodig): in de builder op HorecagelegenheidEventTabelComponentCopy → Widget Tree → de twee Containers binnen de Row (tekst- en afbeeldings-tegel): (1) hoogte 200 vervangen door een responsieve waarde (bv. Expanded ook op de dwarsas laten werken via een buitenste AspectRatio, of de vaste height: 200 gewoon verwijderen en de Row's hoogte laten bepalen door childAspectRatio), (2) de afbeeldings-Container ook in Expanded wrappen zodat beide tegels de celbreedte delen i.p.v. allebei 200px te claimen.
    • 2026-08-05, poging door Claude: in Widget Tree op de tekst- Container geselecteerd — het "Height"-veld (Container Properties) en de "Expansion"-segmented-control (None/Expanded/Flexible) renderen beide net buiten het browservenster, exact hetzelfde structurele rechterpaneel-clippingprobleem als P1-3 (bevestigd met eigenschappen-zoekfilter, scroll, directe klik op geschatte positie — geen succes, geen wijziging aangebracht). Bob: fix hierboven + P1-3's Expansion-fix in dezelfde sessie oppakken, scheelt heen-en- weer-navigeren.

    P2 — features & concept, na livegang

    P2-1 · Eigenaar: Bob — testen in de API, komt terug. Datum-filter: Vandaag / Dit weekend / Deze week.

    P2-2 · Eigenaar: Onbepaald. Google Maps-weergave van horecagelegenheden — bewust niet vóór livegang (Maps API-key + billing, onduidelijk of elke locatie al lat/long heeft, marker-UI — geen quick win).

    P2-3 · Eigenaar: Onbepaald. "In de buurt"/geolocatie-browsen — aanvulling op het provincie/gemeente-model, geen vervanging.

    P2-4 · Eigenaar: Onbepaald. Overige feature-ideeën, geen van alle uitgewerkt: deel-knop op eventpagina · "toevoegen aan agenda" (native kalender) · "events op deze locatie" prominenter op de horeca-detailpagina · reviews/waardering voor horecagelegenheden (groot, vraagt nieuw Drupal content-type + moderatie, eigen project). (De "Wat is er vanavond"-melding is uitgelicht naar P2-10 hieronder — dat idee weegt zwaarder dan de rest van dit lijstje.)

    P2-9 · Eigenaar: Onbepaald. Onboarding/eerste-gebruik-uitleg. Live bevestigd 2026-08-07 (Claude, emulator, pm clear + verse launch = echte eerste-keer-ervaring): een nieuwe gebruiker opent de app en ziet direct de Home-pagina met bovenaan een carousel met kop "OOK LEUK" ("ook leuk" veronderstelt dat je al iets gezien hebt — vreemd als allereerste tekst) en daaronder een kale lijst events, geen welkomsttekst, geen uitleg wat Uitgaanskrant is, geen prompt om een provincie/gemeente te kiezen. (Zie ook P0-3's opmerking dat de eerste-launch-default-locatie 28666/28694 geen naam toont totdat iemand handmatig kiest.) Zonder duidelijke eerste indruk is de kans groot dat een nieuwe gebruiker de app na 1x openen niet snapt/niet terugkomt. Nog geen concrete builder-fix uitgewerkt — eerst met Bob bespreken wat voor onboarding gewenst is (korte welkomsttekst? meteen naar provincie/gemeente-keuze i.p.v. Home?) vóórdat dit gebouwd wordt.

    • Bijvangst, zelfde verkenning: dode terug-pijl-knop in Home's AppBarafgerond (2026-08-10, Claude). IconButtonBack verwijderd via Widget Tree → rechtsklik → "Remove Widget" (op HomeWidgetAppBarRow, naast IconButtonDrawer). Bevestigd via verse flutterflow export-code: geen enkele referentie meer aan IconButtonBack/het bijbehorende Icons.arrow_back_outlined-icoon in home_widget.dart — de AppBar-Row bevat nu alleen nog de hamburger-menuknop. Geen builder-sync-problemen bij deze simpele Remove-Widget-actie (i.t.t. P1-13's multi-property-toggle, zie daar).

    P2-10 · Eigenaar: Onbepaald. "Vanavond in [gemeente/provincie]"- herinnering (pushmelding of in-app-widget) — uitgelicht uit de ongestructureerde lijst van P2-4 omdat dit vermoedelijk de goedkoopste hefboom is voor terugkerend gebruik: dit type overzichts-app wint of verliest niet op features maar op of mensen 'm blijven openen. Een eenmalige/wekelijkse melding met "dit weekend in [gekozen gemeente]" is een directe reden om terug te komen, i.p.v. te wachten tot iemand toevallig weer aan de app denkt. Hangt af van dezelfde Firebase-infra als P1-16 (Firebase Cloud Messaging naast Crashlytics/Analytics) — logisch om in dezelfde builder-sessie op te pakken als P1-16. Nog niet uitgewerkt qua precieze inhoud/frequentie (voorkom spam-gevoel) — eerst met Bob bespreken vóór bouwen.

    P2-5 · Eigenaar: Onbepaald. Ad-banners op horeca-overzicht, horeca-detail, event-detail; vaste regel: geen ads op locatie-kiezer/login/account.

    P2-6 · Eigenaar: Onbepaald. Tekstzoeken op titel op de horeca-overzichtspagina (los van de Datatype/Sort-experimenten die Bob daar zelf op test — die zijn actief werk-in-uitvoering, geen dode code).

    P2-7 · Eigenaar: Bob. Opschonen:

    • Merge kaartTabelUitgaanComp + kaartTabelUitgaanSComp — Bob doet dit zelf ("ik kijk er zelf naar").
    • lib/kanweg opnieuw leegmaken indien teruggekomen na een latere export-pull, plus eventuele nieuwe losse dode componenten in lib/evenement/.
    • Eén browse-by-category-patroon i.p.v. twee: nu Home landelijk is, bepalen hoe Home's categorieën en PUitgaanPage's provincie/ gemeente-gescoopte categorieën zich tot elkaar verhouden.
    • Dubbele Provincie/Gemeente-blok in het menu opruimen (12 menu-items waar 6 zouden volstaan).
    • EventWidget-route: heraansluiten of definitief schrappen (losse orphan-route). Bevestigd orphan 2026-08-05 (Claude, grep): route staat correct geregistreerd (nav.dart, pad /event, param nid) en geëxporteerd (index.dart), maar geen enkele pushNamed/ navigatie-aanroep in de hele codebase gaat er ooit naartoeEventCurrent (pad /eventCurrent) is overal de daadwerkelijk gebruikte event-detailpagina. Alleen bereikbaar via een handmatige directe URL. Beslissing (verwijderen uit nav.dart+index.dart, of alsnog ergens aan koppelen) ligt bij Bob.
    • EstablishmentsNewCall (lib/backend/api_requests/api_calls.dart:845) wordt nergens meer aangeroepen — dode API-call-definitie (gevonden bij de P1-10-performance-audit 2026-08-05).

    P2-8 · Opgegaan in P1-7 (2026-08-09). Hartje-tap op gemeente-/ provincienaam om te favorieten is nu onderdeel van de bredere Favorieten-pagina/profielscherm-taak — zie P1-7 hierboven voor scope en status.