ソースを参照

132-G: besluit route A via custom function tweetalig + fasering

Custom widget bleek niet nodig: een custom function kan via
WidgetsBinding.instance.platformDispatcher.locales bij de taal, zonder
extra import (dart analyze: 0 errors in een verse exportmap). Fallback
naar nl klopt met Flutter's supportedLocales.first.

132-L teruggebracht tot de enige echte bevinding (provincieSelectName
krijgt een nid); 132-M vervallen op verzoek van Bob.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bob 14 時間 前
コミット
f0aa5d1109
1 ファイル変更69 行追加81 行削除
  1. 69 81
      TASKS.md

+ 69 - 81
TASKS.md

@@ -587,7 +587,68 @@ 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 toont een logo i.p.v. een melding · Eigenaar: **Claude — bezig** (onderzoek 2026-09-22 af)
+### 132-G · Lege lijst toont een logo i.p.v. een melding · Eigenaar: **Claude — bezig** (2026-09-23: besluit genomen, fase 1 klaar om te bouwen)
+
+#### ✅ BESLUIT 2026-09-23 (Bob): route A, maar met een custom FUNCTION — geen custom widget
+
+Het uitgangspunt "custom widget" bleek niet nodig. Een custom **function** kan wél bij
+de taal, ook zonder `BuildContext`:
+
+```dart
+String tweetalig(String nlText, String enText) {
+  final locales = WidgetsBinding.instance.platformDispatcher.locales;
+  for (final l in locales) {
+    if (l.languageCode == 'en') { return enText; }
+    if (l.languageCode == 'nl') { return nlText; }
+  }
+  return nlText;
+}
+```
+
+- **Getest, niet aangenomen:** `WidgetsBinding` komt via de `material.dart`-import die
+  FlutterFlow standaard in `custom_functions.dart` zet — `dart analyze` in een verse
+  exportmap gaf **0 errors**, geen extra import nodig (en het import-blok van een
+  custom function is toch niet bewerkbaar).
+- **De fallback klopt met Flutter zelf:** bij een niet-ondersteunde systeemtaal valt
+  Flutter terug op `supportedLocales.first`, en dat is `Locale('nl')` (nagekeken in
+  `app.dart:150` van de SDK). Vandaar `return nlText` als sluitstuk.
+- **Waarom dit beter is dan een custom widget:** de melding blijft een gewone
+  FlutterFlow-`Text`, dus alle styling blijft in de builder aanpasbaar. Bij een custom
+  widget zou die naar Dart verhuizen.
+- ⚠️ **Return-type: String met *Nullable* UIT.** Bij `String?` eist FlutterFlow een
+  "Default Variable Value", en `valueOrDefault` substitueert die óók bij een lege
+  string.
+- **Prijs:** deze teksten komen niet in `internationalization.dart`, dus geen globe en
+  geen vertaalaudit. Daar staat tegenover dat NL en EN op één regel in de export staan:
+  `grep -rn "functions.tweetalig(" lib/ --include=*.dart` toont beide talen naast
+  elkaar, wat een diff tussen twee bestanden vervangt.
+
+**Bouwen, eenmalig:**
+1. Custom function `tweetalig` (body hierboven).
+2. Nieuw component **`LegeLijstMelding`** — dupliceer `LegeLijstComponent` (Icon + Text
+   staan dan al goed), geef het twee **required** String-parameters `nlTekst` /
+   `enTekst`, en bind de Text-waarde één keer aan `tweetalig(nlTekst, enTekst)`.
+
+Het bestaande `LegeLijstComponent` blijft ongemoeid staan met zijn vier plekken op
+`mijnProfiel` — bewust gefaseerd, zodat er niets breekt en we per plek overschakelen.
+**Per gebruiksplek daarna alleen nog:** Empty List Widget → Widget Type *Component* →
+`LegeLijstMelding` → twee letterlijke strings in het parameterpaneel. Dat is het
+makkelijke klikwerk; de fragiele Set-Variable-dialoog komt maar één keer voor (stap 2).
+
+**Fasering:**
+
+| Fase | Wat | Omvang |
+|---|---|---|
+| 1 | Functie + component + **één** proefplek (`MijnAanmeldingen`) + EN-test op toestel | eenmalig |
+| 2 | De 4 evenementen-plekken (Home-tabs, Home-slider, PUitgaan-lijst, PUitgaan-slider) | 4× |
+| 3 | Horeca: overzicht Current (6) + ProvinciePage (6) + `thuisBezorgen` (1) | 13× |
+| 4 | Later: Favorieten tab 1-3 (hebben nu géén lege staat) + de 4 bestaande `mijnProfiel`-plekken omzetten | optioneel |
+
+EN-test na fase 1:
+`adb shell cmd locale set-app-locales com.uitgaanskrant.app --locales en-US` (daarna
+terug naar `nl-NL`).
+
+#### De inventaris (onderzoek 2026-09-22)
 
 
 Kies je een categorie zonder treffers, dan verschijnt een kaal `logo800px.png`.
 Kies je een categorie zonder treffers, dan verschijnt een kaal `logo800px.png`.
 `LegeLijstComponent` (Icon `event_busy` + `Text`) doet dit al goed op `mijnProfiel`.
 `LegeLijstComponent` (Icon `event_busy` + `Text`) doet dit al goed op `mijnProfiel`.
@@ -728,88 +789,15 @@ 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)
+### 132-L · `provincieSelectName` krijgt een NID i.p.v. de naam · Eigenaar: vrij
 
 
-**Drie plekken, en één ervan doet het expliciet fout:**
+`favorieten_widget.dart:548` bindt `provincieSelectName` aan `$.parent_nid` in plaats
+van `$.parent_titel`, dus in die App State staat een getal waar de provincienaam hoort.
+In `select_state_drop_down_component_widget.dart:556` staat het wél goed — vergelijk die
+twee. Eén binding omzetten.
 
 
-| # | 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.
+*(De rest van het oude 132-L en heel 132-M — gemeentekeuze springt naar Home, en het
+stadseditor-overzicht — zijn op 2026-09-23 door Bob laten vervallen.)*
 
 
 ### 132-K · `&amp;` in de categorie · ✅ GEFIXT OP DEVBOB, productie nog te doen
 ### 132-K · `&amp;` in de categorie · ✅ GEFIXT OP DEVBOB, productie nog te doen