import "package:flutter/material.dart"; import "package:provider/provider.dart"; import "../app/app_router.dart"; import "../app/app_state.dart"; import "../services/api.dart"; import "../widgets/rescan_button.dart"; class BusinessSelectorScreen extends StatefulWidget { const BusinessSelectorScreen({super.key}); @override State createState() => _BusinessSelectorScreenState(); } class _BusinessSelectorScreenState extends State { static const String _imageBaseUrl = "https://biz.payfrit.com/uploads"; String? _parentName; int? _parentBusinessId; int? _servicePointId; String? _servicePointName; List<_BusinessItem>? _businesses; bool _loading = false; bool _initialized = false; @override void didChangeDependencies() { super.didChangeDependencies(); if (!_initialized) { _initialized = true; _initializeData(); } } Future _initializeData() async { final args = ModalRoute.of(context)?.settings.arguments as Map?; final BeaconBusinessMapping? mapping = args?["mapping"] as BeaconBusinessMapping?; final List? children = args?["children"] as List?; if (mapping != null && mapping.businesses.isNotEmpty) { // From beacon mapping setState(() { _parentName = mapping.parent?.businessName ?? mapping.businessName; _parentBusinessId = mapping.parent?.businessId ?? mapping.businessId; _servicePointId = mapping.servicePointId; _servicePointName = mapping.servicePointName; _businesses = mapping.businesses.map((b) => _BusinessItem( businessId: b.businessId, businessName: b.businessName, servicePointId: b.servicePointId, servicePointName: b.servicePointName, )).toList(); }); } else if (children != null && children.isNotEmpty) { // From menu_browse_screen with children list setState(() { _parentName = (args?["parentBusinessName"] as String?) ?? "this location"; _parentBusinessId = args?["parentBusinessId"] as int?; _servicePointId = args?["servicePointId"] as int?; _servicePointName = args?["servicePointName"] as String?; _businesses = children.map((c) => _BusinessItem( businessId: c.businessId, businessName: c.businessName, servicePointId: _servicePointId ?? 0, servicePointName: _servicePointName ?? "", )).toList(); }); } else if (args?["parentBusinessId"] != null) { // From menu back button - need to fetch children _parentBusinessId = args?["parentBusinessId"] as int?; _parentName = args?["parentBusinessName"] as String? ?? "this location"; _servicePointId = args?["servicePointId"] as int?; _servicePointName = args?["servicePointName"] as String?; setState(() => _loading = true); try { final fetchedChildren = await Api.getChildBusinesses(businessId: _parentBusinessId!); if (mounted) { setState(() { _businesses = fetchedChildren.map((c) => _BusinessItem( businessId: c.businessId, businessName: c.businessName, servicePointId: _servicePointId ?? 0, servicePointName: _servicePointName ?? "", )).toList(); _loading = false; }); } } catch (e) { if (mounted) { setState(() => _loading = false); } } } } @override Widget build(BuildContext context) { if (_loading) { return Scaffold( backgroundColor: Colors.black, body: const Center( child: CircularProgressIndicator(color: Colors.white), ), ); } if (_businesses == null || _businesses!.isEmpty) { return Scaffold( backgroundColor: Colors.black, body: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text( "No businesses available", style: TextStyle(color: Colors.white, fontSize: 18), ), const SizedBox(height: 16), FilledButton( onPressed: () => Navigator.of(context).pushReplacementNamed(AppRoutes.restaurantSelect), child: const Text("Browse Restaurants"), ), ], ), ), ); } return Scaffold( backgroundColor: Colors.black, body: SafeArea( child: Column( children: [ // Large header banner with back button overlay _buildHeaderBanner(context, _parentBusinessId, _parentName ?? ""), // Message const Padding( padding: EdgeInsets.fromLTRB(24, 24, 24, 8), child: Text( "Please select one of the businesses below:", style: TextStyle( color: Colors.white70, fontSize: 16, ), textAlign: TextAlign.center, ), ), const SizedBox(height: 16), // Business list with header images Expanded( child: ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: _businesses!.length, itemBuilder: (context, index) { final business = _businesses![index]; return _BusinessCardWithHeader( businessId: business.businessId, businessName: business.businessName, imageBaseUrl: _imageBaseUrl, onTap: () => _selectBusiness(context, business, _parentBusinessId, _parentName), ); }, ), ), ], ), ), ); } Widget _buildHeaderBanner(BuildContext context, int? parentBusinessId, String parentName) { const imageBaseUrl = _imageBaseUrl; return SizedBox( height: 200, width: double.infinity, child: Stack( children: [ // Background image if (parentBusinessId != null) Positioned.fill( child: Image.network( "$_imageBaseUrl/headers/$parentBusinessId.png", fit: BoxFit.fitWidth, errorBuilder: (context, error, stackTrace) { return Image.network( "$_imageBaseUrl/headers/$parentBusinessId.jpg", fit: BoxFit.fitWidth, errorBuilder: (context, error, stackTrace) { return Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Colors.grey.shade800, Colors.grey.shade900, ], ), ), ); }, ); }, ), ), // Subtle gradient overlay at bottom for readability of text below Positioned( bottom: 0, left: 0, right: 0, height: 40, child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withAlpha(150), ], ), ), ), ), // Back button Positioned( top: 8, left: 8, child: IconButton( onPressed: () => Navigator.of(context).pushReplacementNamed(AppRoutes.restaurantSelect), icon: const Icon(Icons.arrow_back), color: Colors.white, style: IconButton.styleFrom( backgroundColor: Colors.black54, ), ), ), // Rescan button Positioned( top: 8, right: 8, child: Container( decoration: BoxDecoration( color: Colors.black54, borderRadius: BorderRadius.circular(20), ), child: const RescanButton(iconColor: Colors.white), ), ), ], ), ); } void _selectBusiness(BuildContext context, _BusinessItem business, int? parentBusinessId, String? parentBusinessName) { final appState = context.read(); // Clear any existing cart appState.clearCart(); // Set the selected business and service point (with parent info for back navigation) appState.setBusinessAndServicePoint( business.businessId, business.servicePointId, businessName: business.businessName, servicePointName: business.servicePointName, parentBusinessId: parentBusinessId, parentBusinessName: parentBusinessName, ); appState.setOrderType(OrderType.dineIn); Api.setBusinessId(business.businessId); // Navigate to menu Navigator.of(context).pushReplacementNamed( AppRoutes.menuBrowse, arguments: { "businessId": business.businessId, "servicePointId": business.servicePointId, }, ); } } /// Internal business item for unified handling class _BusinessItem { final int businessId; final String businessName; final int servicePointId; final String servicePointName; const _BusinessItem({ required this.businessId, required this.businessName, required this.servicePointId, required this.servicePointName, }); } /// Business card with header image background class _BusinessCardWithHeader extends StatelessWidget { final int businessId; final String businessName; final String imageBaseUrl; final VoidCallback onTap; const _BusinessCardWithHeader({ required this.businessId, required this.businessName, required this.imageBaseUrl, required this.onTap, }); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( height: 120, margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(100), blurRadius: 8, offset: const Offset(0, 4), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(16), child: Stack( children: [ // Header image background Positioned.fill( child: Image.network( "$imageBaseUrl/headers/$businessId.png", fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Image.network( "$imageBaseUrl/headers/$businessId.jpg", fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { // Fallback to logo centered return Container( color: Colors.grey.shade800, child: Center( child: Image.network( "$imageBaseUrl/logos/$businessId.png", width: 60, height: 60, fit: BoxFit.contain, errorBuilder: (context, error, stackTrace) { return Image.network( "$imageBaseUrl/logos/$businessId.jpg", width: 60, height: 60, fit: BoxFit.contain, errorBuilder: (context, error, stackTrace) { return Text( businessName.isNotEmpty ? businessName[0].toUpperCase() : "?", style: const TextStyle( color: Colors.white54, fontSize: 36, fontWeight: FontWeight.bold, ), ); }, ); }, ), ), ); }, ); }, ), ), // Gradient overlay Positioned.fill( child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withAlpha(180), ], ), ), ), ), // Business name and arrow at bottom Positioned( bottom: 12, left: 16, right: 16, child: Row( children: [ Expanded( child: Text( businessName, style: const TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, shadows: [ Shadow( offset: Offset(0, 1), blurRadius: 3, color: Colors.black54, ), ], ), ), ), const Icon( Icons.arrow_forward_ios, color: Colors.white70, size: 20, ), ], ), ), ], ), ), ), ); } }