|
|
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(
|
|
|
"What’s 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),
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
}
|