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.
688 lines
32 KiB
688 lines
32 KiB
import 'dart:convert';
|
|
import 'package:auto_size_text/auto_size_text.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:flutter/material.dart';
|
|
import 'package:bookatanker/common/settings.dart';
|
|
import 'package:table_calendar/table_calendar.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:bookatanker/models/supplier_tankers_model.dart';
|
|
import 'package:bookatanker/supplier/cart_summary.dart';
|
|
|
|
class SupplierScreenFromSearch extends StatefulWidget {
|
|
var details;
|
|
SupplierScreenFromSearch({this.details});
|
|
|
|
@override
|
|
State<SupplierScreenFromSearch> createState() => _SupplierScreenFromSearchState();
|
|
}
|
|
|
|
class _SupplierScreenFromSearchState extends State<SupplierScreenFromSearch> {
|
|
DateTime _focusedDay = DateTime.now();
|
|
DateTime? _selectedDay;
|
|
bool isTankerDataLoading = false;
|
|
bool isCartDataLoading = false;
|
|
List<SupplierTankersModel> tankersList = [];
|
|
bool isSereverIssue = false;
|
|
List cart = [];
|
|
Map<String, int> localQuantities = {};
|
|
Map<String, int> localTotalPrices = {};
|
|
|
|
Future<void> getTankers() async {
|
|
isTankerDataLoading = true;
|
|
try {
|
|
var tankerResponse = await AppSettings.getAllTankers(widget.details.supplier_id);
|
|
|
|
setState(() {
|
|
tankersList =
|
|
((jsonDecode(tankerResponse)['data']) as List).map((dynamic model) {
|
|
return SupplierTankersModel.fromJson(model);
|
|
}).toList();
|
|
|
|
|
|
|
|
isTankerDataLoading = false;
|
|
});
|
|
} catch (e) {
|
|
setState(() {
|
|
isTankerDataLoading = false;
|
|
isSereverIssue = true;
|
|
});
|
|
/* AppSettings.longFailedToast('There is an issue at server side please try after some time');
|
|
Navigator.pop(context);*/
|
|
}
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_selectedDay = _focusedDay;
|
|
getTankers();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Color(0XFFFFFFFF),
|
|
appBar:AppSettings.SupplierAppBar('',context),
|
|
body: Padding(
|
|
padding: EdgeInsets.fromLTRB(0, 8, 0, 8),
|
|
child: Column(
|
|
children: [
|
|
// ✅ Fixed Content
|
|
Expanded(
|
|
flex: 0,
|
|
child: Column(
|
|
children: [
|
|
Padding(padding: EdgeInsets.fromLTRB(12, 0, 12, 0),
|
|
child: Column(
|
|
children: [
|
|
Padding(
|
|
padding: EdgeInsets.fromLTRB(8, 8, 8, 8),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Visibility(
|
|
visible: true,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Visibility(
|
|
visible: widget.details.supplier_name != '',
|
|
child: Text(
|
|
widget.details.supplier_name.toString(),
|
|
style: fontTextStyle(
|
|
16, Color(0XFF2D2E30), FontWeight.w600),
|
|
),
|
|
),
|
|
SizedBox(
|
|
width:
|
|
MediaQuery.of(context).size.width *
|
|
.012,
|
|
),
|
|
widget.details.isFavorite?Image.asset(
|
|
'images/heart_active.png',
|
|
fit: BoxFit.cover,
|
|
width:
|
|
16, // Match the diameter of the CircleAvatar
|
|
height: 16,
|
|
):
|
|
Image.asset(
|
|
'images/heart_outline.png',
|
|
fit: BoxFit.cover,
|
|
width:
|
|
16, // Match the diameter of the CircleAvatar
|
|
height: 16,
|
|
),
|
|
],
|
|
),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.rectangle,
|
|
color: Color(0XFFFDF3D3),
|
|
border: Border.all(
|
|
width: 0,
|
|
color: Color(0XFFFDF3D3),
|
|
),
|
|
borderRadius:
|
|
BorderRadius.circular(
|
|
12,
|
|
)),
|
|
child: Padding(
|
|
padding: EdgeInsets.fromLTRB(10,2,10,2),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Image.asset(
|
|
'images/star.png',
|
|
fit: BoxFit.cover,
|
|
width:
|
|
16, // Match the diameter of the CircleAvatar
|
|
height: 16,
|
|
),
|
|
Visibility(
|
|
visible: true,
|
|
child: Text(
|
|
'4.2',
|
|
style: fontTextStyle(11,
|
|
Color(0XFF232527), FontWeight.w600),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
Visibility(
|
|
visible: true,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
widget.details.displayAddress +
|
|
' ' +
|
|
widget.details.distanceInMeters
|
|
.toString() +
|
|
' Km',
|
|
style: fontTextStyle(12, Color(0XFF515253),
|
|
FontWeight.w400)),
|
|
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: MediaQuery.of(context).size.height * .004,),
|
|
Row(
|
|
children: [
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFF8877DD),
|
|
borderRadius: BorderRadius.circular(4),
|
|
border: Border.all(
|
|
width: 1,
|
|
color:Color(0xFF8877DD),
|
|
),
|
|
),
|
|
child: AutoSizeText(
|
|
capitalizeFirst('Bore Water'),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: fontTextStyle(12, Color(0xFFFFFFFF), FontWeight.w400),
|
|
),
|
|
),
|
|
SizedBox(width: MediaQuery.of(context).size.width * .016,),
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFCA86B0),
|
|
borderRadius: BorderRadius.circular(4),
|
|
border: Border.all(
|
|
width: 1,
|
|
color:Color(0xFFCA86B0),
|
|
),
|
|
),
|
|
child: AutoSizeText(
|
|
capitalizeFirst('Drinking Water'),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: fontTextStyle(12, Color(0xFFFFFFFF), FontWeight.w400),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: MediaQuery.of(context).size.height * .016,),
|
|
Row(
|
|
children: [
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFFFFFFF),
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(
|
|
width: 1,
|
|
color:Color(0xFF1D7AFC),
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Image.asset(
|
|
'images/ring.png',
|
|
fit: BoxFit.cover,
|
|
width:
|
|
16, // Match the diameter of the CircleAvatar
|
|
height: 16,
|
|
),
|
|
AutoSizeText(
|
|
capitalizeFirst('Best water quality'),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: fontTextStyle(10, Color(0xFF2D2E30), FontWeight.w400),
|
|
),
|
|
],
|
|
),
|
|
|
|
|
|
),
|
|
SizedBox(width: MediaQuery.of(context).size.width * .016,),
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFFFFFFFF),
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(
|
|
width: 1,
|
|
color:Color(0xFF1D7AFC),
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Image.asset(
|
|
'images/ring.png',
|
|
fit: BoxFit.cover,
|
|
width:
|
|
16, // Match the diameter of the CircleAvatar
|
|
height: 16,
|
|
),
|
|
AutoSizeText(
|
|
capitalizeFirst('Steel casing tankers'),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: fontTextStyle(10, Color(0xFF2D2E30), FontWeight.w400),
|
|
),
|
|
],
|
|
),
|
|
|
|
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
],
|
|
),
|
|
),
|
|
|
|
Padding(
|
|
padding: EdgeInsets.zero,
|
|
child: Container(
|
|
width: double
|
|
.infinity, // makes it expand within the Card's width
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.vertical(
|
|
bottom: Radius.circular(0),
|
|
), // match Card border
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
Color(0xFFFFE8A3),
|
|
Color(0xFFFFF8DF),
|
|
Color(0xFFFFFFFF),
|
|
],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
),
|
|
padding: EdgeInsets.symmetric(vertical: 12),
|
|
alignment: Alignment.center,
|
|
child: Padding(
|
|
padding: EdgeInsets.fromLTRB(12, 0, 12, 0),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Start regular deliveries?',
|
|
style: fontTextStyle(
|
|
16,
|
|
Color(0XFF2D2E30),
|
|
FontWeight.w600)),
|
|
SizedBox(height: MediaQuery.of(context).size.height * .012),
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Expanded(
|
|
flex: 3,
|
|
child: Text(
|
|
'Want to get water regularly from this supplier? Send a plan request.',
|
|
style: fontTextStyle(10, Color(0XFF515253), FontWeight.w400),
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
SizedBox(width: MediaQuery.of(context).size.width * .036),
|
|
Expanded(
|
|
flex: 1,
|
|
child: GestureDetector(
|
|
onTap: () {},
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: Color(0XFFFFFFFF),
|
|
border: Border.all(width: 1, color: Color(0XFF1D7AFC)),
|
|
borderRadius: BorderRadius.circular(24),
|
|
),
|
|
alignment: Alignment.center,
|
|
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 8),
|
|
child: Text(
|
|
'Request',
|
|
style: fontTextStyle(12, Color(0XFF1D7AFC), FontWeight.w600),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
],
|
|
)
|
|
,
|
|
)),
|
|
),
|
|
SizedBox(height: MediaQuery.of(context).size.height * .016),
|
|
|
|
],
|
|
),
|
|
),
|
|
|
|
// ✅ Scrollable
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
|
|
child: Column(
|
|
children: [
|
|
Padding(padding: EdgeInsets.fromLTRB(18, 0, 18, 0),
|
|
child: Container(
|
|
width: double.infinity,
|
|
padding:
|
|
EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
color: Color(0XFFFCF0E7),
|
|
borderRadius: BorderRadius.circular(6),
|
|
border: Border.all
|
|
(
|
|
color: Color(0XFFEFA168)),
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
Image.asset(
|
|
'images/warning.png',
|
|
fit: BoxFit.cover,
|
|
width:
|
|
22, // Match the diameter of the CircleAvatar
|
|
height: 22,
|
|
),
|
|
SizedBox(width: MediaQuery.of(context).size.width * .020),
|
|
Expanded(child: Text(
|
|
'The prices shown below are NOT inclusive of the transport charges. Transport charges are calculated based on the distance between the sourcing location and the delivery location.',
|
|
style: fontTextStyle(
|
|
10,
|
|
Color(0XFF444444),
|
|
FontWeight.w400),
|
|
),)
|
|
],
|
|
)
|
|
|
|
|
|
),),
|
|
SizedBox(height: MediaQuery.of(context).size.height * .016),
|
|
|
|
Padding(
|
|
padding: EdgeInsets.fromLTRB(12, 0, 12, 0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'SOURCE LOCATIONS',
|
|
style: fontTextStyle(12, Color(0XFF646566), FontWeight.w400),
|
|
),
|
|
SizedBox(height: MediaQuery.of(context).size.height * .016),
|
|
Card(
|
|
elevation: 2,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
|
color: Color(0XFFFFFFFF),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(12.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
...[
|
|
{'name': 'Gandipet', 'type': 'Drinking water', 'km': '4.5 Km'},
|
|
{'name': 'Nizampet', 'type': 'Drinking water', 'km': '7.3 Km'},
|
|
{'name': 'Secunderabad', 'type': 'Bore water', 'km': '12.4 Km'},
|
|
].map((location) => Padding(
|
|
padding: const EdgeInsets.only(bottom: 12.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(location['name']!,
|
|
style: fontTextStyle(12, Color(0XFF2D2E30), FontWeight.w500)),
|
|
Text(location['km']!,
|
|
style: fontTextStyle(10, Color(0XFF2D2E30), FontWeight.w500)),
|
|
],
|
|
),
|
|
Text(location['type']!,
|
|
style: fontTextStyle(10, Color(0XFF515253), FontWeight.w400)),
|
|
],
|
|
),
|
|
)),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
|
|
// Tankers
|
|
SizedBox(height: MediaQuery.of(context).size.height * .016),
|
|
Text(
|
|
'TANKERS',
|
|
style: fontTextStyle(12, Color(0XFF646566), FontWeight.w400),
|
|
),
|
|
SizedBox(height: MediaQuery.of(context).size.height * .016),
|
|
|
|
ListView.builder(
|
|
itemCount: tankersList.length,
|
|
shrinkWrap: true,
|
|
physics: NeverScrollableScrollPhysics(),
|
|
itemBuilder: (context, index) {
|
|
final tanker = tankersList[index];
|
|
final isAvailable = tanker.status == 'Available';
|
|
final isEnabled = tanker.enabled;
|
|
|
|
return Card(
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
|
elevation: 2,
|
|
color: Color(0XFFFFFFFF),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(12),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
'${tanker.capacity} Litres',
|
|
style: fontTextStyle(14, Color(0XFF2D2E30), FontWeight.w500),
|
|
),
|
|
Text(
|
|
'\u20B9 ${AppSettings.formDouble(tanker.price)}',
|
|
style: fontTextStyle(10, Color(0XFF515253), FontWeight.w400),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: MediaQuery.of(context).size.height * .004,),
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
|
decoration: BoxDecoration(
|
|
color: tanker.type_of_water.toString().toLowerCase()=='bore water'?Color(0xFF8877DD): Color(0xFFCA86B0),
|
|
borderRadius: BorderRadius.circular(4),
|
|
border: Border.all(
|
|
width: 1,
|
|
color:tanker.type_of_water.toString().toLowerCase()=='bore water'?Color(0xFF8877DD): Color(0xFFCA86B0),
|
|
),
|
|
),
|
|
child: AutoSizeText(
|
|
capitalizeFirst(tanker.type_of_water),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
style: fontTextStyle(12, Color(0xFFFFFFFF), FontWeight.w400),
|
|
),
|
|
),
|
|
SizedBox(height: MediaQuery.of(context).size.height * .008,),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(6),
|
|
border: Border.all(
|
|
color: isAvailable ? Color(0XFF098603) : Colors.grey,
|
|
),
|
|
),
|
|
child: Text(
|
|
tanker.status,
|
|
style: fontTextStyle(
|
|
12,
|
|
isAvailable ? Color(0XFF098603) : Colors.grey,
|
|
FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
/* ElevatedButton(
|
|
onPressed: isEnabled
|
|
? () async {
|
|
AppSettings.preLoaderDialog(context);
|
|
|
|
final productId = tanker.id;
|
|
final name = tanker.tanker_name;
|
|
final priceString = tanker.price;
|
|
final unitPrice = int.parse(priceString.replaceAll(',', ''));
|
|
int currentQuantity = localQuantities[productId] ?? 0;
|
|
int newQuantity = currentQuantity + 1;
|
|
int totalPrice = unitPrice * newQuantity;
|
|
|
|
final payload = {
|
|
"productId": productId,
|
|
"name": name,
|
|
"quantity": newQuantity,
|
|
"price": unitPrice,
|
|
};
|
|
|
|
try {
|
|
final response = await http.post(
|
|
Uri.parse('${AppSettings.host}cart/${AppSettings.customerId}/add'),
|
|
headers: await AppSettings.buildRequestHeaders(),
|
|
body: jsonEncode(payload),
|
|
);
|
|
|
|
Navigator.of(context, rootNavigator: true).pop();
|
|
|
|
if (response.statusCode == 200 || response.statusCode == 201) {
|
|
setState(() {
|
|
localQuantities[productId] = newQuantity;
|
|
localTotalPrices[productId] = totalPrice;
|
|
|
|
int existingIndex = cart.indexWhere((item) => item['productId'] == productId);
|
|
if (existingIndex != -1) {
|
|
cart[existingIndex]['quantity'] = newQuantity;
|
|
cart[existingIndex]['price'] = unitPrice;
|
|
cart[existingIndex]['total'] = totalPrice;
|
|
} else {
|
|
cart.add({
|
|
"productId": productId,
|
|
"name": name,
|
|
"quantity": newQuantity,
|
|
"price": unitPrice,
|
|
"total": totalPrice,
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
print('Failed to add to cart: ${response.body}');
|
|
}
|
|
} catch (e) {
|
|
Navigator.of(context, rootNavigator: true).pop();
|
|
print('Error adding to cart: $e');
|
|
}
|
|
}
|
|
: null,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: isEnabled ? primaryColor : Colors.grey[300],
|
|
foregroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
minimumSize: Size(64, 36),
|
|
padding: EdgeInsets.zero,
|
|
),
|
|
child: Text(
|
|
'Add',
|
|
style: fontTextStyle(12, Colors.white, FontWeight.w400),
|
|
),
|
|
),*/
|
|
],
|
|
)
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
),
|
|
bottomNavigationBar: cart.isNotEmpty
|
|
? Padding(
|
|
padding: EdgeInsets.all(0),
|
|
child: Container(
|
|
height: 56,
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
color: Color(0XFFF5CD47),
|
|
borderRadius: BorderRadius.only(
|
|
topLeft: Radius.circular(12),
|
|
topRight: Radius.circular(12),
|
|
),
|
|
),
|
|
padding: EdgeInsets.symmetric(horizontal: 24),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
"Order updated",
|
|
style: fontTextStyle(12, Color(0XFF232527), FontWeight.w500),
|
|
),
|
|
GestureDetector(
|
|
onTap: () {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => CartSummary(details: cart,supplierDetails: widget.details,)),
|
|
);
|
|
},
|
|
child: Row(
|
|
children: [
|
|
Text(
|
|
"View summary",
|
|
style: fontTextStyle(12, Color(0XFF232527), FontWeight.w500),
|
|
),
|
|
Image.asset(
|
|
'images/arrow-right.png',
|
|
fit: BoxFit.cover,
|
|
width:
|
|
20, // Match the diameter of the CircleAvatar
|
|
height: 20,
|
|
color: Color(0XFF343637),
|
|
),
|
|
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
)
|
|
: null,
|
|
|
|
);
|
|
}
|
|
}
|