@@ -6,8 +6,11 @@ import 'package:latlong2/latlong.dart';
66import '../../core/di/injection.dart' ;
77import '../../l10n/app_localizations.dart' ;
88import '../../models/connectivity_status.dart' ;
9+ import '../../models/fare_formula.dart' ;
10+ import '../../repositories/fare_repository.dart' ;
911import '../../services/connectivity/connectivity_service.dart' ;
1012import '../../services/fare_comparison_service.dart' ;
13+ import '../../services/settings_service.dart' ;
1114import '../controllers/main_screen_controller.dart' ;
1215import '../widgets/main_screen/calculate_fare_button.dart' ;
1316import '../widgets/main_screen/error_message_banner.dart' ;
@@ -19,6 +22,7 @@ import '../widgets/main_screen/main_screen_app_bar.dart';
1922import '../widgets/main_screen/map_preview.dart' ;
2023import '../widgets/main_screen/offline_status_banner.dart' ;
2124import '../widgets/main_screen/passenger_bottom_sheet.dart' ;
25+ import '../widgets/main_screen/transport_mode_selection_modal.dart' ;
2226import '../widgets/main_screen/travel_options_bar.dart' ;
2327import 'map_picker_screen.dart' ;
2428
@@ -34,20 +38,34 @@ class MainScreen extends StatefulWidget {
3438class _MainScreenState extends State <MainScreen > {
3539 late final MainScreenController _controller;
3640 late final ConnectivityService _connectivityService;
41+ late final SettingsService _settingsService;
42+ late final FareRepository _fareRepository;
3743 final TextEditingController _originTextController = TextEditingController ();
3844 final TextEditingController _destinationTextController =
3945 TextEditingController ();
4046 StreamSubscription <ConnectivityStatus >? _connectivitySubscription;
4147 ConnectivityStatus _connectivityStatus = ConnectivityStatus .online;
4248
49+ /// Number of enabled transport modes (not hidden).
50+ int _enabledModesCount = 0 ;
51+
52+ /// Total number of available transport modes.
53+ int _totalModesCount = 0 ;
54+
55+ /// Cached list of all formulas for modal display.
56+ List <FareFormula > _allFormulas = [];
57+
4358 @override
4459 void initState () {
4560 super .initState ();
4661 _controller = MainScreenController ();
4762 _connectivityService = getIt <ConnectivityService >();
63+ _settingsService = getIt <SettingsService >();
64+ _fareRepository = getIt <FareRepository >();
4865 _controller.addListener (_onControllerChanged);
4966 _initializeData ();
5067 _initConnectivity ();
68+ _loadTransportModeCounts ();
5169 }
5270
5371 Future <void > _initConnectivity () async {
@@ -61,6 +79,35 @@ class _MainScreenState extends State<MainScreen> {
6179 });
6280 }
6381
82+ /// Loads transport mode counts for the quick-access button badge.
83+ Future <void > _loadTransportModeCounts () async {
84+ try {
85+ final allFormulas = await _fareRepository.getAllFormulas ();
86+ final hiddenModes = await _settingsService.getHiddenTransportModes ();
87+
88+ // Count unique mode-subtype combinations
89+ final allModeKeys = < String > {};
90+ for (final formula in allFormulas) {
91+ allModeKeys.add ('${formula .mode }::${formula .subType }' );
92+ }
93+
94+ final enabledCount = allModeKeys
95+ .where ((key) => ! hiddenModes.contains (key))
96+ .length;
97+
98+ if (mounted) {
99+ setState (() {
100+ _allFormulas = allFormulas;
101+ _totalModesCount = allModeKeys.length;
102+ _enabledModesCount = enabledCount;
103+ });
104+ }
105+ } catch (e) {
106+ // Silently handle error - the button will show 0/0
107+ debugPrint ('Failed to load transport mode counts: $e ' );
108+ }
109+ }
110+
64111 @override
65112 void dispose () {
66113 _connectivitySubscription? .cancel ();
@@ -152,6 +199,9 @@ class _MainScreenState extends State<MainScreen> {
152199 sortCriteria: _controller.sortCriteria,
153200 onPassengerTap: _showPassengerBottomSheet,
154201 onSortChanged: _controller.setSortCriteria,
202+ enabledModesCount: _enabledModesCount,
203+ totalModesCount: _totalModesCount,
204+ onTransportModesTap: _handleTransportModesTap,
155205 ),
156206 const SizedBox (height: 16 ),
157207 // Map height: 280 when no fare results (40% larger), 200 when showing results
@@ -169,7 +219,7 @@ class _MainScreenState extends State<MainScreen> {
169219 CalculateFareButton (
170220 canCalculate: _controller.canCalculate,
171221 isCalculating: _controller.isCalculating,
172- onPressed: _controller.calculateFare ,
222+ onPressed: _handleCalculateFare ,
173223 ),
174224 if (_controller.errorMessage != null ) ...[
175225 const SizedBox (height: 16 ),
@@ -292,4 +342,85 @@ class _MainScreenState extends State<MainScreen> {
292342 );
293343 }
294344 }
345+
346+ /// Handles the transport modes quick-access button tap.
347+ /// Shows the transport mode selection modal and updates the count after.
348+ Future <void > _handleTransportModesTap () async {
349+ // Ensure we have formulas loaded
350+ if (_allFormulas.isEmpty) {
351+ await _loadTransportModeCounts ();
352+ }
353+
354+ if (! mounted || _allFormulas.isEmpty) return ;
355+
356+ await TransportModeSelectionModal .show (
357+ context: context,
358+ settingsService: _settingsService,
359+ availableFormulas: _allFormulas,
360+ );
361+
362+ // Refresh the count after modal closes
363+ await _loadTransportModeCounts ();
364+ }
365+
366+ /// Handles fare calculation with transport mode check.
367+ /// If no transport modes are enabled, shows the mode selection modal first.
368+ Future <void > _handleCalculateFare () async {
369+ // Check if user has set transport mode preferences
370+ final hasSetPreferences = await _settingsService
371+ .hasSetTransportModePreferences ();
372+
373+ if (! hasSetPreferences) {
374+ // User hasn't set any preferences - show the modal
375+ final allFormulas = await _fareRepository.getAllFormulas ();
376+
377+ if (! mounted) return ;
378+
379+ final confirmed = await TransportModeSelectionModal .show (
380+ context: context,
381+ settingsService: _settingsService,
382+ availableFormulas: allFormulas,
383+ );
384+
385+ // Refresh the count after modal closes
386+ await _loadTransportModeCounts ();
387+
388+ if (! confirmed) {
389+ // User cancelled - don't proceed with fare calculation
390+ return ;
391+ }
392+ } else {
393+ // User has set preferences, check if any modes are actually enabled
394+ final hiddenModes = await _settingsService.getHiddenTransportModes ();
395+ final allFormulas = await _fareRepository.getAllFormulas ();
396+
397+ // Check if ALL modes are hidden
398+ final allModesHidden = allFormulas.every ((formula) {
399+ final modeSubTypeKey = '${formula .mode }::${formula .subType }' ;
400+ return hiddenModes.contains (modeSubTypeKey);
401+ });
402+
403+ if (allModesHidden) {
404+ // All modes are hidden - show the modal
405+ if (! mounted) return ;
406+
407+ final confirmed = await TransportModeSelectionModal .show (
408+ context: context,
409+ settingsService: _settingsService,
410+ availableFormulas: allFormulas,
411+ );
412+
413+ // Refresh the count after modal closes
414+ await _loadTransportModeCounts ();
415+
416+ if (! confirmed) {
417+ // User cancelled - don't proceed with fare calculation
418+ return ;
419+ }
420+ }
421+ }
422+
423+ // Proceed with fare calculation
424+ await _controller.calculateFare ();
425+ }
295426}
0 commit comments