master
Sneha 4 weeks ago
parent 849afdd17a
commit c47bddf151

File diff suppressed because it is too large Load Diff

@ -661,6 +661,101 @@ class AppSettings{
}
}
static Future<Map?> addTankersWithResponse(payload) async {
var uri = Uri.parse(addTankerUrl + '/' + supplierId);
var response = await http.post(
uri,
body: json.encode(payload),
headers: await buildRequestHeaders()
);
if (response.statusCode == 200) {
try {
var _response = json.decode(response.body);
print(_response);
/// RETURN FULL DATA
return _response;
}
catch (e) {
return null;
}
}
else if (response.statusCode == 2083) {
AppSettings.longFailedToast(
'Tanker name already exists'
);
return null;
}
else if (response.statusCode == 401) {
bool status =
await AppSettings.resetToken();
if (status) {
response = await http.post(
uri,
body: json.encode(payload),
headers: await buildRequestHeaders()
);
if (response.statusCode == 200) {
var _response =
json.decode(response.body);
return _response["data"];
}
else {
return null;
}
}
else {
return null;
}
}
else {
return null;
}
}
static Future<bool> updateTanker(payload,tankerName) async {
var uri = Uri.parse(updateTankerUrl+'/'+supplierId);
uri = uri.replace(query: 'tankerName=$tankerName');
@ -1670,6 +1765,54 @@ class AppSettings{
return response.body;
}
static Future<bool> deleteTankerImage(
String tankerId,
String imageUrl
) async {
try{
var response = await http.delete(
Uri.parse(
AppSettings.host+
"delete_tanker_image/$tankerId"
),
headers:{
'Content-Type':'application/json'
},
body: jsonEncode({
"imageUrl": imageUrl
}),
);
print(response.body);
return response.statusCode==200;
}
catch(e){
print(e);
return false;
}
}
/*Apis ends here*/
//save data local

@ -0,0 +1,37 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:supplier_new/common/settings.dart';
class AuthManager {
static final FlutterSecureStorage storage = FlutterSecureStorage(
aOptions: AndroidOptions(
resetOnError: true,
encryptedSharedPreferences: true,
),
);
static Future<String> decideStartScreen() async {
String? token = await storage.read(key: 'authToken');
if(token == null){
return "login";
}
await AppSettings.loadDataFromMemory();
String? onboarding = await storage.read(key: 'onboardingCompleted');
if(onboarding == null){
await storage.write(
key: 'onboardingCompleted',
value: 'true',
);
return "resources";
}
return "dashboard";
}
}

File diff suppressed because it is too large Load Diff

@ -10,7 +10,10 @@ class DriversModel {
String phone_number='';
String alt_phone_number='';
String license_number='';
String age='';
String license_expiry_date='';
String picture='';
List<dynamic> licenseImages= [];
DriversModel();
factory DriversModel.fromJson(Map<String, dynamic> json) {
@ -25,7 +28,10 @@ class DriversModel {
rtvm.years_of_experience = json['years_of_experience'] ?? '';
rtvm.license_number = json['license_number'] ?? '';
rtvm.deliveries = json['deliveries'] ?? '';
rtvm.picture = json['picture'] ?? '';
rtvm.license_expiry_date=json['license_number'] ?? '';
rtvm.age=json['age'] ?? '';
rtvm.licenseImages = json['images'] ?? [];
return rtvm;
}
}

File diff suppressed because it is too large Load Diff

@ -1,9 +1,12 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:supplier_new/common/settings.dart';
import 'package:supplier_new/resources/tanker_details.dart';
import 'package:supplier_new/resources/tankers_model.dart';
import 'package:http/http.dart' as http;
class FirstCharUppercaseFormatter extends TextInputFormatter {
const FirstCharUppercaseFormatter();
@ -93,6 +96,67 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
"Capacity"
];
final ImagePicker _picker = ImagePicker();
List<XFile> tankerImages = [];
final int maxImages = 5;
Future<void> pickTankerImages(Function modalSetState) async {
if(tankerImages.length>=5){
AppSettings.longFailedToast("Maximum 5 images allowed");
return;
}
final images =
await _picker.pickMultiImage(imageQuality:70);
if(images!=null){
int remaining = 5 - tankerImages.length;
tankerImages.addAll(
images.take(remaining)
);
modalSetState((){});
}
}
Future<void> pickFromCamera(Function modalSetState) async {
if(tankerImages.length>=5){
AppSettings.longFailedToast("Maximum 5 images allowed");
return;
}
final image =
await _picker.pickImage(
source:ImageSource.camera,
imageQuality:70,
);
if(image!=null){
tankerImages.add(image);
modalSetState((){});
}
}
@override
void initState() {
super.initState();
@ -392,7 +456,612 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
}
}
Future<void> uploadTankerImages(
String tankerId
) async {
var request = http.MultipartRequest(
'POST',
Uri.parse(
AppSettings.host +
"uploads_tanker_images/$tankerId"
)
);
request.headers.addAll(
await AppSettings.buildRequestHeaders()
);
for(var img in tankerImages){
request.files.add(
await http.MultipartFile.fromPath(
'files',
img.path
)
);
}
var response =
await request.send();
if(response.statusCode != 200){
throw Exception(
"Upload failed"
);
}
}
Future<void> _addTankerNew() async {
/// FORM VALIDATION
final ok = _formKey.currentState?.validate() ?? false;
if (!ok) {
setState(() {});
return;
}
try {
AppSettings.preLoaderDialog(context);
/// STEP 1 CREATE TANKER
final payload = {
"tankerName": _nameCtrl.text.trim(),
"capacity": _capacityCtrl.text.trim(),
"typeofwater": selectedTypeOfWater ?? "",
"supplier_address": AppSettings.userAddress,
"supplier_name": AppSettings.userName,
"phoneNumber": AppSettings.phoneNumber,
"tanker_type": selectedType ?? "",
"license_plate": _plateCtrl.text.trim(),
"manufacturing_year": _mfgYearCtrl.text.trim(),
"insurance_exp_date": _insExpiryCtrl.text.trim(),
};
final response =
await AppSettings.addTankersWithResponse(payload);
if(response == null){
Navigator.pop(context);
AppSettings.longFailedToast(
"Tanker creation failed"
);
return;
}
/// IMPORTANT GET TANKER ID
String tankerId =
response["tankerId"] ??
response["_id"] ??
"";
/// STEP 2 UPLOAD IMAGES
if(tankerImages.isNotEmpty){
try{
await uploadTankerImages(tankerId);
}
catch(e){
debugPrint(
"Image upload failed $e"
);
AppSettings.longFailedToast(
"Tanker created but images failed"
);
}
}
Navigator.pop(context);
if (!mounted) return;
AppSettings.longSuccessToast(
"Tanker Created Successfully"
);
Navigator.pop(context,true);
_resetForm();
_fetchTankers();
}
catch (e) {
Navigator.pop(context);
debugPrint(
"⚠️ addTanker error $e"
);
if (!mounted) return;
AppSettings.longFailedToast(
"Something went wrong"
);
}
}
Future<void> openTankerSimpleSheet(BuildContext context) async {
await showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) {
return StatefulBuilder(
builder: (context, modalSetState) {
final viewInsets = MediaQuery.of(context).viewInsets.bottom;
return FractionallySizedBox(
heightFactor: 0.75,
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Padding(
padding: EdgeInsets.fromLTRB(20,16,20,20+viewInsets),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
Expanded(
child: Center(
child: Container(
width: 86,
height: 4,
margin: const EdgeInsets.only(bottom: 12),
decoration: BoxDecoration(
color: const Color(0xFFE0E0E0),
borderRadius: BorderRadius.circular(2),
),
),
),
),
],
),
_LabeledField(
label: "Tanker Name *",
child: TextFormField(
controller: _nameCtrl,
validator: (v) => _required(v, field: "Tanker Name"),
textCapitalization: TextCapitalization.characters,
inputFormatters: const [
FirstCharUppercaseFormatter(), // << live first-letter caps
],
decoration: InputDecoration(
hintText: "Enter Tanker Name",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
),
textInputAction: TextInputAction.next,
),
),
_LabeledField(
label: "Tanker Capacity (in L) *",
child: TextFormField(
controller: _capacityCtrl,
validator: (v) => _required(v, field: "Tanker Capacity"),
decoration: InputDecoration(
hintText: "10,000",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
),
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[0-9,]')),
],
textInputAction: TextInputAction.next,
),
),
_LabeledField(
label: "Tanker Type *",
child: DropdownButtonFormField<String>(
value: selectedType,
dropdownColor: Colors.white,
items: tankerTypes
.map((t) => DropdownMenuItem(value: t, child: Text(t)))
.toList(),
onChanged: (v) => setState(() => selectedType = v),
validator: (v) => v == null || v.isEmpty ? "Tanker Type is required" : null,
isExpanded: true,
alignment: Alignment.centerLeft,
hint: Text(
"Select Type",
style: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
),
icon: Image.asset('images/downarrow.png', width: 16, height: 16),
decoration: const InputDecoration(
border: OutlineInputBorder(),
isDense: false,
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 14),
),
),
),
_LabeledField(
label: "Type of water *",
child: DropdownButtonFormField<String>(
value: selectedTypeOfWater,
dropdownColor: Colors.white,
items: typeOfWater
.map((t) => DropdownMenuItem(value: t, child: Text(t)))
.toList(),
onChanged: (v) => setState(() => selectedTypeOfWater = v),
validator: (v) => v == null || v.isEmpty ? "Type of water is required" : null,
isExpanded: true,
alignment: Alignment.centerLeft,
hint: Text(
"Select type of water",
style: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
),
icon: Image.asset('images/downarrow.png', width: 16, height: 16),
decoration: const InputDecoration(
border: OutlineInputBorder(),
isDense: false,
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 14),
),
),
),
_LabeledField(
label: "License Plate *",
child: TextFormField(
controller: _plateCtrl,
validator: (v) => _required(v, field: "License Plate"),
decoration: InputDecoration(
hintText: "AB 05 H 4948",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
),
textCapitalization: TextCapitalization.characters,
textInputAction: TextInputAction.next,
),
),
_LabeledField(
label: " Age of vehicle (opt)",
child: TextFormField(
controller: _mfgYearCtrl,
decoration: InputDecoration(
hintText: "12",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
),
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
LengthLimitingTextInputFormatter(4),
],
textInputAction: TextInputAction.next,
),
),
_LabeledField(
label: "Insurance Expiry Date (opt)",
child: TextFormField(
controller: _insExpiryCtrl,
readOnly: true,
decoration: InputDecoration(
hintText: "DD-MM-YYYY",
hintStyle: fontTextStyle(14, const Color(0xFF939495), FontWeight.w400),
border: const OutlineInputBorder(),
isDense: true,
suffixIcon: const Icon(Icons.calendar_today_outlined, size: 18),
),
onTap: _pickInsuranceDate,
),
),
_LabeledField(
label: "Tanker Images (Max 5)",
child: Column(
children: [
/// IMAGE GRID
if(tankerImages.isNotEmpty)
GridView.builder(
shrinkWrap:true,
physics:NeverScrollableScrollPhysics(),
itemCount:tankerImages.length,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount:3,
crossAxisSpacing:8,
mainAxisSpacing:8,
),
itemBuilder:(context,index){
return Stack(
children:[
ClipRRect(
borderRadius:BorderRadius.circular(8),
child:Image.file(
File(tankerImages[index].path),
width:double.infinity,
height:double.infinity,
fit:BoxFit.cover,
),
),
Positioned(
right:4,
top:4,
child:GestureDetector(
onTap:(){
tankerImages.removeAt(index);
modalSetState((){}); /// FIXED
},
child:Container(
decoration:const BoxDecoration(
color:Colors.red,
shape:BoxShape.circle,
),
child:const Icon(
Icons.close,
color:Colors.white,
size:18,
),
),
),
)
],
);
},
),
const SizedBox(height:10),
/// BUTTONS
Row(
children:[
Expanded(
child:OutlinedButton.icon(
onPressed:(){
pickTankerImages(modalSetState); /// FIXED
},
icon:Icon(Icons.photo),
label:Text("Gallery"),
),
),
const SizedBox(width:10),
Expanded(
child:OutlinedButton.icon(
onPressed:(){
pickFromCamera(modalSetState); /// FIXED
},
icon:Icon(Icons.camera_alt),
label:Text("Camera"),
),
),
],
),
const SizedBox(height:5),
Text(
"${tankerImages.length}/5 images selected",
style: fontTextStyle(
12,
Colors.grey,
FontWeight.w400
),
),
],
),
),
/// SAVE BUTTON (UNCHANGED)
const SizedBox(height:20),
SizedBox(
width:double.infinity,
child:ElevatedButton(
style:ElevatedButton.styleFrom(
backgroundColor:const Color(0xFF8270DB),
foregroundColor:Colors.white,
padding:const EdgeInsets.symmetric(vertical:14),
shape:RoundedRectangleBorder(
borderRadius:BorderRadius.circular(24),
),
),
onPressed:_addTankerNew,
child:Text(
"Save",
style:fontTextStyle(
14,
Colors.white,
FontWeight.w600
),
),
),
),
],
),
),
),
),
),
);
},
);
},
);
}
/*Future<void> openTankerSimpleSheet1(BuildContext context) async {
await showModalBottomSheet(
context: context,
isScrollControlled: true,
@ -571,6 +1240,120 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
onTap: _pickInsuranceDate,
),
),
_LabeledField(
label: "Tanker Images (Max 5)",
child: Column(
children: [
/// Grid Images
if(tankerImages.isNotEmpty)
GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: tankerImages.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
itemBuilder: (context,index){
return Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.file(
File(tankerImages[index].path),
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
),
),
Positioned(
right: 4,
top: 4,
child: GestureDetector(
onTap: (){
tankerImages.removeAt(index);
setState(() {});
},
child: Container(
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Icon(
Icons.close,
color: Colors.white,
size: 18,
),
),
),
)
],
);
},
),
const SizedBox(height:10),
/// Add Buttons
Row(
children: [
Expanded(
child: OutlinedButton.icon(
onPressed: pickTankerImages,
icon: Icon(Icons.photo),
label: Text("Gallery"),
),
),
const SizedBox(width:10),
Expanded(
child: OutlinedButton.icon(
onPressed: pickFromCamera,
icon: Icon(Icons.camera_alt),
label: Text("Camera"),
),
),
],
),
const SizedBox(height:5),
Text(
"${tankerImages.length}/5 images selected",
style: fontTextStyle(
12,
Colors.grey,
FontWeight.w400
),
),
],
),
),
const SizedBox(height: 20),
@ -601,7 +1384,7 @@ class _ResourcesFleetScreenState extends State<ResourcesFleetScreen> {
);
},
);
}
}*/

@ -2,9 +2,11 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:supplier_new/resources/tanker_trips_model.dart';
import '../common/settings.dart';
import 'package:http/http.dart' as http;
class FirstCharUppercaseFormatter extends TextInputFormatter {
const FirstCharUppercaseFormatter();
@ -76,6 +78,11 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
String? currentAvailability;
List<TankerTripsModel> tankerTripsList = [];
List<String> tankerImageUrls = [];
List<XFile> newImages = [];
final int maxImages = 5;
@override
void initState() {
@ -84,6 +91,15 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
_nameCtrl.text =
widget.tankerDetails.tanker_name ?? '';
if(widget.tankerDetails.images != null){
tankerImageUrls =
List<String>.from(
widget.tankerDetails.images
);
}
/// FIX allow null availability
if (widget.tankerDetails.availability != null &&
widget.tankerDetails.availability is List &&
@ -481,26 +497,57 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
}
Future<void> _refreshTankerDetails() async {
try {
setState(() => isLoading = true);
final updatedDetails = await AppSettings.getTankerDetailsByName(
final updatedDetails =
await AppSettings.getTankerDetailsByName(
_nameCtrl.text.trim(),
);
if (updatedDetails != null) {
setState(() {
widget.tankerDetails = updatedDetails;
/// VERY IMPORTANT FIX
tankerImageUrls =
List<String>.from(
updatedDetails.images ?? []
);
});
} else {
AppSettings.longFailedToast("Failed to fetch updated tanker details");
}
} catch (e) {
debugPrint("⚠️ Error refreshing tanker details: $e");
AppSettings.longFailedToast("Error refreshing tanker details");
} finally {
else{
AppSettings.longFailedToast(
"Failed to fetch updated tanker details"
);
}
}
catch(e){
debugPrint(
"⚠️ Error refreshing tanker details: $e"
);
AppSettings.longFailedToast(
"Error refreshing tanker details"
);
}
finally{
setState(() => isLoading = false);
}
}
String? fitToOption(String? incoming, List<String> options) {
@ -830,6 +877,280 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
);
}
Future<void> pickNewImages() async {
int totalImages =
tankerImageUrls.length + newImages.length;
if(totalImages >= maxImages){
AppSettings.longFailedToast(
"Maximum 5 images allowed"
);
return;
}
showModalBottomSheet(
context: context,
builder:(context){
return SafeArea(
child:Column(
mainAxisSize:MainAxisSize.min,
children:[
ListTile(
leading:Icon(Icons.photo),
title:Text("Gallery"),
onTap:() async {
Navigator.pop(context);
await _pickFromGallery();
},
),
ListTile(
leading:Icon(Icons.camera_alt),
title:Text("Camera"),
onTap:() async {
Navigator.pop(context);
await _pickFromCamera();
},
),
],
),
);
}
);
}
Future<void> _pickFromGallery() async {
final picker = ImagePicker();
final images =
await picker.pickMultiImage();
if(images.isEmpty) return;
int remaining =
maxImages - tankerImageUrls.length;
if(images.length > remaining){
AppSettings.longFailedToast(
"You can upload only $remaining more images"
);
newImages =
images.take(remaining).toList();
}
else{
newImages = images;
}
await uploadUpdatedImages();
}
Future<void> _pickFromCamera() async {
if(tankerImageUrls.length >= maxImages){
AppSettings.longFailedToast(
"Maximum 5 images allowed"
);
return;
}
final picker = ImagePicker();
final image =
await picker.pickImage(
source: ImageSource.camera,
imageQuality:70,
maxWidth:1280,
maxHeight:1280,
);
if(image == null) return;
newImages = [image];
await uploadUpdatedImages();
}
Future<void> deleteImage(int index) async {
try{
AppSettings.preLoaderDialog(context);
String imageUrl =
tankerImageUrls[index];
bool status =
await AppSettings.deleteTankerImage(
widget.tankerDetails.dbId,
imageUrl
);
Navigator.pop(context);
if(status){
tankerImageUrls.removeAt(index);
setState((){});
AppSettings.longSuccessToast(
"Image deleted"
);
/// optional refresh
await _refreshTankerDetails();
}
else{
AppSettings.longFailedToast(
"Delete failed"
);
}
}
catch(e){
Navigator.pop(context);
AppSettings.longFailedToast(
"Network error"
);
}
}
Future<void> uploadUpdatedImages() async {
try{
AppSettings.preLoaderDialog(context);
var request = http.MultipartRequest(
'POST',
Uri.parse(
AppSettings.host+
"uploads_tanker_images/"
"${widget.tankerDetails.dbId}"
)
);
request.headers.addAll(
await AppSettings.buildRequestHeaders()
);
for(var img in newImages){
request.files.add(
await http.MultipartFile.fromPath(
'files',
img.path
)
);
}
var response =
await request.send();
Navigator.pop(context);
var resp =
await http.Response.fromStream(response);
if(response.statusCode==200){
AppSettings.longSuccessToast(
"Images Updated"
);
newImages.clear();
await _refreshTankerDetails();
}
else{
print(resp.body);
AppSettings.longFailedToast(
"Upload failed"
);
}
}
catch(e){
Navigator.pop(context);
AppSettings.longFailedToast(
"Upload failed"
);
}
}
@override
Widget build(BuildContext context) {
return WillPopScope(
@ -868,13 +1189,223 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
padding: const EdgeInsets.all(16),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Images (${tankerImageUrls.length}/5)",
style: fontTextStyle(
12,
Color(0XFF515253),
FontWeight.w600
),
),
Text(
"Max 5 allowed",
style: fontTextStyle(
10,
Color(0XFF939495),
FontWeight.w400
),
),
],
),
SizedBox(height:8),
ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.asset(
'images/tanker_image.jpeg',
width: double.infinity,
height: 180,
fit: BoxFit.cover,
child: SizedBox(
height:180,
child:tankerImageUrls.isEmpty
? Image.asset(
'images/tanker_image.jpeg',
fit:BoxFit.cover
)
: ListView.builder(
scrollDirection:Axis.horizontal,
itemCount:tankerImageUrls.length,
itemBuilder:(context,index){
return Padding(
padding:EdgeInsets.only(right:8),
child:ClipRRect(
borderRadius:
BorderRadius.circular(12),
child:Stack(
children:[
Image.network(
tankerImageUrls[index],
width:250,
height:180,
fit:BoxFit.cover,
errorBuilder:(context,error,stack){
return Container(
width:250,
height:180,
color:Colors.grey[300],
child:Icon(
Icons.image_not_supported,
size:40,
color:Colors.grey,
),
);
},
loadingBuilder:(context,child,progress){
if(progress == null)
return child;
return Container(
width:250,
height:180,
alignment:Alignment.center,
child:CircularProgressIndicator(),
);
},
),
/// DELETE BUTTON
Positioned(
top:6,
right:6,
child:GestureDetector(
onTap:(){
showDialog(
context:context,
builder:(context){
return AlertDialog(
title:Text("Delete Image?"),
actions:[
TextButton(
onPressed:(){
Navigator.pop(context);
},
child:Text("Cancel")
),
TextButton(
onPressed:(){
Navigator.pop(context);
deleteImage(index);
},
child:Text("Delete")
)
],
);
}
);
},
child:Container(
decoration:BoxDecoration(
color:Colors.white,
shape:BoxShape.circle
),
padding:EdgeInsets.all(6),
child:Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
),
padding: EdgeInsets.all(6),
child: Image.asset(
'images/delete.png',
width: 18,
height: 18,
colorBlendMode: BlendMode.srcIn,
),
),
),
),
),
],
),
),
);
},
),
),
),
const SizedBox(height: 16),
@ -1135,9 +1666,11 @@ class _TankerDetailsPageState extends State<TankerDetailsPage> {
width: 0.5),
),
),
onPressed: () async {},
onPressed: () async {
pickNewImages();
},
child: Text(
"Assign",
"Update Images",
style: fontTextStyle(
14,
const Color(0xFFFFFFFF),

@ -14,6 +14,7 @@ class TankersModel {
String tanker_type='';
String pumping_fee='';
List<dynamic> availability= [];
List<dynamic> images= [];
TankersModel();
factory TankersModel.fromJson(Map<String, dynamic> json){
@ -29,6 +30,8 @@ class TankersModel {
rtvm.price = json['price'] ?? '';
rtvm.delivery_fee = json['delivery_fee'] ?? '';
rtvm.availability = json['availability'] ?? [];
rtvm.images = json['images'] ?? [];
rtvm.manufacturing_year = json['manufacturing_year'] ?? '';
rtvm.insurance_expiry = json['insurance_exp_date'] ?? '';
rtvm.tanker_type = json['tanker_type'] ?? '';

Loading…
Cancel
Save