Prechádzať zdrojové kódy

P2-1 afgerond: datumfilter-chips op Home werkend van UI tot API

- ChoiceChips (Alles/Vandaag/Dit weekend/Deze week) op Home, tussen de
  slider en de tabbalk; On Selected vult App State datumFilter.
- Alle 5 HomeUitgaantabelKaartComponent-instanties (services_3 t/m _7)
  krijgen datumVan = filterDatumVan(datumFilter) en
  datumTot = filterDatumTot(datumFilter), plus een Value Key op
  datumFilter zodat de gepagineerde lijst echt herbouwt bij een wissel.
- filterDatumVan/filterDatumTot mappen de Nederlandse chip-labels op de
  interne sleutels en leveren YYYY-MM-DD HH:MM:SS (tot-grens 23:59:59).

Geverifieerd met een verse export: 5x ValueKey(FFAppState().datumFilter)
en de juiste Van/Tot-binding per tab; dart analyze lib/ geeft 0 errors.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bob 4 hodín pred
rodič
commit
f92c87cbb2

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

@@ -49,8 +49,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>"; };
-		6436409427A31CD800820AF7 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
-		6436409D27A31CD600820AF7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		6436409E27A31CDC00820AF7 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		6436409C27A31CDF00820AF7 /* 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>"; };
 		A9C17DEFA21738E5FBD7F54A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
 		B8285832C7E7A3262A5A897C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -317,8 +317,8 @@
 		6436409C27A31CD800820AF7 /* InfoPlist.strings */ = {
 			isa = PBXVariantGroup;
 			children = (
-				6436409427A31CD800820AF7 /* nl */,
-				6436409D27A31CD600820AF7 /* en */,
+				6436409E27A31CDC00820AF7 /* nl */,
+				6436409C27A31CDF00820AF7 /* en */,
 			);
 			name = InfoPlist.strings;
 			sourceTree = "<group>";

+ 2 - 2
lib/backend/schema/util/schema_util.dart

@@ -58,8 +58,8 @@ List<T>? getStructList<T>(
     value is! List
         ? null
         : value
-            .where((e) => e is Map<String, dynamic>)
-            .map((e) => structBuilder(e as Map<String, dynamic>))
+            .whereType<Map>()
+            .map((e) => structBuilder(Map<String, dynamic>.from(e)))
             .toList();
 
 Color? getSchemaColor(dynamic value) => value is String

+ 6 - 0
lib/flutter_flow/custom_functions.dart

@@ -279,6 +279,9 @@ List<dynamic>? categorieAlsLijst(dynamic categorie) {
 }
 
 String? filterDatumVan(String? keuze) {
+  if (keuze == 'Vandaag') keuze = 'vandaag';
+  if (keuze == 'Dit weekend') keuze = 'weekend';
+  if (keuze == 'Deze week') keuze = 'week';
   if (keuze == null) {
     return '';
   }
@@ -298,6 +301,9 @@ String? filterDatumVan(String? keuze) {
 }
 
 String? filterDatumTot(String? keuze) {
+  if (keuze == 'Vandaag') keuze = 'vandaag';
+  if (keuze == 'Dit weekend') keuze = 'weekend';
+  if (keuze == 'Deze week') keuze = 'week';
   if (keuze == null) {
     return '';
   }

+ 179 - 0
lib/flutter_flow/flutter_flow_choice_chips.dart

@@ -0,0 +1,179 @@
+import 'form_field_controller.dart';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/scheduler.dart';
+import 'package:font_awesome_flutter/font_awesome_flutter.dart';
+import '/flutter_flow/flutter_flow_util.dart';
+
+class ChipData {
+  const ChipData(this.label, [this.iconData]);
+  final String label;
+  final IconData? iconData;
+}
+
+class ChipStyle {
+  const ChipStyle({
+    this.backgroundColor,
+    this.textStyle,
+    this.iconColor,
+    this.iconSize,
+    this.labelPadding,
+    this.elevation,
+    this.borderColor,
+    this.borderWidth,
+    this.borderRadius,
+  });
+  final Color? backgroundColor;
+  final TextStyle? textStyle;
+  final Color? iconColor;
+  final double? iconSize;
+  final EdgeInsetsGeometry? labelPadding;
+  final double? elevation;
+  final Color? borderColor;
+  final double? borderWidth;
+  final BorderRadius? borderRadius;
+}
+
+class FlutterFlowChoiceChips extends StatefulWidget {
+  const FlutterFlowChoiceChips({
+    super.key,
+    required this.options,
+    required this.onChanged,
+    required this.controller,
+    required this.selectedChipStyle,
+    required this.unselectedChipStyle,
+    required this.chipSpacing,
+    this.rowSpacing = 0.0,
+    required this.multiselect,
+    this.initialized = true,
+    this.alignment = WrapAlignment.start,
+    this.disabledColor,
+    this.wrapped = true,
+  });
+
+  final List<ChipData> options;
+  final void Function(List<String>?)? onChanged;
+  final FormFieldController<List<String>> controller;
+  final ChipStyle selectedChipStyle;
+  final ChipStyle unselectedChipStyle;
+  final double chipSpacing;
+  final double rowSpacing;
+  final bool multiselect;
+  final bool initialized;
+  final WrapAlignment alignment;
+  final Color? disabledColor;
+  final bool wrapped;
+
+  @override
+  State<FlutterFlowChoiceChips> createState() => _FlutterFlowChoiceChipsState();
+}
+
+class _FlutterFlowChoiceChipsState extends State<FlutterFlowChoiceChips> {
+  late List<String> choiceChipValues;
+  List<String> get selectedValues => widget.controller.value ?? [];
+
+  @override
+  void initState() {
+    super.initState();
+    choiceChipValues = List.from(selectedValues);
+    if (!widget.initialized && choiceChipValues.isNotEmpty) {
+      SchedulerBinding.instance.addPostFrameCallback(
+        (_) {
+          if (widget.onChanged != null) {
+            widget.onChanged!(choiceChipValues);
+          }
+        },
+      );
+    }
+  }
+
+  @override
+  void dispose() {
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final children = widget.options.map<Widget>(
+      (option) {
+        final selected = selectedValues.contains(option.label);
+        final style =
+            selected ? widget.selectedChipStyle : widget.unselectedChipStyle;
+        return Theme(
+          data: Theme.of(context).copyWith(canvasColor: Colors.transparent),
+          child: ChoiceChip(
+            selected: selected,
+            onSelected: widget.onChanged != null
+                ? (isSelected) {
+                    choiceChipValues = List.from(selectedValues);
+                    if (isSelected) {
+                      widget.multiselect
+                          ? choiceChipValues.add(option.label)
+                          : choiceChipValues = [option.label];
+                      widget.controller.value = List.from(choiceChipValues);
+                      setState(() {});
+                    } else {
+                      if (widget.multiselect) {
+                        choiceChipValues.remove(option.label);
+                        widget.controller.value = List.from(choiceChipValues);
+                        setState(() {});
+                      }
+                    }
+                    widget.onChanged!(choiceChipValues);
+                  }
+                : null,
+            label: Text(
+              option.label,
+              style: style.textStyle,
+              overflow: TextOverflow.ellipsis,
+            ),
+            labelPadding: style.labelPadding,
+            avatar: option.iconData != null
+                ? FaIcon(
+                    option.iconData,
+                    size: style.iconSize,
+                    color: style.iconColor,
+                  )
+                : null,
+            elevation: style.elevation,
+            disabledColor: widget.disabledColor,
+            selectedColor:
+                selected ? widget.selectedChipStyle.backgroundColor : null,
+            backgroundColor:
+                selected ? null : widget.unselectedChipStyle.backgroundColor,
+            shape: RoundedRectangleBorder(
+              borderRadius: style.borderRadius ?? BorderRadius.circular(16),
+              side: BorderSide(
+                color: style.borderColor ?? Colors.transparent,
+                width: style.borderWidth ?? 0,
+              ),
+            ),
+            materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+          ),
+        );
+      },
+    ).toList();
+
+    if (widget.wrapped) {
+      return Wrap(
+        spacing: widget.chipSpacing,
+        runSpacing: widget.rowSpacing,
+        alignment: widget.alignment,
+        crossAxisAlignment: WrapCrossAlignment.center,
+        children: children,
+      );
+    } else {
+      return SingleChildScrollView(
+        scrollDirection: Axis.horizontal,
+        clipBehavior: Clip.none,
+        child: Row(
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: children.divide(
+            SizedBox(width: widget.chipSpacing),
+          ),
+        ),
+      );
+    }
+  }
+}

+ 20 - 0
lib/flutter_flow/internationalization.dart

@@ -204,6 +204,26 @@ final kTranslationsMap = <Map<String, Map<String, String>>>[
   },
   // home
   {
+    '8khvlnye': {
+      'nl': 'Alles',
+      'en': '',
+    },
+    'iov8u1yi': {
+      'nl': 'Vandaag',
+      'en': '',
+    },
+    'gco4jgol': {
+      'nl': 'Dit weekend',
+      'en': '',
+    },
+    'h6ou1q9q': {
+      'nl': 'Deze week',
+      'en': '',
+    },
+    'g09d1fb5': {
+      'nl': 'Alles',
+      'en': '',
+    },
     'eor4c9rz': {
       'nl': 'Uitgaan',
       'en': 'Go Out',

+ 20 - 0
lib/uitgaanspaginas/home/home_model.dart

@@ -1,11 +1,14 @@
 import '/components/header_buttons_component_widget.dart';
+import '/flutter_flow/flutter_flow_choice_chips.dart';
 import '/flutter_flow/flutter_flow_theme.dart';
 import '/flutter_flow/flutter_flow_util.dart';
 import '/flutter_flow/flutter_flow_widgets.dart';
+import '/flutter_flow/form_field_controller.dart';
 import '/shared/drawer_component/drawer_component_widget.dart';
 import '/uitgaanspaginas/home_uitgaan_slider_component/home_uitgaan_slider_component_widget.dart';
 import '/uitgaanspaginas/home_uitgaantabel_kaart_component/home_uitgaantabel_kaart_component_widget.dart';
 import 'dart:ui';
+import '/flutter_flow/custom_functions.dart' as functions;
 import 'home_widget.dart' show HomeWidget;
 import 'package:flutter/material.dart';
 import 'package:flutter_spinkit/flutter_spinkit.dart';
@@ -51,6 +54,15 @@ class HomeModel extends FlutterFlowModel<HomeWidget> {
 
   // Model for HomeUitgaanSliderComponent component.
   late HomeUitgaanSliderComponentModel homeUitgaanSliderComponentModel;
+  // State field(s) for ChoiceChips widget.
+  FormFieldController<List<String>>? choiceChipsValueController;
+  String? get choiceChipsValue =>
+      choiceChipsValueController?.value?.firstOrNull;
+  set choiceChipsValue(String? val) {
+    choiceChipsValueController?.value = val != null ? [val] : [];
+    debugLogWidgetClass(this);
+  }
+
   // State field(s) for TabBar widget.
   TabController? tabBarController;
   int get tabBarCurrentIndex =>
@@ -155,6 +167,14 @@ class HomeModel extends FlutterFlowModel<HomeWidget> {
           )
         }.entries,
         widgetStates: {
+          'choiceChipsValue': debugSerializeParam(
+            choiceChipsValue,
+            ParamType.String,
+            link:
+                'https://app.flutterflow.io/project/uitgaanskrant-1qhvtd?tab=uiBuilder&page=home',
+            name: 'String',
+            nullable: true,
+          ),
           'tabBarCurrentIndex': debugSerializeParam(
             tabBarCurrentIndex,
             ParamType.int,

+ 122 - 0
lib/uitgaanspaginas/home/home_widget.dart

@@ -1,11 +1,14 @@
 import '/components/header_buttons_component_widget.dart';
+import '/flutter_flow/flutter_flow_choice_chips.dart';
 import '/flutter_flow/flutter_flow_theme.dart';
 import '/flutter_flow/flutter_flow_util.dart';
 import '/flutter_flow/flutter_flow_widgets.dart';
+import '/flutter_flow/form_field_controller.dart';
 import '/shared/drawer_component/drawer_component_widget.dart';
 import '/uitgaanspaginas/home_uitgaan_slider_component/home_uitgaan_slider_component_widget.dart';
 import '/uitgaanspaginas/home_uitgaantabel_kaart_component/home_uitgaantabel_kaart_component_widget.dart';
 import 'dart:ui';
+import '/flutter_flow/custom_functions.dart' as functions;
 import 'package:flutter/material.dart';
 import 'package:flutter_spinkit/flutter_spinkit.dart';
 import 'package:google_fonts/google_fonts.dart';
@@ -101,6 +104,7 @@ class _HomeWidgetState extends State<HomeWidget>
     DebugFlutterFlowModelContext.maybeOf(context)
         ?.parentModelCallback
         ?.call(_model);
+    context.watch<FFAppState>();
 
     return GestureDetector(
       onTap: () {
@@ -180,6 +184,87 @@ class _HomeWidgetState extends State<HomeWidget>
                   ),
                 ),
               ),
+              FlutterFlowChoiceChips(
+                options: [
+                  ChipData(FFLocalizations.of(context).getText(
+                    '8khvlnye' /* Alles */,
+                  )),
+                  ChipData(FFLocalizations.of(context).getText(
+                    'iov8u1yi' /* Vandaag */,
+                  )),
+                  ChipData(FFLocalizations.of(context).getText(
+                    'gco4jgol' /* Dit weekend */,
+                  )),
+                  ChipData(FFLocalizations.of(context).getText(
+                    'h6ou1q9q' /* Deze week */,
+                  ))
+                ],
+                onChanged: (val) async {
+                  safeSetState(
+                      () => _model.choiceChipsValue = val?.firstOrNull);
+                  FFAppState().datumFilter = _model.choiceChipsValue!;
+                  safeSetState(() {});
+                },
+                selectedChipStyle: ChipStyle(
+                  backgroundColor: FlutterFlowTheme.of(context).primary,
+                  textStyle: FlutterFlowTheme.of(context).bodyMedium.override(
+                        font: GoogleFonts.roboto(
+                          fontWeight: FlutterFlowTheme.of(context)
+                              .bodyMedium
+                              .fontWeight,
+                          fontStyle:
+                              FlutterFlowTheme.of(context).bodyMedium.fontStyle,
+                        ),
+                        color: FlutterFlowTheme.of(context).info,
+                        letterSpacing: 0.0,
+                        fontWeight:
+                            FlutterFlowTheme.of(context).bodyMedium.fontWeight,
+                        fontStyle:
+                            FlutterFlowTheme.of(context).bodyMedium.fontStyle,
+                      ),
+                  iconColor: FlutterFlowTheme.of(context).info,
+                  iconSize: 16.0,
+                  elevation: 0.0,
+                  borderRadius: BorderRadius.circular(8.0),
+                ),
+                unselectedChipStyle: ChipStyle(
+                  backgroundColor:
+                      FlutterFlowTheme.of(context).secondaryBackground,
+                  textStyle: FlutterFlowTheme.of(context).bodyMedium.override(
+                        font: GoogleFonts.roboto(
+                          fontWeight: FlutterFlowTheme.of(context)
+                              .bodyMedium
+                              .fontWeight,
+                          fontStyle:
+                              FlutterFlowTheme.of(context).bodyMedium.fontStyle,
+                        ),
+                        color: FlutterFlowTheme.of(context).secondaryText,
+                        letterSpacing: 0.0,
+                        fontWeight:
+                            FlutterFlowTheme.of(context).bodyMedium.fontWeight,
+                        fontStyle:
+                            FlutterFlowTheme.of(context).bodyMedium.fontStyle,
+                      ),
+                  iconColor: FlutterFlowTheme.of(context).secondaryText,
+                  iconSize: 16.0,
+                  elevation: 0.0,
+                  borderRadius: BorderRadius.circular(8.0),
+                ),
+                chipSpacing: 8.0,
+                rowSpacing: 8.0,
+                multiselect: false,
+                initialized: _model.choiceChipsValue != null,
+                alignment: WrapAlignment.start,
+                controller: _model.choiceChipsValueController ??=
+                    FormFieldController<List<String>>(
+                  [
+                    FFLocalizations.of(context).getText(
+                      'g09d1fb5' /* Alles */,
+                    )
+                  ],
+                ),
+                wrapped: true,
+              ),
               Expanded(
                 child: Column(
                   children: [
@@ -296,7 +381,12 @@ class _HomeWidgetState extends State<HomeWidget>
                                       rootModel: _model.rootModel,
                                       child:
                                           HomeUitgaantabelKaartComponentWidget(
+                                        key: ValueKey(FFAppState().datumFilter),
                                         displayid: 'services_3',
+                                        datumVan: functions.filterDatumVan(
+                                            FFAppState().datumFilter),
+                                        datumTot: functions.filterDatumTot(
+                                            FFAppState().datumFilter),
                                       ),
                                     );
                                   }),
@@ -321,7 +411,15 @@ class _HomeWidgetState extends State<HomeWidget>
                                             rootModel: _model.rootModel,
                                             child:
                                                 HomeUitgaantabelKaartComponentWidget(
+                                              key: ValueKey(
+                                                  FFAppState().datumFilter),
                                               displayid: 'services_4',
+                                              datumVan:
+                                                  functions.filterDatumVan(
+                                                      FFAppState().datumFilter),
+                                              datumTot:
+                                                  functions.filterDatumTot(
+                                                      FFAppState().datumFilter),
                                             ),
                                           );
                                         }),
@@ -358,7 +456,15 @@ class _HomeWidgetState extends State<HomeWidget>
                                             rootModel: _model.rootModel,
                                             child:
                                                 HomeUitgaantabelKaartComponentWidget(
+                                              key: ValueKey(
+                                                  FFAppState().datumFilter),
                                               displayid: 'services_5',
+                                              datumVan:
+                                                  functions.filterDatumVan(
+                                                      FFAppState().datumFilter),
+                                              datumTot:
+                                                  functions.filterDatumTot(
+                                                      FFAppState().datumFilter),
                                             ),
                                           );
                                         }),
@@ -395,7 +501,15 @@ class _HomeWidgetState extends State<HomeWidget>
                                             rootModel: _model.rootModel,
                                             child:
                                                 HomeUitgaantabelKaartComponentWidget(
+                                              key: ValueKey(
+                                                  FFAppState().datumFilter),
                                               displayid: 'services_6',
+                                              datumVan:
+                                                  functions.filterDatumVan(
+                                                      FFAppState().datumFilter),
+                                              datumTot:
+                                                  functions.filterDatumTot(
+                                                      FFAppState().datumFilter),
                                             ),
                                           );
                                         }),
@@ -432,7 +546,15 @@ class _HomeWidgetState extends State<HomeWidget>
                                             rootModel: _model.rootModel,
                                             child:
                                                 HomeUitgaantabelKaartComponentWidget(
+                                              key: ValueKey(
+                                                  FFAppState().datumFilter),
                                               displayid: 'services_7',
+                                              datumVan:
+                                                  functions.filterDatumVan(
+                                                      FFAppState().datumFilter),
+                                              datumTot:
+                                                  functions.filterDatumTot(
+                                                      FFAppState().datumFilter),
                                             ),
                                           );
                                         }),