import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/profile/service_locations_radius.dart'; import '../resources/source_loctaions_model.dart'; import 'availability.dart'; void main() => runApp(const MaterialApp(home: ServiceLocation())); class ServiceLocation extends StatefulWidget { const ServiceLocation({super.key}); @override State createState() => _ServiceLocationState(); } class _ServiceLocationState extends State { final _formKey = GlobalKey(); String _deliveryFrom = 'business'; final TextEditingController _radiusController = TextEditingController(text: "10"); bool _customizeEachSource = false; bool isLoading = false; int currentStep = 3; List sourceLocationsList = []; // 🔹 Notifier for dynamic map radius late final ValueNotifier _radiusKmNotifier; final List _services = [ "24/7 Emergency services", "Scheduled water deliveries", "Bulk water deliveries", "Long-term water delivery plans", "Industrial/Commercial water deliveries" ]; final Set _selectedServices = {}; final Map _expandedMap = {}; @override void initState() { super.initState(); _radiusKmNotifier = ValueNotifier( double.tryParse(_radiusController.text) ?? 10, ); // 🔹 Listen to radius text changes _radiusController.addListener(() { final v = double.tryParse(_radiusController.text); _radiusKmNotifier.value = (v == null || v.isNaN || v <= 0) ? 10 : v; }); _fetchSources(); } @override void dispose() { _radiusController.dispose(); _radiusKmNotifier.dispose(); super.dispose(); } Future _fetchSources() async { setState(() => isLoading = true); try { final response = await AppSettings.getSourceLoctaions(); final data = (jsonDecode(response)['data'] as List) .map((e) => SourceLocationsModel.fromJson(e)) .toList(); if (!mounted) return; setState(() { sourceLocationsList = data; isLoading = false; for (var i = 0; i < data.length; i++) { _expandedMap[i] = false; } }); } catch (e) { debugPrint("⚠️ Error fetching source locations: $e"); setState(() => isLoading = false); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, surfaceTintColor: Colors.transparent, elevation: 0, title: const Text("Complete Profile"), ), body: SafeArea( child: isLoading ? const Center(child: CircularProgressIndicator()) : Form( key: _formKey, child: ListView( padding: const EdgeInsets.fromLTRB(20, 10, 20, 24), children: [ Text("Step $currentStep/5", style: fontTextStyle( 16, const Color(0xFFC3C4C4), FontWeight.w500)), const SizedBox(height: 16), Row( children: List.generate(5, (index) { final isFilled = index < currentStep; return Expanded( child: Container( margin: const EdgeInsets.symmetric(horizontal: 2), height: 5, decoration: BoxDecoration( color: isFilled ? const Color(0xFF0D3771) : const Color(0xFFE6E6E6), borderRadius: BorderRadius.circular(2), ), ), ); }), ), const SizedBox(height: 16), Text("SERVICE LOCATIONS", style: fontTextStyle( 20, const Color(0xFF515253), FontWeight.w600)), const SizedBox(height: 16), Align( alignment: Alignment.centerLeft, child: Image.asset('images/marker-pin.png', width: 24, height: 24), ), const SizedBox(height: 16), Text( "Define where you want to provide delivery services", style: fontTextStyle( 14, const Color(0xFF939495), FontWeight.w500), ), const SizedBox(height: 16), RadioListTile( value: 'business', groupValue: _deliveryFrom, onChanged: (value) => setState(() => _deliveryFrom = value ?? 'business'), title: Text("From Business Location", style: fontTextStyle( 12, const Color(0xFF2D2E30), FontWeight.w400)), dense: true, contentPadding: EdgeInsets.zero, visualDensity: const VisualDensity(horizontal: 0, vertical: -3), ), RadioListTile( value: 'source', groupValue: _deliveryFrom, onChanged: (value) => setState(() => _deliveryFrom = value ?? 'source'), title: Text("From Source Locations", style: fontTextStyle( 12, const Color(0xFF2D2E30), FontWeight.w400)), dense: true, contentPadding: EdgeInsets.zero, visualDensity: const VisualDensity(horizontal: 0, vertical: -3), ), const SizedBox(height: 16), // 🔹 BUSINESS LOCATION SECTION Visibility( visible: _deliveryFrom == 'business', child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Delivery Radius (in Kms) *", style: fontTextStyle(12, const Color(0xFF2F3036), FontWeight.w600)), const SizedBox(height: 16), TextFormField( controller: _radiusController, keyboardType: TextInputType.number, decoration: InputDecoration( hintText: "Enter radius in kms", hintStyle: fontTextStyle( 14, const Color(0xFF939495), FontWeight.w400), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), contentPadding: const EdgeInsets.symmetric( horizontal: 12, vertical: 12), ), ), const SizedBox(height: 16), Container( width: double.infinity, height: 220, // 👈 small map fits neatly decoration: BoxDecoration( border: Border.all(color: const Color(0xFFE6E6E6)), borderRadius: BorderRadius.circular(8), ), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: ServiceLocationsRadiusScreen( initialPosition: const LatLng(17.381597, 78.481791), radiusKmListenable: _radiusKmNotifier, ), ), ), ], ), ), // 🔹 SOURCE LOCATIONS SECTION Visibility( visible: _deliveryFrom == 'source', child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Delivery Radius (in Kms) *", style: fontTextStyle(12, const Color(0xFF2F3036), FontWeight.w600)), const SizedBox(height: 16), TextFormField( controller: _radiusController, keyboardType: TextInputType.number, decoration: InputDecoration( hintText: "Enter radius in kms", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), ), ), const SizedBox(height: 16), Row( children: [ Checkbox( value: _customizeEachSource, onChanged: (val) => setState(() { _customizeEachSource = val ?? false; }), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: const VisualDensity(horizontal: -4, vertical: -4), ), const SizedBox(width: 6), Expanded( child: Text( "Customize for each source location", style: fontTextStyle( 12, const Color(0xFF2D2E30), FontWeight.w400), ), ), ], ), const SizedBox(height: 12), // 🔹 Show source list if enabled if (_customizeEachSource) Column( crossAxisAlignment: CrossAxisAlignment.start, children: sourceLocationsList.isEmpty ? [ const Text("No source locations available"), ] : List.generate(sourceLocationsList.length, (index) { final d = sourceLocationsList[index]; final isExpanded = _expandedMap[index] ?? false; return Container( margin: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0), decoration: BoxDecoration( color: const Color(0xFFF1F1F1), border: Border.all(color: const Color(0xFFE5E5E5)), borderRadius: BorderRadius.circular(29), ), child: Column( children: [ ListTile( dense: true, contentPadding: EdgeInsets.zero, minVerticalPadding: 0, visualDensity: const VisualDensity(vertical: -4, horizontal: 0), title: Text( d.source_name ?? 'Unnamed location', style: fontTextStyle( 14, const Color(0xFF2D2E30), FontWeight.w600), ), trailing: IconButton( icon: Image.asset( isExpanded ? 'images/arrow-up.png' : 'images/downarrow.png', width: 18, height: 18, ), onPressed: () { setState(() { _expandedMap[index] = !isExpanded; }); }, ), ), if (isExpanded) Column( children: [ Container( margin: const EdgeInsets.only( left: 10, right: 10, bottom: 6), padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all( color: const Color(0xFFE5E5E5)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Delivery Radius (in Kms) *", style: fontTextStyle( 12, const Color(0xFF2F3036), FontWeight.w600)), const SizedBox(height: 16), TextFormField( controller: _radiusController, keyboardType: TextInputType.number, decoration: InputDecoration( hintText: "Enter radius in kms", hintStyle: fontTextStyle( 14, const Color(0xFF939495), FontWeight.w400), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), contentPadding: const EdgeInsets.symmetric( horizontal: 12, vertical: 12), ), ), const SizedBox(height: 16), Container( width: double.infinity, height: 180, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), border: Border.all( color: const Color(0xFFE6E6E6)), ), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: ServiceLocationsRadiusScreen( initialPosition: LatLng( d.latitude ?? 17.3850, d.longitude ?? 78.4867, ), radiusKmListenable: _radiusKmNotifier, ), ), ), ], ), ), ], ), ], ), ); }), ), // 🔹 Hide main map when customizeEachSource = true if (!_customizeEachSource) ...[ const SizedBox(height: 16), Container( width: double.infinity, height: 250, decoration: BoxDecoration( border: Border.all(color: const Color(0xFFE6E6E6)), borderRadius: BorderRadius.circular(8), ), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: ServiceLocationsRadiusScreen( initialPosition: const LatLng(20.5937, 78.9629), radiusKmListenable: _radiusKmNotifier, ), ), ), ], ], ), ), const SizedBox(height: 24), Text("Types of Services", style: fontTextStyle( 16, const Color(0xFF2D2E30), FontWeight.w600)), const SizedBox(height: 12), Text( "Define what type of services you would wish to provide", style: fontTextStyle( 14, const Color(0xFF939495), FontWeight.w500)), const SizedBox(height: 16), ..._services .map((service) => _serviceItem(service)) .toList(), const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF8270DB), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(24)), ), onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (_) => const AvailabilityScreen())); }, child: Text("Save & Continue", style: fontTextStyle( 14, Colors.white, FontWeight.w400)), ), ), ], ), ), ), ); } // ✅ Service item checkbox list Widget _serviceItem(String label) { final bool selected = _selectedServices.contains(label); return GestureDetector( onTap: () { setState(() { if (selected) { _selectedServices.remove(label); } else { _selectedServices.add(label); } }); }, child: Container( margin: const EdgeInsets.only(bottom: 8), child: Row( children: [ Icon( selected ? Icons.check_box : Icons.check_box_outline_blank, color: selected ? const Color(0xFF8270DB) : const Color(0xFF939495), size: 20, ), const SizedBox(width: 8), Expanded( child: Text(label, style: fontTextStyle( 12, const Color(0xFF2D2E30), FontWeight.w400)), ), ], ), ), ); } }