import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:supplier_new/common/settings.dart'; import 'employees.dart'; import 'fleet_1.dart'; void main() => runApp(const MaterialApp(home: FleetStep1Page())); 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 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() { final ok = _formKey.currentState?.validate() ?? false; setState(() {}); // in case you show chip validation below labels if (!ok || selectedFeatures.isEmpty) { if (selectedFeatures.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("Select at least one Tanker Feature")), ); } return; } _tankers.add(_buildPayload()); _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: "Tanker Features *", 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: left-aligned, vertically centered by padding hint: Text( "Select Features", 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: () { Navigator.push( context, MaterialPageRoute(builder: (_) => const FleetStep2Page()), ); }, 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), ), ), ], ), ); } }