Ver Fonte

P2-15 bouwstap 3: live getest, 3 bugs gefixt + sessie-cookie-vondst

Live test op emulator-5554 van stadsactiviteitAanmaken. Gefixt:
- Sessie-cookie ging nooit mee: 5 API Calls hadden Postman-syntax
  ({{var}}) in de Cookie-header i.p.v. FlutterFlow's [var]. ApiManager
  substitueert {{ }} niet. Weerlegt de aanname dat drupalRequest nodig
  was voor cookie-auth. Entreeopties/Categorieen/MijnStadsrechten om;
  MijnHorecagelegenheden en FavorietenAgenda staan nog open.
- Datumpickers vuurden nooit (actie op On Submit van een readOnly veld);
  nu op een omhullende Container's On Tap + Enabled uit.
- Crashes op lege API-responses: guards op gemeente-/plaats-dropdown en
  verzendknop.

Open: geen preview na logo-/foto-upload (Image-Path-binding accepteert
alleen List<String>, debugplan uitgeschreven), en de categorie-filter
op diepte 1 is nog niet live geverifieerd.

field_town_access blijkt 9.292 plaats-niveau rijen over 6 accounts;
mijn_stadsrechten is niet stuk. Migratiescript klaar, maar eerst een
productbeslissing over de landelijke scope.

CLAUDE.md: 5 nieuwe builderpatronen vastgelegd.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bob há 2 semanas atrás
pai
commit
8c892a75da
1 ficheiros alterados com 134 adições e 12 exclusões
  1. 134 12
      TASKS.md

+ 134 - 12
TASKS.md

@@ -2736,7 +2736,7 @@ overwegen bij een volgende theme-update:
 
 ---
 
-**P2-15 · Eigenaar: Bob (builder), Claude regisseert/verifieert — bezig (sessie 2026-08-31 avond, BOUWSTAP 5 `uitgaansevenementAanmaken`: custom action `evenementCreate` + formulierpagina).
+**P2-15 · Eigenaar: Bob (builder), Claude regisseert/verifieert (niet meer actief bezig — sessie 2026-08-31 avond afgesloten na bouwstap 5 stap 1; zie STAND VAN ZAKEN bij bouwstap 5).
 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
@@ -3126,6 +3126,39 @@ een volgende sessie niet opnieuw hoeft te reconstrueren:
 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.
+   **Update 2026-08-31:** bindingen staan inmiddels op
+   `$[?(@.diepte == 1)]` — zie de live-testnotitie hieronder; nog niet
+   bevestigd of die filtersyntax werkt.
+10. **Basis-URL centraliseren — Fase A af, Fase B open (app-breed,
+    overweeg een eigen taak-ID).** Aanleiding: op devbob kunnen testen
+    zonder overal URL's te wijzigen. **Gedaan:** App State-variabele
+    **`apiBaseUrl`** (default `https://uitgaanskrant.com`), en alle vier
+    de custom actions (`stadsactiviteitCreate`, `bestandUpload`,
+    `drupalRequest`, `drupalLogin`) bouwen hun URL daaruit op. Ze zijn
+    **tolerant**: een argument dat met `http(s)://` begint wordt
+    ongewijzigd gebruikt, anders als pad achter `apiBaseUrl` geplakt —
+    dus alle ~26 bestaande aanroepen met een volledige URL blijven
+    werken en kunnen in eigen tempo ingekort worden. Truc: de parameter
+    zelf wordt overschreven (`url = ...`), zodat verderop in de action
+    niets aangepast hoefde te worden. **Let op:** custom *Functions*
+    kunnen `FFAppState()` NIET lezen (`custom_functions.dart`
+    importeert `app_state.dart` niet, en dat importblok is niet
+    bewerkbaar) — custom *Actions* wel.
+    **Nog open (Fase B):** de 13 top-level API Calls in `api_calls.dart`
+    hebben nog een hardcoded host. Centraliseren betekent ze in de
+    bestaande API Group onderbrengen (`ProductieGroup`) — check eerst
+    of het ⋮-menu van een API Call een "Move to group" heeft; zo niet
+    moet elke call opnieuw aangemaakt worden ín de groep en moet **elke
+    Backend Query die 'm gebruikt opnieuw gebonden** worden (het dure,
+    foutgevoelige deel). Hernoem bij die gelegenheid de groep
+    `productie` → `drupal`/`backend`, want de naam klopt niet meer
+    zodra hij naar devbob wijst.
+11. **Devbob zit achter HTTP Basic Auth** — alleen `apiBaseUrl` omzetten
+    naar devbob geeft op álles een 401. Er is een
+    `Authorization: Basic <base64>`-header nodig die meegaat wanneer de
+    base-URL devbob is: in de custom actions één `if` erbij, voor de
+    API Calls een group-level header (extra argument om Fase B te doen).
+    Nog niet gebouwd.
 
 **Live test 2026-08-31 — pagina werkt grotendeels, drie bugs gevonden
 en gefixt, twee open.**
@@ -3226,13 +3259,22 @@ Custom Function.**
 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).)*
 
-**Bouwstap 5 — pagina `uitgaansevenementAanmaken`. VOLLEDIG
-VOORBEREID op 2026-08-31, klaar om mee te beginnen; nog geen regel
-gebouwd.** Dit is stap 3 uit de oorspronkelijke bouwvolgorde bovenaan
+**Bouwstap 5 — pagina `uitgaansevenementAanmaken`. IN UITVOERING
+sinds 2026-08-31 avond. Stap 1 (custom action `evenementCreate`) is AF
+en exportgeverifieerd; stap 2 (los testen tegen productie) staat klaar
+op 2 kleine handelingen na — zie "STAND VAN ZAKEN" onderaan dit blok,
+begin daar.** Dit is stap 3 uit de oorspronkelijke bouwvolgorde bovenaan
 P2-15 ("Pagina Evenement aanmaken"). Alles hieronder is uitgezocht en
 geverifieerd — een nieuwe sessie kan direct bouwen zonder eerst het
 Artifact te hoeven lezen.
 
+> ⚠️ **LET OP — de FlutterFlow-export is op dit moment GEBLOKKEERD.**
+> `flutterflow export-code` faalt met `Status: 400 / Error generating
+> code for the project`. Oorzaak is bekend en klein: het argument
+> `fotosFids` van de testknop staat nog op "Unset" (zie STAND VAN ZAKEN
+> punt 1). Zolang dat niet gezet is, kan **niemand** exporteren — dus
+> dit als eerste oplossen, ook als je aan een heel andere taak begint.
+
 **Kernpunt: deze pagina is EENVOUDIGER dan `stadsactiviteitAanmaken`,
 niet moeilijker.** Het zwaarste stuk van bouwstap 3 — de 3-traps
 provincie→gemeente→plaats-cascade — vervalt hier volledig. Drupal leidt
@@ -3291,14 +3333,17 @@ sectie "API-contract"; curl-bevestigd 2026-08-26):
   placeholder-snackbar toont; die wordt straks de entry-point.
 
 **Wat nieuw gebouwd moet worden:**
-1. **Custom action `evenementCreate`** — kopie van
-   `stadsactiviteit_create.dart` met de argumentenlijst hierboven
-   (13 i.p.v. 20 argumenten, geen `adres`-struct). POST naar
-   `$base/en/flutterdrup/evenementen/create.json`.
-   ⚠️ Bouw 'm plat, zonder lokale closures (bekende
-   "cannot be parsed"-validatorbug), en check vóór Save even
-   **"View Boilerplate Code"** (`</>`-icoon) op een leeg naamloos
-   extra argument — dat kostte bij `stadsactiviteitCreate` tijd.
+1. ~~**Custom action `evenementCreate`**~~ — **AF (2026-08-31).**
+   Staat in `lib/custom_code/actions/evenement_create.dart`, 16
+   argumenten (`sessionName`, `sessionId`, `token`,
+   `horecagelegenheidNid`, `titel`, `datumStart` verplicht; de rest
+   nullable, waarvan `categorieTids` en `fotosFids` als
+   `List<String>?`). Return type JSON (`Future<dynamic>`). POST naar
+   `$base/en/flutterdrup/evenementen/create.json` met `apiBaseUrl` uit
+   App State. 403 wordt apart afgevangen met de tekst "Deze
+   horecagelegenheid is niet van jou". Geverifieerd met een verse
+   export: byte-identiek aan de aangeleverde bron en `dart analyze` op
+   de hele export gaf 0 errors.
 2. **Pagina `uitgaansevenementAanmaken`** — Scaffold + AppBar
    ("Show Default Button" aan), scrollbare Column, padding 16.
    6 TextFields (Titel · Omschrijving · Entreeprijs · Toelichting
@@ -3326,6 +3371,83 @@ werkte.
 
 ---
 
+### STAND VAN ZAKEN bouwstap 5 (2026-08-31 avond) — hier verder
+
+**Klaar:** stap 1, de custom action (zie punt 1 hierboven).
+
+**Bezig:** stap 2, `evenementCreate` los testen tegen productie. Daarvoor
+staat op de bestaande wegwerp-testpagina **`kanwegTestUpload`** een
+**tweede knop "Test evenement"** (sibling van de bestaande "Test
+Upload"-knop, in dezelfde `Column`). Zijn On Tap heeft één actie:
+Custom Action `evenementCreate`, met deze waarden al gezet en
+UI-geverifieerd:
+
+| Argument | Waarde |
+|---|---|
+| `sessionName` | App State `userSessionname` |
+| `sessionId` | App State `userSessionid` |
+| `token` | App State `userToken` |
+| `titel` | letterlijk `Testevenement Claude` |
+| `datumStart` | letterlijk `2026-09-15 20:00:00` |
+| `categorieTids` | Inline Function, expression `<String>[]` |
+
+Er is **bewust géén snackbar-actie** toegevoegd: `evenementCreate` print
+URL, body, status en response al naar de console, dus `adb logcat` is de
+uitleesroute. (Wil je 'm tijdens het testen tóch zichtbaar op het
+toestel, voeg dan een Show Snack Bar toe met Action Output → JSON Path
+`$`, zoals de bestaande upload-knop doet — dan is een Action Output
+Variable Name nodig, die staat nu niet ingesteld.)
+
+**Nog te doen om stap 2 af te maken:**
+
+1. **`fotosFids` zetten — DIT DEBLOKKEERT DE EXPORT.** Pagina
+   `kanwegTestUpload` → knop "Test evenement" → Actions → argument
+   `fotosFids` → potlood naast Value → **Inline Function** → Expression
+   `<String>[]` → Check Errors → Confirm. *(Claude kon dit veld niet
+   zelf bereiken: het rechterpaneel scrollt niet en zelfs met alle 15
+   argumenten erboven ingeklapt blijft het waardeveld ~40px onder de
+   viewportrand. In Bob's eigen browser staat het gewoon in beeld.)*
+2. **`horecagelegenheidNid` invullen** met het nid van een
+   horecagelegenheid op Bob's eigen account (op te zoeken via
+   `mijn_horecagelegenheden` of in de app op Mijn profiel). Verplicht
+   argument, staat nu op Unset.
+3. **Verse export + `dart analyze`** ter controle (moet weer slagen).
+4. **Live testen:** app draaien op `emulator-5554`, eerst `adb logcat -c`,
+   dan de knop "Test evenement" indrukken en de `EVENEMENT CREATE`-blokken
+   (URL/BODY/STATUS/response) uit `logcat` lezen. Verwacht:
+   `{"status": "created", "nid": "..."}` en een **direct gepubliceerde**
+   node op productie — daarna die testnode weer opruimen in Drupal.
+5. **Testknop opruimen** zodra stap 2 groen is (de knop verwijderen,
+   `kanwegTestUpload` zelf blijft staan als herbruikbare testtool).
+
+**Daarna pas** aan de formulierpagina beginnen (punt 2 t/m 5 van "Wat
+nieuw gebouwd moet worden" hierboven).
+
+**Nieuwe FlutterFlow-valkuil, gevonden tijdens deze stap (geldt straks
+óók voor de formulierpagina):** een **List-typed custom-action-argument
+mag niet op "Unset" blijven staan**, ook niet als het in Dart nullable
+is. Het Issues-paneel meldt dan `Custom action argument "X" is not set
+properly` en dat **blokkeert élke export** met een generieke
+`Status: 400 / Error generating code for the project` — de foutmelding
+zelf noemt de oorzaak niet, dus check bij die melding altijd eerst het
+Issues-paneel. Optionele **String**-argumenten mogen wél gewoon Unset
+blijven; alleen List-types niet. Oplossing: Value → **Inline Function**
+→ expression `<String>[]`. Op de echte formulierpagina verdwijnt het
+vanzelf zodra de lijsten aan page state gebonden worden.
+
+**Doodlopend spoor, niet opnieuw proberen:** het niet-scrollende
+rechterpaneel is *niet* te omzeilen met page-zoom. `document.body.style
+.zoom='0.75'` via `javascript_tool` wérkt visueel (alles wordt kleiner),
+maar Flutter Web relayout niet — het canvas houdt zijn logische
+afmetingen, dus je ziet exact dezelfde hoeveelheid content, alleen
+kleiner. Ook `flutter-view` handmatig groter maken (`style.width/height`)
+plus een `resize`-event dispatchen verandert er niets aan. Argumenten
+één voor één inklappen werkt wel, maar het paneel accepteert **maar één
+inklap-klik per tool-aanroep** — meerdere kliks in één `browser_batch`
+laten alleen de eerste landen.
+
+---
+
 **P2-16 · Eigenaar: Bob** (klein). Tabnamen gelijktrekken met de site.
 Home: app heeft Uitgaan/Activiteiten/Cultuur/Films/Jeugd, site heeft
 Uitgaan/Stadsactiviteiten/Cultuur&Info → "Activiteiten" wordt