소스 검색

P1-40: tab-indicator van rood naar merk-oranje op alle 6 live tabbalken

Home, Favorieten, horecagelegenheidCurrent, HorecagelegenhedenOverzicht,
...ProvinciePage en EvenementHorecagelegenheid staan nu op thema-secondary
(#FF680D) — geverifieerd via verse export. De resterende primary-indicators
zitten alleen nog in dode kopieën (_copy/_copy2/kanweg).

CLAUDE.md: het Component-Name-overschrijfrisico aangescherpt met het exacte
coördinaat-conflict (naamveld van een component staat waar de
properties-zoekbalk van een widget staat) plus de herstelprocedure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bob 2 주 전
부모
커밋
62bc69fa3d
2개의 변경된 파일96개의 추가작업 그리고 39개의 파일을 삭제
  1. 16 1
      CLAUDE.md
  2. 80 38
      TASKS.md

+ 16 - 1
CLAUDE.md

@@ -895,7 +895,22 @@ volgorde van proberen:
   tijd dan Bob het zelf kan doen — meld concreet (component, exacte
   stappen) en vraag het aan hem.
 
-**Component Name kan per ongeluk overschreven worden.** Vlak na
+**Component Name kan per ongeluk overschreven worden.** **Concreet
+coördinaat-risico (bevestigd 2026-08-31, Claude, 1x echt gebeurd):** bij
+een geselecteerd *widget* staat "Search properties..." op ±y=116, maar
+staat er een **component-root** geselecteerd, dan zit op vrijwel exact
+diezelfde plek het **Component Name**-veld (±y=123). Landt een
+tree-klik niet (het bekende selectie-verlies), dan typ je je
+zoekterm dus regelrecht in de componentnaam — `EvenementHorecagelegenheid`
+werd zo hernoemd naar `color`, zichtbaar aan de URL die omsloeg naar
+`?tab=widgetTree&component=color`. **Herstel is volledig en ongevaarlijk:**
+component-root in de tree selecteren → naamveld → triple-click → juiste
+naam typen → Return; een verse export laat daarna weer de originele
+bestands-, map- én klassenaam zien (FlutterFlow leidt die allemaal af
+van de componentnaam, er blijft niets achter). **Voorkomen:** vóór je in
+het rechterpaneel typt altijd eerst een `zoom` op de paneelkop
+(regio ±[970,30,1148,130]) om te bevestigen dát het gewenste widget
+geselecteerd is — de widgetnaam staat daar bovenaan. Vlak na
 paginanavigatie kan een klik bedoeld voor "Search properties..." op
 het Component Name-veld landen (focus/z-order race), en typen
 hernoemt dan stilletjes het component. Zelfde risico bij een

+ 80 - 38
TASKS.md

@@ -2120,15 +2120,6 @@ pagina bouwde. Fix per knop: Button-node selecteren → rechterpaneel
 **Fill Color** → swatch → **Theme Colors → Secondary**. Vuistregel
 blijft: rood = merk en chroom, oranje = wat je aanklikt.
 
-**P1-40 · Eigenaar: Bob (ontwerpbesluit).** De `TabBar`-
-`indicatorColor` staat op thema-`primary` (rood) op o.a.
-`home_widget.dart:257` en `horecagelegenheden_overzicht_widget.dart:268`
-(+ de twee overzicht-kopieën). Op uitgaanskrant.com is de *actieve*
-pagina/tab juist **oranje** — dus die indicator hoort waarschijnlijk
-`secondary` te worden. Niet zelf omgezet omdat het de vraag oproept of
-een tab-indicator "chroom" of "actie" is; jij beslist. Zelfde
-Fill-Color/Theme-Colors-route als P1-39.
-
 **P1-41 · Eigenaar: Bob (ontwerpbesluit).** Het **dark-mode-thema**
 staat aan én `main.dart` gebruikt `ThemeMode.system` — een gebruiker
 met een donker toestel krijgt dus het donkere thema. De merkkleuren
@@ -3079,35 +3070,54 @@ top-level aangemaakt mét een *relatief* pad (`/nl/flutterdrup/...`)
 (`${baseUrl}` wordt voorgeplakt); top-level moet de volledige
 `https://uitgaanskrant.com/...`-URL.
 
-**Restpunten om mee te beginnen in de volgende sessie:**
-1. **`DropDownPlaats` → On Selected ontbreekt nog**: moet
-   `createPlaatsID` (Page State) zetten. De andere twee dropdowns doen
-   dit al; deze is als enige nog niet gewired. Kleinste eerstvolgende
-   stap.
-2. **Rechten-shortcut bouwen**: dropdown/rij bovenaan gevuld uit
-   `MijnStadsrechten`, die bij selectie direct `createGemeenteId` zet
-   (schrijft naar dezelfde Page State-variabele, dus de Plaats-dropdown
-   pikt 'm automatisch op). Sectie verbergen als de lijst leeg is.
-3. **Categorie-multiselect** (`Categorieen`, meerdere waarden →
-   `categorieTids`) en **entree-dropdown** (`Entreeopties` →
-   `entreeTid`).
-4. **Foto-upload** koppelen: `bestandUpload` (bestaat al, werkt) voor
-   logo (`logoFid`) + max 5 slideshow-foto's (`fotosFids`).
-5. **Verzendknop**: roept `stadsactiviteitCreate` aan (custom action
-   bestaat al, 20 argumenten). Let op: de datumvelden bevatten Dart's
-   kale `DateTime.toString()` (bv. `2026-08-28 14:30:00.000`) terwijl
-   de API `YYYY-MM-DD HH:MM:SS` verwacht — de `.000` moet er nog
-   afgeknipt worden in de verzendactie.
-6. Na succes: melding **"wordt beoordeeld"**, niet "geplaatst".
-
-**Nieuwe restpunten (sessie 2026-08-31, live pair-fix):**
-7. **Verzendknop crasht bij ontbrekende plaats.** Argument #5 van
-   `stadsactiviteitCreate` genereert `_model.createPlaatsID!` (non-null
-   assertion) — indienen zonder een plaats te kiezen geeft een
-   `Null check operator used on a null value` vóórdat de custom action
-   zijn eigen nette "Ongeldige plaats"-melding kan tonen. Guard nodig:
-   knop uitschakelen/verbergen zolang `createPlaatsID` niet gezet is,
-   of een conditie vooraan de actieketen.
+**Bouwstap 3 is functioneel AF (2026-08-31, live pair-sessie).**
+Restpunten 1 t/m 7 uit de vorige sessie zijn alle zeven gebouwd en
+exportgeverifieerd (`dart analyze`: 0 errors). Kort wat er nu staat, zodat
+een volgende sessie niet opnieuw hoeft te reconstrueren:
+- `DropDownPlaats` → On Selected zet Page State `createPlaatsID`.
+- **Rechten-shortcut** `DropDownGemeentenMijngemeenten` bovenaan: staat in
+  een wrapper-`Column` die de Backend Query `MijnStadsrechten` draagt
+  (de query moest één niveau omhoog — een widget kan zijn *eigen*
+  Backend-Query-response niet gebruiken in zijn eigen Visibility-conditie,
+  wel voor Options). Options `$[:].tid` / labels `$[:].titel`, On Selected
+  zet `createGemeenteID`. Verbergen-bij-leeg via conditie
+  `$[0].titel` **Is Set** — géén "Number of Items", want een
+  JSON-Path-binding is Json-getypeerd en biedt geen lijst-transforms
+  (zelfde beperking als P1-24).
+- **Let op naamswijziging:** de Page State heet nu `createGemeenteID`
+  (hoofdletter D), niet `createGemeenteId`.
+- `DropDownCategorieen` (multi-select, → `createCategorieTids` als echte
+  `List<String>`) en `DropDownEntree` (→ `createEntreeTid`), beide
+  options `$[:].tid` / labels `$[:].naam`.
+- **Foto-upload**: knop "Logo kiezen" (→ `createLogoFid`) en "Foto's
+  kiezen" (→ `addToCreateFotosFids`), beide via het `bestandUpload`-
+  patroon uit `kanwegTestUpload`. Fotoknop verdwijnt bij 5 foto's
+  (`if (_model.createFotosFids.length < 5)`).
+- **Verzendknop** "Activiteit indienen": alle 20 argumenten van
+  `stadsactiviteitCreate` gebonden; datums lopen door de nieuwe custom
+  function **`datumVoorApi`** (knipt Dart's `.000` eraf). Knop heeft een
+  Visibility-guard op `createPlaatsID` **Is Set** (voorkomt de
+  `createPlaatsID!`-null-crash). Daarna een conditional op
+  **`$.success`** → snackbar "wordt beoordeeld" + Navigate Back, anders
+  snackbar met `$.error`.
+  ⚠️ **Valkuil vastgelegd:** een conditie op `$.nid` genereerde
+  `if (getJsonField(...))` zonder null-check — dat compileert (dynamic)
+  maar crasht bij runtime op de bool-cast. Gebruik een sleutel die
+  écht een bool is (`$.success`), of bouw een Single Condition met een
+  expliciete operator.
+
+**Nog te doen op deze pagina:**
+1. **Entry-point ontbreekt** — `stadsactiviteitAanmaken` is alleen via de
+   route bereikbaar. De "+ Voeg toe"-knoppen op `mijnProfiel` staan nog
+   op een placeholder-snackbar (bouwstap 4, restpunt 1) en moeten
+   Navigate-To hierheen worden.
+2. **Nooit end-to-end live getest** — profile-build lukte, maar de AVD
+   crashte tijdens de eerste poging (bekend SEGV-patroon). Nog te
+   bevestigen: dat een ingediende node ongepubliceerd in Drupal
+   binnenkomt met de juiste plaats/datum/categorieën/entree/logo/foto's.
+
+**Overige restpunten (sessie 2026-08-31, live pair-fix):**
+
 8. **`field_town_access` bevat nog plaats-niveau tids (Drupal-kant).**
    De omzetting naar gemeente-niveau (2026-08-27) wijzigde alleen de
    widget-instellingen, niet de al opgeslagen waarden — bevestigd via
@@ -3121,6 +3131,38 @@ top-level aangemaakt mét een *relatief* pad (`/nl/flutterdrup/...`)
    `count(taxonomy_get_parents_all($tid)) === 3` vervangen door hun
    gemeente-parent (`$parents[1]->tid`), dedupliceren, `user_save()`.
    Eerst devbob, dan productie. Script is in de sessie aan Bob gegeven.
+10. **Basis-URL centraliseren — Fase A af, Fase B open (app-breed, niet
+    alleen deze pagina; overweeg een eigen taak-ID).** Aanleiding: op
+    devbob kunnen testen zonder overal URL's te wijzigen. **Gedaan:**
+    nieuwe App State-variabele **`apiBaseUrl`** (default
+    `https://uitgaanskrant.com`), en alle vier de custom actions
+    (`stadsactiviteitCreate`, `bestandUpload`, `drupalRequest`,
+    `drupalLogin`) bouwen hun URL nu daaruit op. Ze zijn **tolerant**:
+    een argument dat met `http(s)://` begint wordt ongewijzigd gebruikt,
+    anders wordt het als pad achter `apiBaseUrl` geplakt — dus alle 26
+    bestaande aanroepen met een volledige URL blijven werken en kunnen
+    in eigen tempo ingekort worden tot een pad. 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 (16
+    plekken). Centraliseren betekent ze in de bestaande API Group
+    onderbrengen (nu `ProductieGroup`, base-URL-veld) — 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.
+
 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.