import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/resources/source_location1.dart'; import 'Fleet_1.dart'; void main() => runApp(const MaterialApp(home: SourceLocation())); class SourceLocation extends StatefulWidget { const SourceLocation({super.key}); @override State createState() => _SourceLocationState(); } class _SourceLocationState extends State { final _formKey = GlobalKey(); // Controllers final _nameCtrl = TextEditingController(); final _mobileCtrl = TextEditingController(); final _altMobileCtrl = TextEditingController(); // Dropdowns final List waterTypes = [ "Drinking Water", "Industrial", "Construction", "Non-potable", ]; String? selectedWaterType; String? selectedLicense; final List yearOptions = ["1", "2", "3", "4", "5"]; String? selectedExperience; // Data bucket final List> _drivers = []; // Validators 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; } @override void dispose() { _nameCtrl.dispose(); _mobileCtrl.dispose(); _altMobileCtrl.dispose(); super.dispose(); } bool addBusinessAsSource = false; Map _buildPayload() => { "driver_name": _nameCtrl.text.trim(), "license_number": selectedLicense, "experience_years": selectedExperience, "phone": _mobileCtrl.text.trim(), "alt_phone": _altMobileCtrl.text.trim(), }; void _clearForm() { _nameCtrl.clear(); _mobileCtrl.clear(); _altMobileCtrl.clear(); selectedLicense = null; selectedExperience = null; setState(() {}); } void _addDriver() { final ok = _formKey.currentState?.validate() ?? false; setState(() {}); // ensure error texts render if (!ok || selectedLicense == null || selectedExperience == null || selectedLicense!.isEmpty || selectedExperience!.isEmpty) { if (selectedLicense == null || selectedExperience == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Please select License & Experience")), ); } return; } _drivers.add(_buildPayload()); _clearForm(); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Driver added (${_drivers.length})")), ); } @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: [ Padding( padding: const EdgeInsets.fromLTRB(10, 10, 0, 10), child: IconButton( splashRadius: 20, padding: EdgeInsets.zero, icon: const Image(image: AssetImage('images/calendar_appbar.png'), width: 22, height: 22), onPressed: () {}, ), ), Padding( padding: const EdgeInsets.fromLTRB(0, 10, 10, 10), child: IconButton( splashRadius: 20, padding: EdgeInsets.zero, icon: Image.asset('images/notification_appbar.png', width: 22, height: 22), onPressed: () {}, ), ), ], ), body: SafeArea( child: Form( key: _formKey, child: ListView( padding: const EdgeInsets.fromLTRB(20, 10, 20, 24), children: [ // Step indicator Text( "Step 1/5", style: fontTextStyle(16, const Color(0xFFC3C4C4), FontWeight.w500), ), const SizedBox(height: 16), Row( children: List.generate(4, (index) { return Expanded( child: Container( margin: const EdgeInsets.symmetric(horizontal: 2), height: 5, decoration: BoxDecoration( color: index < 4 ? const Color(0xFFC3C4C4) : Colors.grey, borderRadius: BorderRadius.circular(2), ), ), ); }), ), const SizedBox(height: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text("SORURCE LOCATION", style: fontTextStyle(20, const Color(0xFF515253), FontWeight.w600)), const SizedBox(height: 8), Container( width: 24, height: 24, decoration: const BoxDecoration( image: DecorationImage(image: AssetImage('images/flag.png'), fit: BoxFit.contain), ), ), ], ), const SizedBox(height: 6), Text( "Add your source Location", style: fontTextStyle(14, const Color(0xFF939495), FontWeight.w500), ), const SizedBox(height: 6), Align( alignment: Alignment.centerLeft, // keep the whole thing on the left child: Row( mainAxisSize: MainAxisSize.min, // don't stretch full width children: [ Checkbox( value: addBusinessAsSource, onChanged: (v) => setState(() => addBusinessAsSource = v ?? false), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: const VisualDensity(horizontal: -4, vertical: -4), ), const SizedBox(width: 6), // control the exact gap Text( "Add Business Location as a Source Location", style: fontTextStyle(14, const Color(0xFF939495), FontWeight.w500), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ), const SizedBox(height: 16), // Section header (just the bar) _SectionHeaderBar( title: "SOURCE LOCATION #1", icon: Image.asset('images/arrow-up.png', width: 16, height: 16), radius: 20, ), const SizedBox(height: 12), // === Fields _LabeledField( label: "Location Name *", child: TextFormField( controller: _nameCtrl, validator: (v) => _required(v, field: "Location Name"), decoration: InputDecoration( hintText: "Location Name", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), border: OutlineInputBorder(), isDense: true, ), textInputAction: TextInputAction.next, ), ), _LabeledField( label: "Mobile Number *", child: TextFormField( controller: _mobileCtrl, validator: (v) => _validatePhone(v, label: "Mobile Number"), keyboardType: TextInputType.phone, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(10), ], decoration: InputDecoration( hintText: "Mobile Number", hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), border: const OutlineInputBorder(), isDense: true, ), textInputAction: TextInputAction.next, ), ), Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: _addDriver, icon: Image.asset('images/Add_icon.png', width: 16, height: 16), label: Text( "Add Location on map", style: fontTextStyle(14, const Color(0xFF646566), FontWeight.w600), ), ), ), const SizedBox(height: 12), ], ), _LabeledField( label: "Water Type *", child: DropdownButtonFormField( value: selectedWaterType, items: waterTypes .map((w) => DropdownMenuItem(value: w, child: Text(w))) .toList(), onChanged: (v) => setState(() => selectedWaterType = v), validator: (v) => v == null || v.isEmpty ? "Water Type is required" : null, isExpanded: true, alignment: Alignment.centerLeft, hint: Text( "Select Water Type", style: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), ), icon: Image.asset('images/downarrow.png', width: 16, height: 16), decoration: const InputDecoration( border: OutlineInputBorder(), isDense: false, contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 14), ), ), ), const SizedBox(height: 20), // Actions Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: _addDriver, icon: Image.asset('images/Add_icon.png', width: 16, height: 16), label: Text( "Add Location", 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: () { // TODO: Navigate to the next step/screen Navigator.push(context, MaterialPageRoute(builder: (_) => const SourceLocation1())); // ScaffoldMessenger.of(context).showSnackBar( // SnackBar(content: Text("Saved ${_drivers.length} driver(s). Proceeding…")), // ); }, child: Text( "Continue", style: fontTextStyle(14, Colors.white, FontWeight.w400), ), ), ), ], ), ], ), ), ), ); } } // ======= UI helpers ======= class _SectionHeaderBar extends StatelessWidget { final String title; final Widget? icon; final Color backgroundColor; final Color borderColor; final double radius; const _SectionHeaderBar({ required this.title, this.icon, this.backgroundColor = const Color(0xFFEEEEEE), this.borderColor = const Color(0xFFE5E7EB), this.radius = 12, Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: backgroundColor, border: Border.all(color: borderColor, width: 1), borderRadius: BorderRadius.circular(radius), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.04), blurRadius: 6, offset: const Offset(0, 2), ), ], ), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), child: Row( children: [ Expanded( child: Text( title, style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w600), ), ), if (icon != null) icon!, ], ), ); } } class _LabeledField extends StatelessWidget { final String label; final Widget child; final String? Function()? validator; // (kept from your earlier helper; not used here) const _LabeledField({ required this.label, required this.child, this.validator, }); @override Widget build(BuildContext context) { final errorText = validator != null ? validator!() : null; return Padding( padding: const EdgeInsets.only(bottom: 14.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600)), const SizedBox(height: 6), child, if (errorText != null) Padding( padding: const EdgeInsets.only(top: 6), child: Text( errorText, style: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), ), ), ], ), ); } }