import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:supplier_new/common/settings.dart'; import '../resources/source_loctaions_model.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 = []; 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(); _fetchSources(); } 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, 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, 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, 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, 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, Color(0xFF2D2E30), FontWeight.w400)), dense: true, contentPadding: EdgeInsets.zero, visualDensity: const VisualDensity(horizontal: 0, vertical: -3), ), const SizedBox(height: 16), Visibility( visible: _deliveryFrom == 'business', child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Delivery Radius (in Kms) *", style: fontTextStyle(12, Color(0xFF2F3036), FontWeight.w600)), const SizedBox(height: 16), TextFormField( controller: _radiusController, keyboardType: TextInputType.number, decoration: InputDecoration( hintText: "Enter radius in kms", hintStyle: fontTextStyle(14, 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: 160, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('images/google_maps.png'), fit: BoxFit.contain, ), ), ), ], ), ), // ✅ Source Location Customization Section Visibility( visible: _deliveryFrom == 'source', child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("Delivery Radius (in Kms) *", style: fontTextStyle(12, 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, Color(0xFF2D2E30), FontWeight.w400), ), ), ], ), const SizedBox(height: 12), // 🔹 Show all source locations when checkbox checked if (_customizeEachSource) Column( crossAxisAlignment: CrossAxisAlignment.start, children: sourceLocationsList.isEmpty ? [ const Text("No source locations available"), ] : List.generate(sourceLocationsList.length, (index) { final d = sourceLocationsList[index]; return StatefulBuilder( builder: (context, setInner) { // ✅ Always read from map dynamically (not fixed final variable) final isExpanded = _expandedMap[index] ?? false; return Container( margin: const EdgeInsets.only(bottom: 8), decoration: BoxDecoration( color: const Color(0xFFF7F7F7), border: Border.all(color: const Color(0xFFE5E5E5)), borderRadius: BorderRadius.circular(12), ), 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: () { setInner(() { _expandedMap[index] = !isExpanded; }); }, ), ), if (isExpanded) 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: Text( "Address: ${d.address ?? 'N/A'}", style: fontTextStyle(12, const Color(0xFF646566), FontWeight.w400), ), ), ], ), ); }, ); }), ), const SizedBox(height: 16), Container( width: double.infinity, height: 160, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('images/google_maps.png'), fit: BoxFit.contain, ), ), ), ], ), ), const SizedBox(height: 24), Text("Types of Services", style: fontTextStyle(16, Color(0xFF2D2E30), FontWeight.w600)), const SizedBox(height: 12), Text( "Define what type of services you would wish to provide", style: fontTextStyle(14, 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: () { final selected = _selectedServices.isEmpty ? "No services selected" : _selectedServices.join(", "); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( "Saved successfully for ${_deliveryFrom == 'business' ? 'Business Location' : 'Source Locations'}\nSelected: $selected"), ), ); }, child: Text("Save & Continue", style: fontTextStyle(14, Color(0xFFFFFFFF), FontWeight.w400)), ), ), ], ), ), ), ); } // ✅ Service item 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 ? Color(0xFF8270DB) : Color(0xFF939495), size: 20, ), const SizedBox(width: 8), Expanded( child: Text(label, style: fontTextStyle(12, Color(0xFF2D2E30), FontWeight.w400), ), ), ], ), ), ); } }