// travel_screen.dart - City selection with modal arrival messages + event dialogs import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/game_provider.dart'; import '../providers/player_provider.dart'; import '../models/city.dart'; import '../models/gang_territory.dart'; import '../models/game_state.dart'; import '../widgets/city_card.dart'; import '../widgets/event_dialog.dart'; import '../theme/app_theme.dart'; class TravelScreen extends ConsumerWidget { const TravelScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final gameState = ref.watch(gameProvider); final player = ref.watch(playerProvider); // Show event dialog if pending (e.g., from previous travel/trade) gameState.whenData((state) { if (state.pendingEvent != null) { WidgetsBinding.instance.addPostFrameCallback((_) async { if (context.mounted) { final action = await showEventDialog(context, state.pendingEvent!); if (context.mounted && action != null) { ref.read(gameProvider.notifier).resolveEvent(state.pendingEvent!, action); } else { ref.read(gameProvider.notifier).clearPendingEvent(); } } }); } }); return gameState.when( loading: () => const Center(child: CircularProgressIndicator(color: AppTheme.primary)), error: (e, _) => Center(child: Text('Error: $e')), data: (state) { final isTraveling = state.status == GameStatus.traveling; return Column( children: [ // War status banner if (state.player.warActive) Container( width: double.infinity, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), color: const Color(0xFFFF6600).withAlpha(50), child: const Row( children: [ Text('🌍', style: TextStyle(fontSize: 16)), SizedBox(width: 8), Expanded( child: Text( 'IRAN WAR ACTIVE — Dubai & Istanbul prices volatile. High risk, high reward.', style: TextStyle(color: Color(0xFFFF6600), fontSize: 12, fontWeight: FontWeight.bold), ), ), ], ), ), // Header Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), child: Row( children: [ const Text('SELECT DESTINATION', style: TextStyle( color: AppTheme.textSecondary, fontSize: 11, letterSpacing: 2, fontWeight: FontWeight.bold, ), ), const Spacer(), if (isTraveling) const Row( children: [ SizedBox(width: 12, height: 12, child: CircularProgressIndicator(strokeWidth: 2, color: AppTheme.primary)), SizedBox(width: 8), Text('IN TRANSIT', style: TextStyle(color: AppTheme.primary, fontSize: 11, letterSpacing: 1)), ], ), ], ), ), // Traveling overlay if (isTraveling) Container( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppTheme.primary.withAlpha(30), border: Border.all(color: AppTheme.primary.withAlpha(100)), borderRadius: BorderRadius.circular(12), ), child: Column( children: [ const Text('✈️ IN TRANSIT', style: TextStyle(color: AppTheme.primary, fontSize: 18, fontWeight: FontWeight.bold, letterSpacing: 2)), const SizedBox(height: 8), Text(state.statusMessage ?? 'Traveling...', textAlign: TextAlign.center, style: const TextStyle(color: AppTheme.textPrimary, fontSize: 15)), const SizedBox(height: 12), const LinearProgressIndicator(color: AppTheme.primary, backgroundColor: AppTheme.divider), ], ), ), // City list Expanded( child: ListView( padding: const EdgeInsets.only(bottom: 16), children: kCities.map((city) { final netWorth = state.player.netWorth; final isUnlocked = city.isUnlocked(netWorth); if (!isUnlocked) { return _LockedCityCard(city: city, netWorth: netWorth); } final territory = state.player.gangTerritories[city.id]; return CityCard( onChallengeBoss: territory?.canChallenge == true ? () => _handleChallengeBoss(context, ref, city) : null, onGatherIntel: () => _handleGatherIntel(context, ref, city), onBuildInfluence: () => _handleBuildInfluence(context, ref, city), city: city, isCurrentCity: city.id == player?.currentCityId, isTraveling: isTraveling, territory: territory, onTravel: () => _handleTravel(context, ref, city), ); }).toList(), ), ), ], ); }, ); } void _handleTravel(BuildContext context, WidgetRef ref, City destination) async { final message = await ref.read(gameProvider.notifier).travelTo(destination.id); if (context.mounted) { // Show arrival as prominent center dialog instead of SnackBar await showDialog( context: context, barrierDismissible: true, builder: (ctx) => AlertDialog( backgroundColor: AppTheme.surfaceVariant, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: const BorderSide(color: AppTheme.secondary, width: 2), ), title: Row( children: [ Text(destination.emoji, style: const TextStyle(fontSize: 32)), const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(destination.name, style: const TextStyle(color: AppTheme.secondary, fontSize: 18, fontWeight: FontWeight.bold)), if (destination.isWarZone) const Text('⚠️ WAR ZONE', style: TextStyle(color: Color(0xFFFF6600), fontSize: 12, fontWeight: FontWeight.bold)), ], ), ], ), content: Text( message, style: const TextStyle(color: AppTheme.textPrimary, fontSize: 16, height: 1.4), ), actions: [ ElevatedButton( onPressed: () => Navigator.pop(ctx), style: ElevatedButton.styleFrom(backgroundColor: AppTheme.secondary), child: const Text('LET\'S DEAL', style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)), ), ], ), ); } }