You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1831 lines
76 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:bookatanker/common/settings.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:bookatanker/supplier/filter_screen.dart';
import 'package:bookatanker/supplier/plans/plan_suppliers_model.dart';
import 'package:bookatanker/supplier/supplier_details.dart';
import 'package:bookatanker/supplier/supplier_details_from_search.dart';
import 'package:bookatanker/supplier/suppliers_model.dart';
class PlanRequestScreen extends StatefulWidget {
const PlanRequestScreen({super.key});
@override
State<PlanRequestScreen> createState() => _PlanRequestScreenState();
}
class _PlanRequestScreenState extends State<PlanRequestScreen> {
String? selectedWaterType;
String? selectedFrequency;
String? selectedCapacity;
String? selectedQuantity;
String? selectedTime;
DateTime? selectStartDate;
DateTime? selectStopDate;
List<PlanSuppliersModel> PlanSuppliersList = [];
bool isDataLoading = false;
bool isSearchEnabled = false;
int sentRequests = 0;
int maxRequests = 5;
DateTime? firstRequestTime;
Timer? _resetTimer;
Timer? _countdownTimer;
String remainingTime = '';
double progress = 1.0;
int totalCooldown = 900; // 15 minutes in seconds
RangeValues? selectedRadius;
RangeValues? selectedRating;
RangeValues? selectedPrice;
String? selectedPump;
bool filterAll = true, filterConnected = false, filterNotConnected = false;
final TextEditingController _quotedAmountController = TextEditingController();
// TimeOfDay _selectedTime = (TimeOfDay.now());
final List<String> waterTypes = ['Drinking Water', 'Bore water'];
final List<String> frequencyTypes = ['Daily', 'Weekly Once','Weekly Twice','Weekly Thrice'];
final List<String> capacities = [
'1,000 L',
'2,000 L',
'3,000 L',
'5,000 L',
'10,000 L',
'20,000 L'
];
final List<String> quantities = ['1', '2', '3'];
final List<String> timeSlots = ['8 AM', '12 PM', '4 PM', '8 PM'];
@override
void initState() {
// TODO: implement initState
super.initState();
_selectedTime = _roundToNextHour(TimeOfDay.now());
_loadRequestState();
// Defer the bottom sheet call until after build
WidgetsBinding.instance.addPostFrameCallback((_) {
_showLocationBottomSheet();
});
}
@override
void dispose() {
_countdownTimer?.cancel();
_quotedAmountController.dispose();
super.dispose();
}
Future<void> _loadRequestState() async {
List<DateTime> validTimes = await _getValidRequestTimes();
validTimes.sort(); // Ensure chronological order
setState(() {
sentRequests = validTimes.length;
});
if (validTimes.isNotEmpty) {
final firstExpiry = validTimes.first.add(Duration(minutes: 15));
final remaining = firstExpiry.difference(DateTime.now()).inSeconds;
if (remaining > 0) {
_startCountdownTimer(remaining);
}
}
}
Future<List<DateTime>> _getValidRequestTimes() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final rawList = prefs.getStringList('requestTimes') ?? [];
final now = DateTime.now();
final validTimes = rawList
.map((s) => DateTime.tryParse(s))
.whereType<DateTime>()
.where((t) => now.difference(t).inMinutes < 15)
.toList();
return validTimes;
}
Future<void> _saveRequestTimes(List<DateTime> times) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setStringList('requestTimes', times.map((e) => e.toIso8601String()).toList());
}
void _startCountdownTimer(int totalSeconds) {
_countdownTimer?.cancel();
totalCooldown = totalSeconds;
progress = 1.0;
_countdownTimer = Timer.periodic(Duration(seconds: 1), (timer) async {
final elapsed = timer.tick;
final remaining = totalSeconds - elapsed;
if (remaining <= 0) {
timer.cancel();
// 🧹 Clean expired request times
List<DateTime> updatedTimes = await _getValidRequestTimes();
updatedTimes.sort(); // Ensure order
await _saveRequestTimes(updatedTimes);
setState(() {
sentRequests = updatedTimes.length;
remainingTime = '';
progress = 0.0;
});
// 🕐 If more valid requests remain, restart countdown with new first one
if (updatedTimes.isNotEmpty) {
final nextExpiry = updatedTimes.first.add(Duration(minutes: 15));
final newRemaining = nextExpiry.difference(DateTime.now()).inSeconds;
if (newRemaining > 0) {
_startCountdownTimer(newRemaining);
}
}
} else {
final minutes = (remaining ~/ 60).toString().padLeft(2, '0');
final seconds = (remaining % 60).toString().padLeft(2, '0');
setState(() {
remainingTime = "$minutes:$seconds";
progress = remaining / totalCooldown;
});
}
});
}
void _showLocationBottomSheet() {
showModalBottomSheet(
context: context,
isScrollControlled: true,
isDismissible: false,
enableDrag: false, // 🔒 Prevents dragging
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
builder: (context) {
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: Container(
padding: EdgeInsets.all(16),
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.45,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Confirm Address?",
style: fontTextStyle(16, Color(0XFF343637), FontWeight.w600),
),
SizedBox(height: MediaQuery.of(context).size.height * .024),
Row(
children: [
Text(
"Your current selected address is",
style: fontTextStyle(12, Color(0XFF515253), FontWeight.w600),
),
SizedBox(width: MediaQuery.of(context).size.width * .004),
Text(
"HOME",
style: fontTextStyle(12, Color(0XFF2D2E30), FontWeight.w600),
),
],
),
SizedBox(height: MediaQuery.of(context).size.height * .012),
Row(
children: [
Image.asset(
'images/marker-pin.png',
width: 24,
height: 24,
),
SizedBox(width: MediaQuery.of(context).size.width * .024),
Expanded(
child: Text(
AppSettings.userAddress,
style: fontTextStyle(12, Color(0XFF515253), FontWeight.w400),
),
)
],
),
SizedBox(height: MediaQuery.of(context).size.height * .012),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: GestureDetector(
onTap: () {
// Optional: handle "Change"
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(width: 1, color: Color(0XFF939495)),
borderRadius: BorderRadius.circular(24),
),
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 12),
child: Text(
'Change',
style: fontTextStyle(14, Color(0XFF939495), FontWeight.w600),
),
),
),
),
SizedBox(width: MediaQuery.of(context).size.width * .010),
Expanded(
child: GestureDetector(
onTap: () {
Navigator.pop(context);
/* setState(() {
_isConfirmed = true;
});*/
},
child: Container(
decoration: BoxDecoration(
color: Color(0XFF1D7AFC),
border: Border.all(width: 1, color: Colors.white),
borderRadius: BorderRadius.circular(24),
),
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 12),
child: Text(
'Confirm',
style: fontTextStyle(14, Colors.white, FontWeight.w600),
),
),
),
),
],
),
],
),
),
),
);
},
);
}
TimeOfDay _roundToNextHour(TimeOfDay time) {
int nextHour = (time.minute > 0) ? (time.hour + 1) % 24 : time.hour;
return TimeOfDay(hour: nextHour, minute: 0);
}
void sendRequest() {
if (sentRequests < maxRequests) {
setState(() {
sentRequests++;
});
}
}
Future<void> _selectFromDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: selectStartDate ?? DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime.now().add(Duration(days: 3)),
helpText: 'Select Date',
initialEntryMode: DatePickerEntryMode.calendarOnly,
builder: (BuildContext context, Widget? child) {
return Theme(
data: ThemeData.light().copyWith(
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none, // Removes the text field border
),
colorScheme: ColorScheme.light(
primary: Color(0XFF1D7AFC),
onPrimary: Color(0XFFFFFFFF), // Header text color
surface: Color(0XFFFFFFFF),
onSurface: Colors.black,
secondary: Colors.pink,
),
dividerColor: Color(0XFFF5F6F6),
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(
Color(0XFF1D7AFC),
), // Text color
//backgroundColor: MaterialStateProperty.all(Colors.grey[200]), // Background
textStyle: MaterialStateProperty.all(
fontTextStyle(14, Color(0XFF1D7AFC), FontWeight.w600),
), // Font style
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8))), // Rounded corners
),
// Background of the dialog box
),
textTheme: TextTheme(
bodyLarge: fontTextStyle(14, Color(0XFF1D7AFC), FontWeight.w600),
labelLarge: fontTextStyle(14, Color(0XFF1D7AFC), FontWeight.w600),
titleLarge: fontTextStyle(14, Color(0XFF1D7AFC), FontWeight.w600),
headlineLarge:
fontTextStyle(20, Color(0XFF1D7AFC), FontWeight.w600),
),
),
child: child!,
);
},
);
if (picked != null) {
setState(() {
selectStartDate = picked;
//toDate1 = null; // Reset To Date
//toDateController1.clear();
});
}
}
Future<void> _selectToDate(BuildContext context) async {
if (selectStartDate == null) {
// Handle case when start date is not selected
return;
}
final DateTime firstDate = selectStartDate!;
final DateTime lastDate = DateTime(
firstDate.year,
firstDate.month + 1,
firstDate.day,
);
final DateTime? picked = await showDatePicker(
context: context,
initialDate: selectStopDate ?? firstDate,
firstDate: firstDate,
lastDate: lastDate,
helpText: 'Select Date',
initialEntryMode: DatePickerEntryMode.calendarOnly,
builder: (BuildContext context, Widget? child) {
return Theme(
data: ThemeData.light().copyWith(
inputDecorationTheme: const InputDecorationTheme(
border: InputBorder.none,
),
colorScheme: const ColorScheme.light(
primary: Color(0XFF1D7AFC),
onPrimary: Colors.white,
surface: Colors.white,
onSurface: Colors.black,
secondary: Colors.pink,
),
dividerColor: Color(0XFFF5F6F6),
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
foregroundColor: MaterialStatePropertyAll(Color(0XFF1D7AFC)),
textStyle: MaterialStatePropertyAll(
fontTextStyle(14, Color(0XFF1D7AFC), FontWeight.w600),
),
shape: MaterialStatePropertyAll(
RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
),
),
),
textTheme: TextTheme(
bodyLarge: fontTextStyle(14, Color(0XFF1D7AFC), FontWeight.w600),
labelLarge: fontTextStyle(14, Color(0XFF1D7AFC), FontWeight.w600),
titleLarge: fontTextStyle(14, Color(0XFF1D7AFC), FontWeight.w600),
headlineLarge: fontTextStyle(20, Color(0XFF1D7AFC), FontWeight.w600),
),
),
child: child ?? const SizedBox.shrink(),
);
},
);
if (picked != null) {
setState(() {
selectStopDate = picked;
});
}
}
TimeOfDay _selectedTime = TimeOfDay.now();
String _timeRangeText = '';
Future<void> _selectTime(BuildContext context) async {
final TimeOfDay? picked = await showTimePicker(
context: context,
initialTime: _selectedTime,
cancelText: 'Cancel',
confirmText: 'Confirm',
builder: (BuildContext context, Widget? child) {
return Theme(
data: ThemeData.light().copyWith(
primaryColor: Color(0XFF1D7AFC),
timePickerTheme: TimePickerThemeData(
backgroundColor: Colors.white,
dialBackgroundColor: Colors.white,
hourMinuteTextColor: Color(0XFF1D7AFC),
dayPeriodTextColor: Color(0XFF1D7AFC),
dialTextColor: Color(0XFF1D7AFC),
dayPeriodColor: Color(0XFFC3C4C4),
hourMinuteShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
side: BorderSide(color: Color(0XFFFFFFFF), width: 2),
),
dayPeriodShape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12)),
dialHandColor: Color(0XFFC3C4C4),
hourMinuteColor: Color(0XFFFFFFFF),
dialTextStyle:
TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
dayPeriodTextStyle:
TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
hourMinuteTextStyle:
TextStyle(fontSize: 50, fontWeight: FontWeight.w600),
helpTextStyle:
TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
),
),
child: child!,
);
},
);
if (picked != null) {
final now = TimeOfDay.now();
final today = DateTime.now();
final isToday = selectStartDate?.day == today.day &&
selectStartDate?.month == today.month &&
selectStartDate?.year == today.year;
bool isValid = true;
if (isToday) {
final nowMinutes = now.hour * 60 + now.minute;
final pickedMinutes = picked.hour * 60 + picked.minute;
isValid = pickedMinutes >= nowMinutes;
}
if (isValid) {
setState(() {
_selectedTime = picked;
_timeRangeText = _formatTimeRange(_selectedTime);
});
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Please select a time after the current time.")),
);
}
}
}
String _formatTimeRange(TimeOfDay start) {
final endHour = (start.hour + 2) % 24;
final end = TimeOfDay(hour: endHour, minute: start.minute);
return '${_formatTime(start)} to ${_formatTime(end)}';
}
String _formatTime(TimeOfDay time) {
final now = DateTime.now();
final dt = DateTime(now.year, now.month, now.day, time.hour, time.minute);
return TimeOfDay.fromDateTime(dt).format(context);
}
Widget _beforeDataScreen() {
return Padding(padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
"Whats new?",
style: fontTextStyle(12, Color(0XFF515253), FontWeight.w400),
),
),
SizedBox(height: MediaQuery.of(context).size.height * .012),
RichText(
text: TextSpan(
text: "Find ",
style: fontTextStyle(20, Color(0XFF343637), FontWeight.w600),
children: [
TextSpan(
text: "exclusive offers",
style: fontTextStyle(20, Color(0XFF8270DB), FontWeight.w600),
),
TextSpan(
text: " & best deals available for you.",
style: fontTextStyle(20, Color(0XFF343637), FontWeight.w600),
),
],
),
),
SizedBox(height: MediaQuery.of(context).size.height * .024),
Container(
height: 80,
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
gradient: LinearGradient(
colors: [
Color(0xFFFFFFFF),
Color(0xFFE2DCFF)
], // Light gradient background
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
border: Border.all(color: Color(0xFF8270DB)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'AQUINTO',
style:
fontTextStyle(20, Color(0XFF8270DB), FontWeight.w800),
),
SizedBox(height: MediaQuery.of(context).size.height * .004),
Text(
'Your Water, Your Data, Your Control.',
style:
fontTextStyle(12, Color(0XFF8270DB), FontWeight.w500),
),
],
),
/*Image.asset(
'images/WaterTankImage.png', // Replace with your actual image asset path
height: 40,
width: 40,
fit: BoxFit.contain,
),*/
],
),
)
],
),);
}
Widget _beforeDataScreenAbove() {
return Column(
children: [
SizedBox(height: MediaQuery.of(context).size.height * .024),
CircleAvatar(radius: 80, backgroundColor: Colors.grey.shade300),
SizedBox(height: MediaQuery.of(context).size.height * .016),
Center(
child: Text("Plans",
style: fontTextStyle(20, Color(0XFF000000), FontWeight.w600)),
),
SizedBox(height: MediaQuery.of(context).size.height * .008),
Text(
"No more last-minute orders! Set up a regular water delivery schedule with this supplier and stay stress-free",
textAlign: TextAlign.center,
style: fontTextStyle(12, Color(0XFF515253), FontWeight.w400),
),
],
);
}
Widget _suppliersDataScreen() {
if (isDataLoading) {
return Center(
child: CircularProgressIndicator(
color: primaryColor,
strokeWidth: 5.0,
),
);
}
if (PlanSuppliersList.isEmpty) {
return Center(
child: Text(
'No Data Available',
style: fontTextStyle(12, Color(0XFF000000), FontWeight.w500),
),
);
}
return Container(
color: Color(0xFFF1F1F1), // Set your desired background color
padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: Column(
children: [
Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 12),
decoration: BoxDecoration(
color: Color(0xFFF1F1F1),
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
Row(
children: [
Image.asset(
'images/info.png',
fit: BoxFit.cover,
width:
16, // Match the diameter of the CircleAvatar
height: 16,
),
SizedBox(
width: MediaQuery.of(context).size.width * .008,
),
Text(
"Plan requests sent",
style: fontTextStyle(14, Color(0XFF2D2E30), FontWeight.w600),
),
SizedBox(
width: MediaQuery.of(context).size.width * .012,
),
Text("$sentRequests/$maxRequests",style: fontTextStyle(14, Color(0XFF515253), FontWeight.w600),),
Spacer(),
Text("$remainingTime",style: fontTextStyle(12, Color(0XFF515253), FontWeight.w400),),
],
),
SizedBox(
height: MediaQuery.of(context).size.height * .016,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: List.generate(maxRequests, (index) {
return Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 4),
height: 3,
decoration: BoxDecoration(
color: index < sentRequests
?Color(0XFF114690)
:Color(0XFF939495),
borderRadius: BorderRadius.circular(2),
),
),
);
}),
),
Padding(
padding: EdgeInsets.only(top: 12, right: 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
onTap: (){},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
border: Border.all(color: Color(0XFF515253)),
borderRadius: BorderRadius.circular(45),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
'images/sort.png',
width: 12,
height: 12,
color: Color(0XFF515253),
fit: BoxFit.contain,
),
SizedBox(width: MediaQuery.of(context).size.width * .008),
Text(
"Sort",
style: fontTextStyle(12, Color(0XFF515253), FontWeight.w400),
),
SizedBox(width: MediaQuery.of(context).size.width * .008),
Image.asset(
'images/arrow_down.png',
width: 16,
height: 16,
color: Color(0XFF515253),
fit: BoxFit.contain,
),
],
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * .016,
),
GestureDetector(
onTap: () async {
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (_) => FilterScreen(
initialFilters: {
'all': filterAll,
'connected': filterConnected,
'notConnected': filterNotConnected,
'radiusRange': selectedRadius,
'ratingRange': selectedRating,
'priceRange': selectedPrice,
'pumpChoice': selectedPump,
},
),
),
);
if (result != null && result is Map) {
setState(() {
filterAll = result['all'];
filterConnected = result['connected'];
filterNotConnected = result['notConnected'];
selectedRadius = result['radiusRange'];
selectedRating = result['ratingRange'];
selectedPrice = result['priceRange'];
selectedPump = result['pumpChoice'];
});
await getAllSuppliersPlans();
}
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
border: Border.all(color: Color(0XFF515253)),
borderRadius: BorderRadius.circular(45),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
'images/filter.png',
width: 12,
height: 12,
color: Color(0XFF515253),
fit: BoxFit.contain,
),
SizedBox(width: MediaQuery.of(context).size.width * .008),
Text(
"Filter",
style: fontTextStyle(12, Color(0XFF515253), FontWeight.w400),
),
],
),
),
)
],
),
)
],
)),
],
),
ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
itemCount: PlanSuppliersList.length,
separatorBuilder: (context, index) => SizedBox(
height: MediaQuery.of(context).size.height * .008,
),
itemBuilder: (BuildContext context, int index) {
//final supplier = SuppliersList[index];
return GestureDetector(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SupplierScreenFromSearch(details: PlanSuppliersList[index],)),
);
},
child:Card(
color: Colors.white,
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: EdgeInsets.all(12),
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
radius: 25,
backgroundColor: Color(0XFFE8F2FF),
child: Image.asset(
'images/profile_user.png',
fit: BoxFit.cover,
width: 50,
height: 50,
),
),
SizedBox(
width: MediaQuery.of(context).size.width * .024,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/// Name and Rating Row
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
PlanSuppliersList[index].supplier_name,
style: fontTextStyle(16,
Color(0XFF2D2E30), FontWeight.w600),
overflow: TextOverflow.ellipsis,
),
),
Row(
children: [
Image.asset(
'images/star.png',
width: 16,
height: 16,
),
SizedBox(
width:
MediaQuery.of(context).size.width *
.008,
),
Text(
'4.2',
style: fontTextStyle(10,
Color(0XFF515253), FontWeight.w400),
),
],
),
],
),
SizedBox(
height:
MediaQuery.of(context).size.height * .004,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Drinking | Bore Water',
style: fontTextStyle(
12, Color(0XFF4692FD), FontWeight.w500),
),
Text(
PlanSuppliersList[index].matchedPrice.toString()!="null"&&PlanSuppliersList[index].matchedPrice.toString()!=""
""? '\u20B9 ${AppSettings.formDouble(PlanSuppliersList[index].matchedPrice.toString())}': '',
style: fontTextStyle(10, Color(0XFF515253), FontWeight.w400),
),
],
),
SizedBox(
height:
MediaQuery.of(context).size.height * .004,
),
/// Address and Favourite
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
'${PlanSuppliersList[index].displayAddress} ${PlanSuppliersList[index].distanceInMeters} Km',
style: fontTextStyle(12,
Color(0XFF515253), FontWeight.w400),
overflow: TextOverflow.ellipsis,
),
),
GestureDetector(
onTap: () async {
AppSettings.preLoaderDialog(context);
if (PlanSuppliersList[index].isFavorite) {
try {
bool tankerResponse =
await AppSettings
.removeFavourites(
PlanSuppliersList[index]
.supplier_id);
if (tankerResponse) {
Navigator.of(context,
rootNavigator: true)
.pop();
AppSettings.longSuccessToast(
'Supplier removed from favourites');
await getAllSuppliersPlans();
// await getConnectedSuppliersData();
} else {
Navigator.of(context,
rootNavigator: true)
.pop();
AppSettings.longFailedToast(
'Failed to remove from favourites');
}
} catch (e) {
Navigator.of(context,
rootNavigator: true)
.pop();
AppSettings.longFailedToast(
'Failed to remove from favourites');
}
} else {
try {
bool tankerResponse =
await AppSettings.addFavourites(
PlanSuppliersList[index]
.supplier_id);
if (tankerResponse) {
Navigator.of(context,
rootNavigator: true)
.pop();
AppSettings.longSuccessToast(
'Supplier added to favourites');
await getAllSuppliersPlans();
//await getConnectedSuppliersData();
//await getAllFavouritesData();
} else {
Navigator.of(context,
rootNavigator: true)
.pop();
AppSettings.longFailedToast(
'Failed to add favourites');
}
} catch (e) {
Navigator.of(context,
rootNavigator: true)
.pop();
AppSettings.longFailedToast(
'Failed to add favourites');
}
}
},
child: Image.asset(
PlanSuppliersList[index].isFavorite
? 'images/heart_active.png'
: 'images/heart_outline.png',
width: 20,
height: 20,
),
),
],
),
],
),
),
],
),
SizedBox(
height: MediaQuery.of(context).size.height * .016,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: GestureDetector(
onTap: () {},
child: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Color(0XFFFFFFFF),
border: Border.all(
width: 1,
color: PlanSuppliersList[index].isRequetsedBooking?Color(0XFF1D7AFC):Color(0XFF939495),
),
borderRadius: BorderRadius.circular(
24,
)),
alignment: Alignment.center,
child: Padding(
padding: EdgeInsets.fromLTRB(16, 12, 16, 12),
child: Text('Call',
style: fontTextStyle(12, PlanSuppliersList[index].isRequetsedBooking?Color(0XFF1D7AFC):Color(0XFF939495),
FontWeight.w600)),
),
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * .010,
),
Expanded(
child: GestureDetector(
onTap: () async{
if(!PlanSuppliersList[index].isRequetsedBooking){
requestPlanDialog(PlanSuppliersList[index]);
}
/* Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PlaceOrder(details: connectedSuppliersList[index],)),
);*/
},
child: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: PlanSuppliersList[index].isRequetsedBooking?Color(0XFFDBDBDC):Color(0XFF1D7AFC),
border: Border.all(
width: 1,
color: Color(0XFFFFFFFF),
),
borderRadius: BorderRadius.circular(
24,
)),
alignment: Alignment.center,//
child: Padding(
padding: EdgeInsets.fromLTRB(16, 12, 16, 12),
child: Text('Request plan',
style: fontTextStyle(12, Color(0XFFFFFFFF), FontWeight.w600)),
),
),
))
],
)
],
),
),
) ,
)
;
},
)
],
),
);
}
requestPlanDialog(var details) {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return AlertDialog(
backgroundColor: Color(0XFFFFFFFF),// Set your desired background color
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), // Optional: Rounded corners
),
title: Center(child: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text('ORDER DETAILS',style:fontTextStyle(16,Color(0XFF646566),FontWeight.w400)),
),
SizedBox(height: MediaQuery.of(context).size.height * .024,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Water Type',style:fontTextStyle(14,Color(0XFF646566),FontWeight.w500)),
Text(selectedWaterType!,style:fontTextStyle(14,Color(0XFF2D2E30),FontWeight.w500)),
],
),
SizedBox(height: MediaQuery.of(context).size.height * .010,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Capacity',style:fontTextStyle(14,Color(0XFF646566),FontWeight.w500)),
Text(selectedCapacity!,style:fontTextStyle(14,Color(0XFF2D2E30),FontWeight.w500)),
],
),
SizedBox(height: MediaQuery.of(context).size.height * .010,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Quantity',style:fontTextStyle(14,Color(0XFF646566),FontWeight.w500)),
Text(selectedQuantity!,style:fontTextStyle(14,Color(0XFF2D2E30),FontWeight.w500)),
],
),
SizedBox(height: MediaQuery.of(context).size.height * .010,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Start Date',style:fontTextStyle(14,Color(0XFF646566),FontWeight.w500)),
Text(DateFormat('dd-MMM-yyyy').format(selectStartDate!),style:fontTextStyle(14,Color(0XFF2D2E30),FontWeight.w500)),
],
),
SizedBox(height: MediaQuery.of(context).size.height * .010,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('End Date',style:fontTextStyle(14,Color(0XFF646566),FontWeight.w500)),
Text(DateFormat('dd-MMM-yyyy').format(selectStopDate!),style:fontTextStyle(14,Color(0XFF2D2E30),FontWeight.w500)),
],
),
SizedBox(height: MediaQuery.of(context).size.height * .010,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Actual Price',style:fontTextStyle(14,Color(0XFF646566),FontWeight.w500)),
Text(
details.matchedPrice.toString()!="null"&&details.matchedPrice.toString()!=""
""? '\u20B9 ${AppSettings.formDouble(details.matchedPrice.toString())}': '',
style:fontTextStyle(14,Color(0XFF2D2E30),FontWeight.w500),
),
],
),
SizedBox(height: MediaQuery.of(context).size.height * .010,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Your Price',style:fontTextStyle(14,Color(0XFF646566),FontWeight.w500)),
SizedBox(
width: MediaQuery.of(context).size.width * 0.4, // Adjust width as needed
child: TextFormField(
controller: _quotedAmountController,
keyboardType: TextInputType.number,
textCapitalization: TextCapitalization.sentences,
maxLength: 10,
decoration: textFormFieldDecoration(Icons.phone,''),
style:fontTextStyle(14,Color(0XFF2D2E30),FontWeight.w500),
cursorColor: Color(0XFF1D7AFC),
//TextStyle(color: Colors.black,fontWeight: FontWeight.bold),
)
),
],
),
],
),),
actions: <Widget>[
Center(
child: Row(
children: [
Expanded(
child: GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Color(0XFF1D7AFC), width: 1),
borderRadius: BorderRadius.circular(24),
),
alignment: Alignment.center,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 12),
child: Text(
'Cancel',
style: fontTextStyle(14, Color(0XFF1D7AFC), FontWeight.w600),
),
),
),
),
),
SizedBox(width: MediaQuery.of(context).size.width * .010,),
Expanded(
child: GestureDetector(
onTap: () async {
final now = DateTime.now();
List<DateTime> validTimes = await _getValidRequestTimes();
if (validTimes.length >= maxRequests) {
AppSettings.longFailedToast("Maximum 5 requests allowed in any 15-minute window.");
return;
}
final text = _quotedAmountController.text.trim();
if (text.isEmpty) return;
final quoted = int.tryParse(text);
if (quoted == null) {
AppSettings.longFailedToast("Invalid number");
return;
}
int matched = int.parse(details.matchedPrice);
if (quoted > matched + 300 || quoted < matched - 300) {
AppSettings.longFailedToast("Enter less than 300 within matched price ${details.matchedPrice}");
return;
}
AppSettings.preLoaderDialog(context);
bool isOnline = await AppSettings.internetConnectivity();
if (!isOnline) {
Navigator.of(context, rootNavigator: true).pop();
AppSettings.longFailedToast("Check your internet connection.");
return;
}
String freq='';
if(selectedFrequency.toString().toLowerCase()=='daily'){
freq='daily';
}
else if(selectedFrequency.toString().toLowerCase()=='weekly once'){
freq='weekly_once';
}
else if(selectedFrequency.toString().toLowerCase()=='weekly twice'){
freq='weekly_twice';
}
else if(selectedFrequency.toString().toLowerCase()=='weekly thrice'){
freq='weekly_thrice';
}
var payload = {
"customerId": AppSettings.customerId,
"type_of_water":selectedWaterType,
"capacity":selectedCapacity,
"quantity":selectedQuantity,
"start_date": DateFormat('dd-MMM-yyyy').format(selectStartDate!),
"end_date": DateFormat('dd-MMM-yyyy').format(selectStopDate!),
"time": DateFormat('dd-MM-yyyy HH:mm').format(now),
"frequency": freq,
"weekly_count": 1,
"requested_suppliers": [
{
"supplierId": details.supplier_id,
"quoted_amount": quoted,
"time": DateFormat('dd-MM-yyyy HH:mm').format(now),
}
],
};
bool status = await AppSettings.requestPlan(payload);
Navigator.of(context, rootNavigator: true).pop();
if (status) {
_quotedAmountController.clear();
Navigator.pop(context);
validTimes.add(now);
validTimes.sort();
await _saveRequestTimes(validTimes);
sentRequests = validTimes.length;
if (validTimes.isNotEmpty) {
final firstExpiry = validTimes.first.add(Duration(minutes: 15));
final remaining = firstExpiry.difference(DateTime.now()).inSeconds;
if (remaining > 0) _startCountdownTimer(remaining);
}
setState(() {});
await getAllSuppliersPlans();
AppSettings.longSuccessToast("Request Sent");
} else {
AppSettings.longFailedToast("Request sending failed");
}
/* final text = _quotedAmountController.text.trim();
if (text.isNotEmpty) {
final quoted = int.tryParse(text);
if (quoted == null) {
// Handle invalid number if needed
} else if (quoted > int.parse(details.matchedPrice) + 300 || quoted < int.parse(details.matchedPrice) - 300) {
AppSettings.longFailedToast("Please Enter below 300 or above 300 for the selected tanker price ${details.matchedPrice}");
} else {
AppSettings.preLoaderDialog(context);
bool isOnline = await AppSettings.internetConnectivity();
if (isOnline) {
var payload = <String, dynamic>{
"customerId": AppSettings.customerId,
"type_of_water": selectedWaterType,
"capacity": selectedCapacity,
"quantity": selectedQuantity,
"date": DateFormat('dd-MMM-yyyy').format(selectedDate!), // e.g., '2025-07-01'
"time": _timeRangeText, // e.g., '14:00'
"requested_suppliers": [
{
"supplierId": details.supplier_id,
"quoted_amount": int.parse(_quotedAmountController.text),
"time": DateFormat('dd-MM-yyyy HH:mm').format(DateTime.now()),
}
],
};
bool status = await AppSettings.requestOrder(payload);
if(status){
_quotedAmountController.clear();
Navigator.of(context, rootNavigator: true).pop();
Navigator.pop(context);
await getAllSuppliers();
AppSettings.longSuccessToast("Request Sent");
}
else{
_quotedAmountController.clear();
Navigator.of(context, rootNavigator: true).pop();
AppSettings.longFailedToast("Request sending failed");
}
} else {
Navigator.of(context, rootNavigator: true).pop();
AppSettings.longFailedToast("Please Check internet");
}
}
}*/
},
child: Container(
decoration: BoxDecoration(
color: Color(0XFF1D7AFC),
border: Border.all(color: Color(0XFF1D7AFC), width: 1),
borderRadius: BorderRadius.circular(24),
),
alignment: Alignment.center,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 12),
child: Text(
'Send Request',
style: fontTextStyle(14, Colors.white, FontWeight.w600),
),
),
),
),
),
],
),
),
],
);
});
});
}
Future<void> getAllSuppliersPlans() async {
AppSettings.preLoaderDialog(context);
bool isOnline = await AppSettings.internetConnectivity();
String freq='';
if(selectedFrequency.toString().toLowerCase()=='daily'){
freq='daily';
}
else if(selectedFrequency.toString().toLowerCase()=='weekly once'){
freq='weekly_once';
}
else if(selectedFrequency.toString().toLowerCase()=='weekly twice'){
freq='weekly_twice';
}
else if(selectedFrequency.toString().toLowerCase()=='weekly thrice'){
freq='weekly_thrice';
}
if (isOnline) {
var payload = new Map<String, dynamic>();
payload["type_of_water"] = selectedWaterType.toString();
payload["capacity"] = selectedCapacity.toString();
payload["quantity"] = selectedQuantity.toString();
payload["frequency"] = freq;
payload["start_date"] = DateFormat('dd-MMM-yyyy').format(selectStartDate!);
payload["end_date"] = DateFormat('dd-MMM-yyyy').format(selectStopDate!);
payload["radius_from"] = selectedRadius?.start.round().toString() ?? "";
payload["radius_to"] = selectedRadius?.end.round().toString() ?? "";
payload["rating_from"] = selectedRating?.start.toString() ?? "";
payload["rating_to"] = selectedRating?.end.toString() ?? "";
payload["price_from"] = selectedPrice?.start.round().toString() ?? "";
payload["price_to"] = selectedPrice?.end.round().toString() ?? "";
payload["pump"] = selectedPump.toString();
setState(() {
isDataLoading = true;
});
try {
var response = await AppSettings.getSuppliersForPlan(payload);
setState(() {
PlanSuppliersList =
((jsonDecode(response)['suppliers']) as List)
.map((dynamic model) {
return PlanSuppliersModel.fromJson(model);
}).toList();
// Clean the selected value: remove comma and " L"
String normalizedSelectedLitres = selectedCapacity!.replaceAll(",", "").replaceAll(" L", "").trim();
List<dynamic> suppliersJson = jsonDecode(response)['suppliers'];
PlanSuppliersList = suppliersJson.map((supplierData) {
List<dynamic> tankers = supplierData['tankers'];
String? matchedPrice;
for (var tanker in tankers) {
String capacity = tanker['capacity'].replaceAll(",", "").trim();
if (capacity == normalizedSelectedLitres) {
matchedPrice = tanker['price'];
break;
}
}
// Optional: attach matchedPrice to model if supported
var supplierModel = PlanSuppliersModel.fromJson(supplierData);
supplierModel.matchedPrice = matchedPrice; // <- Add this field to your model class
return supplierModel;
}).toList();
isDataLoading = false;
Navigator.of(context, rootNavigator: true).pop();
});
} catch (e) {
setState(() {
isDataLoading = false;
Navigator.of(context, rootNavigator: true).pop();
});
}
} else {
AppSettings.longFailedToast('Please check internet connection');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Color(0XFFFFFFFF),
elevation: 0,
scrolledUnderElevation: 0,
titleSpacing: 0,
title: GestureDetector(
onTap: () {
_showLocationBottomSheet();
},
child:Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisSize:
MainAxisSize.min, // Ensures it doesn't take extra space
children: [
Text(
'Home',
style:
fontTextStyle(16, Color(0XFF232527), FontWeight.w600),
),
SizedBox(width: 5), // Space between text and icon
Image.asset(
'images/arrow_down.png', // Replace with your arrow image
width: 24, // Adjust size
height: 24,
)
],
),
Text(
AppSettings.userAddress,
style:
fontTextStyle(10, Color(0XFF515253), FontWeight.w400),
),
],
)
),
iconTheme: IconThemeData(color: Color(0XFF2A2A2A)),
actions: [
Row(
children: [
Padding(
padding: EdgeInsets.fromLTRB(0, 10, 10, 10),
child: IconButton(
icon: Image.asset(
'images/notification_appbar.png', // Example URL image
),
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, // Adjust the fit
),
),
),
),
body: ListView(
padding: EdgeInsets.symmetric(horizontal: 0),
children: [
Padding(padding: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: Column(
children: [
!isSearchEnabled ? _beforeDataScreenAbove() : Container(),
SizedBox(height: MediaQuery.of(context).size.height * .024),
_buildDropdownField(
hint: "Type of Water",
value: selectedWaterType,
items: waterTypes,
path: 'images/water.png',
onChanged: (val) => setState(() => selectedWaterType = val),
),
SizedBox(height: MediaQuery.of(context).size.height * .012),
Row(
children: [
Expanded(
child: _buildDropdownField(
hint: "Capacity",
value: selectedCapacity,
items: capacities,
path:'',
onChanged: (val) =>
setState(() => selectedCapacity = val))),
SizedBox(width: MediaQuery.of(context).size.width * .024),
Expanded(
child: _buildDropdownField(
hint: "Quantity",
value: selectedQuantity,
items: quantities,
path:'',
onChanged: (val) =>
setState(() => selectedQuantity = val))),
],
),
SizedBox(height: MediaQuery.of(context).size.height * .012),
_buildDropdownField(
hint: "Frequency",
value: selectedFrequency,
items: frequencyTypes,
path:'images/frequency.png',
onChanged: (val) => setState(() => selectedFrequency = val),
),
SizedBox(height: MediaQuery.of(context).size.height * .012),
Row(
children: [
Expanded(
child: _buildDatePickerField(
hint: "Start date",
value: selectStartDate != null
? DateFormat('dd-MMM-yyyy').format(selectStartDate!)
: null,
onTap: () => _selectFromDate(context))),
SizedBox(width: MediaQuery.of(context).size.width * .024),
Expanded(
child: _buildDatePickerField(
hint: "End date",
value: selectStopDate != null
? DateFormat('dd-MMM-yyyy').format(selectStopDate!)
: null,
onTap: () => _selectToDate(context))),
],
),
SizedBox(height: MediaQuery.of(context).size.height * .024),
SizedBox(
width: double.infinity,
height: 41,
child: ElevatedButton(
onPressed: () async {
// ✅ FIELD VALIDATIONS
if (selectedWaterType == null || selectedWaterType!.isEmpty) {
AppSettings.longFailedToast('Please select Water Type');
return;
}
if (selectedCapacity == null || selectedCapacity!.isEmpty) {
AppSettings.longFailedToast('Please select Capacity');
return;
}
if (selectedQuantity == null || selectedQuantity!.isEmpty) {
AppSettings.longFailedToast('Please select Quantity');
return;
}
if (selectedFrequency == null || selectedFrequency!.isEmpty) {
AppSettings.longFailedToast('Please select Frequency');
return;
}
if (selectStartDate == null) {
AppSettings.longFailedToast('Please select Start Date');
return;
}
if (selectStopDate == null) {
AppSettings.longFailedToast('Please select End Date');
return;
}
// ✅ END DATE VALIDATION
if (selectStopDate!.isBefore(selectStartDate!)) {
AppSettings.longFailedToast('End Date must be after Start Date');
return;
}
// ✅ SEARCH ENABLE
setState(() {
isSearchEnabled = true;
});
await getAllSuppliersPlans();
},
style: ElevatedButton.styleFrom(
backgroundColor: Color(0XFF1D7AFC),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
),
child: Text(
"Search",
style: fontTextStyle(
14, Color(0xFFFFFFFF), FontWeight.w600),
),
),
),
SizedBox(height: MediaQuery.of(context).size.height * .036),
],
),
),
!isSearchEnabled ? _beforeDataScreen() : _suppliersDataScreen(),
],
),
);
}
Widget _buildDropdownField({
required String hint,
required String? value,
required List<String> items,
String? path, // ✅ Make path optional
required ValueChanged<String?> onChanged,
}) {
return DropdownButtonHideUnderline(
child: DropdownButton2<String>(
isExpanded: true,
hint: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (path != null&&path!='') ...[
Image.asset(
path,
width: 16,
height: 16,
color: Color(0XFF939495),
),
SizedBox(width: 6),
],
Text(
hint,
style: fontTextStyle(14, Color(0XFF939495), FontWeight.w400),
),
],
),
value: value,
items: items.map((item) {
return DropdownMenuItem<String>(
value: item,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 4),
child: Text(
item,
style: fontTextStyle(14, Color(0xFF2D2E30), FontWeight.w400),
),
),
);
}).toList(),
onChanged: onChanged,
buttonStyleData: ButtonStyleData(
height: 48,
padding: EdgeInsets.only(left: 0, right: 12),
decoration: BoxDecoration(
border: Border.all(color: Color(0XFF939495)),
borderRadius: BorderRadius.circular(12),
),
),
iconStyleData: IconStyleData(
icon: Padding(
padding: EdgeInsets.only(right: 4),
child: Image.asset(
'images/arrow_down.png',
width: 16,
height: 16,
color: Color(0XFF939495),
),
),
),
dropdownStyleData: DropdownStyleData(
padding: EdgeInsets.zero,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
),
menuItemStyleData: MenuItemStyleData(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
),
),
);
}
Widget _buildDatePickerField({
required String hint,
String? value,
required VoidCallback onTap,
}) {
return GestureDetector(
onTap: onTap,
child: Container(
height: 48,
padding: EdgeInsets.symmetric(horizontal: 12),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade400),
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Image.asset(
'images/calender_supplier_landing.png',
fit: BoxFit.cover,
width: 16, // Match the diameter of the CircleAvatar
height: 16,
color: Color(0XFF939495),
),
SizedBox(
width:
MediaQuery.of(context).size.width * .012,
),
Text(
value ?? hint,
style: value != null
? fontTextStyle(14, Color(0xFF2D2E30), FontWeight.w400)
: fontTextStyle(14, Color(0XFF939495), FontWeight.w400),
),
],
),
Image.asset(
'images/arrow_down.png',
width: 16,
height: 16,
color: Color(0XFF939495),
),
],
),
),
);
}
Widget _buildTimePickerField({
required String hint,
String? value,
required VoidCallback onTap,
}) {
return GestureDetector(
onTap: onTap,
child: Container(
height: 48,
padding: EdgeInsets.symmetric(horizontal: 12),
decoration: BoxDecoration(
border: Border.all(color: Color(0XFF939495)),
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Text(
value ?? hint,
style: value != null
? fontTextStyle(14, Color(0xFF2D2E30), FontWeight.w400)
: fontTextStyle(14, Color(0XFF939495), FontWeight.w400),
overflow: TextOverflow.visible,
),
),
),
SizedBox(width: MediaQuery.of(context).size.width * .008),
Image.asset(
'images/arrow_down.png',
width: 16,
height: 16,
color: Color(0XFF939495),
),
],
),
),
);
}
}