Ver Fonte

Favorieten: header/drawer + scrollbare tabs + sessie-fix Tab 3; P1-6 laatste restpunt (PUitgaanSliderKaartComponent datumfallback)

- favorieten_widget.dart: Scaffold kreeg Drawer- en AppBar-slot
  (drawerComponent / HeaderButtonsComponent, showBackButton: false,
  automaticallyImplyLeading: false om dubbele hamburger te voorkomen)
- TabBar isScrollable: true zodat alle 4 tab-labels volledig tonen
  i.p.v. af te kappen
- Tab 2-tekst kreeg 16px links/rechts padding (liep tot schermrand)
- Tab 3 (FavorietenAgendaCall) kreeg sessionName/sessionId gebonden
  aan FFAppState, i.p.v. altijd anoniem aan te roepen
- p_uitgaan_slider_kaart_component_widget.dart: Visibility-guard op
  de rauwe datum-parameter, 'def'-placeholder niet meer bereikbaar

Alles bevestigd via verse export + flutter analyze (0 nieuwe treffers),
header/drawer + tabs + Tab2-padding ook live geverifieerd op
emulator-5554.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
bob há 3 semanas atrás
pai
commit
f453157c90

+ 44 - 0
CLAUDE.md

@@ -403,6 +403,50 @@ dat al bevestigd werkt.
 
 ## FlutterFlow-builder: bekende problemen & patronen
 
+**Een pagina die nog geen `Drawer`/`AppBar` heeft alsnog toevoegen
+(bv. een pagina zonder header/hamburger-menu): via slepen, niet via
+rechtsklik.** Gevonden 2026-08-19 (Favorieten-pagina miste een
+header/drawer volledig). Stappen:
+1. Selecteer de root **Scaffold**-node in de Widget Tree → klik het
+   kleine **"+"-icoontje naast de node-naam** (niet rechtsklik →
+   Insert Widget, dat menu heeft geen Drawer/AppBar-optie op dit
+   niveau) → zoek "Drawer" (of "App Bar") → kies de kaart. Dit voegt
+   een lege `Drawer`/`AppBar`-slot toe als eigen tree-node, sibling van
+   `body`.
+2. Om die slot te **vullen met een custom Project Component** (bv.
+   `drawerComponent`, `HeaderButtonsComponent`): rechtsklik/Insert
+   Widget op de nieuwe Drawer/AppBar-node werkt **niet** (geen
+   "Insert Widget"-optie in het contextmenu, en de node zelf toont geen
+   "+"-icoontje in de tree). **Werkende route:** open het linker
+   widget-paneel (Build-tab, 1e icoon) → **2e icoon in dat paneel se­
+   lecteert "Project Components"** → zoek de component op naam →
+   **sleep de kaart direct naar de juiste canvas-dropzone** (bij een
+   AppBar toont de canvas tijdens het slepen zelf de "Leading"/
+   "Title"/"Actions"-zones; bij een Drawer volstaat een sleep ergens
+   op het lege-Drawer-canvas). Voor een kale generieke widget (bv.
+   "Text") werkt exact dezelfde sleep-techniek vanuit het gewone
+   Elements-paneel (1e icoon in dat linkerpaneel).
+3. Een component met een verplichte parameter (bv. `HeaderButtonsComponent`'s
+   `showBackButton`) krijgt na het slepen gewoon een normaal
+   Component Parameters-blok in het rechterpaneel — zet die zoals
+   altijd (zie ook P1-20's `showBackButton`-precedent verderop in dit
+   bestand: `false` voor een drawer-nav-bestemming zoals Home, niet
+   voor een subpagina).
+4. **Let op dubbele hamburger-knop:** als de nieuwe `AppBar` een
+   `HeaderButtonsComponent` als title krijgt (die zelf al een eigen
+   `Scaffold.of(context).openDrawer()`-knop bevat) én er inmiddels ook
+   een `Drawer` op de Scaffold staat, zet FlutterFlow **automatisch**
+   `automaticallyImplyLeading: true` — dat genereert een **2e**,
+   overbodige hamburger-knop naast de component's eigen knop. Fix:
+   AppBar-node selecteren → Visibility-sectie → **"Show Default
+   Button" uit** (genereert `automaticallyImplyLeading: false`, exact
+   het patroon dat de bestaande pagina's al gebruiken).
+5. Tab-labels die afkappen op een `TabBar` met veel/lange tabs: geen
+   losse widget-wrap nodig — de `TabBar`-node zelf heeft een
+   **"Tab Bar Scrollable"**-toggle (Search properties → "scroll").
+   Zet aan: labels tonen voortaan volledig uitgeschreven en de balk
+   scrollt horizontaal i.p.v. tekst af te kappen.
+
 **Widget Tree-nesting nooit uit een codefragment afleiden — altijd de
 tree/screenshot als bron van waarheid gebruiken.** Bevestigde misser
 (2026-08-11, `HorecagelegenheidoverzichtKaartWidget`): op basis van een

+ 39 - 21
TASKS.md

@@ -1,20 +1,27 @@
 # Uitgaanskrant — takenlijst
 
 **Deze sessie (2026-08-19, Bob aanwezig achter zijn scherm, gedeelde
-Chrome-browserautomatisering):** drie kleine, mechanische fixes
-afgerond, elk bevestigd via verse export + gerichte `flutter
-analyze`. Twee op de Favorieten-pagina (zie P1-7 hieronder voor
-details): (1) Tab 3 "Favoriete Gelegenheden" riep zijn API-call altijd
-anoniem aan (`sessionName`/`sessionId` nu gebonden aan `FFAppState().
-userSessionname`/`userSessionid`), (2) Tab 2's beschrijvingstekst liep
-tot de schermrand (nu 16px links/rechts padding). Daarna (3) het
+Chrome-browserautomatisering):** vijf fixes afgerond, elk bevestigd via
+verse export + gerichte `flutter analyze` (en de laatste twee ook
+live op emulator-5554). Op de Favorieten-pagina (zie P1-7 hieronder
+voor details): (1) Tab 3 "Favoriete Gelegenheden" riep zijn API-call
+altijd anoniem aan (`sessionName`/`sessionId` nu gebonden aan
+`FFAppState().userSessionname`/`userSessionid`), (2) Tab 2's
+beschrijvingstekst liep tot de schermrand (nu 16px links/rechts
+padding), (3) de hele pagina miste een header/drawer (nu Scaffold
+Drawer- + AppBar-slot, zelfde patroon als andere pagina's), (4) alle 4
+tab-labels waren afgekapt (nu "Tab Bar Scrollable" aan). Daarna (5) het
 laatste P1-6-restpunt op `PUitgaanSliderKaartComponent` (`'def'`-
 datumfallback) opgelost met een Visibility-guard op de rauwe `datum`-
-component-parameter. **P2-7's orphan-mappen-`git rm`** (5 bevestigde
-dode mappen) is opnieuw geprobeerd (met Bob's expliciete toestemming
-in de chat) maar blijft geblokkeerd door de permissie-classifier zelf
-(systeemniveau, niet te overrulen via chat-toestemming) — commando
-staat nog steeds klaar in de P2-7-sectie voor Bob om zelf te draaien.
+component-parameter. **Nieuwe bouwtechniek ontdekt** (zie `CLAUDE.md`):
+een Scaffold's Drawer/AppBar-slot vullen met een custom component lukt
+niet via de gewone rechtsklik-Insert-Widget-flow — wel via **slepen
+vanuit het linker widget-paneel direct naar de canvas-dropzone**.
+**P2-7's orphan-mappen-`git rm`** (5 bevestigde dode mappen) is opnieuw
+geprobeerd (met Bob's expliciete toestemming in de chat) maar blijft
+geblokkeerd door de permissie-classifier zelf (systeemniveau, niet te
+overrulen via chat-toestemming) — commando staat nog steeds klaar in de
+P2-7-sectie voor Bob om zelf te draaien.
 
 ---
 
@@ -1135,15 +1142,26 @@ Nu 16px links/rechts padding, bevestigd via verse export
 2026-08-14-herbouw (ListView + Generate Dynamic Children) geen eigen
 beschrijvingsregel meer — de "vergelijkbare tekst op Tab 3" bestond
 niet meer, dat deel van de melding was stale.)*
-- **Nieuw gevonden, structureel (2026-08-17 avond): de hele
-  Favorieten-pagina mist een header/drawer.** Geen "☰"-menu, geen
-  terugknop — de pagina begint direct bij de `TabBar`, enige uitweg is
-  Android's systeem-terugknop. Bovendien zijn alle 4 tab-labels
-  afgekapt op telefoonformaat ("Persoon…", "Favoriete…" x2,
-  "Gebruike…") — de `TabBar` is te smal voor 4 volledige labels.
-  Vraagt een structurele aanpassing (Scaffold met AppBar/Drawer zoals
-  andere pagina's, of kortere tab-labels/kleiner lettertype), geen
-  quick fix.
+*(Structureel gat + tab-label-afkapping afgerond 2026-08-19 — Claude,
+builder + live geverifieerd op emulator-5554. Favorieten had geen
+header/drawer (geen "☰"-menu, geen terugweg behalve Android's
+systeem-terugknop) en alle 4 tab-labels waren afgekapt op
+telefoonformaat. Fix: Scaffold-node in de widget tree kreeg een
+**Drawer**-slot (`drawerComponent`, zelfde als andere pagina's) en een
+**AppBar**-slot (`HeaderButtonsComponentWidget(showBackButton: false)`
+in een `FlexibleSpaceBar`-title, achtergrondkleur "Info", hoogte 80px,
+"Show Default Button" uit om een dubbele hamburger te voorkomen —
+identiek patroon aan `PUitgaanPage`). Widgets zoals `Drawer`/`AppBar`
+zijn zelf niet via de gewone rechtsklik-Insert-Widget-flow te vullen;
+werkende route: **slepen vanuit het linker widget-paneel direct naar de
+canvas-dropzone** (de AppBar/Drawer canvas toont bij een sleep-actie
+zelf de "Leading"/"Title"/"Actions"-zones) — zie ook de nieuwe
+`CLAUDE.md`-notitie. Tab-label-afkapping: `TabBar` kreeg **"Tab Bar
+Scrollable"** aan (Search properties → "scroll") — labels tonen nu
+volledig uitgeschreven en scrollen horizontaal i.p.v. af te kappen.
+Bevestigd via verse export + `flutter analyze` (0 nieuwe treffers) én
+live: drawer opent via het hamburger-icoon, geen dubbele knop, alle 4
+tabs met volledig label bereikbaar. Uit deze lijst verwijderd.)*
 - **Nieuw gevonden, UX-gat (2026-08-17 avond): nergens in de app is
   zichtbaar dát je bent ingelogd**, behalve als je zelf naar
   Favorieten-tab 4 navigeert. De drawer's "Mijn Account"-item opent

+ 4 - 4
ios/Runner.xcodeproj/project.pbxproj

@@ -44,8 +44,8 @@
 		97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
 		97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
 		97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
-		6436409C27A31CD400820AF7 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
-		6436409227A31CD100820AF7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		6436409E27A31CD700820AF7 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		6436409027A31CD400820AF7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -225,8 +225,8 @@
 		6436409C27A31CD800820AF7 /* InfoPlist.strings */ = {
 			isa = PBXVariantGroup;
 			children = (
-				6436409C27A31CD400820AF7 /* nl */,
-				6436409227A31CD100820AF7 /* en */,
+				6436409E27A31CD700820AF7 /* nl */,
+				6436409027A31CD400820AF7 /* en */,
 			);
 			name = InfoPlist.strings;
 			sourceTree = "<group>";

+ 16 - 0
lib/favorieten/favorieten_model.dart

@@ -1,7 +1,9 @@
 import '/backend/api_requests/api_calls.dart';
+import '/components/header_buttons_component_widget.dart';
 import '/flutter_flow/flutter_flow_theme.dart';
 import '/flutter_flow/flutter_flow_util.dart';
 import '/flutter_flow/flutter_flow_widgets.dart';
+import '/shared/drawer_component/drawer_component_widget.dart';
 import '/uitgaanspaginas/uitgaantabel_kaart/uitgaantabel_kaart_widget.dart';
 import 'dart:ui';
 import '/custom_code/actions/index.dart' as actions;
@@ -68,18 +70,28 @@ class FavorietenModel extends FlutterFlowModel<FavorietenWidget> {
 
   // Models for UitgaantabelKaart dynamic component.
   Map<String, FlutterFlowModel> uitgaantabelKaartModels = {};
+  // Model for drawerComponent component.
+  late DrawerComponentModel drawerComponentModel;
+  // Model for HeaderButtonsComponent component.
+  late HeaderButtonsComponentModel headerButtonsComponentModel;
 
   final Map<String, DebugDataField> debugGeneratorVariables = {};
   final Map<String, DebugDataField> debugBackendQueries = {};
   final Map<String, FlutterFlowModel> widgetBuilderComponents = {};
   @override
   void initState(BuildContext context) {
+    drawerComponentModel = createModel(context, () => DrawerComponentModel());
+    headerButtonsComponentModel =
+        createModel(context, () => HeaderButtonsComponentModel());
+
     debugLogWidgetClass(this);
   }
 
   @override
   void dispose() {
     tabBarController?.dispose();
+    drawerComponentModel.dispose();
+    headerButtonsComponentModel.dispose();
   }
 
   @override
@@ -136,6 +148,10 @@ class FavorietenModel extends FlutterFlowModel<FavorietenWidget> {
         generatorVariables: debugGeneratorVariables.entries,
         backendQueries: debugBackendQueries.entries,
         componentStates: {
+          'drawerComponentModel (drawerComponent)':
+              drawerComponentModel?.toWidgetClassDebugData(),
+          'headerButtonsComponentModel (HeaderButtonsComponent)':
+              headerButtonsComponentModel?.toWidgetClassDebugData(),
           ...widgetBuilderComponents.map(
             (key, value) => MapEntry(
               key,

+ 68 - 17
lib/favorieten/favorieten_widget.dart

@@ -1,7 +1,9 @@
 import '/backend/api_requests/api_calls.dart';
+import '/components/header_buttons_component_widget.dart';
 import '/flutter_flow/flutter_flow_theme.dart';
 import '/flutter_flow/flutter_flow_util.dart';
 import '/flutter_flow/flutter_flow_widgets.dart';
+import '/shared/drawer_component/drawer_component_widget.dart';
 import '/uitgaanspaginas/uitgaantabel_kaart/uitgaantabel_kaart_widget.dart';
 import 'dart:ui';
 import '/custom_code/actions/index.dart' as actions;
@@ -129,6 +131,44 @@ class _FavorietenWidgetState extends State<FavorietenWidget>
       child: Scaffold(
         key: scaffoldKey,
         backgroundColor: FlutterFlowTheme.of(context).primaryBackground,
+        drawer: Drawer(
+          elevation: 16.0,
+          child: wrapWithModel(
+            model: _model.drawerComponentModel,
+            updateCallback: () => safeSetState(() {}),
+            child: Builder(builder: (_) {
+              return DebugFlutterFlowModelContext(
+                rootModel: _model.rootModel,
+                child: DrawerComponentWidget(),
+              );
+            }),
+          ),
+        ),
+        appBar: PreferredSize(
+          preferredSize: Size.fromHeight(80.0),
+          child: AppBar(
+            backgroundColor: FlutterFlowTheme.of(context).info,
+            automaticallyImplyLeading: false,
+            actions: [],
+            flexibleSpace: FlexibleSpaceBar(
+              title: wrapWithModel(
+                model: _model.headerButtonsComponentModel,
+                updateCallback: () => safeSetState(() {}),
+                child: Builder(builder: (_) {
+                  return DebugFlutterFlowModelContext(
+                    rootModel: _model.rootModel,
+                    child: HeaderButtonsComponentWidget(
+                      showBackButton: false,
+                    ),
+                  );
+                }),
+              ),
+              centerTitle: true,
+              expandedTitleScale: 1.0,
+            ),
+            elevation: 0.0,
+          ),
+        ),
         body: SafeArea(
           top: true,
           child: Column(
@@ -140,6 +180,8 @@ class _FavorietenWidgetState extends State<FavorietenWidget>
                     Align(
                       alignment: Alignment(0.0, 0),
                       child: TabBar(
+                        isScrollable: true,
+                        tabAlignment: TabAlignment.center,
                         labelColor: FlutterFlowTheme.of(context).primaryText,
                         unselectedLabelColor:
                             FlutterFlowTheme.of(context).secondaryText,
@@ -329,14 +371,27 @@ class _FavorietenWidgetState extends State<FavorietenWidget>
                           Column(
                             mainAxisSize: MainAxisSize.max,
                             children: [
-                              Text(
-                                FFLocalizations.of(context).getText(
-                                  'o7pt2vls' /* De gemeentes die je hebt gemar... */,
-                                ),
-                                style: FlutterFlowTheme.of(context)
-                                    .bodyMedium
-                                    .override(
-                                      font: GoogleFonts.inter(
+                              Padding(
+                                padding: EdgeInsetsDirectional.fromSTEB(
+                                    16.0, 0.0, 16.0, 0.0),
+                                child: Text(
+                                  FFLocalizations.of(context).getText(
+                                    'o7pt2vls' /* De gemeentes die je hebt gemar... */,
+                                  ),
+                                  style: FlutterFlowTheme.of(context)
+                                      .bodyMedium
+                                      .override(
+                                        font: GoogleFonts.inter(
+                                          fontWeight:
+                                              FlutterFlowTheme.of(context)
+                                                  .bodyMedium
+                                                  .fontWeight,
+                                          fontStyle:
+                                              FlutterFlowTheme.of(context)
+                                                  .bodyMedium
+                                                  .fontStyle,
+                                        ),
+                                        letterSpacing: 0.0,
                                         fontWeight: FlutterFlowTheme.of(context)
                                             .bodyMedium
                                             .fontWeight,
@@ -344,14 +399,7 @@ class _FavorietenWidgetState extends State<FavorietenWidget>
                                             .bodyMedium
                                             .fontStyle,
                                       ),
-                                      letterSpacing: 0.0,
-                                      fontWeight: FlutterFlowTheme.of(context)
-                                          .bodyMedium
-                                          .fontWeight,
-                                      fontStyle: FlutterFlowTheme.of(context)
-                                          .bodyMedium
-                                          .fontStyle,
-                                    ),
+                                ),
                               ),
                             ],
                           ),
@@ -359,7 +407,10 @@ class _FavorietenWidgetState extends State<FavorietenWidget>
                             mainAxisSize: MainAxisSize.max,
                             children: [
                               FutureBuilder<ApiCallResponse>(
-                                future: FavorietenAgendaCall.call(),
+                                future: FavorietenAgendaCall.call(
+                                  sessionName: FFAppState().userSessionname,
+                                  sessionId: FFAppState().userSessionid,
+                                ),
                                 builder: (context, snapshot) {
                                   // Customize what your widget looks like when it's loading.
                                   if (!snapshot.hasData) {

+ 20 - 19
lib/uitgaanspaginas/p_uitgaan_slider_kaart_component/p_uitgaan_slider_kaart_component_widget.dart

@@ -277,16 +277,25 @@ class _PUitgaanSliderKaartComponentWidgetState
                           color: FlutterFlowTheme.of(context).primaryText,
                           size: 18.0,
                         ),
-                        Flexible(
-                          child: Text(
-                            valueOrDefault<String>(
-                              functions.kortDatum(widget!.datum),
-                              'def',
-                            ),
-                            style: FlutterFlowTheme.of(context)
-                                .bodyMedium
-                                .override(
-                                  font: GoogleFonts.inter(
+                        if (widget!.datum != null && widget!.datum != '')
+                          Flexible(
+                            child: Text(
+                              valueOrDefault<String>(
+                                functions.kortDatum(widget!.datum),
+                                'def',
+                              ),
+                              style: FlutterFlowTheme.of(context)
+                                  .bodyMedium
+                                  .override(
+                                    font: GoogleFonts.inter(
+                                      fontWeight: FlutterFlowTheme.of(context)
+                                          .bodyMedium
+                                          .fontWeight,
+                                      fontStyle: FlutterFlowTheme.of(context)
+                                          .bodyMedium
+                                          .fontStyle,
+                                    ),
+                                    letterSpacing: 0.0,
                                     fontWeight: FlutterFlowTheme.of(context)
                                         .bodyMedium
                                         .fontWeight,
@@ -294,16 +303,8 @@ class _PUitgaanSliderKaartComponentWidgetState
                                         .bodyMedium
                                         .fontStyle,
                                   ),
-                                  letterSpacing: 0.0,
-                                  fontWeight: FlutterFlowTheme.of(context)
-                                      .bodyMedium
-                                      .fontWeight,
-                                  fontStyle: FlutterFlowTheme.of(context)
-                                      .bodyMedium
-                                      .fontStyle,
-                                ),
+                            ),
                           ),
-                        ),
                       ],
                     ),
                     Padding(