|
@@ -410,10 +410,66 @@ toont dan exact de 3 jazz-treffers van Amsterdam (nagemeten tegen
|
|
|
`flutterflowmobiel1?zoek=jazz`), terwijl het zoekveld *Zoek op titel* als
|
|
`flutterflowmobiel1?zoek=jazz`), terwijl het zoekveld *Zoek op titel* als
|
|
|
placeholder toont. De gebruiker ziet een vrijwel lege pagina zonder oorzaak.
|
|
placeholder toont. De gebruiker ziet een vrijwel lege pagina zonder oorzaak.
|
|
|
|
|
|
|
|
-Fix: *Initial Value* van het TextField binden aan App State `zoekterm` (het veld
|
|
|
|
|
-zit achter `if (FFAppState().zoekOpen)` en wordt dus pas gebouwd nadat de state
|
|
|
|
|
-gevuld is — de bekende "te laat"-valkuil speelt hier niet). Alternatief: de
|
|
|
|
|
-zoekterm wissen bij het verlaten van de pagina.
|
|
|
|
|
|
|
+#### De keten (nagelopen in een verse export, 2026-09-22)
|
|
|
|
|
+
|
|
|
|
|
+1. Tik op het vergrootglas → `FFAppState().zoekOpen = !zoekOpen`, de controller
|
|
|
|
|
+ wordt gewist, `zoekterm = ''`, dan `herlaadLijsten()`.
|
|
|
|
|
+2. Het veld verschijnt (`if (FFAppState().zoekOpen)`) en op Home én `PUitgaanPage`
|
|
|
|
|
+ verdwijnt tegelijk de slider (`if (!FFAppState().zoekOpen)`).
|
|
|
|
|
+3. Typen → `EasyDebounce` 2000 ms → `FFAppState().zoekterm = controller.text` →
|
|
|
|
|
+ `herlaadLijsten()`.
|
|
|
|
|
+4. De pagina's geven `zoekterm: FFAppState().zoekterm` door aan hun
|
|
|
|
|
+ kaartcomponenten (Home 5×, één per tab; `PUitgaanPage` 1×), en die zetten hem
|
|
|
|
|
+ in hun Backend Query als query-parameter `zoek`.
|
|
|
|
|
+
|
|
|
|
|
+Alles hierin is App State — behalve de `TextEditingController`, en díe zit in het
|
|
|
|
|
+**component-model**. Bij een paginawissel wordt dat model vers aangemaakt
|
|
|
|
|
+(`_model.textController ??= TextEditingController()`, zonder `text:`), terwijl
|
|
|
|
|
+`zoekterm` én `zoekOpen` blijven staan. Vandaar: veld open en leeg, filter actief.
|
|
|
|
|
+
|
|
|
|
|
+⚠️ Tweede symptoom van dezelfde oorzaak: omdat `zoekOpen` ook meegaat, is op de
|
|
|
|
|
+nieuwe pagina óók de **slider verborgen**. Dat maakt het beeld nog verwarrender.
|
|
|
|
|
+
|
|
|
|
|
+`zoekterm` is **niet** persisted, dus een herstart van de app lost het vanzelf op
|
|
|
|
|
+— wat verklaart waarom dit niet eerder opviel.
|
|
|
|
|
+
|
|
|
|
|
+#### Plan van aanpak — één binding, in het gedeelde component
|
|
|
|
|
+
|
|
|
|
|
+Zet op `FilterBalkComponent` → het `TextField` → **Initial Value** een binding
|
|
|
|
|
+naar App State **`zoekterm`**. Dat is alles: het component wordt door beide
|
|
|
|
|
+pagina's gedeeld, dus één wijziging dekt Home en `PUitgaanPage`.
|
|
|
|
|
+
|
|
|
|
|
+Waarom dit de juiste richting is: het ontwerp is al "de filterbalk is globaal"
|
|
|
|
|
+(`zoekOpen` reist immers ook mee). Dan hoort het veld te tónen waarop gefilterd
|
|
|
|
|
+wordt, in plaats van de filter stilletjes te verbergen.
|
|
|
|
|
+
|
|
|
|
|
+De bekende "Initial Value wordt te vroeg gelezen"-valkuil speelt hier **niet**:
|
|
|
|
|
+het veld staat achter `if (FFAppState().zoekOpen)` en bestaat dus pas nadat de
|
|
|
|
|
+gebruiker het zoeken heeft geopend — op dat moment is de App State al gevuld.
|
|
|
|
|
+
|
|
|
|
|
+Builder-stappen:
|
|
|
|
|
+1. `FilterBalkComponent` openen, het `TextField` in de tree selecteren.
|
|
|
|
|
+2. Eigenschap **Initial Value** → klik het kleine **⚏-icoontje naast het label**.
|
|
|
|
|
+ ⚠️ Níét het icoontje rechts in die rij — dat is de vertaal-globe, die vervangt
|
|
|
|
|
+ het hele rechterpaneel door "Setting Translations" (onschadelijk, klik *Back*).
|
|
|
|
|
+3. Set from Variable → zoekveld: typ **`zoek`** (levert `zoekterm`, `zoekActief`
|
|
|
|
|
+ en `zoekOpen` op — bewust een term die meer dan één bron overhoudt, anders
|
|
|
|
|
+ rendert de optielijst leeg) → App State → **`zoekterm`**. Rendert de rij leeg:
|
|
|
|
|
+ hover er eerst vanaf een andere positie naartoe, in dezelfde tool-aanroep.
|
|
|
|
|
+4. Confirm.
|
|
|
|
|
+
|
|
|
|
|
+Verwachte export:
|
|
|
|
|
+`_model.textController ??= TextEditingController(text: FFAppState().zoekterm)`.
|
|
|
|
|
+
|
|
|
|
|
+Testen op een toestel: Home → vergrootglas → zoek `jazz` → menu → Gemeente →
|
|
|
|
|
+Uitgaan. Het veld moet nu **`jazz`** tonen bij dezelfde drie treffers. Wis het
|
|
|
|
|
+veld → lijst loopt weer vol (reken op de 2 s debounce).
|
|
|
|
|
+
|
|
|
|
|
+**Alternatief als je liever hebt dat zoeken per scherm is:** zet in plaats
|
|
|
|
|
+daarvan op beide pagina's een On-Page-Load-actie die `zoekterm` én `zoekOpen`
|
|
|
|
|
+reset. Dat is meer werk (twee pagina's) en je verliest de zoekterm bij elke
|
|
|
|
|
+navigatie — maar het is verdedigbaar, want het aanbod verschilt per scherm. Kies
|
|
|
|
|
+er één; de combinatie van beide is zinloos.
|
|
|
|
|
|
|
|
### 132-C · Stadsrechten publiceren NIET direct — backend moet mee · Eigenaar: Bob (Drupal)
|
|
### 132-C · Stadsrechten publiceren NIET direct — backend moet mee · Eigenaar: Bob (Drupal)
|
|
|
|
|
|
|
@@ -469,16 +525,72 @@ De labels eten de ruimte op die de responsive `Max Lines` veronderstelt. Bij é
|
|
|
label klopt het wel. Overweeg de labels op één regel te begrenzen, of de
|
|
label klopt het wel. Overweeg de labels op één regel te begrenzen, of de
|
|
|
omschrijving één regel korter.
|
|
omschrijving één regel korter.
|
|
|
|
|
|
|
|
-### 132-G · Lege lijst op het horeca-overzicht toont alleen een groot logo
|
|
|
|
|
|
|
+### 132-G · Lege lijst toont een logo i.p.v. een melding · Eigenaar: **Claude — bezig** (onderzoek 2026-09-22 af)
|
|
|
|
|
|
|
|
-Kies je een categorie zonder treffers (in Amsterdam geldt dat voor 9 van de 13
|
|
|
|
|
-opties op de tab Activiteiten, want de dropdown toont de **hele taxonomie**, niet
|
|
|
|
|
-wat er in die plaats staat), dan verschijnt een kaal `logo800px.png`. De horeca-
|
|
|
|
|
-detailpagina doet dit al goed met `LegeLijstComponent` ("Geen evenementen
|
|
|
|
|
-gevonden…"). Hergebruik die hier — dat is de goedkoopste fix; het filteren van de
|
|
|
|
|
-dropdown op aanwezige categorieën kan niet betrouwbaar (de lijst is gepagineerd).
|
|
|
|
|
-Zelfde punt voor de **Bezorgen**-tab van een zaak zonder bezorginfo: die is nu
|
|
|
|
|
-volledig leeg.
|
|
|
|
|
|
|
+Kies je een categorie zonder treffers, dan verschijnt een kaal `logo800px.png`.
|
|
|
|
|
+`LegeLijstComponent` (Icon `event_busy` + `Text`) doet dit al goed op `mijnProfiel`.
|
|
|
|
|
+
|
|
|
|
|
+**Volledige inventaris — 18 plekken in LEVENDE code, 9 bestanden.** De dode
|
|
|
|
|
+kopieën (`kanweg/*`, `home_copy`, `home_copy2`, `p_uitgaan_page_copy{,2,3}`,
|
|
|
|
|
+`drawer_component_copy`, `mijn_profiel_copy*`, `evenement/event`) bevatten nog
|
|
|
|
|
+~15 logo's; geverifieerd wees (alleen zelfreferenties), overslaan.
|
|
|
|
|
+
|
|
|
|
|
+| Waar | Plekken | Dekt |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `HomeUitgaantabelKaartComponent` | 1 | **alle 5 Home-tabs** (één component) |
|
|
|
|
|
+| `HomeUitgaanSliderComponent` | 1 | Home-slider (Carousel) |
|
|
|
|
|
+| `PUitgaantabelKaartComponent` | 1 | PUitgaanPage-lijst |
|
|
|
|
|
+| `PUitgaanSliderComponent` | 1 | PUitgaan-slider (Carousel) |
|
|
|
|
|
+| `MijnAanmeldingen` | 1 | staat op `uitgaanskrant.com-applogo.jpg` |
|
|
|
|
|
+| `horecagelegenhedenOverzichtCurrent` | 6 | één per tab |
|
|
|
|
|
+| `HorecagelegenhedenOverzichtProvinciePage` | 6 | ⚠️ **wél bereikbaar**, `drawer_component_widget.dart:1209` |
|
|
|
|
|
+| `thuisBezorgen` | 1 | |
|
|
|
|
|
+| `HorecagelegenheidCurrent:248` | 1 | fotocarousel van een zaak — ander geval, beeld-placeholder verdedigbaar |
|
|
|
|
|
+
|
|
|
|
|
+Daarnaast: **Favorieten tab 1-3 hebben helemáál geen Empty List Widget** (zie
|
|
|
|
|
+132-H), en de agenda-tab van een zaak gebruikt een eigen component
|
|
|
|
|
+`GeenEvenementenComponentmoetweg` (Icon + vaste tekst) — functioneel al goed,
|
|
|
|
|
+opruimkandidaat.
|
|
|
|
|
+
|
|
|
|
|
+**Carousels:** op #2 en #4 staat de toggle al aan (er staat immers een Image),
|
|
|
|
|
+dus alleen *Widget Type* → Component. Reken er toch op dat dit er twee voor Bob
|
|
|
|
|
+zijn; `CLAUDE.md` meldt die checkbox als voor Claude onbereikbaar.
|
|
|
|
|
+
|
|
|
|
|
+#### i18n — onderzocht 2026-09-22, dit is de kern
|
|
|
|
|
+
|
|
|
|
|
+De `tekst`-parameter is een **letterlijke string**, dus geen globe en geen
|
|
|
|
|
+Engelse vertaling. Drie dingen uitgezocht:
|
|
|
|
|
+
|
|
|
|
|
+1. **`FFLocalizations.getVariableText({nlText, enText})` bestaat al** in
|
|
|
|
|
+ `internationalization.dart` — dat is wat FlutterFlow genereert voor een
|
|
|
|
|
+ niet-statische tekst. Nergens in gebruik.
|
|
|
|
|
+2. ⚠️ **De Global Property `locale` is in dit project ONBRUIKBAAR — altijd
|
|
|
|
|
+ `null`.** `MyApp._locale` begint op `null` en `setAppLanguage()` heeft
|
|
|
|
|
+ **nul aanroepers** (er is geen taalkiezer). De werkelijke taal komt uit de
|
|
|
|
|
+ Localizations-delegate (systeemtaal), en die is in de builder geen bron. Een
|
|
|
|
|
+ Visibility-conditie op "huidige taal" werkt hier dus niet. Niet proberen.
|
|
|
|
|
+3. Een custom **function** kan er niet bij (geen `BuildContext`); een custom
|
|
|
|
|
+ **widget** wel.
|
|
|
|
|
+
|
|
|
|
|
+**Drie werkbare routes:**
|
|
|
|
|
+
|
|
|
|
|
+- **D (aanbevolen) — losse componenten per melding.** `Duplicate Component` van
|
|
|
|
|
+ `LegeLijstComponent`, `tekst`-parameter eraf, vaste `Text` + globe. Nul
|
|
|
|
|
+ condities, per aanroepplek alleen "Empty List Widget → Component → kies".
|
|
|
|
|
+ Teksten belanden in `internationalization.dart`, dus de vertaalaudit ziet ze.
|
|
|
|
|
+ Kosten: ~10-12 componenten in de lijst.
|
|
|
|
|
+- **C — één component met een `soort`-parameter** (String) en N conditionele
|
|
|
|
|
+ `Text`-widgets, elk met eigen i18n-sleutel. Houdt de componentenlijst schoon,
|
|
|
|
|
+ maar kost 12× een Visibility-conditie met een letterlijke Second Value (het
|
|
|
|
|
+ bekende verstopte veld). Het patroon zelf is bewezen: `mijn_aanmeldingen_widget.dart:408`
|
|
|
|
|
+ heeft al `if (widget!.type == 'go_out_event')`.
|
|
|
|
|
+- **A — custom widget** met `getVariableText(nlText:, enText:)` en twee
|
|
|
|
|
+ String-parameters. Minste fragiele klikwerk, maar de teksten staan dan niet in
|
|
|
|
|
+ `internationalization.dart` (geen globe, geen audit).
|
|
|
|
|
+
|
|
|
|
|
+**Openstaand besluit voor Bob: D, C of A.** Reken op ~10-12 unieke teksten en
|
|
|
|
|
+22 aanroepplekken (18 hierboven + de 4 bestaande op `mijnProfiel` die van
|
|
|
|
|
+`tekst:` af moeten bij route D of C).
|
|
|
|
|
|
|
|
### 132-H · Favorieten is uitgelogd een leeg scherm
|
|
### 132-H · Favorieten is uitgelogd een leeg scherm
|
|
|
|
|
|
|
@@ -546,6 +658,89 @@ de gemeenten die je volgt"*) staat er altijd en is de algemene toelichting. Met
|
|
|
0 gemeenten staan er dus twee bijna gelijke regels onder elkaar — overweeg er één
|
|
0 gemeenten staan er dus twee bijna gelijke regels onder elkaar — overweeg er één
|
|
|
van te maken.
|
|
van te maken.
|
|
|
|
|
|
|
|
|
|
+### 132-L · Favoriete gemeente kiezen springt naar Home i.p.v. naar die gemeente · Eigenaar: **Claude — bezig** (onderzoek 2026-09-22 af)
|
|
|
|
|
+
|
|
|
|
|
+**Drie plekken, en één ervan doet het expliciet fout:**
|
|
|
|
|
+
|
|
|
|
|
+| # | Bestand | Nu |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| 1 | `favorieten_widget.dart:552` | `context.pushNamed(HomeWidget.routeName)` — **navigeert letterlijk naar Home** |
|
|
|
|
|
+| 2 | `select_state_drop_down_component_widget.dart:559` | tik op favoriete gemeente → `context.safePop()` |
|
|
|
|
|
+| 3 | `select_state_drop_down_component_widget.dart:458` | knop *Toepassen* → `context.safePop()` |
|
|
|
|
|
+
|
|
|
|
|
+Bij #2 en #3 kom je terug op de pagina waar je vandaan kwam — meestal Home, want
|
|
|
|
|
+de keuzepagina wordt geopend vanaf het headerlogo/de drawer. Kwam je van
|
|
|
|
|
+`PUitgaanPage`, dan sta je daar mét de **oude** `plaats`-queryparameter: de
|
|
|
|
|
+gemeente lijkt gewijzigd (de header leest `gemeenteSelectNaam` uit App State)
|
|
|
|
|
+maar de lijst niet.
|
|
|
|
|
+
|
|
|
|
|
+**Bestemming: `PUitgaanPage` met `plaats = FFAppState().gemeenteSelectId` en
|
|
|
|
|
+`services = 'services_3'`** (= *Uitgaan*, het eerste item onder "Gemeente" in de
|
|
|
|
|
+drawer; die navigeert al precies zo).
|
|
|
|
|
+
|
|
|
|
|
+✅ **Gemeten 2026-09-22: een gemeente-tid werkt gewoon als `townid`** — dat was
|
|
|
|
|
+het enige echte risico. Amsterdam gemeente `28694` geeft op `services_3` 50 items
|
|
|
|
|
+en op `services_4` 5, tegen plaats `28695` respectievelijk 50 en 2. De gemeente
|
|
|
|
|
+omvat meer plaatsen, dus dit is zelfs ruimer. Geen Drupal-werk nodig.
|
|
|
|
|
+
|
|
|
|
|
+**Aanpak per plek:** twee acties achter elkaar — eerst `safePop` (keuzepagina
|
|
|
|
|
+sluiten), dan `Navigate To PUitgaanPage`. Backstack wordt dan Home →
|
|
|
|
|
+PUitgaanPage, dus de terugknop gedraagt zich normaal. Bij #1 vervangt de
|
|
|
|
|
+Navigate gewoon de bestaande `pushNamed(Home)`.
|
|
|
|
|
+
|
|
|
|
|
+⚠️ **Bijvangst-bug op dezelfde regels:** `favorieten_widget.dart:548` vult
|
|
|
|
|
+`provincieSelectName` met `$.parent_nid` in plaats van `$.parent_titel` — dus de
|
|
|
|
|
+provincienaam is er een getal. In `select_state_drop_down_component_widget.dart:556`
|
|
|
|
|
+staat het wél goed. Meenemen bij deze taak.
|
|
|
|
|
+
|
|
|
|
|
+### 132-M · Stadseditor-overzicht toont geen ongepubliceerde activiteiten · Eigenaar: nader te bepalen
|
|
|
|
|
+
|
|
|
|
|
+**Onderzocht 2026-09-22 — het is NIET de status, het is het `komend=1`-filter.**
|
|
|
|
|
+
|
|
|
|
|
+De lijst *Eigen activiteiten* (tab Stadseditor op `mijnProfiel`, regel 1180)
|
|
|
|
|
+roept `MijnAanmeldingenCall` aan met `type: 'activity'`, `komend: '1'`, `limit: 5`.
|
|
|
|
|
+
|
|
|
|
|
+Wat er goed is:
|
|
|
|
|
+- Het endpoint `_custom_mijn_aanmeldingen()` filtert **niet** op status — er staat
|
|
|
|
|
+ zelfs expliciet in het commentaar dat status-0 juist mee moet, en het levert
|
|
|
|
|
+ `status` + `status_label` ("Wacht op goedkeuring") uit.
|
|
|
|
|
+- De app filtert ook niet: `isOngepubliceerd()` wordt alleen gebruikt voor een
|
|
|
|
|
+ snackbar bij aantikken (`mijn_profiel_widget.dart:1285`), niet voor zichtbaarheid.
|
|
|
|
|
+
|
|
|
|
|
+Wat het wél is: bij `komend=1` doet het endpoint een INNER JOIN op
|
|
|
|
|
+`field_data_field_date` met `field_date_value >= vandaag`. Gemeten voor **bobcity
|
|
|
|
|
+(uid 3621)**:
|
|
|
|
|
+
|
|
|
|
|
+| nid | status | datum | komt door het filter? |
|
|
|
|
|
+|---|---|---|---|
|
|
|
|
|
+| 222823 | 0 | 2026-09-26 | ✅ (aangemaakt vandaag 15:03 UTC) |
|
|
|
|
|
+| 222818 | 1 | 2026-09-25 | ✅ |
|
|
|
|
|
+| 222819 | 0 | 2026-09-20 | ❌ verleden |
|
|
|
|
|
+| 214445 | 0 | 2026-09-03 | ❌ verleden |
|
|
|
|
|
+
|
|
|
|
|
+Dus 2 van de 3 ongepubliceerde vallen weg op **datum**, niet op status — en de
|
|
|
|
|
+enige die er wel doorkomt bestond vanochtend nog niet. Vandaar de indruk "alleen
|
|
|
|
|
+gepubliceerde".
|
|
|
|
|
+
|
|
|
|
|
+**Dat het juist ongepubliceerde treft is geen toeval:** die liggen bij de
|
|
|
|
|
+redactie, dus hun datum kan verstrijken terwijl ze wachten — en dan verdwijnen ze
|
|
|
|
|
+stil uit het overzicht van de indiener. Dat is de echte bug.
|
|
|
|
|
+
|
|
|
|
|
+**Twee oplossingen:**
|
|
|
|
|
+- **App-kant (1 wijziging, geen Drupal):** laat `komend` leeg op déze lijst. Het
|
|
|
|
|
+ endpoint sorteert dan op `created DESC` — voor een "eigen activiteiten"-lijstje
|
|
|
|
|
+ eigenlijk logischer. Nadeel: verlopen gepubliceerde komen ook mee.
|
|
|
|
|
+- **Server-kant (aanbevolen, Eigenaar: Bob):** laat `komend=1` betekenen
|
|
|
|
|
+ "toekomstig **óf** nog niet gepubliceerd", in de `if ($komend)`-tak van
|
|
|
|
|
+ `custom.mijn_aanmeldingen.inc`:
|
|
|
|
|
+ ```php
|
|
|
|
|
+ $q->condition(db_or()
|
|
|
|
|
+ ->condition('d.field_date_value', gmdate('Y-m-d'), '>=')
|
|
|
|
|
+ ->condition('n.status', 0));
|
|
|
|
|
+ ```
|
|
|
|
|
+ Raakt ook *Mijn evenementen* (`type=go_out_event`), wat daar hetzelfde
|
|
|
|
|
+ gewenste effect heeft.
|
|
|
|
|
+
|
|
|
### 132-K · `&` in de categorie · ✅ GEFIXT OP DEVBOB, productie nog te doen
|
|
### 132-K · `&` in de categorie · ✅ GEFIXT OP DEVBOB, productie nog te doen
|
|
|
|
|
|
|
|
**Stand 2026-09-22: Bob heeft beide regels handmatig aangepast op devbob;
|
|
**Stand 2026-09-22: Bob heeft beide regels handmatig aangepast op devbob;
|