TASKS.md 41 KB

Uitgaanskrant — takenlijst

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

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.

    Status: actief bij Bob (geen Claude-actie nodig, ter info)

    • FavorietenAgenda 403-foutEigenaar: Bob — bezig. Bob troubleshoot dit zelf. FlutterFlow-requests komen bij nginx binnen met een lege Cookie-header; zijn eigen browser/curl (via dezelfde Cloudflare-edge) sturen de sessie-cookie wél mee. Cloudflare Cache Rule voor SSESS* staat al goed (bypass, eerste regel). Werkhypothese: Cloudflare Bot Management behandelt FlutterFlow's server-side traffic anders op basis van IP-reputatie/ TLS-fingerprint. Niet opnieuw diagnosticeren zonder navraag — check eerst of Bob al verder is.

    P0 — blokkeert livegang

    P0-6 · Eigenaar: Onbepaald (mechanisch: widgets verwijderen/verbergen in de builder). Live bevestigd 2026-08-07 (Claude, emulator, verse app-data/eerste-launch-simulatie): de Login-pagina toont onder de "Wachtwoord vergeten?"-link 5 interne test-/debug-navigatieknoppen, onvoorwaardelijk zichtbaar voor elke echte gebruiker (geen kDebugMode-check, gewoon standaard FFButtonWidgets in lib/login/login/login_widget.dart r. 665-880): "HorecagelegenhedenOverzichtPag…", "selectprovinciegemeent", "horecagelegenheid 57897" (hardcoded test-nid), "puitgaan", en "kanwegtest" (linkt naar KanwegWidget — Bob's eigen scratch-testgebied, zie lib/kanweg elders in dit document). Dit moet er sowieso uit vóór livegang — een productie-loginscherm met zichtbare interne testknoppen (incl. een link naar de scratch-pagina) oogt onafgemaakt/onprofessioneel en is verwarrend voor een nieuwe gebruiker. Fix: de 5 bijbehorende FFButtonWidget-nodes in de Widget Tree van Login verwijderen (of, als ze voor Bob's eigen handige interne navigatie tijdens development moeten blijven bestaan, wrappen in een conditie die alleen in een niet-productie-omgeving zichtbaar is — verwijderen is eenvoudiger en veiliger).

    Sub-bevinding, zelfde pagina/bevinding: de e-mail- en wachtwoordvelden op Login hebben geen echte placeholder-tekst ingesteld — hintText is nog gebonden aan de FlutterFlow-standaardtekst "TextField" (keys d507d3b9/t8h5f8ir in lib/flutter_flow/internationalization.dart, nl: 'TextField', en: ''). In het Nederlands zie je dus het onbedoelde woord "TextField" in beide velden; in het Engels (zie P1-17) zijn de velden zelfs volledig leeg — de gebruiker weet dan niet wat hij moet invullen. Fix: hintText op beide velden een echte tekst geven ("E-mailadres" / "Wachtwoord") in zowel de nl- als en-vertaling.

    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.
    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 inloggen — hangt af van FavorietenAgenda-403 hierboven.

    P0-5 · Eigenaar: Bob. Drupal: anonieme leestoegang onderzoeken voor browse-endpoints. Drupal-niveau, geen Claude-taak.

    P1 — snel na livegang

    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: Onbepaald (audit door Claude afgerond, fix is builder-werk). 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.

    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. Aanbevolen fix (snel, vóór er echt in vertalen geïnvesteerd wordt): forceer de locale hard op 'nl' (verwijder 'en' uit FFLocalizations.languages()/ supportedLocales, of zet een harde default) totdat er een bewuste keuze is om Engels aan te bieden — een niet-vertaalde app blijft zo altijd nette Nederlandse tekst tonen in plaats van willekeurig kapotte Engelse tekst. Losstaand echt vertalen is een grotere, aparte contentklus (niet meegenomen in deze taak).

    P1-7 · Eigenaar: Bob. Account/profielscherm (wachtwoord wijzigen, uitloggen, account verwijderen). Bovenop de login/favorieten-P0-basis. Account verwijderen heeft mogelijk AVG-implicaties aan Drupal-kant. Let op prioriteit: dit is niet alleen "nice to have" — Apple's App Store Review Guideline 5.1.1(v) eist dat een app die accountaanmaak aanbiedt ook in-app accountverwijdering aanbiedt; zonder dit scherm is een iOS-store-submissie een blokkade, niet alleen P1.

    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. Op HorecagelegenhedenOverzicht → tab "Activiteiten" gooit de kaartjesgrid herhaaldelijk RenderFlex overflowed-fouten — zowel "on the right" (oplopend van 16 tot 243 pixels, tientallen keren) als één keer "on the bottom" (2653 pixels). 2026-08-07 (Claude): logcat-onderzoek geprobeerd, geen resultaat — geen actieve flutter run/attach-sessie beschikbaar deze sessie (leeg terminal, adb logcat toonde geen Flutter-frames), dus geen verse stack trace te pakken. Op basis van codelezing wél een concrete, nog niet geverifieerde hypothese: HorecagelegenheidoverzichtKaartWidget (horecagelegenheidoverzicht_kaart_widget.dart:337-349) kiest de breedte van de tekst-kolom via MediaQuery.sizeOf(context).width (200/250/300/350px) — dat is de volledige schermbreedte, terwijl deze kaart altijd in een 2- of 3-koloms MasonryGridView staat (horecagelegenheden_overzicht_widget.dart:346-361). Bij logische breedte tussen kBreakpointMedium(767) en kBreakpointLarge(991) → grid met 2 kolommen, kaart-tekstkolom kiest 300px — dat past mogelijk niet meer naast de afbeeldingskolom in een halve-schermbreedte grid-cel. Onzeker of dit de daadwerkelijke overflow-oorzaak is: de tekstkolom staat in een Expanded, en Expanded geeft normaliter tight constraints die een child's eigen width-property juist overschrijven (BoxConstraints.enforce) — dus in theorie zou dit net NIET mogen overflowen op Row-niveau. Kon dit niet verifiëren zonder Flutter DevTools/Layout Explorer in een live debug-sessie. Volgende sessie: als er een live flutter run/flutter attach-sessie beschikbaar is (met console-output), reproduceer de overflow op tab Activiteiten en lees de volledige stack trace — die geeft de exacte widget/regel. Zonder dat blijft dit gokken. 2026-08-07 middag, opnieuw reconfirmed (read-only logtail van de andere sessie's actieve flutter run): de "on the right"-overflows blijven zich herhaaldelijk voordoen (16 t/m 219px, tientallen keren) — nog steeds niet opgelost. In diezelfde log ook Invalid argument(s): No host specified in URI-excepties gezien — dat is een los probleem, zie het nieuwe P1-15 (niet dezelfde oorzaak als deze RenderFlex-overflow).

    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: Home's AppBar heeft een hardcoded terug-pijl-knop (Icons.arrow_back_outlined, roept context.pop() aan) naast het hamburger-menu-icoon (lib/uitgaanspaginas/home/home_widget.dart, rond de FlexibleSpaceBar). Op de root-pagina is er niets om naar terug te gaan — live getest, de knop doet niets (geen crash, stille no-op), maar oogt verwarrend/onafgemaakt op het allereerste scherm. Kleine fix: knop weghalen op Home, of automaticallyImplyLeading/ conditie gebruiken zodat hij alleen verschijnt op pagina's waar terug-navigeren zinvol is.

    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 · Eigenaar: Onbepaald. Hartje-tap-actie op de getoonde gemeente-/provincienaam (favoriete plaats maken/markeren) — losgemaakt van P0-3 (2026-08-05, Bob: te veel voor de eerste release). Naam wordt inmiddels al getoond op de meeste pagina's via HeaderButtonsComponent (zie P0-3); dit punt is puur de hartje-tap-functionaliteit erbovenop. Hangt af van de FavorietenAgenda-403-fix (zie "Status: actief bij Bob" bovenaan dit bestand) — niet oppakken vóórdat die opgelost is.