import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:supplier_new/common/settings.dart'; import '../resources/drivers_model.dart'; import '../resources/tankers_model.dart'; class ChangeDriverScreen extends StatefulWidget { var order; var status; ChangeDriverScreen({this.order, this.status}); @override State createState() => _ChangeDriverScreenState(); } class _ChangeDriverScreenState extends State { int advancePayable = 0; int advance = 0; double amountToPayAfterDelivery = 0.0; double totalFare = 0.0; bool isLoading = false; bool isTankersDataLoading = false; List driversList = []; List tankersList = []; TankersModel? orderTanker; DriversModel? orderDriver; @override void initState() { // TODO: implement initState super.initState(); _fetchTankers(); _fetchDrivers(); advance = 150; advancePayable = advance; totalFare = advance + double.parse(widget.order.quoted_amount); amountToPayAfterDelivery = totalFare - advancePayable; } Future _fetchDrivers() async { setState(() => isLoading = true); try { final response = await AppSettings.getDrivers(); final data = (jsonDecode(response)['data'] as List) .map((e) => DriversModel.fromJson(e)) .toList(); if (!mounted) return; // 🔎 Match driver by name (case-insensitive, trimmed) final wanted = (widget.order.delivery_agent_name ?? '').toString().trim().toLowerCase(); DriversModel? matched; for (final d in data) { final name = (d.driver_name ?? '').toString().trim().toLowerCase(); if (name == wanted) { matched = d; break; } } setState(() { driversList = data; orderDriver = matched; // store matched driver or null isLoading = false; }); } catch (e) { debugPrint("⚠️ Error fetching drivers: $e"); setState(() => isLoading = false); } } Future _fetchTankers() async { setState(() => isTankersDataLoading = true); try { final response = await AppSettings.getTankers(); final data = (jsonDecode(response)['data'] as List) .map((e) => TankersModel.fromJson(e)) .toList(); if (!mounted) return; // 🔎 Find tanker by name (case-insensitive, trimmed) final wanted = (widget.order.tanker_name ?? '').toString().trim().toLowerCase(); TankersModel? matched; for (final t in data) { final name = (t.tanker_name ?? '').toString().trim().toLowerCase(); if (name == wanted) { matched = t; break; } } setState(() { tankersList = data; orderTanker = matched; // <- store the matched tanker (or null if not found) isTankersDataLoading = false; }); } catch (e) { debugPrint("⚠️ Error fetching tankers: $e"); setState(() => isTankersDataLoading = false); } } Widget _assignedTankerDetails() { if (isTankersDataLoading) { return const Center(child: CircularProgressIndicator()); } // If not found, show a simple fallback using just the name from order if (orderTanker == null) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: const Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0XFFFFFFFF)), ), child: Row( children: [ Image.asset('images/square_avatar.png', width: 24, height: 24), const SizedBox(width: 8), Expanded( child: Text( widget.order.tanker_name ?? "Tanker", style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), // No details available ], ), ); } // ✅ Found: show full details from fetched TankersModel final t = orderTanker!; final availability = (t.availability ?? []).cast(); String? primaryStatus; const pref = ['in-use', 'available', 'filled', 'empty', 'maintenance']; for (final s in pref) { if (availability.any((x) => x.toLowerCase() == s)) { primaryStatus = s; break; } } primaryStatus ??= availability.isNotEmpty ? availability.first : null; Color _statusTextColor(String s) { switch (s.toLowerCase()) { case 'filled': return const Color(0xFF1D7AFC); case 'available': return const Color(0xFF0A9E04); case 'empty': return const Color(0xFFE2483D); case 'in-use': return const Color(0xFFEA843B); case 'maintenance': return const Color(0xFFD0AE3C); default: return const Color(0xFF2A2A2A); } } Widget _statusChip(String label) { final c = _statusTextColor(label); return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all(color: c, width: 1), ), child: Text(label, style: fontTextStyle(10, c, FontWeight.w400)), ); } Widget _line(String title, String value) { return Padding( padding: const EdgeInsets.only(top: 6), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title, style: fontTextStyle(12, const Color(0xFF646566), FontWeight.w400)), Flexible( child: Text(value, style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500), textAlign: TextAlign.right, overflow: TextOverflow.ellipsis, maxLines: 1), ), ], ), ); } return Container( padding: const EdgeInsets.all(0), decoration: BoxDecoration( color: const Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0XFFFFFFFF)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Image.asset('images/avatar.png', width: 24, height: 24), const SizedBox(width: 8), Expanded( child: Text( t.tanker_name ?? "", style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), if (primaryStatus != null) _statusChip(primaryStatus), ], ), const SizedBox(height: 8), Visibility( visible:(t.license_plate!="") , child: Text( t.license_plate ?? "", style: fontTextStyle(12, const Color(0XFF646566), FontWeight.w400), maxLines: 1, overflow: TextOverflow.ellipsis, ),) /* _line("License Plate", t.license_plate ?? ""), _line("Water Type", t.type_of_water ?? ""), _line("Capacity", t.capacity ?? ""), if ((t.supplier_name ?? "").isNotEmpty) _line("Owner", t.supplier_name),*/ ], ), ); } Widget _assignedDriverDetails() { if (isLoading) { return const Center(child: CircularProgressIndicator()); } if (orderDriver == null) { // fallback if not found return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: const Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0XFFC3C4C4)), ), child: Row( children: [ Image.asset('images/avatar.png', width: 24, height: 24), const SizedBox(width: 8), Expanded( child: Text( widget.order.delivery_agent_name ?? "Driver", style: fontTextStyle(14, const Color(0XFF2D2E30), FontWeight.w500), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ); } final d = orderDriver!; Color _statusTextColor(String s) { switch (s.toLowerCase()) { case 'available': return const Color(0XFF0A9E04); case 'on delivery': return const Color(0XFFD0AE3C); case 'offline': return const Color(0XFF939495); default: return greyColor; } } Widget _statusChip(String label) { final c = _statusTextColor(label); return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), border: Border.all(color: c, width: 1), ), child: Text(label, style: fontTextStyle(10, c, FontWeight.w400)), ); } Widget _line(String title, String value) { return Padding( padding: const EdgeInsets.only(top: 6), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(title, style: fontTextStyle(12, const Color(0xFF646566), FontWeight.w400)), Flexible( child: Text( value, style: fontTextStyle(12, const Color(0xFF2D2E30), FontWeight.w500), textAlign: TextAlign.right, overflow: TextOverflow.ellipsis, maxLines: 1, ), ), ], ), ); } return Container( padding: const EdgeInsets.all(0), decoration: BoxDecoration( color: const Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0XFFFFFFFF)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Image.asset('images/avatar.png', width: 24, height: 24), const SizedBox(width: 8), Expanded( child: Text( d.driver_name ?? "", style: fontTextStyle(14, const Color(0xFF2D2E30), FontWeight.w500), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), if ((d.status ?? "").isNotEmpty) _statusChip(d.status), ], ), /* const SizedBox(height: 8), _line("Phone", d.phone_number ?? ""),*/ ], ), ); } void _showAssignTankerBottomSheet() { // 🔸 Find default selected indexes int? selectedTankerIndex; int? selectedDriverIndex; int _capToLiters(dynamic cap) { if (cap == null) return -1; if (cap is num) return cap.round(); final s = cap.toString().toLowerCase().replaceAll(',', '').trim(); final match = RegExp(r'(\d+(\.\d+)?)').firstMatch(s); if (match == null) return -1; final n = double.tryParse(match.group(1)!) ?? -1; if (n < 0) return -1; if (s.contains('kl')) return (n * 1000).round(); return n.round(); } // 🧠 Preselect assigned tanker final filteredTankers = tankersList .where((t) => _capToLiters(t.capacity) == _capToLiters(widget.order.capacity)) .toList(); selectedTankerIndex = filteredTankers.indexWhere( (t) => t.tanker_name == widget.order.tanker_name); // 🧠 Preselect assigned driver selectedDriverIndex = driversList.indexWhere( (d) => d.driver_name == widget.order.delivery_agent_name); showModalBottomSheet( backgroundColor: const Color(0XFFFFFFFF), context: context, isScrollControlled: true, isDismissible: false, enableDrag: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), builder: (context) { return WillPopScope( onWillPop: () async => false, child: StatefulBuilder( builder: (context, setModalState) { return FractionallySizedBox( heightFactor: 0.95, child: Column( children: [ Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Center( child: Container( width: 60, height: 4, margin: const EdgeInsets.only(bottom: 12), decoration: BoxDecoration( color: const Color(0xFFE0E0E0), borderRadius: BorderRadius.circular(2), ), ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Edit Order", style: fontTextStyle(16, const Color(0XFF2A2A2A), FontWeight.w600), ), GestureDetector( onTap: () => Navigator.pop(context), child: Image.asset( 'images/cross.png', height: 24, width: 24, color: const Color(0XFF2A2A2A), ), ) ], ), const SizedBox(height: 16), /// 🛻 Tanker List Text( "SELECTED TANKER", style: fontTextStyle( 10, const Color(0XFF2D2E30), FontWeight.w600), ), const SizedBox(height: 12), isTankersDataLoading ? const Center(child: CircularProgressIndicator()) : (filteredTankers.isEmpty ? Center( child: Text( 'No Data Available For Capacity ${widget.order.capacity}', style: fontTextStyle( 12, const Color(0xFF939495), FontWeight.w500), ), ) : ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: filteredTankers.length, separatorBuilder: (_, __) => const SizedBox(height: 12), itemBuilder: (context, idx) { final t = filteredTankers[idx]; final isSelected = selectedTankerIndex == idx; return GestureDetector( onTap: () { setModalState(() { selectedTankerIndex = idx; selectedDriverIndex = null; }); }, child: Card( elevation: 1, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide( color: isSelected ? primaryColor : const Color(0XFFC3C4C4), width: 1, ), ), child: TankersCard( title: t.tanker_name, subtitle: t.type_of_water, capacity: t.capacity, code: t.license_plate, owner: t.supplier_name, status: List.from( t.availability), ), ), ); }, )), const SizedBox(height: 16), /// 🧍 Driver List Text( "SELECTED DRIVER", style: fontTextStyle( 10, const Color(0XFF2D2E30), FontWeight.w600), ), const SizedBox(height: 12), selectedTankerIndex == null ? Container( width: double.infinity, padding: const EdgeInsets.all(16), margin: const EdgeInsets.only(top: 8), decoration: BoxDecoration( color: const Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(12), border: Border.all( color: const Color(0xFFC3C4C4)), ), child: Center( child: Text( 'Select a tanker to choose driver', style: fontTextStyle( 14, const Color(0xFF2D2E30), FontWeight.w400), ), ), ) : ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, itemCount: driversList.length, separatorBuilder: (_, __) => const SizedBox(height: 12), itemBuilder: (context, idx) { final d = driversList[idx]; final isSelected = selectedDriverIndex == idx; final statusColor = d.status == "available" ? const Color(0XFF0A9E04) : (d.status == "on delivery" ? const Color(0XFFD0AE3C) : (d.status == "offline" ? const Color(0XFF939495) : Colors.grey)); return GestureDetector( onTap: () { setModalState(() { selectedDriverIndex = idx; }); }, child: Card( color: const Color(0XFFFFFFFF), elevation: 1, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide( color: isSelected ? primaryColor : const Color(0XFFC3C4C4), width: 1, ), ), child: Padding( padding: const EdgeInsets.all(12.0), child: Row( children: [ Image.asset( 'images/avatar.png', fit: BoxFit.cover, width: 20, height: 20, ), const SizedBox(width: 8), Expanded( child: Text( d.driver_name, style: fontTextStyle( 14, const Color( 0XFF2D2E30), FontWeight.w500), ), ), const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 2), decoration: BoxDecoration( borderRadius: BorderRadius.circular(4), border: Border.all( color: statusColor), ), child: Text( d.status, style: fontTextStyle( 10, statusColor, FontWeight.w400), ), ), ], ), ), ), ); }, ), ], ), ), ), /// ✅ Assign Button SafeArea( top: false, child: Padding( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12), child: SizedBox( width: double.infinity, child: GestureDetector( onTap: () async { if (selectedTankerIndex == null) { AppSettings.longFailedToast( 'Please select tanker'); return; } final selectedTanker = filteredTankers[selectedTankerIndex!]; final selectedDriver = selectedDriverIndex != null ? driversList[selectedDriverIndex!] : null; AppSettings.preLoaderDialog(context); bool isOnline = await AppSettings.internetConnectivity(); if (isOnline) { var payload = {}; payload["tankerName"] = selectedTanker.tanker_name; payload["delivery_agent"] = selectedDriver?.driver_name; payload["delivery_agent_mobile"] = selectedDriver?.phone_number; bool status = await AppSettings.assignTanker( payload, widget.order.dbId); Navigator.of(context, rootNavigator: true).pop(); if (status) { AppSettings.longSuccessToast( "Tanker assigned successfully"); Navigator.pop(context); Navigator.pop(context, true); } else { AppSettings.longFailedToast( "Failed to assign tanker"); } } else { Navigator.of(context, rootNavigator: true).pop(); AppSettings.longFailedToast( "Please Check internet"); } }, child: Container( decoration: BoxDecoration( color: const Color(0XFF8270DB), borderRadius: BorderRadius.circular(24), ), alignment: Alignment.center, padding: const EdgeInsets.symmetric(vertical: 12), child: Text( 'Assign', style: fontTextStyle( 14, Colors.white, FontWeight.w500), ), ), ), ), ), ), ], ), ); }, ), ); }, ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, extendBodyBehindAppBar: true, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, scrolledUnderElevation: 0, title: Text( '', style: fontTextStyle(16, Color(0XFF2A2A2A), FontWeight.w600), ), iconTheme: IconThemeData(color: Color(0XFF2A2A2A)), actions: [ Row( children: [ Padding( padding: EdgeInsets.fromLTRB(0, 10, 10, 10), child: IconButton( icon: Image.asset( 'images/help_appbar.png', height: 20, width: 20, color: Color(0XFFFFFFFF), ), onPressed: () {}, ), ) ], ) ], leading: GestureDetector( onTap: () { Navigator.pop(context); }, child: Padding( padding: const EdgeInsets.fromLTRB(8, 8, 8, 8), // Add padding if needed child: Image.asset( 'images/backbutton_appbar.png', // Replace with your image path fit: BoxFit.contain, color: Color(0XFFFFFFFF), height: 24, width: 24, ), ), ), ), body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// 🔹 Top Card with Image Stack( clipBehavior: Clip.none, children: [ /// 🔹 Background Image ClipRRect( borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(0), bottomRight: Radius.circular(0), ), child: Image.asset( "images/building.png", height: 220, width: double.infinity, fit: BoxFit.cover, ), ), /// 🔹 Floating Info Card (half on image, half below) Positioned( bottom: -40, // pulls the card out by 40px left: 12, right: 12, child: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black12, blurRadius: 6, offset: Offset(0, 3), ), ], ), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /*Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(4), border: Border.all( color: widget.status.statusColor, width: 0.5, ), ), child: Text(widget.status.status, style: fontTextStyle( 12, widget.status.statusColor, FontWeight.w500)), ),*/ Text( widget.order.building_name, style: fontTextStyle( 20, const Color(0XFF2D2E30), FontWeight.w600), ), SizedBox(height: 4), Text( widget.order.displayAddress, style: fontTextStyle( 12, const Color(0XFF939495), FontWeight.w400), ), ], ), const Spacer(), Text( widget.order.distanceInKm.toString() + 'Km', style: fontTextStyle( 12, const Color(0XFF939495), FontWeight.w400), ), ], ), ), ), ], ), SizedBox( height: MediaQuery.of(context).size.height * .08, ), /// 🔹 Order Details Padding( padding: EdgeInsets.fromLTRB(16, 0, 16, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "ORDER DETAILS", style: fontTextStyle( 10, const Color(0XFF2D2E30), FontWeight.w600), ), SizedBox( height: MediaQuery.of(context).size.height * .011, ), _detailTwoRow( "Tanker Price", "₹${AppSettings.formDouble(widget.order.quoted_amount) ?? ''}", "images/financialsBottomIcon.png", "", "", ""), SizedBox( height: MediaQuery.of(context).size.height * .02, ), _detailTwoRow( "Water Type", "${widget.order.type_of_water}", "images/water.png", "Date of Delivery", "${widget.order.date}", "images/calendar_appbar.png", ), SizedBox( height: MediaQuery.of(context).size.height * .02, ), _detailTwoRow( "Capacity", "${widget.order.capacity}", "images/capacity.png", "Time of Delivery", "${widget.order.time}", "images/time.png", ), SizedBox( height: MediaQuery.of(context).size.height * .02, ), _detailTwoRow( "Quantity", "${widget.order.quantity}", "images/quantity.png", "Booking Charges", advance.toString(), "images/advance.png", ), ], ), ), SizedBox( height: MediaQuery.of(context).size.height * .008, ), /// 🔹 Additional Details Padding( padding: EdgeInsets.fromLTRB(16, 0, 16, 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "ADDITIONAL DETAILS", style: fontTextStyle( 10, const Color(0XFF2D2E30), FontWeight.w600), ), SizedBox( height: MediaQuery.of(context).size.height * .011, ), Text( "Lorem ipsum dolor sit amet, consectetur adipiscing elit, " "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " "aliquip ex ea commodo consequat.", style: fontTextStyle( 12, const Color(0XFF646566), FontWeight.w400), ), SizedBox( height: MediaQuery.of(context).size.height * .032, ), Text( "ASSIGNED TANKER", style: fontTextStyle( 10, const Color(0XFF646566), FontWeight.w600), ), SizedBox( height: MediaQuery.of(context).size.height * .012, ), _assignedTankerDetails(), SizedBox( height: MediaQuery.of(context).size.height * .012, ), Text( "ASSIGNED TO", style: fontTextStyle( 10, const Color(0XFF646566), FontWeight.w600), ), SizedBox( height: MediaQuery.of(context).size.height * .012, ), _assignedDriverDetails() ], )), ], ), ), /// 🔹 Bottom Action Buttons bottomNavigationBar: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: Color(0XFFFFFFFF), border: Border(top: BorderSide(color: Color(0XFFF5F6F6))), ), child: Row( children: [ Expanded( child: OutlinedButton( style: OutlinedButton.styleFrom( foregroundColor: Color(0XFFFFFFFF), backgroundColor: Colors.white, side: BorderSide(color: Color(0XFFFFFFFF)), padding: EdgeInsets.symmetric(vertical: 10), ), onPressed: () async { /*AppSettings.preLoaderDialog(context); bool isOnline = await AppSettings.internetConnectivity(); if (isOnline) { var payload = new Map(); payload["supplierId"] = AppSettings.supplierId; payload["amount"] = int.parse(widget.order.quoted_amount); payload["delivery_charges"] = advance; payload["action"] = 'reject'; bool status = await AppSettings.acceptOrderRequests( payload, widget.order.dbId); try { if (status) { Navigator.of(context, rootNavigator: true).pop(); AppSettings.longSuccessToast( "Order request rejected Successfully"); Navigator.pop(context, true); } else { Navigator.of(context, rootNavigator: true).pop(); AppSettings.longFailedToast( "reject of order request Failed"); } } catch (e) { Navigator.of(context, rootNavigator: true).pop(); print(e); } } else { Navigator.of(context, rootNavigator: true).pop(); AppSettings.longFailedToast("Please Check internet"); }*/ Navigator.pop(context); }, child: Text( "CANCEL", style: fontTextStyle( 14, const Color(0XFFE2483D), FontWeight.w400), ), ), ), SizedBox(width: 8), Expanded( child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Color(0XFF8270DB), foregroundColor: Color(0XFFFFFFFF), padding: EdgeInsets.symmetric(vertical: 10), ), onPressed: () async { _showAssignTankerBottomSheet(); }, child: Text( "Edit Order", style: fontTextStyle( 14, const Color(0XFFFFFFFF), FontWeight.w400), ), ), ), ], )), ); } /// 🔹 Helper widget for rows Widget _detailRow(String title, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( title, style: fontTextStyle(12, const Color(0XFF646566), FontWeight.w400), ), Text( value, style: fontTextStyle(12, const Color(0XFF2D2E30), FontWeight.w500), ), ], ), ); } Widget _detailTwoRow( String title1, String value1, String path1, String title2, String value2, String path2, { EdgeInsetsGeometry padding = const EdgeInsets.symmetric(vertical: 6), }) { final titleStyle = fontTextStyle(12, Color(0XFF646566), FontWeight.w400); final valueStyle = fontTextStyle(12, Color(0XFF343637), FontWeight.w500); Widget _col(String t, String v, String path) { return Expanded( child: Padding( padding: const EdgeInsets.only(right: 8.0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ if (path.isNotEmpty) Image.asset( path, fit: BoxFit.contain, height: 20, width: 20, color: const Color(0XFFC3C4C4), ), if (path.isNotEmpty) const SizedBox(width: 6), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(t, style: titleStyle, maxLines: 1, overflow: TextOverflow.ellipsis), Text(v, style: valueStyle, maxLines: 1, overflow: TextOverflow.ellipsis), ], ), ) ], ), ), ); } return Padding( padding: padding, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _col(title1, value1, path1), _col(title2, value2, path2), ], ), ); } } // ====== TankersCard ====== class TankersCard extends StatelessWidget { final String title; final String subtitle; final String capacity; final String code; final String owner; final List status; const TankersCard({ super.key, required this.title, required this.subtitle, required this.capacity, required this.code, required this.owner, required this.status, }); Color _chipColor(String s) { switch (s) { case 'filled': return const Color(0xFFFFFFFF); case 'available': return const Color(0xFFFFFFFF); case 'empty': return const Color(0xFFFFFFFF); case 'in-use': return const Color(0xFFFFFFFF); case 'maintenance': return const Color(0xFFFFFFFF); default: return const Color(0xFFFFFFFF); } } Color _chipTextColor(String s) { switch (s) { case 'filled': return const Color(0xFF1D7AFC); case 'available': return const Color(0xFF0A9E04); case 'empty': return const Color(0xFFE2483D); case 'in-use': return const Color(0xFFEA843B); case 'maintenance': return const Color(0xFFD0AE3C); default: return Color(0xFF2A2A2A); } } @override Widget build(BuildContext context) { /*ImageProvider avatarProvider = (AppSettings.profilePictureUrl != '' && AppSettings.profilePictureUrl != 'null') ? NetworkImage(AppSettings.profilePictureUrl) : const AssetImage("images/profile_pic.png") as ImageProvider;*/ Widget _statusChip(String s) { final chipTextColor = _chipTextColor(s); return Container( margin: const EdgeInsets.only(left: 6), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: _chipColor(s), borderRadius: BorderRadius.circular(8), border: Border.all(color: chipTextColor, width: 1), ), child: Text(s, style: fontTextStyle(10, chipTextColor, FontWeight.w400)), ); } return Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: const Color(0XFFFFFFFF), borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0XFFC3C4C4)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Image.asset( 'images/square_avatar.png', fit: BoxFit.cover, width: 24, height: 24, ), const SizedBox(width: 8), // Title + Chips Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text( "$subtitle • $title", maxLines: 1, overflow: TextOverflow.ellipsis, style: fontTextStyle( 14, const Color(0xFF2D2E30), FontWeight.w500), ), ), const SizedBox(width: 8), ConstrainedBox( constraints: const BoxConstraints(maxWidth: 160), child: SingleChildScrollView( scrollDirection: Axis.horizontal, reverse: true, child: Row( children: status.map(_statusChip).toList(), ), ), ), ], ), Text( code, style: fontTextStyle( 10, const Color(0xFF646566), FontWeight.w400), ), ], ), ), ], ), ], ), ); } }