|
@@ -28,20 +28,179 @@ FlutterFlow-commit op `main`**, de commit-knop in het Version Control-paneel
|
|
|
reageerde niet op Claude's klik. `dart analyze` op de verse export: 0 errors.
|
|
reageerde niet op Claude's klik. `dart analyze` op de verse export: 0 errors.
|
|
|
Emulator-5556 heeft nu de profile-APK van die export + per-app-locale `nl-NL`.*
|
|
Emulator-5556 heeft nu de profile-APK van die export + per-app-locale `nl-NL`.*
|
|
|
|
|
|
|
|
-### 🔴 IN UITVOERING 2026-09-16 (Claude, sessie "zoekveld + look&feel") — Eigenaar: Claude — bezig
|
|
|
|
|
|
|
+### ✅ Sessie 2026-09-16 (Claude, builder + verse export per stap) — zoekveld + look&feel
|
|
|
|
|
|
|
|
-*Geclaimd om 00:0x, vóór het builder-werk begon. Bob's opdracht: "maak van het
|
|
|
|
|
-zoekveld een taak, doe dat direct; pas ook de look & feel suggesties aan; je kunt
|
|
|
|
|
-bij de browser". Raakt deze onderdelen — een andere sessie moet hier NIET
|
|
|
|
|
-tegelijk in bouwen:*
|
|
|
|
|
-
|
|
|
|
|
-- **`home` (pagina)** — zoekveld boven de tabs, chip-kleur.
|
|
|
|
|
-- **API Call `homeTabel`** — nieuwe query-variabele `zoek`.
|
|
|
|
|
-- **`HomeUitgaantabelKaartComponent`** — nieuwe parameter `zoekterm` + Backend Query.
|
|
|
|
|
-- **`HeaderButtonsComponent`** — knopvorm terugknop.
|
|
|
|
|
-- **`drawerComponent`** — ontbrekend icoon "Zoek stad" + Help-menu-item.
|
|
|
|
|
|
|
+*Opdracht Bob: "maak van het zoekveld een taak, doe dat direct; pas ook de look &
|
|
|
|
|
+feel suggesties aan; je kunt bij de browser." Alles hieronder is geverifieerd met
|
|
|
|
|
+een verse export; `dart analyze` op die export: **0 errors**.
|
|
|
|
|
+FlutterFlow-commit: Bob.*
|
|
|
|
|
|
|
|
-*Niet geraakt (bewust): de twee aanmaakpagina's (P2-29, andere sessie).*
|
|
|
|
|
|
|
+**P2-26 · Zoekveld op de Home-evenementenlijsten — ✅ AF.** De Drupal-kant stond
|
|
|
|
|
+al klaar (taak 55, `zoek=` op alle zeven `flutterflowmobiel1`-displays);
|
|
|
|
|
+nagemeten op productie met cache-buster vlak vóór het bouwen:
|
|
|
|
|
+`zoek=jazz` → 3, `zoek=qqqzzz` → 0, `zoek=` (leeg) → 50, controleparameter
|
|
|
|
|
+`onzin=jazz` → 50. Een lege waarde schakelt het filter dus netjes uit.
|
|
|
|
|
+Wat er nu staat:
|
|
|
|
|
+- API Call **`homeTabel`**: variabele `zoek` (String, default leeg) +
|
|
|
|
|
+ query-parameter `zoek` → From Variable. Export: `'zoek': zoek` in `params`.
|
|
|
|
|
+- Component **`HomeUitgaantabelKaartComponent`**: parameter `zoekterm`
|
|
|
|
|
+ (String, **niet** required → nullable, dus geen `!`-crash zoals bij het
|
|
|
|
|
+ bekende P1-15-patroon), doorgegeven in de Backend Query als
|
|
|
|
|
+ `zoek: widget!.zoekterm`.
|
|
|
|
|
+- App State **`zoekterm`** (String, niet persisted, default leeg).
|
|
|
|
|
+- **Home**: een `TextField` met hint *"Zoek op titel"*, On Change →
|
|
|
|
|
+ `Update App State zoekterm = Widget State TextField` → custom action
|
|
|
|
|
+ **`herlaadLijsten`** (dezelfde die voor P2-1 gebouwd is; die reset de
|
|
|
|
|
+ `pagingController`, een Value Key doet dat niet — zie `CLAUDE.md`).
|
|
|
|
|
+- Alle **5** component-instanties (services_3 t/m _7) krijgen
|
|
|
|
|
+ `zoekterm: FFAppState().zoekterm`. Geverifieerd: 5 treffers in de export.
|
|
|
|
|
+- Reken op ~2 s vertraging na de laatste toetsaanslag: FlutterFlow zet
|
|
|
|
|
+ automatisch een `EasyDebounce` van 2000 ms op On Change en die is niet
|
|
|
|
|
+ instelbaar. Bij server-side zoeken is dat juist prettig.
|
|
|
|
|
+
|
|
|
|
|
+**Restpunt voor Bob (1 sleepactie, 10 seconden in je eigen browser):** het
|
|
|
|
|
+zoekveld staat nu **bovenaan** de Column, dus bóven de slider. Bedoeld was:
|
|
|
|
|
+slider bovenaan, dan zoekveld, dan de chips. Twee sleeppogingen in de widget
|
|
|
|
|
+tree landden niet (bekend probleem, zie `CLAUDE.md`). Fix: sleep in de tree op
|
|
|
|
|
+`home` → `Column` de node **`Container`** (die met de slider erin) op de
|
|
|
|
|
+`Column`-rij; een drop op een container-rij voegt altijd als eerste kind in, dus
|
|
|
|
|
+daarna staat de volgorde goed. Functioneel maakt het niets uit — het zoekveld
|
|
|
|
|
+werkt waar het nu staat, en op het horeca-overzicht staat het zoekveld ook
|
|
|
|
|
+bovenaan.
|
|
|
|
|
+
|
|
|
|
|
+**Live getest op de telefoon-emulator (411 dp, profile-APK van deze export,
|
|
|
|
|
+per-app-locale `nl-NL`):** zoeken op `jazz` filtert de Uitgaan-tab meteen naar
|
|
|
|
|
+"Newport Jazz Session" en "Swingende Jazz Middag"; de tab Activiteiten filtert
|
|
|
|
|
+mee en toont terecht zijn Empty List Widget (geen jazz-activiteiten). De
|
|
|
|
|
+gemeentekeuze blijft staan, de slider blijft staan, er is geen paginaherlaad.
|
|
|
|
|
+*Let op, bestaand gedrag en geen regressie:* de Home-tabs zijn **landelijk** —
|
|
|
|
|
+`homeTabel` kent geen `townid`-parameter — dus je krijgt ook treffers uit
|
|
|
|
|
+Rotterdam en Groningen terwijl de header Amsterdam toont.
|
|
|
|
|
+
|
|
|
|
|
+**Look & feel — drie punten aangepast, alle drie export-geverifieerd en op het
|
|
|
|
|
+toestel nagekeken:**
|
|
|
|
|
+1. **De actieve datumfilter-chip was logo-rood** (`primary` #9A141D) terwijl het
|
|
|
|
|
+ merk-DNA zegt: rood = identiteit/chroom, oranje = actie, en de site rood
|
|
|
|
|
+ **nooit** als knopkleur gebruikt. Nu `secondary` (#FF680D). Export:
|
|
|
|
|
+ `selectedChipStyle: ChipStyle(backgroundColor: ...secondary`.
|
|
|
|
|
+2. **"Zoek stad" in het hoofdmenu miste zijn icoon** — het bleek niet te
|
|
|
|
|
+ ontbreken maar op `size: 1.0` te staan (alle andere menu-items hebben geen
|
|
|
|
|
+ expliciete size en krijgen dus de default 24). Nu `size: 24.0`, zelfde beeld
|
|
|
|
|
+ als de rest van het menu.
|
|
|
|
|
+3. **De twee headerknoppen hadden verschillende vormen**: hamburger
|
|
|
|
|
+ `borderRadius: 8`, terugknop `borderRadius: 30` (rond). Beide nu 8. Dat
|
|
|
|
|
+ raakt élke pagina, want `HeaderButtonsComponent` staat op 11 pagina's.
|
|
|
|
|
+
|
|
|
|
|
+**Niet gedaan, bewust (staat hieronder als taak 57):** de overige look&feel-
|
|
|
|
|
+punten uit de review van 15/16 sep — `EventCurrent` (ligt bij de andere sessie,
|
|
|
|
|
+P2-30), de twee kaartstijlen, het horeca-overzicht en de horeca-detailpagina.
|
|
|
|
|
+
|
|
|
|
|
+### 🆕 Taak 57 · Look & feel — twee punten die de review hieronder NIET dekt
|
|
|
|
|
+
|
|
|
|
|
+*De uitgebreide look&feel-review van dezelfde dag (blok "🎨 Look&feel-review
|
|
|
|
|
+2026-09-16" verderop) dekt de rest al en met meer detail: P1-51 headerkleuren,
|
|
|
|
|
+P1-52 `EventCurrent`, P2-30 horeca-overzicht, P2-31 kaartstijlen, P2-32 titels,
|
|
|
|
|
+P2-33 horeca-detail. **Werk uit die lijst, niet uit deze** — hier staan alleen
|
|
|
|
|
+de twee dingen die daar niet in voorkomen, gezien op de telefoon-emulator.*
|
|
|
|
|
+
|
|
|
|
|
+1. **Het Cultuur-icoon in het hoofdmenu springt uit de lijn** — het staat iets
|
|
|
|
|
+ lager en groter dan de zes andere icoontjes in het Gemeente-blok. Zelfde soort
|
|
|
|
|
+ oorzaak als het "Zoek stad"-icoon dat deze sessie gefixt is (dat stond op
|
|
|
|
|
+ `size: 1.0`): kijk met `grep -A3 "leading: Icon(" drawer_component_widget.dart`
|
|
|
|
|
+ welke rij een afwijkende `size:` heeft. Kleine ingreep.
|
|
|
|
|
+2. **Het menu is lang doordat het Gemeente-blok en het Provincie-blok dezelfde
|
|
|
|
|
+ zeven rijen herhalen** (Uitgaan, Activiteiten, Cultuur, Films, Jeugd, Horeca,
|
|
|
|
|
+ Thuis bezorgen). Overweeg het Provincie-blok standaard ingeklapt te tonen.
|
|
|
|
|
+ **Besluit voor Bob**, want het verandert hoe mensen navigeren.
|
|
|
|
|
+
|
|
|
|
|
+*Hangt samen met P1-50:* op `PUitgaanPage` staat een zwart **"Ad Loading…"**-blok.
|
|
|
|
|
+In een testbuild is dat de placeholder, maar zonder consent-initialisatie is dit
|
|
|
|
|
+in productie waarschijnlijk een leeg of zwart vlak. Los P1-50 op (banner weg óf
|
|
|
|
|
+consentflow aan), dan is dit punt vanzelf weg.
|
|
|
|
|
+
|
|
|
|
|
+### 🆕 Taak 58 · Performance — caching, op volgorde van winst
|
|
|
|
|
+
|
|
|
|
|
+*Uitgezocht 2026-09-16 (Claude, code + productiemetingen). De volgorde is
|
|
|
|
|
+opbrengst gedeeld door moeite; 1 en 2 zijn de moeite waard, 3 is klein, 4 niet
|
|
|
|
|
+vóór livegang.*
|
|
|
|
|
+
|
|
|
|
|
+**Eerst het antwoord op Bob's vraag "moet ik caching invullen in de views?" —
|
|
|
|
|
+nee, laat Views-caching op "None".** Views-cache zit **áchter** Drupal's page
|
|
|
|
|
+cache. Vrijwel elk verzoek van de app is anoniem, dus de page cache antwoordt al
|
|
|
|
|
+vóórdat Views aan de beurt komt; sinds taak 54 zit Cloudflare er nog eens vóór
|
|
|
|
|
+met 5 minuten edge-cache. Alleen ingelogde verzoeken passeren de page cache, en
|
|
|
|
|
+dat zijn hier vier kleine calls (`entreeopties`, `categorieen`,
|
|
|
|
|
+`mijn_horecagelegenheden`, `mijn_stadsrechten`). Op `flutterflowmobiel_establishments`
|
|
|
|
|
+is een time-based Views-cache zelfs **riskant**, want die view wordt in
|
|
|
|
|
+`custom_views_query_alter()` per gebruiker op favorieten gefilterd. Meetbewijs
|
|
|
|
|
+uit de sessie van 15 sep: dezelfde URL drie keer achter elkaar gaf 1,23 s (MISS)
|
|
|
|
|
+→ 0,10 s (HIT) → 0,11 s (HIT). Drupal's page cache doet dus 12× zoveel als alle
|
|
|
|
|
+micro-optimalisaties samen.
|
|
|
|
|
+
|
|
|
|
|
+1. **`flutterflowmobiel_establishments.json` alsnog in de Cloudflare-rule
|
|
|
|
|
+ "FlutterFlow publieke endpoints".** Grootste winst die er nog ligt. Dit is
|
|
|
|
|
+ het zwaarste endpoint (100 items per pagina, 1,3–1,8 s gemeten) en het
|
|
|
|
|
+ horeca-overzicht laadt er **zes** van, één per tab. Met de bestaande
|
|
|
|
|
+ rule-voorwaarde *"GET zonder `SESS`-cookie"* is het veilig: de app stuurt op
|
|
|
|
|
+ `HorecagelegenheidoverzichtCall` **geen** sessiecookie mee (`headers: {}` in
|
|
|
|
|
+ de export), en de favorietenfilter in `custom_views_query_alter()` grijpt
|
|
|
|
|
+ alleen bij een ingelogd verzoek. Verwachte winst: ~1,5 s → ~0,1 s per tab.
|
|
|
|
|
+ ⚠️ Zet dit endpoint **nooit** in de rule zonder die cookie-voorwaarde.
|
|
|
|
|
+2. **`cache: true` op meer API Calls.** Nu staat de vlag op 5 van de 18:
|
|
|
|
|
+ `homeTabel`, `EstablishmentInfo`, `Gemeenten`, `Provincies`,
|
|
|
|
|
+ `Horecagelegenheidoverzicht`. Ontbreekt op user-onafhankelijke reads die
|
|
|
|
|
+ binnen één sessie vaak herhaald worden: **`homeSlider`**, **`Uitgaanstabel`**,
|
|
|
|
|
+ **`UitgaanSlider`**, **`Evenement`** (evenement-detail),
|
|
|
|
|
+ **`HorecagelegenheidEvents`**, **`PlaatsenBijGemeente`**, **`Categorieen`**,
|
|
|
|
|
+ **`Entreeopties`**. Levert winst bij terugnavigeren binnen een sessie.
|
|
|
|
|
+ *De cache is veilig* — `ApiCallOptions extends Equatable` met `params` en
|
|
|
|
|
+ `headers` in `props`, dus hij vergelijkt op echte parameterwaarden.
|
|
|
|
|
+ *Kanttekening:* FlutterFlow's cache verloopt nooit binnen een sessie, dus
|
|
|
|
|
+ voor de **sliders** betekent dit dat een gebruiker die de app uren open laat
|
|
|
|
|
+ staan oude slider-inhoud houdt. Voor `Evenement` en `Entreeopties` is dat
|
|
|
|
|
+ geen bezwaar.
|
|
|
|
|
+3. **Langere edge-TTL voor taxonomie.** `plaatsen.json` en
|
|
|
|
|
+ `plaatsen_bij_gemeente.json` veranderen zelden — 30 tot 60 minuten in plaats
|
|
|
|
|
+ van 5. Puur een getal in de bestaande Cloudflare-rule.
|
|
|
|
|
+4. **Lokaal persistent cachen** (Home meteen tonen uit een opgeslagen snapshot,
|
|
|
|
|
+ ook offline). Een custom action van gemiddelde omvang die slecht past op
|
|
|
|
|
+ FlutterFlow's FutureBuilder-patroon, en met Cloudflare op 0,1 s is de winst
|
|
|
|
|
+ klein. **Niet vóór livegang.**
|
|
|
|
|
+
|
|
|
|
|
+### 🆕 Taak 59 · Helppagina — antwoord op Bob's vraag, plus hoe te bouwen
|
|
|
|
|
+
|
|
|
|
|
+**Bob's vraag: "kan ik een helppagina maken waarin URL's van de website zelf
|
|
|
|
|
+getoond worden, zodat ik teksten niet 2× hoef bij te houden?" — Ja, en dat is
|
|
|
|
|
+ook het advies.** Gemeten 2026-09-16: de site heeft er nu nog niets voor staan.
|
|
|
|
|
+`uitgaanskrant.com/nl/help`, `/faq`, `/veelgestelde-vragen`, `/over-ons`,
|
|
|
|
|
+`/contact`, `/uitleg`, `/hoe-werkt-het` en `/privacy` geven alle **404**;
|
|
|
|
|
+`/account-verwijderen` bestaat wél maar geeft anoniem een **403**.
|
|
|
|
|
+
|
|
|
|
|
+**Aanpak, twee delen:**
|
|
|
|
|
+1. **Bob, in Drupal:** maak één node, bijvoorbeeld `/nl/app-help`, met de
|
|
|
|
|
+ inhoud. Wat er in elk geval in hoort: wat Uitgaanskrant is · gemeente kiezen
|
|
|
|
|
+ en volgen · inloggen en favorieten · een evenement of stadsactiviteit
|
|
|
|
|
+ aanmaken (voor horeca en city-editors) · contact · privacy · account
|
|
|
|
|
+ verwijderen. Eén node bijwerken = de app is meteen bij, géén nieuwe release.
|
|
|
|
|
+2. **Claude, in de builder (kleine taak):** menu-item **"Help"** onderaan
|
|
|
|
|
+ `drawerComponent` (dupliceer een bestaand `ListTile`, zie `CLAUDE.md` — dat
|
|
|
|
|
+ is betrouwbaarder dan Insert Widget) met On Tap → **Launch URL** naar die
|
|
|
|
|
+ node. Launch URL staat in de Actions-zoeklijst onder categorie *Share*, niet
|
|
|
|
|
+ onder Navigation.
|
|
|
|
|
+
|
|
|
|
|
+**Keuze die Bob daarbij maakt: extern openen of in de app?**
|
|
|
|
|
+- **Launch URL** (externe browser) is één actie, nul onderhoud, en de gebruiker
|
|
|
|
|
+ ziet de vertrouwde site. Nadeel: hij verlaat de app.
|
|
|
|
|
+- **Een WebView-pagina in de app** houdt hem binnen de app en kan de standaard
|
|
|
|
|
+ header + terugknop krijgen, maar toont de volledige sitehuisstijl inclusief
|
|
|
|
|
+ menu en cookiebanner, tenzij je in Drupal een kale weergave maakt.
|
|
|
|
|
+- **Advies: begin met Launch URL.** Dat kost tien minuten en is altijd nog om
|
|
|
|
|
+ te bouwen naar een WebView.
|
|
|
|
|
+
|
|
|
|
|
+⚠️ **Los hiervan, en het blokkeert de store-review:** `/nl/account-verwijderen`
|
|
|
|
|
+geeft anoniem een 403. Google's reviewers openen die URL **zonder in te loggen**.
|
|
|
|
|
+Daar moet minimaal een publiek zichtbare uitleg staan van hoe je je account laat
|
|
|
|
|
+verwijderen. Dit hoort bij Bob's taak 2 (Play Console).
|
|
|
|
|
|
|
|
### 🟢 AFGEROND 2026-09-16 (Claude, sessie "taal-cluster") — browserloos, geen builder aangeraakt
|
|
### 🟢 AFGEROND 2026-09-16 (Claude, sessie "taal-cluster") — browserloos, geen builder aangeraakt
|
|
|
|
|
|
|
@@ -695,8 +854,10 @@ tonen; alternatief is default "Amsterdam", te wisselen in dezelfde binding).
|
|
|
Verifiëren op telefoonformaat (393 dp): hamburger + terugknop + logo + naam
|
|
Verifiëren op telefoonformaat (393 dp): hamburger + terugknop + logo + naam
|
|
|
moeten op één regel passen, ook bij "'s-Hertogenbosch".
|
|
moeten op één regel passen, ook bij "'s-Hertogenbosch".
|
|
|
|
|
|
|
|
-**P2-26 · Zoekveld op de evenementenlijsten · ⚠️ HERZIEN 2026-09-15 (Claude,
|
|
|
|
|
-gemeten) — het horeca-patroon kan hier NIET, dit begint bij jou in Drupal.**
|
|
|
|
|
|
|
+**P2-26 · Zoekveld op de evenementenlijsten · ✅ AFGEROND 2026-09-16 (Drupal:
|
|
|
|
|
+Bob, taak 55; app-kant: Claude) — zie de sessienotitie bovenaan dit bestand.**
|
|
|
|
|
+
|
|
|
|
|
+*Historie, ter referentie (de analyse die tot de gekozen aanpak leidde):*
|
|
|
De aanname "zelfde patroon als horeca" gaat niet op. Horeca laadt zijn hele
|
|
De aanname "zelfde patroon als horeca" gaat niet op. Horeca laadt zijn hele
|
|
|
lijst in `_model.alleX` en filtert client-side; de Home-tabs draaien op een
|
|
lijst in `_model.alleX` en filtert client-side; de Home-tabs draaien op een
|
|
|
`PagedMasonryGridView` met een `pagingController` (server-side paginering, 25
|
|
`PagedMasonryGridView` met een `pagingController` (server-side paginering, 25
|