diff --git a/lib/profile/availability.dart b/lib/profile/availability.dart new file mode 100644 index 0000000..e1fd76a --- /dev/null +++ b/lib/profile/availability.dart @@ -0,0 +1,354 @@ +import 'package:flutter/material.dart'; +import 'package:supplier_new/common/settings.dart'; +import 'package:supplier_new/resources/resources_fleet.dart'; +import 'package:supplier_new/resources/source_location2.dart'; + +import 'fleet.dart'; + +void main() => runApp(const MaterialApp(home: AvailabilityScreen())); + +class AvailabilityScreen extends StatefulWidget { + const AvailabilityScreen({super.key}); + + @override + _AvailabilityScreenState createState() => _AvailabilityScreenState(); +} + +class _AvailabilityScreenState extends State { + final TextEditingController _advanceNoticeController = + TextEditingController(); + final TextEditingController _minDeliveriesController = + TextEditingController(); + final TextEditingController _phoneController = TextEditingController(); + TimeOfDay? _weekdayStartTime; + TimeOfDay? _weekdayEndTime; + TimeOfDay? _weekendStartTime; + TimeOfDay? _weekendEndTime; + + + final List _days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; + List _selectedDays = List.generate(7, (index) => false); + + Future _pickTime({required int slot}) async { + final TimeOfDay initialTime = TimeOfDay.now(); + final TimeOfDay? picked = + await showTimePicker(context: context, initialTime: initialTime); + if (picked == null) return; + setState(() { + switch (slot) { + case 0: + _weekdayStartTime = picked; + break; + case 1: + _weekdayEndTime = picked; + break; + case 2: + _weekendStartTime = picked; + break; + case 3: + _weekendEndTime = picked; + break; + } + }); + } + + @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: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Step indicator + Text('Step 5/5', + style: fontTextStyle(14, Colors.grey, FontWeight.normal)), + const SizedBox(height: 4), + 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: 20), + + // Availability + Text('AVAILABILITY', + style: fontTextStyle( + 16, const Color(0xFF2D2E30), FontWeight.w500)), + const SizedBox(height: 12), + Container( + width: 24, + height: 24, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('images/calendar_check.png'), + fit: BoxFit.contain), + ), + ), + const SizedBox(height: 5), + Text('Set your operating schedule', + style: fontTextStyle( + 14, const Color(0xFF939495), FontWeight.w500)), + const SizedBox(height: 10), + + Text('AVAILABILITY', + style: fontTextStyle( + 14, const Color(0xFF8270DB), FontWeight.w600)), + const SizedBox(height: 12), + Text('Advance Notice Required (hours) *', + style: fontTextStyle( + 12, const Color(0xFF2F3036), FontWeight.w600)), + const SizedBox(height: 5), + TextField( + controller: _advanceNoticeController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + border: OutlineInputBorder(), + hintText: "1", + hintStyle: + fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), + ), + ), + + const SizedBox(height: 10), + + // Minimum Deliveries + Text('Minimum Deliveries (per day) *', + style: fontTextStyle( + 12, const Color(0xFF2F3036), FontWeight.w600)), + const SizedBox(height: 5), + TextField( + controller: _minDeliveriesController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + border: OutlineInputBorder(), + hintText: '10', + hintStyle: + fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), + ), + ), + const SizedBox(height: 10), + + // Days of Availability + Text( + 'Days of Availability *', + style: + fontTextStyle(12, const Color(0xFF251525), FontWeight.w600), + ), + const SizedBox(height: 5), + // Place this inside your build() where you want the row of day boxes + // Place this where you want the row of day boxes + Theme( + data: Theme.of(context).copyWith( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + visualDensity: VisualDensity.compact, + ), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: List.generate(_days.length, (index) { + final day = _days[index]; + final selected = _selectedDays[index]; + + return Padding( + padding: const EdgeInsets.only(right: 7.0), // gap 10px + child: GestureDetector( + onTap: () => setState( + () => _selectedDays[index] = !_selectedDays[index]), + onSecondaryTap: () {}, + // swallow right-click / context menu + child: SizedBox( + width: 44, // fixed width + height: 42, // fixed height + child: Container( + padding: const EdgeInsets.all(8), + // inner padding 8px + decoration: BoxDecoration( + color: selected + ? const Color(0xFF6F5FBA) + : Colors.white, + // selected background + borderRadius: BorderRadius.circular(9), + // radius 9px + border: Border.all( + color: const Color(0xFF6F5FBA), + width: 0.5, // border 0.5px + ), + ), + alignment: Alignment.center, + child: Text( + day, + textAlign: TextAlign.center, + style: fontTextStyle( + 12, + selected + ? Colors.white + : const Color(0xFF515253), + FontWeight.w600, + ), + ), + ), + ), + ), + ); + }), + ), + ), + ), + + const SizedBox(height: 10), + + // Phone Number + Text('Phone Number *', + style: fontTextStyle( + 12, const Color(0xFF2F3036), FontWeight.w600)), + const SizedBox(height: 5), + TextField( + controller: _phoneController, + keyboardType: TextInputType.phone, + decoration: InputDecoration( + border: OutlineInputBorder(), + hintText: '+91 | Mobile Number', + hintStyle: + fontTextStyle(14, const Color(0xFF939495), FontWeight.w400), + ), + ), + const SizedBox(height: 20), + + // Operating Hours + Text('Operating Hours', + style: fontTextStyle( + 14, const Color(0xFF8270DB), FontWeight.w600)), + const SizedBox(height: 5), + LayoutBuilder( + builder: (context, constraints) { + // compute width for 2 columns with 10px gap and 16px padding (adjust if needed) + final double totalGap = 10.0; + final double itemWidth = (constraints.maxWidth - totalGap) / 2; + + Widget buildTimeBox({ + required String label, + required TimeOfDay? time, + required int slotIndex, + }) { + return SizedBox( + width: itemWidth, + // smaller height than before + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: fontTextStyle(12, const Color(0xFF515253), FontWeight.w600)), + const SizedBox(height: 5), + GestureDetector( + onTap: () => _pickTime(slot: slotIndex), + child: Container( + height: 42, // smaller height + padding: const EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey.shade400), + borderRadius: BorderRadius.circular(6), + ), + alignment: Alignment.centerLeft, + child: Text( + time != null ? time.format(context) : '--:--', + style: fontTextStyle(14, Colors.black, FontWeight.normal), + ), + ), + ), + ], + ), + ); + } + + return Column( + children: [ + Row( + children: [ + buildTimeBox(label: 'Weekday Start Time *', time: _weekdayStartTime, slotIndex: 0), + const SizedBox(width: 10), + buildTimeBox(label: 'Weekday End Time *', time: _weekdayEndTime, slotIndex: 1), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + buildTimeBox(label: 'Weekend Start Time', time: _weekendStartTime, slotIndex: 2), + const SizedBox(width: 10), + buildTimeBox(label: 'Weekend End Time', time: _weekendEndTime, slotIndex: 3), + ], + ), + ], + ); + }, + ), + + 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 FleetStep1Page())); + + }, + child: Text( + " Save \$ Continue", + style: fontTextStyle(14, Colors.white, FontWeight.w400), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/profile/employees.dart b/lib/profile/employees.dart new file mode 100644 index 0000000..a1bc2db --- /dev/null +++ b/lib/profile/employees.dart @@ -0,0 +1,441 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:supplier_new/common/settings.dart'; +import 'package:supplier_new/resources/source_location.dart'; + +import 'Fleet_1.dart'; + + +class FleetEmployees extends StatefulWidget { + const FleetEmployees({super.key}); + + @override + State createState() => _FleetEmployeesState(); +} + +class _FleetEmployeesState extends State { + final _formKey = GlobalKey(); + + // Controllers + final _nameCtrl = TextEditingController(); + final _mobileCtrl = TextEditingController(); + final _altMobileCtrl = TextEditingController(); + + // Dropdowns + final List licenseNumbers = [ + "UP3220050012345", + "UP3220050012355", + "UP3220050012365", + "UP3220050012375", + ]; + 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(); + } + + 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() async{ + final ok = _formKey.currentState?.validate() ?? false; + setState(() {}); // ensure error texts render + if (!ok || + selectedLicense == null || + selectedExperience == null || + selectedExperience!.isEmpty) { + if (selectedExperience == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text("Please select License & Experience")), + ); + } + return; + } + var payload = new Map(); + payload["Name"] = _nameCtrl.text.toString(); + payload["license_number"] =selectedLicense.toString(); + payload["address"] = AppSettings.userAddress; + payload["supplier_name"] = AppSettings.userName; + payload["phone"] = _mobileCtrl.text.toString(); + payload["alternativeContactNumber"] =''; + payload["years_of_experience"] =selectedExperience.toString(); + payload["status"] = 'string'; + + + + bool tankStatus = await AppSettings.addDrivers(payload); + + try { + if (tankStatus) { + AppSettings.longSuccessToast("Tanker Created Successfully"); + _nameCtrl.text = ''; + Navigator.pop(context,true); + + } + else { + AppSettings.longFailedToast("Tanker Creation failed"); + } + } catch (exception) { + print(exception); + } + _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), + + // Header block + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("EMPLOYEES", 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/manage-users.png'), fit: BoxFit.contain), + ), + ), + ], + ), + const SizedBox(height: 6), + Text( + "Details about your water tanker fleet", + style: fontTextStyle(14, const Color(0xFF939495), FontWeight.w500), + ), + const SizedBox(height: 16), + + // Section header (just the bar) + _SectionHeaderBar( + title: "DRIVER #1", + icon: Image.asset('images/arrow-up.png', width: 16, height: 16), + radius: 20, + ), + const SizedBox(height: 12), + + // === Fields + _LabeledField( + label: "Driver Name *", + child: TextFormField( + controller: _nameCtrl, + validator: (v) => _required(v, field: "Driver Name"), + decoration: const InputDecoration( + hintText: "Full Name", + border: OutlineInputBorder(), + isDense: true, + ), + textInputAction: TextInputAction.next, + ), + ), + + _LabeledField( + label: "Driver 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 || v.isEmpty ? "Driver License required" : null, + isExpanded: true, + alignment: Alignment.centerLeft, + hint: Text( + "Select License Number", + 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), + ), + ), + ), + + _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 || v.isEmpty ? "Experience is required" : null, + isExpanded: true, + alignment: Alignment.centerLeft, + hint: Text( + "Years", + 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), + ), + ), + ), + + _LabeledField( + label: "Phone Number *", + child: TextFormField( + controller: _mobileCtrl, + validator: (v) => _validatePhone(v, label: "Phone 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, + ), + ), + + _LabeledField( + label: "Alternate Phone Number", + child: TextFormField( + controller: _altMobileCtrl, + validator: (v) { + if (v == null || v.trim().isEmpty) return null; // optional + return _validatePhone(v, label: "Alternate Phone 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, + ), + ), + + 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 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: () { + // // TODO: Navigate to the next step/screen + // Navigator.push(context, MaterialPageRoute(builder: (_) => const SourceLocation())); + // // 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), + ), + ), + ], + ), + ); + } +} diff --git a/lib/profile/fleet.dart b/lib/profile/fleet.dart new file mode 100644 index 0000000..e8c6399 --- /dev/null +++ b/lib/profile/fleet.dart @@ -0,0 +1,566 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:supplier_new/common/settings.dart'; + +class FleetStep1Page extends StatefulWidget { + const FleetStep1Page({super.key}); + + @override + State createState() => _FleetStep1PageState(); +} + +class _FleetStep1PageState extends State { + final _formKey = GlobalKey(); + + // Controllers + final _nameCtrl = TextEditingController(); + final _capacityCtrl = TextEditingController(); // hint-like + final _plateCtrl = TextEditingController(); + final _mfgYearCtrl = TextEditingController(); + final _insExpiryCtrl = TextEditingController(); + + // Dropdowns / selections + final List tankerTypes = [ + "Rigid Truck", + "Trailer", + "Mini Tanker", + "Hydraulic", + ]; + String? selectedType; + + final List typeOfWater = [ + "Bore Water", + "Drinking Water", + ]; + String? selectedTypeOfWater; + + final List featureOptions = [ + "GPS", + "Stainless Steel", + "Partitioned", + "Food Grade", + "Top Loading", + "Bottom Loading", + ]; + final Set selectedFeatures = {}; + + // Helpers + Future _pickInsuranceDate() async { + final now = DateTime.now(); + final date = await showDatePicker( + context: context, + initialDate: now, + firstDate: DateTime(now.year - 1), + lastDate: DateTime(now.year + 10), + helpText: "Select Insurance Expiry Date", + ); + if (date != null) { + _insExpiryCtrl.text = + "${date.year.toString().padLeft(4, '0')}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}"; + setState(() {}); + } + } + + String? _required(String? v, {String field = "This field"}) { + if (v == null || v.trim().isEmpty) return "$field is required"; + return null; + } + + @override + void dispose() { + _nameCtrl.dispose(); + _capacityCtrl.dispose(); + _plateCtrl.dispose(); + _mfgYearCtrl.dispose(); + _insExpiryCtrl.dispose(); + super.dispose(); + } + + // Store multiple tanker entries + final List> _tankers = []; + + Map _buildPayload() => { + "tanker_name": _nameCtrl.text.trim(), + "capacity": _capacityCtrl.text.trim(), + "type": selectedType, + "features": selectedFeatures.toList(), + "license_plate": _plateCtrl.text.trim(), + "manufacturing_year": _mfgYearCtrl.text.trim(), + "insurance_expiry": _insExpiryCtrl.text.trim(), + }; + + void _clearForm() { + _nameCtrl.clear(); + _capacityCtrl.text = "10,000"; + _plateCtrl.text = "AB 05 H 4948"; + _mfgYearCtrl.clear(); + _insExpiryCtrl.clear(); + selectedType = null; + selectedFeatures.clear(); + setState(() {}); + } + + void _addTanker() async{ + final ok = _formKey.currentState?.validate() ?? false; + setState(() {}); // in case you show chip validation below labels + var payload = new Map(); + payload["tankerName"] = _nameCtrl.text.toString(); + payload["capacity"] = _capacityCtrl.text.toString(); + payload["typeofwater"] =selectedTypeOfWater.toString(); + payload["supplier_address"] = AppSettings.userAddress; + payload["supplier_name"] = AppSettings.userName; + payload["phoneNumber"] = AppSettings.phoneNumber; + payload["tanker_type"] =selectedType; + payload["license_plate"] =_plateCtrl.text.trim(); + payload["manufacturing_year"] = _mfgYearCtrl.text.trim(); + payload["insurance_exp_date"] = _insExpiryCtrl.text.trim(); + + + bool tankStatus = await AppSettings.addTankers(payload); + + try { + if (tankStatus) { + AppSettings.longSuccessToast("Tanker Created Successfully"); + _nameCtrl.text = ''; + _capacityCtrl.text = ''; + Navigator.pop(context,true); + + } + else { + AppSettings.longFailedToast("Tanker Creation failed"); + } + } catch (exception) { + print(exception); + } + _clearForm(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Tanker added (${_tankers.length})")), + ); + } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + title: const Text("Complete Profile"), + actions: [ + Padding(padding: EdgeInsets.fromLTRB(10,10,0,10), + child: IconButton( + icon: Image( + image: AssetImage('images/calendar_appbar.png') + + ), + onPressed: (){ + + }, + ), + ), + + Padding(padding: EdgeInsets.fromLTRB(0,10,10,10), + child: IconButton( + icon: Image.asset( + 'images/notification_appbar.png', // Example URL image + ), + 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), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "FLEET", + 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/truck.png'), + fit: BoxFit.contain, + ), + ), + ), + ], + ), + + const SizedBox(height: 6), + Text( + "Details about your water tanker fleet", + style: + fontTextStyle(14, const Color(0xFF939495), FontWeight.w500), + ), + const SizedBox(height: 16), + + _SectionHeaderBar( + title: "WATER TANKER #1", + icon: Image.asset('images/arrow-up.png', width: 16, height: 16), + radius: 20, + ), + const SizedBox(height: 12), + + _LabeledField( + label: "Tanker Name *", + child: TextFormField( + controller: _nameCtrl, + validator: (v) => _required(v, field: "Tanker Name"), + decoration: const InputDecoration( + hintText: "Enter Tanker Name", + border: OutlineInputBorder(), + isDense: true, + ), + textInputAction: TextInputAction.next, + ), + ), + + _LabeledField( + label: "Tanker Capacity (in L) *", + child: TextFormField( + controller: _capacityCtrl, + validator: (v) => _required(v, field: "Tanker Capacity"), + decoration: InputDecoration( + hintText: "10,000 L", + hintStyle: fontTextStyle( + 14, const Color(0xFF939495), FontWeight.w400), + border: const OutlineInputBorder(), + isDense: true, + ), + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[0-9,]')), + ], + textInputAction: TextInputAction.next, + ), + ), + + _LabeledField( + label: "Tanker Type *", + child: DropdownButtonFormField( + value: selectedType, + items: tankerTypes + .map((t) => DropdownMenuItem(value: t, child: Text(t))) + .toList(), + onChanged: (v) => setState(() => selectedType = v), + validator: (v) => + v == null || v.isEmpty ? "Tanker Type is required" : null, + isExpanded: true, + alignment: Alignment.centerLeft, + hint: Text( + "Select 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), + ), + ), + ), + + _LabeledField( + label: "Type of water *", + child: DropdownButtonFormField( + value: selectedTypeOfWater, + items: typeOfWater + .map((t) => DropdownMenuItem(value: t, child: Text(t))) + .toList(), + onChanged: (v) => setState(() => selectedTypeOfWater = v), + validator: (v) => + v == null || v.isEmpty ? "Type of water is required" : null, + isExpanded: true, + alignment: Alignment.centerLeft, + + // <-- Hint: left-aligned, vertically centered by padding + hint: Text( + "Select type of water", + 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, // keep some height + contentPadding: + EdgeInsets.symmetric(horizontal: 12, vertical: 14), + ), + ), + ), + + _LabeledField( + label: "License Plate *", + child: TextFormField( + controller: _plateCtrl, + validator: (v) => _required(v, field: "License Plate"), + decoration: InputDecoration( + hintText: "AB 05 H 4948", + hintStyle: fontTextStyle( + 14, const Color(0xFF939495), FontWeight.w400), + border: const OutlineInputBorder(), + isDense: true, + ), + textCapitalization: TextCapitalization.characters, + textInputAction: TextInputAction.next, + ), + ), + + _LabeledField( + label: "Manufacturing Year (opt)", + child: TextFormField( + controller: _mfgYearCtrl, + decoration: InputDecoration( + hintText: "YYYY", + hintStyle: fontTextStyle( + 14, const Color(0xFF939495), FontWeight.w400), + border: const OutlineInputBorder(), + isDense: true, + ), + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + LengthLimitingTextInputFormatter(4), + ], + textInputAction: TextInputAction.next, + ), + ), + + _LabeledField( + label: "Insurance Expiry Date (opt)", + child: TextFormField( + controller: _insExpiryCtrl, + readOnly: true, + decoration: InputDecoration( + hintText: "DD-MM-YYYY", + hintStyle: fontTextStyle( + 14, const Color(0xFF939495), FontWeight.w400), + border: const OutlineInputBorder(), + isDense: true, + ), + onTap: _pickInsuranceDate, + ), + ), + + const SizedBox(height: 20), + // Save / Continue + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SizedBox( + width: double.infinity, + child: OutlinedButton.icon( + onPressed: _addTanker, + icon: Image.asset('images/Add_icon.png', + width: 16, height: 16), + // pulsing image + label: Text( + "Add Tanker", + style: fontTextStyle( + 14, const Color(0xFF646566), FontWeight.w600), + ), + ), + ), + + const SizedBox(height: 12), + + // Continue (primary) + /* SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF8270DB), // purple bg + foregroundColor: Colors.white, // ripple/icon/text color + padding: const EdgeInsets.symmetric(vertical: 14), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24)), + ), + onPressed: () async{ + + if (_nameCtrl.text != '' && + _capacityCtrl.text != '' && + _plateCtrl.text != '') { + + var payload = new Map(); + payload["tankerName"] = _nameCtrl.text.toString(); + payload["capacity"] = _capacityCtrl.text.toString(); + payload["typeofwater"] =selectedTypeOfWater.toString(); + payload["supplier_address"] = AppSettings.userAddress; + payload["supplier_name"] = AppSettings.userName; + + bool tankStatus = await AppSettings.addTankers(payload); + + try { + if (tankStatus) { + AppSettings.longSuccessToast( + "Tanker Created Successfully"); + _nameCtrl.text = ''; + //tankerPhoneNumberController.text = ''; + _capacityCtrl.text = ''; + //tankerAlternativePhoneNumberController.text=''; + Navigator.pop(context); + *//* await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => TankersView()), + );*//* + + } + else { + AppSettings.longFailedToast("Tanker Creation failed"); + } + } catch (exception) { + print(exception); + } + } else { + AppSettings.longFailedToast("Please enter valid details"); + } + + _nameCtrl.clear(); + _capacityCtrl.text = "10,000"; + _plateCtrl.text = "AB 05 H 4948"; + _mfgYearCtrl.clear(); + _insExpiryCtrl.clear(); + selectedType = null; + selectedFeatures.clear(); + }, + child: Text( + "Continue", + style: fontTextStyle( + 14, Colors.white, FontWeight.w400), // white text + ), + ), + )*/ + ], + ) + ], + ), + ), + ), + ); + } +} + + +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 = 8, + 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; + + const _LabeledField({ + required this.label, + required this.child, + this.validator, + }); + + @override + Widget build(BuildContext context) { + final labelStyle = Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: Colors.grey.shade800); + + 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), + ), + ), + ], + ), + ); + } +} diff --git a/lib/profile/fleet_1.dart b/lib/profile/fleet_1.dart new file mode 100644 index 0000000..bc84f6f --- /dev/null +++ b/lib/profile/fleet_1.dart @@ -0,0 +1,213 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:supplier_new/common/settings.dart'; + + + +void main() => runApp(const MaterialApp(home: FleetStep2Page())); + +class FleetStep2Page extends StatefulWidget { + const FleetStep2Page({super.key}); + + @override + State createState() => _FleetStep2PageState(); +} + +class _FleetStep2PageState extends State { + final _formKey = GlobalKey(); + + // Store multiple tanker entries (collected on Add Tanker) + final List> _tankers = []; + + // Minimal payload + clear (no fields on Step 2 yet) + Map _buildPayload() => { + "added_at": DateTime.now().toIso8601String(), + "step": 2, + }; + void _clearForm() { + setState(() {}); + } + + void _addTanker() { + final ok = _formKey.currentState?.validate() ?? true; // no fields => true + if (!ok) return; + _tankers.add(_buildPayload()); + _clearForm(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Tanker added (${_tankers.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 2/5", + style: fontTextStyle(16, const Color(0xFFC3C4C4), FontWeight.w500), + ), + const SizedBox(height: 16), + + // FLEET header + small image below (left-aligned) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text("FLEET", 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/truck.png'), fit: BoxFit.contain), + ), + ), + ], + ), + + const SizedBox(height: 6), + Text( + "Details about your water tanker fleet", + style: fontTextStyle(14, const Color(0xFF939495), FontWeight.w500), + ), + const SizedBox(height: 16), + + // Header bar ONLY (rounded, separate "card" look) + _SectionHeaderBar( + title: "WATER TANKER #1", + icon: Image.asset('images/arrow-up.png', width: 16, height: 16), + radius: 20, // rounded corners + ), + const SizedBox(height: 12), + + // (No form fields on Step 2 per your snippet) + + const SizedBox(height: 20), + + // Actions + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SizedBox( + width: double.infinity, + child: OutlinedButton.icon( + onPressed: _addTanker, + icon: Image.asset('images/Add_icon.png', width: 16, height: 16), + label: Text( + "Add Tanker", + 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 FleetEmployees()), + // ); + }, + child: Text( + "Continue", + style: fontTextStyle(14, Colors.white, FontWeight.w400), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } +} + +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!, + ], + ), + ); + } +} diff --git a/lib/profile/source_location.dart b/lib/profile/source_location.dart new file mode 100644 index 0000000..9592fae --- /dev/null +++ b/lib/profile/source_location.dart @@ -0,0 +1,594 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:supplier_new/common/settings.dart'; +import '../common/keys.dart'; +import '../google_maps_place_picker_mb/src/models/pick_result.dart'; +import '../google_maps_place_picker_mb/src/place_picker.dart'; +import 'package:supplier_new/google_maps_place_picker_mb/google_maps_place_picker.dart'; +import 'dart:io' show File, Platform; +import 'package:google_maps_flutter_android/google_maps_flutter_android.dart'; +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; +import 'package:location/location.dart' as locationmap; + +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 _locationNameController = TextEditingController(); + final _mobileCtrl = TextEditingController(); + String address=''; + + String address1 = ''; + String address2 = ''; + String city = ''; + String state = ''; + String zip = ''; + String country = ''; + double lat=0; + double lng=0; + + PickResult? selectedPlace; + + bool _mapsInitialized = false; + final String _mapsRenderer = "latest"; + + var kInitialPosition = const LatLng(15.462477, 78.717401); + + locationmap.Location location = locationmap.Location(); + + final GoogleMapsFlutterPlatform mapsImplementation = + GoogleMapsFlutterPlatform.instance; + + void initRenderer() { + if (_mapsInitialized) return; + if (mapsImplementation is GoogleMapsFlutterAndroid) { + switch (_mapsRenderer) { + case "legacy": + (mapsImplementation as GoogleMapsFlutterAndroid) + .initializeWithRenderer(AndroidMapRenderer.legacy); + break; + case "latest": + (mapsImplementation as GoogleMapsFlutterAndroid) + .initializeWithRenderer(AndroidMapRenderer.latest); + break; + } + } + setState(() { + _mapsInitialized = true; + }); + } + + + // Dropdowns + final List waterTypes = [ + "Drinking Water", + "Bore Water", + "Industrial", + "Construction", + "Non-potable", + ]; + String? selectedWaterType; + + // 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() { + _locationNameController.dispose(); + _mobileCtrl.dispose(); + super.dispose(); + } + bool addBusinessAsSource = false; + + + void _clearForm() { + _locationNameController.clear(); + _mobileCtrl.clear(); + selectedWaterType = null; + setState(() {}); + } + + void _addSourceLocation() async{ + final ok = _formKey.currentState?.validate() ?? false; + + if(addBusinessAsSource){ + setState(() { + address=AppSettings.userAddress; + lat=AppSettings.supplierLatitude; + lng=AppSettings.supplierLongitude; + }); + } + + setState(() {}); // ensure error texts render + if (!ok || + selectedWaterType == null || + selectedWaterType!.isEmpty) { + if (selectedWaterType == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text("Please select Water type")), + ); + } + return; + } + var payload = new Map(); + payload["location_name"] = _locationNameController.text.toString(); + payload["phone"] = _mobileCtrl.text.toString(); + payload["water_type"] =selectedWaterType.toString(); + payload["status"] ='string'; + payload["address"] = address; + payload["city"] = ''; + payload["state"] = ''; + payload["zip"] =''; + payload["latitude"] = lat; + payload["longitude"] = lng; + + + + bool tankStatus = await AppSettings.addSourceLocations(payload); + + try { + if (tankStatus) { + AppSettings.longSuccessToast("Source location added Successfully"); + _locationNameController.text = ''; + Navigator.pop(context,true); + + } + else { + AppSettings.longFailedToast("Tanker Creation failed"); + } + } catch (exception) { + print(exception); + } + _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 3/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: _locationNameController, + 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, + ), + ), + Visibility( + visible: !addBusinessAsSource, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SizedBox( + width: double.infinity, + child: OutlinedButton.icon( + onPressed: (){ + location.serviceEnabled().then((value) { + if (value) { + initRenderer(); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) { + return PlacePicker( + resizeToAvoidBottomInset: false, + hintText: "Find a place ...", + searchingText: "Please wait ...", + selectText: "Select place", + outsideOfPickAreaText: "Place not in area", + initialPosition: kInitialPosition, + useCurrentLocation: true, + selectInitialPosition: true, + usePinPointingSearch: true, + usePlaceDetailSearch: true, + zoomGesturesEnabled: true, + zoomControlsEnabled: true, + onMapCreated: (GoogleMapController controller) {}, + onPlacePicked: (PickResult result) { + setState(() { + selectedPlace = result; + lat=selectedPlace!.geometry!.location.lat; + lng=selectedPlace!.geometry!.location.lng; + if(selectedPlace!.types!.length==1){ + address = + selectedPlace!.formattedAddress!; + } + else{ + address =selectedPlace!.name!+', '+selectedPlace!.formattedAddress!; + } + Navigator.of(context).pop(); + }); + }, + onMapTypeChanged: (MapType mapType) {}, + apiKey: Platform.isAndroid + ? APIKeys.androidApiKey + : APIKeys.iosApiKey, + forceAndroidLocationManager: true, + ); + }, + ), + ); + } else { + showGeneralDialog( + context: context, + pageBuilder: (context, x, y) { + return Scaffold( + backgroundColor: Colors.grey.withOpacity(.5), + body: Center( + child: Container( + width: double.infinity, + height: 150, + padding: + const EdgeInsets.symmetric(horizontal: 20), + child: Card( + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + "Please enable the location", + style: TextStyle( + fontSize:18, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox( + height: 20, + ), + ElevatedButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text("Cancel"), + ), + ], + ), + ), + ), + ), + ), + ); + }, + ); + } + }); + }, + 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: _addSourceLocation, + 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), + ), + ), + ], + ), + ); + } +} diff --git a/lib/profile/source_location1.dart b/lib/profile/source_location1.dart new file mode 100644 index 0000000..c673979 --- /dev/null +++ b/lib/profile/source_location1.dart @@ -0,0 +1,315 @@ +import 'package:flutter/material.dart'; +import 'package:supplier_new/common/settings.dart'; +import 'package:supplier_new/resources/source_location2.dart'; + +void main() => runApp(const MaterialApp(home: SourceLocation1())); + +class SourceLocation1 extends StatefulWidget { + const SourceLocation1({super.key}); + + @override + State createState() => _SourceLocation1State(); +} + +class _SourceLocation1State extends State { + final _formKey = GlobalKey(); + + String _deliveryFrom = 'business'; + final TextEditingController _radiusController = + TextEditingController(text: "10"); + + @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: 16), + 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/marker-pin.png'), + fit: BoxFit.contain), + ), + ), + ], + ), + const SizedBox(height: 12), + Text( + "Define where you want to provide delivery services", + style: + fontTextStyle(14, const Color(0xFF939495), FontWeight.w500), + maxLines: 1, + softWrap: false, + ), + const SizedBox(height: 6), + // Radio ListTiles (vertical) + Column( + mainAxisSize: MainAxisSize.min, + children: [ + RadioListTile( + value: 'business', + groupValue: _deliveryFrom, + onChanged: (value) { + if (value == null) return; + setState(() => _deliveryFrom = value); + }, + title: Text( + "From Business Location", + style: fontTextStyle( + 14, const Color(0xFF2D2E30), FontWeight.w500), + ), + dense: true, + contentPadding: EdgeInsets.zero, + visualDensity: + const VisualDensity(horizontal: 0, vertical: -3), + ), + RadioListTile( + value: 'source', + groupValue: _deliveryFrom, + onChanged: (value) { + if (value == null) return; + setState(() => _deliveryFrom = value); + }, + title: Text( + "From Source Locations", + style: fontTextStyle( + 14, const Color(0xFF2D2E30), FontWeight.w500), + ), + dense: true, + contentPadding: EdgeInsets.zero, + visualDensity: + const VisualDensity(horizontal: 0, vertical: -3), + ), + ], + ), + + const SizedBox(height: 12), + Text( + "Delivery Radius (in Kms) *", + style: + fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500), + ), + const SizedBox(height: 6), + TextFormField( + controller: _radiusController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: "Enter radius in kms", + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + contentPadding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + ), + ), + const SizedBox(height: 12), + InkWell( + onTap: () => setState( + () => _customizeEachSource = !_customizeEachSource), + child: Padding( + padding: EdgeInsets.zero, + + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + + children: [ + + Checkbox( + value: _customizeEachSource, + onChanged: (val) => + setState(() => _customizeEachSource = val ?? false), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + + const SizedBox(width: 2), + Expanded( + child: Text( + "Customize for every each source location", + style: fontTextStyle( + 14, const Color(0xFF2D2E30), FontWeight.w500), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + + ], + ), + ), + ), + const SizedBox(height: 12), + Container( + width: 343, + height: 166, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('images/google_maps.png'), + fit: BoxFit.contain), + ), + ), + const SizedBox(height: 20), + 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: 20), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "24/7 Emergency services", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "Scheduled water deliveries", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "Bulk water deliveries", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "Long-term water delivery planes", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "Industrial/Commercial water deliveries", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + const SizedBox(height: 16), + 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 SourceLocation2())); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text("Saved ${_drivers.length} driver(s). Proceeding…")), + // ); + }, + child: Text( + "Continue", + style: fontTextStyle(14, Colors.white, FontWeight.w400), + ), + ), + ), + ], + ), + ), + ), + ); + } + + bool _customizeEachSource = false; +} + + diff --git a/lib/profile/source_location2.dart b/lib/profile/source_location2.dart new file mode 100644 index 0000000..2578033 --- /dev/null +++ b/lib/profile/source_location2.dart @@ -0,0 +1,415 @@ +import 'package:flutter/material.dart'; +import 'package:supplier_new/common/settings.dart'; +import 'package:supplier_new/resources/source_location2.dart'; + + +void main() => runApp(const MaterialApp(home: SourceLocation2())); + +class SourceLocation2 extends StatefulWidget { + const SourceLocation2({super.key}); + + @override + State createState() => _SourceLocation2State(); +} + +class _SourceLocation2State extends State { + final _formKey = GlobalKey(); + + String _deliveryFrom = 'business'; + final TextEditingController _radiusController = + TextEditingController(text: "10"); + + @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: 16), + 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/marker-pin.png'), + fit: BoxFit.contain), + ), + ), + ], + ), + const SizedBox(height: 12), + Text( + "Define where you want to provide delivery services", + style: + fontTextStyle(14, const Color(0xFF939495), FontWeight.w500), + maxLines: 1, + softWrap: false, + ), + const SizedBox(height: 6), + // Radio ListTiles (vertical) + Column( + mainAxisSize: MainAxisSize.min, + children: [ + RadioListTile( + value: 'business', + groupValue: _deliveryFrom, + onChanged: (value) { + if (value == null) return; + setState(() => _deliveryFrom = value); + }, + title: Text( + "From Business Location", + style: fontTextStyle( + 14, const Color(0xFF2D2E30), FontWeight.w500), + ), + dense: true, + contentPadding: EdgeInsets.zero, + visualDensity: + const VisualDensity(horizontal: 0, vertical: -3), + ), + RadioListTile( + value: 'source', + groupValue: _deliveryFrom, + onChanged: (value) { + if (value == null) return; + setState(() => _deliveryFrom = value); + }, + title: Text( + "From Source Locations", + style: fontTextStyle( + 14, const Color(0xFF2D2E30), FontWeight.w500), + ), + dense: true, + contentPadding: EdgeInsets.zero, + visualDensity: + const VisualDensity(horizontal: 0, vertical: -3), + ), + ], + ), + + const SizedBox(height: 12), + Text( + "Delivery Radius (in Kms) *", + style: + fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500), + ), + const SizedBox(height: 6), + TextFormField( + controller: _radiusController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: "Enter radius in kms", + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + contentPadding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + ), + ), + const SizedBox(height: 12), + InkWell( + onTap: () => setState( + () => _customizeEachSource = !_customizeEachSource), + child: Padding( + padding: EdgeInsets.zero, + + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + + children: [ + + Checkbox( + value: _customizeEachSource, + onChanged: (val) => + setState(() => _customizeEachSource = val ?? false), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + + const SizedBox(width: 2), + Expanded( + child: Text( + "Customize for every each source location", + style: fontTextStyle( + 14, const Color(0xFF2D2E30), FontWeight.w500), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + + ], + ), + ), + ), + const SizedBox(height: 12), + _SectionHeaderBar( + title: "SOURCE LOCATION #1", + radius: 29, + ), + + const SizedBox(height: 12), + Text( + "Delivery Radius (in Kms) *", + style: + fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500), + ), + const SizedBox(height: 6), + TextFormField( + controller: _radiusController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: "Enter radius in kms", + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + contentPadding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + ), + ), + const SizedBox(height: 12), + _SectionHeaderBar( + title: "SOURCE LOCATION #2", + radius: 29, + ), + + const SizedBox(height: 12), + Text( + "Delivery Radius (in Kms) *", + style: + fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500), + ), + const SizedBox(height: 6), + TextFormField( + controller: _radiusController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: "Enter radius in kms", + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + contentPadding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + ), + ), + + const SizedBox(height: 12), + Container( + width: 343, + height: 166, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('images/google_maps.png'), + fit: BoxFit.contain), + ), + ), + const SizedBox(height: 20), + 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: 20), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "24/7 Emergency services", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "Scheduled water deliveries", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "Bulk water deliveries", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "Long-term water delivery planes", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + const Icon(Icons.check_box_outline_blank, size: 20, color: Color(0xFF939495)), + const SizedBox(width: 8), + Text( + "Industrial/Commercial water deliveries", + style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w400), + ), + ], + ), + 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 AvailabilityScreen())); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar(content: Text("Saved ${_drivers.length} driver(s). Proceeding…")), + // ); + }, + child: Text( + " Save \$ Continue", + style: fontTextStyle(14, Colors.white, FontWeight.w400), + ), + + ), + ), + + ], + ), + ), + ), + ); + } + + bool _customizeEachSource = false; +} + +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: 12), + child: Row( + children: [ + Expanded( + child: Text( + title, + style: fontTextStyle(10, const Color(0xFF2D2E30), FontWeight.w600), + ), + ), + if (icon != null) icon!, + ], + ), + ); + } +} +