import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/profile/source_location.dart'; import '../resources/driver_details.dart'; import '../resources/drivers_model.dart'; import '../resources/resources_drivers.dart'; import 'availability.dart'; class FleetEmployees extends StatefulWidget { const FleetEmployees({super.key}); @override State createState() => _FleetEmployeesState(); } class _FleetEmployeesState extends State { bool isLoading = false; int currentStep = 1; List driversList = []; // Controllers for adding new driver final _formKey = GlobalKey(); final _nameCtrl = TextEditingController(); final _mobileCtrl = TextEditingController(); final _altMobileCtrl = TextEditingController(); final _locationCtrl = TextEditingController(); final List licenseNumbers = [ "UP3220050012345", "UP3220050012355", "UP3220050012365", "UP3220050012375", ]; String? selectedLicense; final List yearOptions = ["1", "2", "3", "4", "5"]; String? selectedExperience; @override void initState() { super.initState(); _fetchDrivers(); } String? _status; // 'available' | 'on delivery' | 'offline' final List _statusOptions = const ['available', 'on delivery', 'offline']; Future _fetchDrivers() async { setState(() => isLoading = true); try { final response = await AppSettings.getDrivers(); final data = (jsonDecode(response)['data'] as List) .map((e) => DriversModel.fromJson(e)) .toList(); if (!mounted) return; setState(() { driversList = data; isLoading = false; }); } catch (e) { debugPrint("⚠️ Error fetching drivers: $e"); setState(() => isLoading = false); } } String? _required(String? v, {String field = "This field"}) { if (v == null || v.trim().isEmpty) return "$field is required"; return null; } String? _validatePhone(String? v, {String label = "Phone Number"}) { if (v == null || v.trim().isEmpty) return "$label is required"; final digits = v.replaceAll(RegExp(r'\D'), ''); if (digits.length != 10) return "Enter a 10-digit $label"; if (!RegExp(r'^[6-9]\d{9}$').hasMatch(digits)) { return "$label must start with 6/7/8/9"; } return null; } void _clearForm() { _nameCtrl.clear(); _mobileCtrl.clear(); _altMobileCtrl.clear(); selectedLicense = null; selectedExperience = null; setState(() {}); } Future _addDriver() async { if (!(_formKey.currentState?.validate() ?? false)) return; if (selectedLicense == null || selectedExperience == null) { AppSettings.longFailedToast("Select License & Experience"); return; } var payload = { "Name": _nameCtrl.text.trim(), "license_number": selectedLicense, "address": AppSettings.userAddress, "supplier_name": AppSettings.userName, "phone": _mobileCtrl.text.trim(), "alternativeContactNumber": _altMobileCtrl.text.trim(), "years_of_experience": selectedExperience, "status": "active", }; bool status = await AppSettings.addDrivers(payload); if (status) { AppSettings.longSuccessToast("Driver Added Successfully"); _clearForm(); Navigator.pop(context, true); _fetchDrivers(); } else { AppSettings.longFailedToast("Failed to add driver"); } } void _onContinue() { if (currentStep < 5) { setState(() => currentStep += 1); } else { // You can navigate to next screen here // Navigator.push(context, MaterialPageRoute(builder: (_) => const NextScreen())); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, surfaceTintColor: Colors.transparent, elevation: 0, scrolledUnderElevation: 0, title: const Text("Complete Profile"), actions: [ IconButton( splashRadius: 20, icon: const Image( image: AssetImage('images/calendar_appbar.png'), width: 22, height: 22, ), onPressed: () {}, ), IconButton( splashRadius: 20, icon: Image.asset('images/notification_appbar.png', width: 22, height: 22), onPressed: () { }, ), ], ), body: SafeArea( child: isLoading ? const Center(child: CircularProgressIndicator()) : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header Padding( padding: const EdgeInsets.fromLTRB(20, 10, 20, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, 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("EMPLOYEES", style: fontTextStyle(20, Color(0xFF515253), FontWeight.w600)), const SizedBox(height: 8), Image.asset('images/manage-users.png', width: 24, height: 24), const SizedBox(height: 8), Text( "Details about your driver fleet", style: fontTextStyle(14, Color(0xFF939495), FontWeight.w500), ), ], ), ), const SizedBox(height: 16), // Driver list Expanded( child: driversList.isEmpty ? Center( child: Text( "No drivers added yet.", style: fontTextStyle( 14, const Color(0xFF939495), FontWeight.w400), ), ) : ListView.separated( padding: const EdgeInsets.fromLTRB(16, 4, 16, 100), itemCount: driversList.length, separatorBuilder: (_, __) => const SizedBox(height: 8), itemBuilder: (context, idx) { final d = driversList[idx]; bool expanded = false; return StatefulBuilder( builder: (context, setInnerState) { return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0), decoration: BoxDecoration( color: Color(0xFFF1F1F1), // background color border: Border.all(color: Color(0xFFE5E5E5)), borderRadius: BorderRadius.circular(29), ), child: Column( children: [ ListTile( dense: true, // makes tile shorter contentPadding: EdgeInsets.zero, // removes default horizontal padding minVerticalPadding: 0, visualDensity: const VisualDensity(vertical: -4, horizontal: 0), title: Text( d.driver_name ?? 'Unnamed Driver', style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w600), ), trailing: IconButton( padding: EdgeInsets.zero, constraints: const BoxConstraints(minWidth: 32, minHeight: 32), icon: Image.asset( expanded ? 'images/arrow-up.png' : 'images/downarrow.png', width: 18, height: 18, ), onPressed: () => setInnerState(() { expanded = !expanded; }), ), ), if (expanded) Align( alignment: Alignment.centerLeft, child: Container( margin: const EdgeInsets.only(left: 10, right: 10, bottom: 6), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: Color(0xFFFFFFFF), // 👈 white background border: Border.all(color:Color(0xFFFFFFFF)), // light border borderRadius: BorderRadius.circular(8), // smooth rounded edges ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${d.address ?? 'N/A'} : " " ${d.phone_number ?? 'N/A'}", style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500), ), const SizedBox(height: 4), ], ), ), ), ], ), ); }, ); }, ), ) ], ), ), // Bottom buttons bottomSheet: Container( color: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 20).copyWith(bottom: 24), child: Column( mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: () { _openAddDriverSheet(context); }, icon: Image.asset('images/Add_icon.png', width: 16, height: 16), label: Text( "Add Driver", style: fontTextStyle( 14, const Color(0xFF646566), FontWeight.w600), ), ), ), const SizedBox(height: 12), 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 SourceLocation())); }, child: Text( "Continue", style: fontTextStyle(14, Colors.white, FontWeight.w400), ), ), ), ], ), ), ); } // Bottom sheet for Add Driver form void _openAddDriverSheet(BuildContext context) { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(24)), ), builder: (_) { return Padding( padding: MediaQuery.of(context).viewInsets.add(const EdgeInsets.all(20)), child: SingleChildScrollView( child: Form( key: _formKey, child: Column( mainAxisSize: MainAxisSize.min, children: [ Text("Add New Driver", style: fontTextStyle( 18, const Color(0xFF2D2E30), FontWeight.w600)), const SizedBox(height: 16), _LabeledField( label: "Driver Name *", child: TextFormField( controller: _nameCtrl, validator: (v) => _required(v, field: "Driver Name"), textCapitalization: TextCapitalization.none, inputFormatters: const [ FirstCharUppercaseFormatter(), // << live first-letter caps ], decoration: InputDecoration( hintText: "Full Name", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), border: OutlineInputBorder(), isDense: true, ), ), ), _LabeledField( label: "License Number *", child: DropdownButtonFormField( value: selectedLicense, items: licenseNumbers .map((t) => DropdownMenuItem(value: t, child: Text(t))) .toList(), onChanged: (v) => setState(() => selectedLicense = v), validator: (v) => v == null ? "Select License" : null, decoration: const InputDecoration( border: OutlineInputBorder(), isDense: true, ), ), ), _LabeledField( label: "Years of Experience *", child: DropdownButtonFormField( value: selectedExperience, items: yearOptions .map((t) => DropdownMenuItem(value: t, child: Text(t))) .toList(), onChanged: (v) => setState(() => selectedExperience = v), validator: (v) => v == null ? "Select Experience" : null, decoration: const InputDecoration( border: OutlineInputBorder(), isDense: true, ), ), ), _LabeledField( label: "Phone Number *", child: TextFormField( controller: _mobileCtrl, validator: (v) => _validatePhone(v), keyboardType: TextInputType.phone, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(10), ], decoration: InputDecoration( hintText: "Mobile Number", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), border: OutlineInputBorder(), isDense: true, ), ), ), _LabeledField( label: "Alternate Phone Number", child: TextFormField( controller: _altMobileCtrl, keyboardType: TextInputType.phone, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(10), ], decoration: InputDecoration( hintText: "Mobile Number", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), border: OutlineInputBorder(), isDense: true, ), ), ), _LabeledField( label: "Location *", child: TextFormField( controller: _locationCtrl, validator: (v) => _required(v, field: "Location"), textCapitalization: TextCapitalization.none, inputFormatters: const [ FirstCharUppercaseFormatter(), // << live first-letter caps ], decoration: InputDecoration( hintText: "Area / locality", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), border: const OutlineInputBorder(), isDense: true, ), textInputAction: TextInputAction.done, ), ), _LabeledField( label: "Status *", child: DropdownButtonFormField( value: _status, items: _statusOptions .map((s) => DropdownMenuItem(value: s, child: Text(s))) .toList(), onChanged: (v) => setState(() => _status = v), validator: (v) => v == null || v.isEmpty ? "Status is required" : null, isExpanded: true, alignment: Alignment.centerLeft, hint: Text( "Select status", style: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), ), icon: const Icon(Icons.keyboard_arrow_down_rounded), decoration: const InputDecoration( border: OutlineInputBorder(), isDense: false, contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 14), ), ), ), const SizedBox(height: 16), ElevatedButton( onPressed: _addDriver, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF8270DB), foregroundColor: Colors.white, minimumSize: const Size(343, 41), // Width & Height padding: const EdgeInsets.fromLTRB(24, 12, 24, 12),), child: const Text("Add Driver"), ), ], ), ), ), ); }, ); } } // ============ UI Helper ============== class _LabeledField extends StatelessWidget { final String label; final Widget child; const _LabeledField({required this.label, required this.child}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(bottom: 14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600)), const SizedBox(height: 6), child, ], ), ); } }