Преглед изворни кода

P2-15: verificatie stadsactiviteitAanmaken (0 errors) + 2 blokkades gevonden

Bob's ronde geverifieerd via verse export + dart analyze + live profile-run:
orphan-kopieen weg (0 errors), Entree/Media erven al w600, $.success op
ButtonLogo, kop "Wat" toegevoegd, MijnHorecagelegenheden-cookieheader gefixt.

Nieuw gevonden:
- Plaats-dropdown valt op telefoon buiten het scherm (3x width 200 in een Row)
  -> formulier niet in te dienen via de handmatige cascade; shortcut-pad werkt
- ButtonFotos leest logouploadResult i.p.v. fotouploadResult (crash/valse TRUE)
- 6 look&feel-punten, o.a. onzichtbare tekstvelden en Container(height:200)
  om TextFieldAdres

Stadsrechten-migratie afgevinkt (live bevestigd: 4 gemeenten i.p.v. 1254).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bob пре 1 недеља
родитељ
комит
d415ca56e6
1 измењених фајлова са 152 додато и 73 уклоњено
  1. 152 73
      TASKS.md

+ 152 - 73
TASKS.md

@@ -2072,14 +2072,14 @@ in Drupal, geen uitputtende audit.
 Volledige onderbouwing met screenshots: [Designbrug-rapport](https://claude.ai/code/artifact/29f3412a-305f-49f3-971c-cd9bd310beb1).
 Afvinkbare werklijst: [Designbrug werklijst](https://claude.ai/code/artifact/0c0c7347-d681-417d-83d7-7feb1de6457d).)*
 
-**P1-35 · Eigenaar: Bob** (klein per pagina). Advertentieblok staat op
+**P1-35 · Eigenaar: Claude — bezig (sessie 2026-09-03, live pair met Bob in de builder)** (klein per pagina). Advertentieblok staat op
 de detailpagina's direct onder de titel en duwt tabs/adres/tijden onder
 de vouw. De site zet advertenties consequent ná de inhoud. Verplaats de
 `AdBanner`-node naar onder de Info-tab of onderaan de pagina, op
 `horecagelegenheid_current` en `event_current`/
 `evenement_horecagelegenheid`.
 
-**P1-36 · Eigenaar: Bob.** In `horecagelegenheidoverzicht_kaart_widget.dart`
+**P1-36 · Eigenaar: Claude — bezig (sessie 2026-09-03, live pair met Bob in de builder).** In `horecagelegenheidoverzicht_kaart_widget.dart`
 liggen drie groene categoriepillen over het logo van de zaak heen
 (precies over de naam in het beeldmerk), met daarnaast een leeg grijs
 vlak van dezelfde grootte — leest als een kapotte afbeelding. Fix:
@@ -2699,7 +2699,7 @@ overwegen bij een volgende theme-update:
 
 ---
 
-**P2-15 · Eigenaar: Claude (niet actief bezig — sessie 2026-09-02 afgesloten; de pagina `uitgaansevenementAanmaken` staat er en de export is open. Zie "STAND VAN ZAKEN bouwstap 5" voor wat er nog moet).
+**P2-15 · Eigenaar: Claude — bezig (sessie 2026-09-03, verificatie + live test `stadsactiviteitAanmaken`; sessie 2026-09-02 afgesloten; de pagina `uitgaansevenementAanmaken` staat er en de export is open. Zie "STAND VAN ZAKEN bouwstap 5" voor wat er nog moet).
 Bouwstap 1 afgerond en bevestigd (2026-08-27): custom action
 `bestandUpload` (`lib/custom_code/actions/bestand_upload.dart`) upload
 foto → fid, live getest tegen productie
@@ -3124,79 +3124,158 @@ Bob's eigen browser ~5 seconden per widget kost.
 **Huisstijl AF (2026-09-03, geverifieerd).** Alle border-radii op 0
 (12 tekstvelden, 6 dropdowns, 3 knoppen, 2 afbeeldingen — 0 treffers
 `circular(8.0)` over), sectiekoppen op 16px.
-**Twee restjes:** "Entree" en "Media" hebben fontSize 16 maar nog **niet**
-`FontWeight.w600` (de andere drie wel) — alleen Font Weight nog op
-600 zetten.
-
-**🚨 BLOKKEREND: 3 compile-errors, de app bouwt niet.** Er staan vier
-versies van de pagina in het project: `stadsactiviteitAanmaken` (de
-echte) plus **`Copy`, `Copy2` en `Copy3`** — orphans, nergens naartoe
-genavigeerd (`grep` op de widget-klassen geeft 0 externe treffers).
-`stadsactiviteit_aanmaken_copy2` verwijst 3× naar een niet-bestaande
-`columnMijnStadsrechtenResponse` (bij het dupliceren is de wrapper-
-`Column` met de Backend Query niet meegekomen). `dart analyze` geeft
-daardoor 3 errors en elke build faalt.
-**Op te lossen door de drie kopieën te verwijderen** — of, als
-verwijderen op de bekende "Invalid Action"-blokkade stuit (precedent
-P2-7), te hernoemen met een `kanweg_`-prefix conform de bestaande
-conventie. Doe dit vóór de eindtest, anders wacht je op een build die
-niet komt.
-
-**Openstaande takenlijst voor Bob op deze pagina:**
-1. **`$.success`-conditie op beide upload-knoppen.** Bij annuleren wordt
-   `bestandUpload` alsnog aangeroepen met een leeg bestand; `.toString()`
-   maakt van het ontbrekende veld de tekst `"null"`, en de preview toont
-   dan `Invalid argument(s): No host specified in URI file:///null`.
-   Conditional ná de upload-actie: TRUE-tak schrijft fid/url weg,
-   FALSE-tak toont een snackbar met `$.error`.
-2. **Twee sectiekoppen staan nog op "Hello World"** — de groepen "Waar"
-   en "Organisatie".
-3. **Groep 1 (`ContainerWat`) heeft geen sectiekop** — de andere vijf wel.
-4. **Onderaan staat een lege, wél gestileerde container met alleen een
-   "Hello World"-Text** (7e container). Vullen of verwijderen.
-5. **`ContainerMedia` is niet gestileerd** — Fill Color en Border Color
-   staan op Unset, terwijl de andere groepen wit met 3px `#EEEEEE` zijn.
-   Zet Fill = Secondary Background, Border = `#EEEEEE`, Border Width = 3,
-   Border Radius 0 — én Width op `infinity` (staat er wel al op).
-6. **`TextFieldTitel` en `TextFieldWebsiteURL` staan op `width: 200`**,
-   alle andere velden op infinity.
-7. **De dropdowns staan op `width: 200`.** ⚠️ `DropDownProvincie`,
-   `DropDownGemeente` en `DropDownPlaats` zitten in een **`Row`** — daar
-   is `infinity` ongeldig en weigert FlutterFlow de wijziging met
-   "Invalid Action: would have caused a crashing error" (zelf getest).
-   Wil je die vol laten lopen, wrap ze dan eerst in een `Expanded`/`Flex`
-   of haal ze uit de Row.
-8. **Nooit een activiteit ingediend.** Alles wat het pad blokkeerde is nu
-   weg; dit is de eerstvolgende echte test.
-9. Afwerking: geen validatie vooraf, lege AppBar, geen "bezig"-indicatie
-   bij indienen, foto's niet verwijderbaar.
+(De eerdere notitie dat "Entree"/"Media" nog geen `FontWeight.w600`
+hadden is achterhaald — zie de verificatie hieronder: ze erven w600 al
+van `headlineSmall`.)
+
+**✅ BLOKKADE OPGEHEVEN + huisstijl-restjes gecontroleerd (2026-09-03,
+Claude, verse export + `flutter pub get` + `dart analyze` + live
+profile-run op `emulator-5556`/telefoon).** Wat Bob deze ronde deed is
+geverifieerd:
+- **`Copy`/`Copy2`/`Copy3` zijn weg** — `dart analyze lib/` geeft nu
+  **0 errors** (was 3), de app bouwt en draait weer.
+- **"Entree" + "Media" zijn wél 16px/600** — ze staan op basisstijl
+  `headlineSmall` (die is in het thema al `FontWeight.w600`) i.p.v.
+  `bodyMedium` + expliciete override zoals de andere drie. Klaar, ook
+  al ziet de code er anders uit dan bij "Wanneer"/"Waar"/"Organisatie".
+- **`$.success`-conditie staat op `ButtonLogo`** — correct: TRUE-tak
+  schrijft fid/url, FALSE-tak snackbar met `$.error`.
+- **Sectiekop "Wat" is toegevoegd** (i18n-key `hu7xw8pm`).
+- **`MijnHorecagelegenheden`-cookieheader is gefixt** — export toont
+  `'Cookie': '${sessionName}=${sessid}'` en de aanroeper in
+  `mijn_profiel_widget.dart:270` geeft beide App-State-velden mee. Er
+  staat nergens in `api_calls.dart` nog een `{{…}}`.
+
+**🚨 BLOKKEREND 1 — de Plaats-dropdown is op een telefoon onbereikbaar,
+dus het formulier is niet in te dienen via de handmatige cascade.**
+Live bevestigd (telefoon 411dp): `DropDownProvincie`,
+`DropDownGemeente` en `DropDownPlaats` staan naast elkaar in één `Row`,
+elk met `width: 200` (regels 1569/1703/1844 in
+`stadsactiviteit_aanmaken_widget.dart`). 3 × 200 = 600 > 411dp, dus
+zodra je een gemeente kiest valt de derde dropdown **volledig buiten
+het scherm** — hij staat niet eens in de accessibility-tree
+(`get_ui_tree` toont alleen de eerste twee). Zonder `createPlaatsID`
+verschijnt de verzendknop nooit (die heeft een Is-Set-guard), dus de
+pagina is via dit pad onbruikbaar. In profile-mode is er géén
+zichtbare overflow-melding en niets in `logcat` — puur stille clipping.
+**Wél werkend pad:** de shortcut `DropDownGemeentenMijngemeenten`
+bovenaan. Die zet `createGemeenteID` zonder `createProvincieID`, dus de
+Gemeente-dropdown blijft verborgen en er staan maar 2 dropdowns in de
+Row (2 × 200 = 400 < 411) → Plaats is dan wél bereikbaar. Live getest:
+Amsterdam (gemeente) → Plaats "Amsterdam"/"Amsterdam-Zuidoost" laadt
+via `PlaatsenBijGemeente`, en dán verschijnt "Activiteit indienen".
+**Fix:** haal de drie dropdowns uit de `Row` en zet ze onder elkaar op
+`infinity` (een `Column` is hier logischer dan een Row — het zijn drie
+opeenvolgende keuzes, geen naast-elkaar-groep). ⚠️ `infinity` direct op
+een Row-kind weigert FlutterFlow met "Invalid Action" (al eerder
+getest), dus eerst uit de Row halen. Zie ook `CLAUDE.md`: "Remove
+Widget" op de Row behoudt de kinderen — precies wat je hier wil.
+
+**🚨 BLOKKEREND 2 — de Foto's-knop leest de verkeerde
+actie-uitkomst.** In de `onPressed` van `ButtonFotos` staat de
+`$.success`-conditie én de fout-snackbar op `_model.logouploadResult`
+(het resultaat van de **logo**-upload) i.p.v.
+`_model.fotouploadResult` — regels 3456 en 3474; alleen de twee
+`addTo…`-regels (3460/3464) pakken de juiste variabele. Twee gevolgen:
+(1) kies je een foto **voordat** je ooit een logo hebt geüpload, dan is
+`logouploadResult` nog `null` → `if (getJsonField(null, r'$.success'))`
+→ **runtime-crash op de bool-cast** (exact de valkuil die al in
+`CLAUDE.md` staat); (2) is de logo-upload eerder wél gelukt, dan neemt
+de fotoknop **altijd** de TRUE-tak, ook als de foto-upload faalde →
+`"null"` als fid in `createFotosFids`.
+**Fix:** in de Action Flow Editor van `ButtonFotos` de conditie en de
+fout-snackbar opnieuw binden aan `fotouploadResult`. Dit is dezelfde
+copy-paste-valkuil als het `datePicked0`/`datePicked1`-geval eerder op
+deze pagina.
+
+**Look & feel — live bekeken, 6 punten die er echt uitspringen:**
+1. **De tekstvelden zijn onzichtbaar.** `enabledBorder`/`focusedBorder`
+   staan op `Color(0x00000000)` (transparant) en `fillColor` op
+   `secondaryBackground` = `#FFFFFF` — precies de kleur van de kaart
+   waar ze in staan. Je ziet alleen zwevende grijze labeltekst, geen
+   invulvak: op het scherm lijkt "Titel"/"Omschrijving"/"Adres"/
+   "Postcode"/"Plaats"/"Organisator"/"Contact"/"WebsiteURL" losse tekst
+   i.p.v. een veld. Dit is de grootste visuele misser. **Fix:** geef de
+   velden een zichtbare rand (`alternate` #EEEEEE, of `primaryText` op
+   lage opaciteit) óf zet `fillColor` op `primaryBackground` (#F2F2F2)
+   zodat het vak contrasteert met de witte kaart. De site zelf gebruikt
+   een lichtgrijze rand om invoervakken.
+2. **`Container(height: 200)` om `TextFieldAdres`** (regel 1903) — een
+   leftover vaste hoogte die een gat van ~200px in de "Waar"-kaart
+   slaat. Weghalen (of de Container zelf verwijderen).
+3. **`ContainerMedia` mist de `Align > Padding(16)`-wrapper** die de
+   andere vijf kaarten wél hebben (regel 3206 vs 196/693/1281/2276/2690).
+   Gevolg: de Media-kaart is 32px breder dan de rest en ligt zichtbaar
+   niet in lijn. Ook de twee oranje knoppen erin steken links buiten de
+   kaartrand.
+4. **Sectiekoppen zijn inconsistent uitgelijnd.** "Wat", "Wanneer",
+   "Waar" en "Organisatie" staan **gecentreerd** (geen `Align`, dus
+   Column-default), "Entree" en "Media" staan **links** (in een
+   `Align(-1.0)`). Kies er één — links past bij de site.
+5. **"Wat" heeft niet dezelfde kopstijl als de rest.** De kop staat op
+   kale `bodyMedium` (14px, normal) i.p.v. 16px/600 — visueel duidelijk
+   lichter dan "Wanneer"/"Waar". Nog omzetten.
+6. **Dubbele/zwevende veldlabels.** Boven vier velden staat een lósse
+   `Text`-widget die het label herhaalt dat het veld zelf al als
+   `labelText`/`hintText` heeft: "Categorie evenement" (regel 494),
+   "Stadseditor" (1467), "Toelichting Entree" (2874) en "Entreeprijs"
+   (3037). Bij "Toelichting Entree" en "Entreeprijs" staat het label
+   daardoor letterlijk 2× op het scherm. "Stadseditor" is bovendien een
+   zwevend, gecentreerd label zonder duidelijk bijhorend veld. Óf de
+   losse Texts weg, óf ze bij álle velden consequent gebruiken (en dan
+   de `labelText` van het veld leegmaken).
+   Kleiner, in dezelfde categorie: de kaarten hebben **geen interne
+   padding**, dus deze losse labels raken de 3px-rand van de kaart.
+
+**Kleinere restpunten op deze pagina (niet blokkerend):**
+1. **Entry-point ontbreekt nog** — `stadsactiviteitAanmaken` is alleen
+   via de route bereikbaar. De "+ Voeg toe"-knoppen op `mijnProfiel`
+   staan nog op een placeholder-snackbar en moeten Navigate-To hierheen
+   worden (bouwstap 4, restpunt 1).
+2. **Lege container met "Hello World" onderaan** (regel 3688-3704) —
+   staat er nog steeds, en is op het toestel gewoon zichtbaar onder de
+   verzendknop. Vullen of verwijderen.
+3. **Nog nooit een activiteit ingediend.** Beide blokkades hierboven
+   moeten eerst weg; daarna is dit de echte eindtest (node moet
+   ongepubliceerd binnenkomen met de juiste plaats/datum/categorieën/
+   entree/logo/foto's).
+4. **Geen validatie vooraf.** Alle 12 `…TextControllerValidator`-velden
+   zijn in het model gedeclareerd maar nergens toegekend, dus er is geen
+   enkele verplicht-veld-check. Een leeg Titel/Datum gaat gewoon mee
+   naar de server (`datumVoorApi('')` geeft `''`, geen crash) en komt
+   terug als een Drupal-foutmelding in de snackbar. Werkt, maar rauw.
+5. **Geen "bezig"-indicatie bij indienen** — geen enkele knop op deze
+   pagina heeft `showLoadingIndicator`. Bij een trage upload/create
+   lijkt de knop niets te doen.
+6. **De 6 dropdowns staan nog op `width: 200`** (regels 576, 1407,
+   1569, 1703, 1844, 2819). `DropDownCategorieen` (576) en
+   `DropDownEntree` (2819) zitten in een `Align`, niet in een `Row` —
+   die kunnen dus zonder gedoe naar `infinity`. De drie cascade-
+   dropdowns zie blokkade 1; de shortcut (1407) kan mee zodra die uit
+   de Row is.
+7. **Foto's zijn niet te verwijderen** — de Wrap toont ze als 80×80
+   `Image.network` zonder verwijderknop; verkeerd gekozen foto betekent
+   pagina verlaten en opnieuw beginnen.
+8. **Lege AppBar** — alleen een rode balk met terugknop, geen titel.
+9. **De verzendknop is onzichtbaar tot er een plaats gekozen is** (de
+   Is-Set-guard) zonder enige uitleg. Overweeg de knop altijd te tonen
+   maar uit te schakelen met een hint "Kies eerst een plaats" — dat is
+   duidelijker dan een knop die er niet is.
+10. De laadspinner van elke dropdown-`FutureBuilder` is een
+    `SpinKitFadingCircle` van **80×80 in een `Center`** — die springt
+    bij het laden groter dan de dropdown zelf en laat de layout
+    verschuiven.
 
 **Overige restpunten (sessie 2026-08-31, live pair-fix):**
 
-8. **`field_town_access` staat volledig op plaats-niveau — 9.292 rijen
-   over 6 accounts (Drupal-kant).** Gemeten 2026-08-31 via SQL:
-   Bee 5200, Disco-Party.nl 2317, bobcity 1254, nomad 517, bobhoreca 2,
-   Team Klein Frankrijk 2 — alles niveau 3 (Plaats). De omzetting naar
-   gemeente-niveau (2026-08-27) wijzigde alleen de widget-instellingen,
-   niet de opgeslagen waarden. **`mijn_stadsrechten` is NIET stuk** —
-   het endpoint geeft correct terug wat er staat (bevestigd: API-length
-   1254 == SQL-count voor bobcity).
-   **Correctie op een eerdere notitie in deze taak:** de conclusie
-   "bobcity heeft 's-Gravendeel als stadsrecht" was gebaseerd op het
-   eerste item van een `head -20` over de volledige, alfabetisch
-   gesorteerde lijst — geen bewijs van iets. De omvang bleek pas via
-   de database.
-   **Migratiescript is aan Bob gegeven** (dry-run + `$APPLY`-vlag,
-   haalt de hele hiërarchie in 2 queries op i.p.v.
-   `taxonomy_get_parents_all()` per term; plaats-tid → gemeente-ouder,
-   dedupliceren, `user_save()`). Nog niet gedraaid. Eerst devbob.
-   **⚠️ Productbeslissing die eerst gemaakt moet worden:** na conversie
-   houdt bobcity ~300 gemeenten en Bee mogelijk heel Nederland — dan is
-   de "Mijn gemeenten"-shortcut geen snelkoppeling maar een tweede
-   plaatsenlijst. Ofwel de landelijke scope terugbrengen tot wat die
-   accounts echt beheren, ofwel de shortcut anders vormgeven (alleen
-   tonen bij ≤ ~25 gemeenten, of een zoekveld i.p.v. een dropdown).
-   Zonder die keuze heeft de migratie weinig zin.
+8. **✅ AFGEROND (Bob, 2026-09-03): stadsrechten-migratie is gedraaid.**
+   `field_town_access` stond op plaats-niveau (9.292 rijen over 6
+   accounts); de migratie naar gemeente-niveau is uitgevoerd voor alle
+   accounts en de scope-beslissing is gemaakt. Live bevestigd in de app
+   (2026-09-03): de "Mijn gemeenten"-shortcut toont voor dit testaccount
+   nu **4 gemeenten** (Amsterdam, Drechterland, Enkhuizen, Stede Broec)
+   i.p.v. 1254 plaatsen — de shortcut werkt dus zoals bedoeld en is een
+   echte snelkoppeling geworden, geen tweede plaatsenlijst.
 9. **Categorie-dropdown toont de hele hiërarchie plat.** `categorieen`
    geeft `diepte`/`parent_tid` mee; de multiselect toont nu ouder- én
    kindtermen door elkaar zonder inspringing. Optionele verfijning.