|
|
@@ -1,151 +1,47 @@
|
|
|
## ▶ Nu aan de beurt (stand 2026-09-13)
|
|
|
|
|
|
-### 🔧 Verbindingsmelding in de header — Eigenaar: Bob — bezig (2026-09-13)
|
|
|
-
|
|
|
-⚠️ **Observatie Claude 2026-09-13 ±20:08 (verse export van 20:02, profile-build
|
|
|
-op de telefoon-emulator): de header is volledig LEEG — geen hamburger, geen
|
|
|
-logo, online én offline.** `home_widget.dart` is byte-identiek aan de
|
|
|
-nulmeting; alleen `header_buttons_component_widget.dart` verschilt: de oude
|
|
|
-`Align > Row` zit nu in een `Column(mainAxisSize: max)` met daaronder een
|
|
|
-`SizedBox(200×40) > VerbindingsBanner`. Vermoedelijke oorzaak: in die Column
|
|
|
-krijgt de Row een **onbegrensde hoogte** (Home zet het component als
|
|
|
-`FlexibleSpaceBar.background` in een `PreferredSize(50)`-AppBar), en met het
|
|
|
-200×200-logo erin gaat dat in een profile-build stil op zwart. Geen fout in
|
|
|
-`logcat`, `dart analyze` 0 errors — het is een layout-exceptie tijdens de
|
|
|
-build. Suggestie: Column op **Main Axis Size = Min**, en de Row een vaste
|
|
|
-hoogte geven (of het logo begrenzen); daarna even op een toestel kijken.
|
|
|
-Kan ook zijn dat dit een tussenstand is die je al gezien hebt.
|
|
|
-
|
|
|
-Bob's keuze 2026-09-13: niet elke pagina aanpassen, maar **één melding in de
|
|
|
-header**, gevoed door een App State-vlag die de app zelf zet. Claude heeft de
|
|
|
-custom code geschreven en live getest op emulator-5556 (eigen profile-build,
|
|
|
-banner tijdelijk in `home_widget.dart` geprikt); **Bob voert de builder-stappen
|
|
|
-zelf uit.**
|
|
|
-
|
|
|
-📄 **De code staat in de repo: `snippets/check_verbinding.dart.txt` en
|
|
|
-`snippets/verbindings_banner.dart.txt`** (buiten `lib/`, dus een export raakt ze
|
|
|
-niet aan). Zie `snippets/LEESMIJ.md`.
|
|
|
-
|
|
|
-⚠️ **Waarom dit een Custom WIDGET is en geen Text met een Visibility-conditie.**
|
|
|
-De widgets in dit project lezen App State via de singleton `FFAppState()`, niet
|
|
|
-via `context.watch`. `main.dart` zet er wel een `ChangeNotifierProvider`
|
|
|
-omheen, maar niemand abonneert zich. Een Visibility-conditie op een App State-
|
|
|
-bool zou dus pas opnieuw evalueren als er toevallig iets ánders een rebuild
|
|
|
-veroorzaakt — de balk verschijnt dan niet of veel te laat. Het widget luistert
|
|
|
-zelf via `AnimatedBuilder(animation: FFAppState())`. Om dezelfde reden zet de
|
|
|
-action de vlag met `FFAppState().update(...)` en niet met een kale toewijzing:
|
|
|
-**alleen `update()` roept `notifyListeners()` aan** (de setters in
|
|
|
-`app_state.dart` doen dat niet).
|
|
|
-
|
|
|
-Plak alles onder de `// DO NOT REMOVE`-regel — **inclusief de eigen importregel
|
|
|
-die daar direct onder staat** (er staat een `⬇ PLAK VANAF HIER ⬇`-markering).
|
|
|
-De FlutterFlow-importkop erbóven genereert de builder zelf.
|
|
|
-
|
|
|
-⚠️ **Valkuil, 2026-09-13 aan den lijve:** zonder
|
|
|
-`import 'package:http/http.dart' as http;` slaat de Custom Code-editor de action
|
|
|
-gewoon op en meldt de builder **niets** — maar de Gradle-build faalt met
|
|
|
-`Error: Undefined name 'http'`. De editor controleert eigen imports dus niet.
|
|
|
-Het widget heeft dit probleem niet: `go_router` komt daar ook via de
|
|
|
-FlutterFlow-imports binnen (getest, compileert met én zonder).
|
|
|
-- **Custom Action `checkVerbinding`** — één HEAD-request op de site-root.
|
|
|
- Gemeten: HTTP 200, **0 bytes, 57 ms** (tegenover 34 KB / 1,3 s voor een gewone
|
|
|
- data-call), dus verwaarloosbaar. Een 401/404 telt als bereikbaar; alleen 5xx,
|
|
|
- timeouts en netwerkfouten zetten de vlag. Return Type **Boolean**, geen
|
|
|
- argumenten.
|
|
|
-- **Custom Widget `VerbindingsBanner`** — parameters `width`, `height`, `tekst`
|
|
|
- (alle drie optioneel; **leeg laten**). Het widget rendert zelf **niets**
|
|
|
- (`SizedBox.shrink`) en toont de melding via de **`ScaffoldMessenger`** over de
|
|
|
- pagina heen — daardoor kan het in de vaste-hoogte-header staan zonder iets te
|
|
|
- breken. Throttlet de automatische check op **max. 1 per 20 seconden over alle
|
|
|
- pagina's samen**, en herlaadt bij een geslaagde tik op "Opnieuw" de huidige
|
|
|
- route zodat de data alsnog binnenkomt.
|
|
|
-
|
|
|
-**Stappen in de builder:**
|
|
|
-1. App Values → App State → `+ Add App State Variable`: naam **`geenVerbinding`**,
|
|
|
- type **Boolean**, initial **false**, **Persisted uit**. Dit moet er zijn vóór
|
|
|
- stap 2, anders kan de action niet opslaan.
|
|
|
-2. Custom Code → `+` → **Action** → naam `checkVerbinding` → body plakken →
|
|
|
- Return Type Boolean → **Ctrl+S**.
|
|
|
-3. Custom Code → `+` → **Widget** → naam `VerbindingsBanner` → body plakken →
|
|
|
- de drie parameters aanmaken → **Ctrl+S**.
|
|
|
-4. `HeaderButtonsComponent` openen en het widget **als laatste kind in de
|
|
|
- bestaande `Row`** zetten (Build-tab → Elements → zoeken op
|
|
|
- `VerbindingsBanner` → naar het canvas slepen). Laat `width`, `height` én
|
|
|
- `tekst` **leeg**.
|
|
|
-5. Vier pagina's hebben géén `HeaderButtonsComponent`: `mijnProfiel`,
|
|
|
- `wachtwoordVergeten`, `stadsactiviteitAanmaken`, `uitgaansevenementAanmaken`.
|
|
|
- Op de twee **aanmaakpagina's** is de melding wel zinvol — daar het widget
|
|
|
- ergens in de bestaande layout zetten (het neemt toch geen ruimte in).
|
|
|
-6. Testen: `adb -s <device> shell svc wifi disable` + `svc data disable`, app
|
|
|
- herstarten, daarna weer `enable`.
|
|
|
-
|
|
|
-🛑 **Twee valkuilen die 2026-09-13 allebei toegeslagen hebben — lees dit vóór
|
|
|
-stap 4.**
|
|
|
-
|
|
|
-**(a) Wrap de Row NIET in een Column.** Dat was Claude's eerste instructie en hij
|
|
|
-is fout. De header zit in een `FlexibleSpaceBar.background` met een **vaste
|
|
|
-hoogte van 74 px**; `Align > Row` krijgt die 74 px netjes opgelegd. Zet je er een
|
|
|
-`Column` omheen, dan geeft die zijn kinderen **onbegrensde** hoogte op de
|
|
|
-hoofdas: de knoppen-Row neemt dan zijn natuurlijke ±200 px en je krijgt
|
|
|
-`A RenderFlex overflowed by 166 pixels`. **Erger nog, en dit meldt niets: de
|
|
|
-hamburgerknop verdwijnt dan uit de header op alle elf pagina's.** Alleen de
|
|
|
-overflow staat in de log; de verdwenen knop zie je pas op een screenshot.
|
|
|
-Omdat het widget geen ruimte inneemt, is een Column ook nergens voor nodig —
|
|
|
-gewoon in de bestaande Row.
|
|
|
-
|
|
|
-**(b) Laat FlutterFlow geen Container met vaste maten om het widget zetten.**
|
|
|
-De builder vult standaard `width: 200, height: 40` in. Die 40 px eet in een
|
|
|
-header van 74 px de ruimte van de knoppen op, en op 200 px breedte wrapt de
|
|
|
-meldingstekst naar meerdere regels. **Maak beide velden leeg.**
|
|
|
-
|
|
|
-✅ **Alle drie de paden nagemeten op de emulator met de definitieve opstelling
|
|
|
-(widget in de Row, geen Container):** offline → **0** render-fouten, hamburger
|
|
|
-gewoon zichtbaar, rode balk onderin met "Opnieuw"; netwerk terug + tik → balk
|
|
|
-weg en Home **volledig hersteld** (slider met kaarten, tabs gevuld), opnieuw 0
|
|
|
-fouten. Screenshots staan in de chat.
|
|
|
-
|
|
|
-⚠️ **Wat de banner NIET oplost:** het grijze blok op Home blijft staan, want dat
|
|
|
-blok ís de gecrashte widget (bevinding C hieronder). De banner maakt het alleen
|
|
|
-verklaarbaar in plaats van kapot. De vier crashplekken blijven dus een aparte
|
|
|
-taak.
|
|
|
-
|
|
|
-### ✅ Bevinding C · offline-crash op Home/P-Uitgaan-slider — AFGEROND 2026-09-13 (Claude, builder + live offline-test); restpunt tab 6 voor Bob
|
|
|
-
|
|
|
-**Wat er gedaan is (exportgeverifieerd, `dart analyze` 0 errors):**
|
|
|
-- Op `HomeSlider`, `UitgaanSlider` en `Horecagelegenheidoverzicht` (API Calls →
|
|
|
- Response & Test) een JSON Path **`items` = `$[:]`, Is List aan** toegevoegd →
|
|
|
- `static List? items(dynamic response)` in `api_calls.dart`.
|
|
|
-- Generate Dynamic Children van de Carousel op `HomeUitgaanSliderComponent` en
|
|
|
- `PUitgaanSliderComponent` herbonden naar **Predefined Path → items**. De
|
|
|
- export genereert nu `(XCall.items(jsonBody)?.toList() ?? []).take(12)` in
|
|
|
- plaats van `getJsonField(jsonBody, r'$').toList()` — null-veilig bij een
|
|
|
- mislukte call (`jsonBody == null`), bij een foutpagina-object én bij `[]`.
|
|
|
- Bij een fout toont de slider gewoon zijn bestaande lege-lijst-afbeelding en
|
|
|
- blijven de tabs eronder staan; Bob's verbindingsbanner erboven zegt waarom.
|
|
|
-
|
|
|
-**Terugdraaien bij calamiteit (per component één dialoog):** Carousel
|
|
|
-selecteren → Generate Dynamic Children (4e icoontje) → klik op de Value-tekst
|
|
|
-(niet het potlood) → dialoog: Available Options **"JSON Path"** → JSON Path
|
|
|
-**`$`** → tweede Available Options **"No Further Changes"** → Confirm → Save
|
|
|
-in het rechterpaneel. Dat is exact de oude binding. Nulmeting-export van vóór
|
|
|
-alle wijzigingen: `/tmp/ff-checkN0`. De drie `items`-paths mogen blijven
|
|
|
-staan; ongebruikt doen ze niets.
|
|
|
-
|
|
|
-**Live getest op de telefoon-emulator (profile-build van de verse export,
|
|
|
-`svc wifi/data disable`):** geen `NoSuchMethodError` meer in de log; de slider
|
|
|
-toont offline het logo (lege-lijst-fallback) en de tabs eronder blijven staan
|
|
|
-met hún lege-staat-logo. Online: slider met kaarten, tabs gevuld, log schoon.
|
|
|
-⚠️ Let op bij een eigen test: een `export-code` zónder `--include-assets` mist
|
|
|
-`logo800px.png`, en dan zie je alsnog een grijs blok dat níét van deze bug is
|
|
|
-(zie `CLAUDE.md`).
|
|
|
-
|
|
|
-**Nog open, voor Bob:** `horecagelegenhedenOverzichtCurrent` tab 6 (Verhuur,
|
|
|
-catering), `StaggeredView` → Generate Dynamic Children → zelfde herbinding
|
|
|
-naar **Predefined Path → items** (de path staat al op de call). Dat paneel
|
|
|
-schrijft in Claude's browser op die pagina niet weg. De zes treffers op
|
|
|
-`horecagelegenhedenOverzichtProvinciePage` en die op
|
|
|
-`SliderUitgaanComponentSmallCurrent` blijven bewust liggen: geen enkele knop
|
|
|
-navigeert daarheen / nul gebruikers.
|
|
|
+### ✅ Verbindingsmelding in de header — AF (2026-09-13, Bob + Claude)
|
|
|
+
|
|
|
+Gebouwd en live geverifieerd op de telefoon-emulator met een **verse export van
|
|
|
+de echte FlutterFlow-staat** (dus niet een nabouw). Alle drie de paden:
|
|
|
+
|
|
|
+| situatie | resultaat |
|
|
|
+|---|---|
|
|
|
+| online | geen melding, hamburger zichtbaar, **0** render-fouten |
|
|
|
+| offline | rode balk onderin met wolkje + "Opnieuw", **0** render-fouten, **0** `toList`-crashes |
|
|
|
+| netwerk terug + tik op "Opnieuw" | balk weg, Home **volledig hersteld** (slider + tabs gevuld), 0 fouten |
|
|
|
+
|
|
|
+**Hoe het in elkaar zit**, voor als het ooit aangepast moet worden:
|
|
|
+- App State **`geenVerbinding`** (Boolean, niet persisted).
|
|
|
+- Custom Action **`checkVerbinding`** — HEAD op de site-root (200, 0 bytes,
|
|
|
+ ±57 ms), zet de vlag via `FFAppState().update(...)`.
|
|
|
+- Custom Widget **`VerbindingsBanner`** — rendert zelf `SizedBox.shrink()` en
|
|
|
+ toont de melding via de `ScaffoldMessenger`. Staat als laatste kind in de
|
|
|
+ `Row` van `HeaderButtonsComponent`, in een Container van 20×20 (FlutterFlow
|
|
|
+ eist maten; in een Row kost dat alleen 20 px horizontaal en dat is
|
|
|
+ onschadelijk — **in een Column zou een hoogte wél schadelijk zijn**).
|
|
|
+- De code staat in `snippets/` en overleeft daar een export.
|
|
|
+
|
|
|
+⚠️ **Twee valkuilen die hier zijn opgetreden — relevant zodra er nóg iets aan
|
|
|
+de header toegevoegd wordt:**
|
|
|
+1. **Wrap de knoppen-Row NOOIT in een Column.** De header zit in een
|
|
|
+ `FlexibleSpaceBar.background` met een **vaste hoogte van 74 px**;
|
|
|
+ `Align > Row` krijgt die keurig opgelegd, maar een `Column` geeft zijn
|
|
|
+ kinderen **onbegrensde** hoogte — de Row neemt dan zijn natuurlijke ±200 px
|
|
|
+ en je krijgt `RenderFlex overflowed by 166 pixels`. **En stiller maar erger:
|
|
|
+ de hamburgerknop verdwijnt dan uit de header op alle elf pagina's, zonder
|
|
|
+ enige melding in de log.**
|
|
|
+2. **Eigen imports in Custom Code worden niet gecontroleerd door de editor.**
|
|
|
+ `checkVerbinding` heeft `import 'package:http/http.dart' as http;` nodig,
|
|
|
+ direct onder de `// DO NOT REMOVE`-regel. Zonder die regel slaat de editor
|
|
|
+ gewoon op en meldt niets — pas de Gradle-build faalt met
|
|
|
+ `Error: Undefined name 'http'`.
|
|
|
+
|
|
|
+📌 **Nog niet gedaan:** het widget staat alleen in `HeaderButtonsComponent`, dus
|
|
|
+niet op `mijnProfiel`, `wachtwoordVergeten`, `stadsactiviteitAanmaken` en
|
|
|
+`uitgaansevenementAanmaken`. Op de twee **aanmaakpagina's** is het wel zinvol
|
|
|
+(een formulier verzenden zonder netwerk) — daar het widget ergens in de
|
|
|
+bestaande layout zetten, het neemt toch geen ruimte in.
|
|
|
|
|
|
### 🐞 Nieuw gevonden 2026-09-13 (Claude, code-audit op verse export)
|
|
|
|
|
|
@@ -4755,7 +4651,7 @@ en `/node/217916` redirect naar
|
|
|
`/nl/Noord-Holland/Enkhuizen/Café-de-Vriendschap/2026/TEST-app-Claude-13sep-niet-echt`.
|
|
|
**Testnode 217916 mag weg (Bob).**
|
|
|
|
|
|
-⚠️ **Bevinding 1 — tijd verschuift 2 uur (Drupal-kant, Bob).** De app stuurde
|
|
|
+⚠️ **Bevinding 1 — tijd verschuift 2 uur (Drupal-kant, Bob). Kant-en-klare patch: `snippets/drupal-datum-tijdzone.md`.** De app stuurde
|
|
|
`"datum_start":"2026-09-25 20:20:00"` (lokale tijd, zie logcat), maar de views
|
|
|
én de publieke pagina tonen **22:20**. Drupal leest de string dus als UTC en
|
|
|
rendert in Europe/Amsterdam (+2 in de zomer). Fix in
|
|
|
@@ -4765,7 +4661,7 @@ DateTimeZone('Europe/Amsterdam'))` → naar UTC), of afspreken dat de app UTC
|
|
|
stuurt. Drupal-kant is netter: dan blijven oudere/andere clients ook goed.
|
|
|
Geldt vermoedelijk ook voor `stadsactiviteiten/create`.
|
|
|
|
|
|
-**Bevinding 2 — cosmetisch (builder, Claude kan dit):** het Datum-veld toont
|
|
|
+**Bevinding 2 — cosmetisch (builder) — Claude bezig 2026-09-13 ±20:45:** het Datum-veld toont
|
|
|
na kiezen de rauwe `2026-09-25 20:20:00.000`. De Text-binding van dat veld
|
|
|
door een `dateTimeFormat` halen (bv. `d MMM yyyy, HH:mm`) — alleen de weergave,
|
|
|
`datumVoorApi` blijft de bron voor het verzenden.
|