updateProfile
This commit is contained in:
@@ -9,7 +9,8 @@ class NameTextField extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
return
|
||||
Container(
|
||||
height: 60,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
decoration: BoxDecoration(border: Border.all(color: APPCOLOR.lightGreen), borderRadius: BorderRadius.circular(15)),
|
||||
@@ -40,5 +41,7 @@ class NameTextField extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,8 +60,10 @@ class AppNetworkImage extends StatelessWidget {
|
||||
)),
|
||||
);
|
||||
},
|
||||
placeholder: (context, url) {
|
||||
return Container(
|
||||
placeholder: (context, url)
|
||||
{
|
||||
return
|
||||
Container(
|
||||
width: width,
|
||||
height: height,
|
||||
decoration: BoxDecoration(
|
||||
@@ -76,6 +78,7 @@ class AppNetworkImage extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
imageBuilder: (context, cIMage) {
|
||||
return Container(
|
||||
width: width,
|
||||
|
||||
@@ -1,33 +1,36 @@
|
||||
class APIURL {
|
||||
static const BASE_URL = "http://210.89.44.183:3333/xam/";
|
||||
static const String sendOtp = "${BASE_URL}auth/send-otp/customer";
|
||||
|
||||
static const String verifyOtp = "${BASE_URL}auth/verify-otp/customer";
|
||||
|
||||
static const String loginOtp = "${BASE_URL}auth/login/customer";
|
||||
|
||||
static const String loginOtp = "${BASE_URL}auth/login/customer";
|
||||
static const String login = "${BASE_URL}auth/login/vendor";
|
||||
static const String customerRegister = "${BASE_URL}auth/register/customer";
|
||||
static const String getAllProduct = "${BASE_URL}products";
|
||||
static const String getProductDetails = "${BASE_URL}products/";
|
||||
static const String getProductDetails = "${BASE_URL}products/";
|
||||
static const String getBanners = "${BASE_URL}banners";
|
||||
static const String customerLogOut = "${BASE_URL}auth/logout/customer";
|
||||
static const String getBestDealProduct = "${BASE_URL}products/best-deals";
|
||||
static const String getAllcategory = "${BASE_URL}categories";
|
||||
static const String addToWish = "${BASE_URL}carts/wishlist/items";
|
||||
static const String deleteToWish = "${BASE_URL}carts/wishlist/items";
|
||||
static const String deleteToWish = "${BASE_URL}carts/wishlist/items";
|
||||
static const String addToCart = "${BASE_URL}carts/items";
|
||||
static const String gettAllWishList = "${BASE_URL}carts/wishlist";
|
||||
static const String similarProduct = "${BASE_URL}products/";
|
||||
static const String getItemCards = "${BASE_URL}carts/current";
|
||||
static const String checkPin = "${BASE_URL}pin-codes/check/";
|
||||
static const String deleteItem = "${BASE_URL}carts/items/";
|
||||
|
||||
|
||||
static const String userAddress = "${BASE_URL}user/addresses";
|
||||
static const String addAddress = "${BASE_URL}user/addresses";
|
||||
static const String getprofile = "${BASE_URL}user/profile/customer";
|
||||
static const String refresh_token = "${BASE_URL}auth/refresh-token";
|
||||
static const String uploadImage = "${BASE_URL}images/upload";
|
||||
static const String updateProfile = "${BASE_URL}user/profile";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const String updateStore = "${BASE_URL}stores/";
|
||||
|
||||
static const String forgetPassword = "${BASE_URL}auth/forgot-password/vendor";
|
||||
static const String verifyForgetPassword =
|
||||
"${BASE_URL}auth/forgot-password-verify-otp/vendor";
|
||||
@@ -36,10 +39,10 @@ class APIURL {
|
||||
static const String getProduct = "${BASE_URL}products";
|
||||
static const String getCategoryByLevel = "${BASE_URL}categories/by-level/1";
|
||||
static const String getMe = "${BASE_URL}auth/me";
|
||||
static const String refresh_token = "${BASE_URL}auth/refresh-token";
|
||||
|
||||
static const String createProduct = "${BASE_URL}products";
|
||||
|
||||
static const String uploadImage = "${BASE_URL}images/upload";
|
||||
|
||||
static const String deleteProduct = "${BASE_URL}products/";
|
||||
static const String updateProduct = "${BASE_URL}products/";
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:grocery_app/src/data/allProduct_model.dart';
|
||||
import 'package:grocery_app/src/ui/bottomnavigation/bottom_bar_widget.dart';
|
||||
import 'package:grocery_app/src/ui/coupons/coupons_screen.dart';
|
||||
import 'package:grocery_app/src/ui/entername/enter_fullname_screen.dart';
|
||||
import 'package:grocery_app/src/ui/fruitvegidetail/fruit_veggie_detail.dart';
|
||||
import 'package:grocery_app/src/ui/login/login_screen.dart';
|
||||
import 'package:grocery_app/src/ui/login/signup_screen.dart';
|
||||
import 'package:grocery_app/src/ui/map/add_locations.dart';
|
||||
import 'package:grocery_app/src/ui/onboarding/on_boarding_screen.dart';
|
||||
import 'package:grocery_app/src/ui/otp/login_otp.dart';
|
||||
import 'package:grocery_app/src/ui/otp/otp_screen.dart';
|
||||
@@ -72,14 +74,16 @@ class MyRoutes {
|
||||
pageBuilder: (context, state) => const FruitVeggieDetail(),
|
||||
),
|
||||
|
||||
// animatedGoRoute(
|
||||
// path: PRODUCTDETAILS,
|
||||
// name: PRODUCTDETAILS,
|
||||
// pageBuilder: (context, state)
|
||||
// {
|
||||
// return const ProductDetails();
|
||||
// }
|
||||
// ),
|
||||
animatedGoRoute(
|
||||
path: COUPONSSCREEN,
|
||||
name: COUPONSSCREEN,
|
||||
pageBuilder: (context, state) => CouponsScreen(),
|
||||
),
|
||||
animatedGoRoute(
|
||||
path: ADDRESSS,
|
||||
name: ADDRESSS,
|
||||
pageBuilder: (context, state) => AddLocationAddress(),
|
||||
),
|
||||
|
||||
animatedGoRoute(
|
||||
path: PRODUCTDETAILS,
|
||||
@@ -219,44 +223,39 @@ class MyRoutes {
|
||||
static const FRUITVEGGIEDETAIL = "/FruitVeggieDetail";
|
||||
static const PRODUCTDETAILS = "/productdetails";
|
||||
static const LOGINOTPSCREEN = "/loginotpscreen";
|
||||
|
||||
|
||||
|
||||
static const SELECTACCOUNT = "/selectAccount";
|
||||
static const DASHBOARD = "/dashboard";
|
||||
|
||||
|
||||
static const COUPONSSCREEN = "/CouponsScreen";
|
||||
static const ADDRESSS = "/address";
|
||||
static const LOGIN = "/login";
|
||||
static const SIGNUP = "/signup";
|
||||
|
||||
static const ONBOARDING = "/onboarding";
|
||||
static const TERMANDCONDITIONS = "/termsandcondition";
|
||||
static const SETUPBUSSINESS = "/setupbussiness";
|
||||
static const CREATESTORE = "/createStore";
|
||||
static const SUBMITSCREEN = "/submitscreen";
|
||||
static const APPROVEDSTATUS = "/approvedstatus";
|
||||
|
||||
static const DASHBOARDSCREEN = "/dashboardscreen";
|
||||
static const CUSTOMERORDER = "/customerorder";
|
||||
// static const TERMANDCONDITIONS = "/termsandcondition";
|
||||
// static const SETUPBUSSINESS = "/setupbussiness";
|
||||
// static const CREATESTORE = "/createStore";
|
||||
// static const SUBMITSCREEN = "/submitscreen";
|
||||
// static const APPROVEDSTATUS = "/approvedstatus";
|
||||
|
||||
static const PRODUCTFORMSCREEN = "/productformscreen";
|
||||
// static const DASHBOARDSCREEN = "/dashboardscreen";
|
||||
// static const CUSTOMERORDER = "/customerorder";
|
||||
|
||||
static const TRANSACTIONHISTORY = "/transationhistory";
|
||||
// static const PRODUCTFORMSCREEN = "/productformscreen";
|
||||
|
||||
static const INSIGHTSHISTORY = "/insightshistory";
|
||||
// static const TRANSACTIONHISTORY = "/transationhistory";
|
||||
|
||||
static const DETAILSBUSSINESS = "/detailsbussiness";
|
||||
// static const INSIGHTSHISTORY = "/insightshistory";
|
||||
|
||||
static const STOREMANAGEMENT = "/storemanagement";
|
||||
// static const DETAILSBUSSINESS = "/detailsbussiness";
|
||||
|
||||
static const SETTING = "/settings";
|
||||
// static const STOREMANAGEMENT = "/storemanagement";
|
||||
|
||||
static const FORGETPASSWORD = "/forgetpassword";
|
||||
static const VERIFYPASSWORD = "/verifypassword";
|
||||
// static const SETTING = "/settings";
|
||||
|
||||
static const FORGETNEWPASSWORD = "/forgetnewpassword";
|
||||
// static const FORGETPASSWORD = "/forgetpassword";
|
||||
// static const VERIFYPASSWORD = "/verifypassword";
|
||||
|
||||
static const UPDATESTORE = "/updatestore";
|
||||
// static const FORGETNEWPASSWORD = "/forgetnewpassword";
|
||||
|
||||
// static const UPDATESTORE = "/updatestore";
|
||||
static const OTPSCREEN = "/otpscreen";
|
||||
}
|
||||
|
||||
|
||||
182
lib/src/data/address.dart
Normal file
182
lib/src/data/address.dart
Normal file
@@ -0,0 +1,182 @@
|
||||
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
AddressResponse addressResponseFromJson(dynamic str) =>
|
||||
AddressResponse.fromJson(json.decode(str));
|
||||
|
||||
dynamic addressResponseToJson(AddressResponse data) =>
|
||||
json.encode(data.toJson());
|
||||
|
||||
class AddressResponse {
|
||||
List<Datum>? data;
|
||||
Meta? meta;
|
||||
|
||||
AddressResponse({
|
||||
this.data,
|
||||
this.meta,
|
||||
});
|
||||
|
||||
factory AddressResponse.fromJson(Map<dynamic, dynamic> json) =>
|
||||
AddressResponse(
|
||||
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
|
||||
meta: Meta.fromJson(json["meta"]),
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
"data": List<dynamic>.from(data!.map((x) => x.toJson())),
|
||||
"meta": meta!.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class Datum {
|
||||
dynamic id;
|
||||
dynamic pincode;
|
||||
dynamic phoneNumber;
|
||||
dynamic alternatePhoneNumber;
|
||||
dynamic addressLine;
|
||||
dynamic landmark;
|
||||
dynamic addressType;
|
||||
dynamic city;
|
||||
dynamic district;
|
||||
dynamic name;
|
||||
dynamic state;
|
||||
dynamic country;
|
||||
bool? isDeliverable;
|
||||
bool? isDefault;
|
||||
dynamic additionalInstructions;
|
||||
DateTime? createdAt;
|
||||
DateTime? updatedAt;
|
||||
dynamic userId;
|
||||
User? user;
|
||||
|
||||
Datum({
|
||||
this.id,
|
||||
this.pincode,
|
||||
this.phoneNumber,
|
||||
this.alternatePhoneNumber,
|
||||
this.addressLine,
|
||||
this.landmark,
|
||||
this.addressType,
|
||||
this.city,
|
||||
this.district,
|
||||
this.name,
|
||||
this.state,
|
||||
this.country,
|
||||
this.isDeliverable,
|
||||
this.isDefault,
|
||||
this.additionalInstructions,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.userId,
|
||||
this.user,
|
||||
});
|
||||
|
||||
factory Datum.fromJson(Map<dynamic, dynamic> json) => Datum(
|
||||
id: json["id"],
|
||||
pincode: json["pincode"],
|
||||
phoneNumber: json["phoneNumber"],
|
||||
alternatePhoneNumber: json["alternatePhoneNumber"],
|
||||
addressLine: json["addressLine"],
|
||||
landmark: json["landmark"],
|
||||
addressType: json["addressType"],
|
||||
city: json["city"],
|
||||
district: json["district"],
|
||||
name: json["name"],
|
||||
state: json["state"],
|
||||
country: json["country"],
|
||||
isDeliverable: json["isDeliverable"],
|
||||
isDefault: json["isDefault"],
|
||||
additionalInstructions: json["additionalInstructions"],
|
||||
createdAt: DateTime.parse(json["createdAt"]),
|
||||
updatedAt: DateTime.parse(json["updatedAt"]),
|
||||
userId: json["userId"],
|
||||
user: User.fromJson(json["user"]),
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"pincode": pincode,
|
||||
"phoneNumber": phoneNumber,
|
||||
"alternatePhoneNumber": alternatePhoneNumber,
|
||||
"addressLine": addressLine,
|
||||
"landmark": landmark,
|
||||
"addressType": addressType,
|
||||
"city": city,
|
||||
"district": district,
|
||||
"name": name,
|
||||
"state": state,
|
||||
"country": country,
|
||||
"isDeliverable": isDeliverable,
|
||||
"isDefault": isDefault,
|
||||
"additionalInstructions": additionalInstructions,
|
||||
"createdAt": createdAt,
|
||||
"updatedAt": updatedAt,
|
||||
"userId": userId,
|
||||
"user": user!.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class User {
|
||||
dynamic firstName;
|
||||
dynamic lastName;
|
||||
dynamic email;
|
||||
dynamic phone;
|
||||
|
||||
User({
|
||||
this.firstName,
|
||||
this.lastName,
|
||||
this.email,
|
||||
this.phone,
|
||||
});
|
||||
|
||||
factory User.fromJson(Map<dynamic, dynamic> json) => User(
|
||||
firstName: json["firstName"],
|
||||
lastName: json["lastName"],
|
||||
email: json["email"],
|
||||
phone: json["phone"],
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
"firstName": firstName,
|
||||
"lastName": lastName,
|
||||
"email": email,
|
||||
"phone": phone,
|
||||
};
|
||||
}
|
||||
|
||||
class Meta {
|
||||
int? total;
|
||||
int? page;
|
||||
int? limit;
|
||||
int? lastPage;
|
||||
bool? hasNextPage;
|
||||
bool? hasPreviousPage;
|
||||
|
||||
Meta({
|
||||
this.total,
|
||||
this.page,
|
||||
this.limit,
|
||||
this.lastPage,
|
||||
this.hasNextPage,
|
||||
this.hasPreviousPage,
|
||||
});
|
||||
|
||||
factory Meta.fromJson(Map<dynamic, dynamic> json) => Meta(
|
||||
total: json["total"],
|
||||
page: json["page"],
|
||||
limit: json["limit"],
|
||||
lastPage: json["lastPage"],
|
||||
hasNextPage: json["hasNextPage"],
|
||||
hasPreviousPage: json["hasPreviousPage"],
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
"total": total,
|
||||
"page": page,
|
||||
"limit": limit,
|
||||
"lastPage": lastPage,
|
||||
"hasNextPage": hasNextPage,
|
||||
"hasPreviousPage": hasPreviousPage,
|
||||
};
|
||||
}
|
||||
53
lib/src/data/upload_image.dart
Normal file
53
lib/src/data/upload_image.dart
Normal file
@@ -0,0 +1,53 @@
|
||||
// To parse this JSON data, do
|
||||
//
|
||||
// final uploadImage = uploadImageFromJson(jsonString);
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
UploadImage uploadImageFromJson(String str) => UploadImage.fromJson(json.decode(str));
|
||||
|
||||
String uploadImageToJson(UploadImage data) => json.encode(data.toJson());
|
||||
|
||||
class UploadImage {
|
||||
int? status;
|
||||
String? message;
|
||||
Image? data;
|
||||
|
||||
UploadImage({
|
||||
this.status,
|
||||
this.message,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory UploadImage.fromJson(Map<String, dynamic> json) => UploadImage(
|
||||
status: json["status"],
|
||||
message: json["message"],
|
||||
data: Image.fromJson(json["data"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"status": status,
|
||||
"message": message,
|
||||
"data": data!.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class Image {
|
||||
String? url;
|
||||
String? publicId;
|
||||
|
||||
Image({
|
||||
this.url,
|
||||
this.publicId,
|
||||
});
|
||||
|
||||
factory Image.fromJson(Map<String, dynamic> json) => Image(
|
||||
url: json["url"],
|
||||
publicId: json["publicId"],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"url": url,
|
||||
"publicId": publicId,
|
||||
};
|
||||
}
|
||||
110
lib/src/data/user_profile.dart
Normal file
110
lib/src/data/user_profile.dart
Normal file
@@ -0,0 +1,110 @@
|
||||
// To parse this JSON data, do
|
||||
//
|
||||
// final userProfile = userProfileFromJson(jsondynamic);
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
UserProfile userProfileFromJson(dynamic str) =>
|
||||
UserProfile.fromJson(json.decode(str));
|
||||
|
||||
dynamic userProfileToJson(UserProfile data) => json.encode(data.toJson());
|
||||
|
||||
class UserProfile {
|
||||
dynamic id;
|
||||
dynamic email;
|
||||
dynamic firstName;
|
||||
dynamic lastName;
|
||||
dynamic name;
|
||||
dynamic img;
|
||||
dynamic authType;
|
||||
dynamic role;
|
||||
dynamic phone;
|
||||
dynamic password;
|
||||
bool? isActive;
|
||||
bool? isPhoneVerified;
|
||||
dynamic vendorType;
|
||||
dynamic businessId;
|
||||
bool? isVendorAccountCreated;
|
||||
bool? isVendorAccountActive;
|
||||
bool? vendorTermsAccepted;
|
||||
DateTime? createdAt;
|
||||
DateTime? updatedAt;
|
||||
dynamic rtHash;
|
||||
dynamic resetToken;
|
||||
dynamic resetTokenExpiresAt;
|
||||
|
||||
UserProfile({
|
||||
this.id,
|
||||
this.email,
|
||||
this.firstName,
|
||||
this.lastName,
|
||||
this.name,
|
||||
this.img,
|
||||
this.authType,
|
||||
this.role,
|
||||
this.phone,
|
||||
this.password,
|
||||
this.isActive,
|
||||
this.isPhoneVerified,
|
||||
this.vendorType,
|
||||
this.businessId,
|
||||
this.isVendorAccountCreated,
|
||||
this.isVendorAccountActive,
|
||||
this.vendorTermsAccepted,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.rtHash,
|
||||
this.resetToken,
|
||||
this.resetTokenExpiresAt,
|
||||
});
|
||||
|
||||
factory UserProfile.fromJson(Map<dynamic, dynamic> json) => UserProfile(
|
||||
id: json["id"],
|
||||
email: json["email"],
|
||||
firstName: json["firstName"],
|
||||
lastName: json["lastName"],
|
||||
name: json["name"],
|
||||
img: json["img"],
|
||||
authType: json["authType"],
|
||||
role: json["role"],
|
||||
phone: json["phone"],
|
||||
password: json["password"],
|
||||
isActive: json["isActive"],
|
||||
isPhoneVerified: json["isPhoneVerified"],
|
||||
vendorType: json["vendorType"],
|
||||
businessId: json["businessId"],
|
||||
isVendorAccountCreated: json["isVendorAccountCreated"],
|
||||
isVendorAccountActive: json["isVendorAccountActive"],
|
||||
vendorTermsAccepted: json["vendorTermsAccepted"],
|
||||
createdAt: DateTime?.parse(json["createdAt"]),
|
||||
updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
rtHash: json["rtHash"],
|
||||
resetToken: json["resetToken"],
|
||||
resetTokenExpiresAt: json["resetTokenExpiresAt"],
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"email": email,
|
||||
"firstName": firstName,
|
||||
"lastName": lastName,
|
||||
"name": name,
|
||||
"img": img,
|
||||
"authType": authType,
|
||||
"role": role,
|
||||
"phone": phone,
|
||||
"password": password,
|
||||
"isActive": isActive,
|
||||
"isPhoneVerified": isPhoneVerified,
|
||||
"vendorType": vendorType,
|
||||
"businessId": businessId,
|
||||
"isVendorAccountCreated": isVendorAccountCreated,
|
||||
"isVendorAccountActive": isVendorAccountActive,
|
||||
"vendorTermsAccepted": vendorTermsAccepted,
|
||||
"createdAt": createdAt,
|
||||
"updatedAt": updatedAt,
|
||||
"rtHash": rtHash,
|
||||
"resetToken": resetToken,
|
||||
"resetTokenExpiresAt": resetTokenExpiresAt,
|
||||
};
|
||||
}
|
||||
@@ -1,3 +1,256 @@
|
||||
// // To parse this JSON data, do
|
||||
// //
|
||||
// // final wishListModel = wishListModelFromJson(jsondynamic);
|
||||
|
||||
// import 'dart:convert';
|
||||
|
||||
// WishListModel wishListModelFromJson(dynamic str) => WishListModel.fromJson(json.decode(str));
|
||||
|
||||
// dynamic wishListModelToJson(WishListModel data) => json.encode(data.toJson());
|
||||
|
||||
// class WishListModel {
|
||||
// dynamic id;
|
||||
// dynamic userId;
|
||||
// DateTime?? createdAt;
|
||||
// DateTime?? updatedAt;
|
||||
// List<WishListItem>? items;
|
||||
// dynamic? totalItems;
|
||||
|
||||
// WishListModel({
|
||||
// this.id,
|
||||
// this.userId,
|
||||
// this.createdAt,
|
||||
// this.updatedAt,
|
||||
// this.items,
|
||||
// this.totalItems,
|
||||
// });
|
||||
|
||||
// factory WishListModel.fromJson(Map<dynamic, dynamic> json) => WishListModel(
|
||||
// id: json["id"],
|
||||
// userId: json["userId"],
|
||||
// createdAt: DateTime?.parse(json["createdAt"]),
|
||||
// updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
// items: List<WishListItem>.from(json["items"].map((x) => WishListItem.fromJson(x))),
|
||||
// totalItems: json["totalItems"],
|
||||
// );
|
||||
|
||||
// Map<dynamic, dynamic> toJson() => {
|
||||
// "id": id,
|
||||
// "userId": userId,
|
||||
// "createdAt": createdAt,
|
||||
// "updatedAt": updatedAt,
|
||||
// "items": List<dynamic>.from(items!.map((x) => x.toJson())),
|
||||
// "totalItems": totalItems,
|
||||
// };
|
||||
// }
|
||||
|
||||
// class WishListItem {
|
||||
// dynamic id;
|
||||
// dynamic wishlistId;
|
||||
// dynamic productId;
|
||||
// dynamic storeId;
|
||||
// DateTime?? createdAt;
|
||||
// DateTime?? updatedAt;
|
||||
// ProductDatum? product;
|
||||
// Store? store;
|
||||
|
||||
// WishListItem({
|
||||
// this.id,
|
||||
// this.wishlistId,
|
||||
// this.productId,
|
||||
// this.storeId,
|
||||
// this.createdAt,
|
||||
// this.updatedAt,
|
||||
// this.product,
|
||||
// this.store,
|
||||
// });
|
||||
|
||||
// factory WishListItem.fromJson(Map<dynamic, dynamic> json) => WishListItem(
|
||||
// id: json["id"],
|
||||
// wishlistId: json["wishlistId"],
|
||||
// productId: json["productId"],
|
||||
// storeId: json["storeId"],
|
||||
// createdAt: DateTime?.parse(json["createdAt"]),
|
||||
// updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
// product: ProductDatum.fromJson(json["product"]),
|
||||
// store: Store.fromJson(json["store"]),
|
||||
// );
|
||||
|
||||
// Map<dynamic, dynamic> toJson() => {
|
||||
// "id": id,
|
||||
// "wishlistId": wishlistId,
|
||||
// "productId": productId,
|
||||
// "storeId": storeId,
|
||||
// "createdAt": createdAt,
|
||||
// "updatedAt": updatedAt,
|
||||
// "product": product!.toJson(),
|
||||
// "store": store!.toJson(),
|
||||
// };
|
||||
// }
|
||||
|
||||
// class ProductDatum {
|
||||
// dynamic id;
|
||||
// dynamic name;
|
||||
// dynamic description;
|
||||
// dynamic additionalInfo;
|
||||
// dynamic brand;
|
||||
// dynamic basePrice;
|
||||
// dynamic discountPrice;
|
||||
// dynamic stock;
|
||||
// dynamic quantity;
|
||||
// dynamic unit;
|
||||
// dynamic slug;
|
||||
// dynamic rating;
|
||||
// bool? isInStock;
|
||||
// bool? isActive;
|
||||
// bool? isInWishlist;
|
||||
// DateTime?? createdAt;
|
||||
// DateTime?? updatedAt;
|
||||
// dynamic storeId;
|
||||
// dynamic categoryId;
|
||||
// dynamic productTypeId;
|
||||
// dynamic timeSlotId;
|
||||
|
||||
// ProductDatum({
|
||||
// this.id,
|
||||
// this.name,
|
||||
// this.description,
|
||||
// this.additionalInfo,
|
||||
// this.brand,
|
||||
// this.basePrice,
|
||||
// this.discountPrice,
|
||||
// this.stock,
|
||||
// this.quantity,
|
||||
// this.unit,
|
||||
// this.slug,
|
||||
// this.rating,
|
||||
// this.isInStock,
|
||||
// this.isActive,
|
||||
// this.isInWishlist,
|
||||
// this.createdAt,
|
||||
// this.updatedAt,
|
||||
// this.storeId,
|
||||
// this.categoryId,
|
||||
// this.productTypeId,
|
||||
// this.timeSlotId,
|
||||
// });
|
||||
|
||||
// factory ProductDatum.fromJson(Map<dynamic, dynamic> json) => ProductDatum(
|
||||
// id: json["id"],
|
||||
// name: json["name"],
|
||||
// description: json["description"],
|
||||
// additionalInfo: json["additionalInfo"],
|
||||
// brand: json["brand"],
|
||||
// basePrice: json["basePrice"],
|
||||
// discountPrice: json["discountPrice"],
|
||||
// stock: json["stock"],
|
||||
// quantity: json["quantity"],
|
||||
// unit: json["unit"],
|
||||
// slug: json["slug"],
|
||||
// rating: json["rating"],
|
||||
// isInStock: json["isInStock"],
|
||||
// isActive: json["isActive"],
|
||||
// isInWishlist: json["isInWishlist"],
|
||||
// createdAt: DateTime?.parse(json["createdAt"]),
|
||||
// updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
// storeId: json["storeId"],
|
||||
// categoryId: json["categoryId"],
|
||||
// productTypeId: json["productTypeId"],
|
||||
// timeSlotId: json["timeSlotId"],
|
||||
// );
|
||||
|
||||
// Map<dynamic, dynamic> toJson() => {
|
||||
// "id": id,
|
||||
// "name": name,
|
||||
// "description": description,
|
||||
// "additionalInfo": additionalInfo,
|
||||
// "brand": brand,
|
||||
// "basePrice": basePrice,
|
||||
// "discountPrice": discountPrice,
|
||||
// "stock": stock,
|
||||
// "quantity": quantity,
|
||||
// "unit": unit,
|
||||
// "slug": slug,
|
||||
// "rating": rating,
|
||||
// "isInStock": isInStock,
|
||||
// "isActive": isActive,
|
||||
// "isInWishlist": isInWishlist,
|
||||
// "createdAt": createdAt,
|
||||
// "updatedAt": updatedAt,
|
||||
// "storeId": storeId,
|
||||
// "categoryId": categoryId,
|
||||
// "productTypeId": productTypeId,
|
||||
// "timeSlotId": timeSlotId,
|
||||
// };
|
||||
|
||||
// void add(ProductDatum productDatum) {}
|
||||
// }
|
||||
|
||||
// class Store {
|
||||
// dynamic id;
|
||||
// dynamic storeName;
|
||||
// dynamic storeDescription;
|
||||
// dynamic officialPhoneNumber;
|
||||
// dynamic storeAddress;
|
||||
// dynamic gstNumber;
|
||||
// dynamic gumastaNumber;
|
||||
// dynamic storePicture;
|
||||
// DateTime?? createdAt;
|
||||
// DateTime?? updatedAt;
|
||||
// dynamic vendorId;
|
||||
// bool? isActive;
|
||||
// dynamic couponId;
|
||||
|
||||
// Store({
|
||||
// this.id,
|
||||
// this.storeName,
|
||||
// this.storeDescription,
|
||||
// this.officialPhoneNumber,
|
||||
// this.storeAddress,
|
||||
// this.gstNumber,
|
||||
// this.gumastaNumber,
|
||||
// this.storePicture,
|
||||
// this.createdAt,
|
||||
// this.updatedAt,
|
||||
// this.vendorId,
|
||||
// this.isActive,
|
||||
// this.couponId,
|
||||
// });
|
||||
|
||||
// factory Store.fromJson(Map<dynamic, dynamic> json) => Store(
|
||||
// id: json["id"],
|
||||
// storeName: json["storeName"],
|
||||
// storeDescription: json["storeDescription"],
|
||||
// officialPhoneNumber: json["officialPhoneNumber"],
|
||||
// storeAddress: json["storeAddress"],
|
||||
// gstNumber: json["gstNumber"],
|
||||
// gumastaNumber: json["gumastaNumber"],
|
||||
// storePicture: json["storePicture"],
|
||||
// createdAt: DateTime?.parse(json["createdAt"]),
|
||||
// updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
// vendorId: json["vendorId"],
|
||||
// isActive: json["isActive"],
|
||||
// couponId: json["couponId"],
|
||||
// );
|
||||
|
||||
// Map<dynamic, dynamic> toJson() => {
|
||||
// "id": id,
|
||||
// "storeName": storeName,
|
||||
// "storeDescription": storeDescription,
|
||||
// "officialPhoneNumber": officialPhoneNumber,
|
||||
// "storeAddress": storeAddress,
|
||||
// "gstNumber": gstNumber,
|
||||
// "gumastaNumber": gumastaNumber,
|
||||
// "storePicture": storePicture,
|
||||
// "createdAt": createdAt,
|
||||
// "updatedAt": updatedAt,
|
||||
// "vendorId": vendorId,
|
||||
// "isActive": isActive,
|
||||
// "couponId": couponId,
|
||||
// };
|
||||
// }
|
||||
|
||||
|
||||
// To parse this JSON data, do
|
||||
//
|
||||
// final wishListModel = wishListModelFromJson(jsondynamic);
|
||||
@@ -14,7 +267,7 @@ class WishListModel {
|
||||
DateTime? createdAt;
|
||||
DateTime? updatedAt;
|
||||
List<WishListItem>? items;
|
||||
dynamic? totalItems;
|
||||
dynamic totalItems;
|
||||
|
||||
WishListModel({
|
||||
this.id,
|
||||
@@ -28,8 +281,8 @@ class WishListModel {
|
||||
factory WishListModel.fromJson(Map<dynamic, dynamic> json) => WishListModel(
|
||||
id: json["id"],
|
||||
userId: json["userId"],
|
||||
createdAt: DateTime.parse(json["createdAt"]),
|
||||
updatedAt: DateTime.parse(json["updatedAt"]),
|
||||
createdAt: DateTime?.parse(json["createdAt"]),
|
||||
updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
items: List<WishListItem>.from(json["items"].map((x) => WishListItem.fromJson(x))),
|
||||
totalItems: json["totalItems"],
|
||||
);
|
||||
@@ -70,8 +323,8 @@ class WishListItem {
|
||||
wishlistId: json["wishlistId"],
|
||||
productId: json["productId"],
|
||||
storeId: json["storeId"],
|
||||
createdAt: DateTime.parse(json["createdAt"]),
|
||||
updatedAt: DateTime.parse(json["updatedAt"]),
|
||||
createdAt: DateTime?.parse(json["createdAt"]),
|
||||
updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
product: ProductDatum.fromJson(json["product"]),
|
||||
store: Store.fromJson(json["store"]),
|
||||
);
|
||||
@@ -96,20 +349,24 @@ class ProductDatum {
|
||||
dynamic brand;
|
||||
dynamic basePrice;
|
||||
dynamic discountPrice;
|
||||
dynamic stock;
|
||||
dynamic quantity;
|
||||
dynamic? stock;
|
||||
dynamic? quantity;
|
||||
dynamic unit;
|
||||
dynamic slug;
|
||||
dynamic rating;
|
||||
dynamic averageRating;
|
||||
bool? isInStock;
|
||||
bool? isActive;
|
||||
bool? isInWishlist;
|
||||
DateTime? createdAt;
|
||||
DateTime? updatedAt;
|
||||
dynamic storeId;
|
||||
dynamic categoryId;
|
||||
dynamic productTypeId;
|
||||
dynamic timeSlotId;
|
||||
List<ProductImage>? productImages;
|
||||
Category? category;
|
||||
List<ProductTag>? productTags;
|
||||
List<dynamic>? zones;
|
||||
List<ProductReview>? productReview;
|
||||
|
||||
ProductDatum({
|
||||
this.id,
|
||||
@@ -123,16 +380,20 @@ class ProductDatum {
|
||||
this.quantity,
|
||||
this.unit,
|
||||
this.slug,
|
||||
this.rating,
|
||||
this.averageRating,
|
||||
this.isInStock,
|
||||
this.isActive,
|
||||
this.isInWishlist,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.storeId,
|
||||
this.categoryId,
|
||||
this.productTypeId,
|
||||
this.timeSlotId,
|
||||
this.productImages,
|
||||
this.category,
|
||||
this.productTags,
|
||||
this.zones,
|
||||
this.productReview,
|
||||
});
|
||||
|
||||
factory ProductDatum.fromJson(Map<dynamic, dynamic> json) => ProductDatum(
|
||||
@@ -147,16 +408,20 @@ class ProductDatum {
|
||||
quantity: json["quantity"],
|
||||
unit: json["unit"],
|
||||
slug: json["slug"],
|
||||
rating: json["rating"],
|
||||
averageRating: json["averageRating"],
|
||||
isInStock: json["isInStock"],
|
||||
isActive: json["isActive"],
|
||||
isInWishlist: json["isInWishlist"],
|
||||
createdAt: DateTime.parse(json["createdAt"]),
|
||||
updatedAt: DateTime.parse(json["updatedAt"]),
|
||||
createdAt: DateTime?.parse(json["createdAt"]),
|
||||
updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
storeId: json["storeId"],
|
||||
categoryId: json["categoryId"],
|
||||
productTypeId: json["productTypeId"],
|
||||
timeSlotId: json["timeSlotId"],
|
||||
productImages: List<ProductImage>.from(json["productImages"].map((x) => ProductImage.fromJson(x))),
|
||||
category: Category.fromJson(json["category"]),
|
||||
productTags: List<ProductTag>.from(json["productTags"].map((x) => ProductTag.fromJson(x))),
|
||||
zones: List<dynamic>.from(json["zones"].map((x) => x)),
|
||||
productReview: List<ProductReview>.from(json["ProductReview"].map((x) => ProductReview.fromJson(x))),
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
@@ -171,16 +436,204 @@ class ProductDatum {
|
||||
"quantity": quantity,
|
||||
"unit": unit,
|
||||
"slug": slug,
|
||||
"rating": rating,
|
||||
"averageRating": averageRating,
|
||||
"isInStock": isInStock,
|
||||
"isActive": isActive,
|
||||
"isInWishlist": isInWishlist,
|
||||
"createdAt": createdAt,
|
||||
"updatedAt": updatedAt,
|
||||
"storeId": storeId,
|
||||
"categoryId": categoryId,
|
||||
"productTypeId": productTypeId,
|
||||
"timeSlotId": timeSlotId,
|
||||
"productImages": List<dynamic>.from(productImages!.map((x) => x.toJson())),
|
||||
"category": category!.toJson(),
|
||||
"productTags": List<dynamic>.from(productTags!.map((x) => x.toJson())),
|
||||
"zones": List<dynamic>.from(zones!.map((x) => x)),
|
||||
"ProductReview": List<dynamic>.from(productReview!.map((x) => x.toJson())),
|
||||
};
|
||||
}
|
||||
|
||||
class Category {
|
||||
dynamic id;
|
||||
dynamic name;
|
||||
dynamic description;
|
||||
dynamic image;
|
||||
dynamic slug;
|
||||
dynamic? level;
|
||||
bool? isActive;
|
||||
DateTime? createdAt;
|
||||
DateTime? updatedAt;
|
||||
dynamic parentCategoryId;
|
||||
dynamic path;
|
||||
|
||||
Category({
|
||||
this.id,
|
||||
this.name,
|
||||
this.description,
|
||||
this.image,
|
||||
this.slug,
|
||||
this.level,
|
||||
this.isActive,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.parentCategoryId,
|
||||
this.path,
|
||||
});
|
||||
|
||||
factory Category.fromJson(Map<dynamic, dynamic> json) => Category(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
description: json["description"],
|
||||
image: json["image"],
|
||||
slug: json["slug"],
|
||||
level: json["level"],
|
||||
isActive: json["isActive"],
|
||||
createdAt: DateTime?.parse(json["createdAt"]),
|
||||
updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
parentCategoryId: json["parentCategoryId"],
|
||||
path: json["path"],
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"image": image,
|
||||
"slug": slug,
|
||||
"level": level,
|
||||
"isActive": isActive,
|
||||
"createdAt": createdAt,
|
||||
"updatedAt": updatedAt,
|
||||
"parentCategoryId": parentCategoryId,
|
||||
"path": path,
|
||||
};
|
||||
}
|
||||
|
||||
class ProductImage {
|
||||
dynamic id;
|
||||
dynamic url;
|
||||
bool? isDefault;
|
||||
dynamic productId;
|
||||
|
||||
ProductImage({
|
||||
this.id,
|
||||
this.url,
|
||||
this.isDefault,
|
||||
this.productId,
|
||||
});
|
||||
|
||||
factory ProductImage.fromJson(Map<dynamic, dynamic> json) => ProductImage(
|
||||
id: json["id"],
|
||||
url: json["url"],
|
||||
isDefault: json["isDefault"],
|
||||
productId: json["productId"],
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"url": url,
|
||||
"isDefault": isDefault,
|
||||
"productId": productId,
|
||||
};
|
||||
}
|
||||
|
||||
class ProductReview {
|
||||
dynamic id;
|
||||
dynamic userId;
|
||||
dynamic productId;
|
||||
dynamic rating;
|
||||
dynamic title;
|
||||
dynamic description;
|
||||
dynamic? likes;
|
||||
dynamic? dislikes;
|
||||
dynamic? helpfulCount;
|
||||
bool? verifiedPurchase;
|
||||
dynamic status;
|
||||
DateTime? createdAt;
|
||||
DateTime? updatedAt;
|
||||
|
||||
ProductReview({
|
||||
this.id,
|
||||
this.userId,
|
||||
this.productId,
|
||||
this.rating,
|
||||
this.title,
|
||||
this.description,
|
||||
this.likes,
|
||||
this.dislikes,
|
||||
this.helpfulCount,
|
||||
this.verifiedPurchase,
|
||||
this.status,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory ProductReview.fromJson(Map<dynamic, dynamic> json) => ProductReview(
|
||||
id: json["id"],
|
||||
userId: json["userId"],
|
||||
productId: json["productId"],
|
||||
rating: json["rating"],
|
||||
title: json["title"],
|
||||
description: json["description"],
|
||||
likes: json["likes"],
|
||||
dislikes: json["dislikes"],
|
||||
helpfulCount: json["helpfulCount"],
|
||||
verifiedPurchase: json["verifiedPurchase"],
|
||||
status: json["status"],
|
||||
createdAt: DateTime?.parse(json["createdAt"]),
|
||||
updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"userId": userId,
|
||||
"productId": productId,
|
||||
"rating": rating,
|
||||
"title": title,
|
||||
"description": description,
|
||||
"likes": likes,
|
||||
"dislikes": dislikes,
|
||||
"helpfulCount": helpfulCount,
|
||||
"verifiedPurchase": verifiedPurchase,
|
||||
"status": status,
|
||||
"createdAt": createdAt,
|
||||
"updatedAt": updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
class ProductTag {
|
||||
dynamic id;
|
||||
dynamic name;
|
||||
dynamic description;
|
||||
bool? isActive;
|
||||
DateTime? createdAt;
|
||||
DateTime? updatedAt;
|
||||
|
||||
ProductTag({
|
||||
this.id,
|
||||
this.name,
|
||||
this.description,
|
||||
this.isActive,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory ProductTag.fromJson(Map<dynamic, dynamic> json) => ProductTag(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
description: json["description"],
|
||||
isActive: json["isActive"],
|
||||
createdAt: DateTime?.parse(json["createdAt"]),
|
||||
updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
);
|
||||
|
||||
Map<dynamic, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"isActive": isActive,
|
||||
"createdAt": createdAt,
|
||||
"updatedAt": updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -224,8 +677,8 @@ class Store {
|
||||
gstNumber: json["gstNumber"],
|
||||
gumastaNumber: json["gumastaNumber"],
|
||||
storePicture: json["storePicture"],
|
||||
createdAt: DateTime.parse(json["createdAt"]),
|
||||
updatedAt: DateTime.parse(json["updatedAt"]),
|
||||
createdAt: DateTime?.parse(json["createdAt"]),
|
||||
updatedAt: DateTime?.parse(json["updatedAt"]),
|
||||
vendorId: json["vendorId"],
|
||||
isActive: json["isActive"],
|
||||
couponId: json["couponId"],
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:grocery_app/src/core/network_services/service_locator.dart';
|
||||
import 'package:grocery_app/src/data/address.dart';
|
||||
import 'package:grocery_app/src/data/all_cart_items.dart';
|
||||
import 'package:grocery_app/src/logic/repo/product_repo.dart';
|
||||
import 'package:grocery_app/utils/extensions/extensions.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class AddtocartProvider extends ChangeNotifier {
|
||||
@@ -15,6 +18,7 @@ class AddtocartProvider extends ChangeNotifier {
|
||||
String get pinCode => _pinCode;
|
||||
bool get isLoading => _isLoading;
|
||||
bool get isDeliverable => _isDeliverable;
|
||||
TextEditingController checkPinCode = TextEditingController();
|
||||
|
||||
Future<void> getCurrentLocation(BuildContext context) async {
|
||||
_isLoading = true;
|
||||
@@ -23,16 +27,6 @@ class AddtocartProvider extends ChangeNotifier {
|
||||
try {
|
||||
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
_pinCode = "Location services disabled.";
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LocationPermission permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
_pinCode = "Permission denied.";
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
|
||||
@@ -52,54 +46,58 @@ class AddtocartProvider extends ChangeNotifier {
|
||||
|
||||
if (placemarks.isNotEmpty) {
|
||||
_pinCode = placemarks.first.postalCode ?? "Unknown";
|
||||
checkPinCode.text = _pinCode;
|
||||
print("Pincode found: $_pinCode");
|
||||
|
||||
// Now check if this pin code is deliverable
|
||||
await checkPin(context, _pinCode);
|
||||
} else {
|
||||
_pinCode = "Could not fetch pin code.";
|
||||
_pinCode = "unable to current pi code";
|
||||
print("Error: No placemarks found.");
|
||||
}
|
||||
} catch (e) {
|
||||
_pinCode = "Error: ${e.toString()}";
|
||||
_pinCode = "unable to current pi code";
|
||||
print("Error: ${e.toString()}");
|
||||
}
|
||||
|
||||
_pinCode = "unable to current pi code";
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool ischeckpin = false;
|
||||
Future<void> checkPin(BuildContext context, pin) async {
|
||||
ischeckpin = true;
|
||||
_pinCode = pin;
|
||||
notifyListeners();
|
||||
var data = {};
|
||||
try {
|
||||
var result = await _homeRepo.checkPin(data, pin);
|
||||
|
||||
return result.fold(
|
||||
(error) {
|
||||
ischeckpin = false;
|
||||
_isDeliverable = false;
|
||||
isLoaddcartItem = false;
|
||||
notifyListeners();
|
||||
},
|
||||
(response) {
|
||||
print("kdhfgkjfkghkfghkj ${response.isDeliverable!}");
|
||||
if (response.isDeliverable!) {
|
||||
_isDeliverable = true;
|
||||
}
|
||||
|
||||
ischeckpin = false;
|
||||
isLoaddcartItem = false;
|
||||
notifyListeners();
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
ischeckpin = false;
|
||||
_isDeliverable = false;
|
||||
isLoaddcartItem = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Map<String, bool> isRemoveItem = {};
|
||||
Map<String, bool> isRemoveItem = {};
|
||||
|
||||
Future<void> deleteItem(BuildContext context, id) async {
|
||||
isRemoveItem[id] = true;
|
||||
@@ -109,18 +107,17 @@ class AddtocartProvider extends ChangeNotifier {
|
||||
var result = await _homeRepo.deleteItem(data, id);
|
||||
return result.fold(
|
||||
(error) {
|
||||
|
||||
isRemoveItem[id] = false;
|
||||
notifyListeners();
|
||||
},
|
||||
(response) {
|
||||
getItemCards(context);
|
||||
isRemoveItem[id] = false;
|
||||
isRemoveItem[id] = false;
|
||||
notifyListeners();
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
isRemoveItem[id] = false;
|
||||
isRemoveItem[id] = false;
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
@@ -140,12 +137,10 @@ class AddtocartProvider extends ChangeNotifier {
|
||||
|
||||
return result.fold(
|
||||
(error) {
|
||||
print("dsjfgkjhkdfgdkjfhg");
|
||||
isLoaddcartItem = false;
|
||||
notifyListeners();
|
||||
},
|
||||
(response) {
|
||||
print("dsjfgkjhkdjsfjkdhfsgfgdkjfhg");
|
||||
allitem = response!;
|
||||
isLoaddcartItem = false;
|
||||
notifyListeners();
|
||||
@@ -157,4 +152,165 @@ class AddtocartProvider extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////// address/////////////////////////
|
||||
List<Datum> addresslist = [];
|
||||
|
||||
Future<void> getAddress(BuildContext context) async {
|
||||
var data = {};
|
||||
try {
|
||||
var result = await _homeRepo.getAddress(data);
|
||||
|
||||
return result.fold(
|
||||
(error) {
|
||||
print("dsjfgkjhkdfgdkjfhg");
|
||||
|
||||
notifyListeners();
|
||||
},
|
||||
(response) {
|
||||
addresslist = response.data!;
|
||||
if (response.data!.isNotEmpty) {
|
||||
_selectedAddress = addresslist.last.id ?? "";
|
||||
} else {
|
||||
_selectedAddress = "";
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
print("sfddsfdfff");
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
String _selectedAddress = "";
|
||||
|
||||
String get selectedAddress => _selectedAddress;
|
||||
|
||||
void selectAddress(String address) {
|
||||
_selectedAddress = address;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Set<String> cartItems = {};
|
||||
Map<String, bool> isLoadings = {};
|
||||
|
||||
bool isLoadingCart = false;
|
||||
bool iscardAdded = false;
|
||||
|
||||
Future<void> addToCart(
|
||||
BuildContext context, String productId, int quantity) async {
|
||||
context.showLoader(show: true);
|
||||
|
||||
isLoadingCart = true;
|
||||
isLoadings[productId] = true;
|
||||
notifyListeners();
|
||||
|
||||
var data = {"productId": productId, "quantity": quantity};
|
||||
|
||||
try {
|
||||
var result = await _homeRepo.addToCart(data);
|
||||
context.showLoader(
|
||||
show: false,
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(error) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(error.message),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
},
|
||||
(response) async {
|
||||
await getItemCards(context);
|
||||
cartItems.add(productId); // Add product to cart
|
||||
// Fluttertoast.showToast(
|
||||
// msg: "Added to cart successfully!",
|
||||
// toastLength: Toast.LENGTH_SHORT,
|
||||
// gravity: ToastGravity.BOTTOM,
|
||||
// backgroundColor: Colors.green,
|
||||
// textColor: Colors.white,
|
||||
// fontSize: 14.0,
|
||||
// );
|
||||
iscardAdded = true;
|
||||
notifyListeners(); // Update UI after adding to cart
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text("Something went wrong"),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
isLoadingCart = false;
|
||||
isLoadings[productId] = false;
|
||||
notifyListeners(); // Ensure UI updates after operation
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> decreaseCartQuantity(
|
||||
BuildContext context, String itemId, int quantity) async {
|
||||
context.showLoader(show: true);
|
||||
|
||||
isLoadingCart = true;
|
||||
|
||||
notifyListeners();
|
||||
|
||||
// var data = {"productId": productId, "quantity": quantity};
|
||||
|
||||
final Map<String, dynamic> cartData = {
|
||||
"items": [
|
||||
{"itemId": itemId, "quantity": quantity}
|
||||
]
|
||||
};
|
||||
|
||||
try {
|
||||
var result = await _homeRepo.decreaseQuantity(cartData);
|
||||
context.showLoader(
|
||||
show: false,
|
||||
);
|
||||
|
||||
result.fold(
|
||||
(error) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(error.message),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
},
|
||||
(response) async {
|
||||
await getItemCards(context);
|
||||
|
||||
// Fluttertoast.showToast(
|
||||
// msg: "Added to cart successfully!",
|
||||
// toastLength: Toast.LENGTH_SHORT,
|
||||
// gravity: ToastGravity.BOTTOM,
|
||||
// backgroundColor: Colors.green,
|
||||
// textColor: Colors.white,
|
||||
// fontSize: 14.0,
|
||||
// );
|
||||
iscardAdded = true;
|
||||
notifyListeners(); // Update UI after adding to cart
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text("Something went wrong"),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
isLoadingCart = false;
|
||||
|
||||
notifyListeners(); // Ensure UI updates after operation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
74
lib/src/logic/provider/address_provider.dart
Normal file
74
lib/src/logic/provider/address_provider.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grocery_app/src/core/network_services/service_locator.dart';
|
||||
import 'package:grocery_app/src/logic/repo/product_repo.dart';
|
||||
|
||||
class AddressProvider extends ChangeNotifier {
|
||||
bool ischeckpin = false;
|
||||
|
||||
Future<bool> checkPin(BuildContext context, pin) async {
|
||||
final _homeRepo = getIt<ProductRepo>();
|
||||
ischeckpin = true;
|
||||
notifyListeners();
|
||||
var data = {};
|
||||
try {
|
||||
var result = await _homeRepo.checkPin(data, pin);
|
||||
|
||||
return result.fold(
|
||||
(error) {
|
||||
ischeckpin = false;
|
||||
ischeckpin = false;
|
||||
return false;
|
||||
},
|
||||
(response) {
|
||||
ischeckpin = false;
|
||||
notifyListeners();
|
||||
return true;
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
ischeckpin = false;
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> addAddress(BuildContext context, name, pincode, phone,
|
||||
alternatePhoneNumber, address, landmark, addresstype) async {
|
||||
ischeckpin = false;
|
||||
|
||||
final _homeRepo = getIt<ProductRepo>();
|
||||
|
||||
notifyListeners();
|
||||
var data = {
|
||||
"name": name,
|
||||
"pincode": pincode,
|
||||
"phoneNumber": "+91$phone",
|
||||
"alternatePhoneNumber": "+91$alternatePhoneNumber",
|
||||
"addressLine": address,
|
||||
"landmark": landmark,
|
||||
"addressType": addresstype,
|
||||
"isDefault": false,
|
||||
"additionalInstructions": "Please ring doorbell twice"
|
||||
};
|
||||
try {
|
||||
var result = await _homeRepo.addAddress(data);
|
||||
|
||||
return result.fold(
|
||||
(error) {
|
||||
ischeckpin = false;
|
||||
|
||||
return false;
|
||||
},
|
||||
(response) {
|
||||
ischeckpin = false;
|
||||
notifyListeners();
|
||||
return true;
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
ischeckpin = false;
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grocery_app/src/core/network_services/service_locator.dart';
|
||||
import 'package:grocery_app/src/data/user_profile.dart';
|
||||
import 'package:grocery_app/src/logic/repo/product_repo.dart';
|
||||
import 'package:grocery_app/utils/constants/shared_pref_utils.dart';
|
||||
|
||||
class BottomNavProvider with ChangeNotifier {
|
||||
int _currentIndex = 0;
|
||||
@@ -7,10 +11,58 @@ class BottomNavProvider with ChangeNotifier {
|
||||
int get currentIndex => _currentIndex;
|
||||
PageController get pageController => _pageController;
|
||||
|
||||
void setIndex(int index)
|
||||
{
|
||||
void setIndex(int index) {
|
||||
_currentIndex = index;
|
||||
_pageController.jumpToPage(index);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
UserProfile allitem = UserProfile();
|
||||
final _homeRepo = getIt<ProductRepo>();
|
||||
bool isLoading = true;
|
||||
|
||||
Future<void> getProfile(BuildContext context) async {
|
||||
print("kjdkjghdfjglhjdfhgldflghjkldfjgh");
|
||||
isLoading = true;
|
||||
notifyListeners();
|
||||
var data = {};
|
||||
try {
|
||||
var result = await _homeRepo.getProfile(data);
|
||||
|
||||
return result.fold(
|
||||
(error) {
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
},
|
||||
(response) async {
|
||||
print("kjdshgkjhdfkjg ${response.firstName}");
|
||||
|
||||
await SharedPrefUtils.saveUser(user: response);
|
||||
allitem = response!;
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> refreshToken(BuildContext context) async {
|
||||
var data = {"refresh_token": "${await SharedPrefUtils.getRefreshToken()}"};
|
||||
|
||||
|
||||
var result = await _homeRepo.refreshToken(data, context);
|
||||
return result.fold(
|
||||
(error) {
|
||||
|
||||
return true;
|
||||
},
|
||||
(response) {
|
||||
|
||||
return true;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ class ProductProvider extends ChangeNotifier {
|
||||
var data = {};
|
||||
productDetails = ProductDetailsData();
|
||||
isProductLoading = true;
|
||||
quantitys = 1;
|
||||
_totalPrice = 0.0;
|
||||
notifyListeners();
|
||||
|
||||
var result = await _homeRepo.getProductDetails(data, context, id);
|
||||
@@ -186,8 +188,6 @@ class ProductProvider extends ChangeNotifier {
|
||||
|
||||
// Mock API call
|
||||
Future<bool> addToWish(BuildContext context, String productId) async {
|
||||
print("jsdkjfhkdfkg ${productId}");
|
||||
|
||||
var data = {
|
||||
"productId": productId,
|
||||
};
|
||||
@@ -206,6 +206,7 @@ class ProductProvider extends ChangeNotifier {
|
||||
return false;
|
||||
},
|
||||
(response) {
|
||||
iswishloading = false;
|
||||
Fluttertoast.showToast(
|
||||
msg: "Wishlist updated successfully!",
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
@@ -223,18 +224,24 @@ class ProductProvider extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> wishlist = {}; // To store product IDs in the wishlist
|
||||
Set<String> wishlist = {};
|
||||
|
||||
bool iswishloading = false;
|
||||
|
||||
Future<void> toggleWishlist(BuildContext context, String productId) async {
|
||||
iswishloading = true;
|
||||
notifyListeners();
|
||||
try {
|
||||
if (wishlist.contains(productId)) {
|
||||
wishlist.remove(productId);
|
||||
iswishloading = false;
|
||||
} else {
|
||||
var result = await addToWish(context, productId);
|
||||
|
||||
wishlist.add(productId); // Add the product ID to the wishlist
|
||||
wishlist.add(productId);
|
||||
}
|
||||
notifyListeners(); // Notify listeners to update the UI
|
||||
iswishloading = false;
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
@@ -297,13 +304,16 @@ class ProductProvider extends ChangeNotifier {
|
||||
Set<String> cartItems = {};
|
||||
Map<String, bool> isLoading = {};
|
||||
|
||||
Future<void> addToCart(BuildContext context, String productId) async {
|
||||
//if (cartItems.contains(productId)) return; // Prevent duplicate additions
|
||||
bool isLoadingCart=false;
|
||||
bool iscardAdded=false;
|
||||
|
||||
Future<void> addToCart(BuildContext context, String productId,int quantity) async {
|
||||
//if (cartItems.contains(productId)) return; // Prevent duplicate additions
|
||||
isLoadingCart=true;
|
||||
isLoading[productId] = true;
|
||||
notifyListeners(); // Notify UI to show loading indicator
|
||||
|
||||
var data = {"productId": productId, "quantity": 1};
|
||||
var data = {"productId": productId, "quantity": quantity};
|
||||
|
||||
try {
|
||||
var result = await _homeRepo.addToCart(data);
|
||||
@@ -327,6 +337,7 @@ class ProductProvider extends ChangeNotifier {
|
||||
textColor: Colors.white,
|
||||
fontSize: 14.0,
|
||||
);
|
||||
iscardAdded=true;
|
||||
notifyListeners(); // Update UI after adding to cart
|
||||
},
|
||||
);
|
||||
@@ -338,19 +349,20 @@ class ProductProvider extends ChangeNotifier {
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
isLoadingCart=false;
|
||||
isLoading[productId] = false;
|
||||
notifyListeners(); // Ensure UI updates after operation
|
||||
}
|
||||
}
|
||||
|
||||
List<BestDeal> countList = [];
|
||||
String lastImageurl = '';
|
||||
|
||||
Future<void> addToWithCart(
|
||||
BuildContext context, String productId, BestDeal bestdealproduct) async {
|
||||
//if (cartItems.contains(productId)) return; // Prevent duplicate additions
|
||||
|
||||
Future<void> addToWithCart(BuildContext context, String productId,
|
||||
BestDeal bestdealproduct, url) async {
|
||||
|
||||
isLoading[productId] = true;
|
||||
notifyListeners(); // Notify UI to show loading indicator
|
||||
notifyListeners();
|
||||
|
||||
var data = {"productId": productId, "quantity": 1};
|
||||
|
||||
@@ -368,6 +380,7 @@ class ProductProvider extends ChangeNotifier {
|
||||
},
|
||||
(response) {
|
||||
countList.add(bestdealproduct);
|
||||
lastImageurl = url;
|
||||
cartItems.add(productId); // Add product to cart
|
||||
Fluttertoast.showToast(
|
||||
msg: "Added to cart successfully!",
|
||||
@@ -393,6 +406,63 @@ class ProductProvider extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<ProductDatum> productDatum = [];
|
||||
String productDatumlastImageurl = '';
|
||||
|
||||
Future<void> addToCartWithWishlist(BuildContext context, String productId,ProductDatum productdataum,
|
||||
url) async {
|
||||
|
||||
isLoading[productId] = true;
|
||||
notifyListeners();
|
||||
|
||||
var data = {"productId": productId, "quantity": 1};
|
||||
|
||||
try {
|
||||
var result = await _homeRepo.addToCart(data);
|
||||
|
||||
result.fold(
|
||||
(error) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(error.message),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
},
|
||||
(response) {
|
||||
productDatum.add(productdataum);
|
||||
productDatumlastImageurl = url;
|
||||
cartItems.add(productId); // Add product to cart
|
||||
Fluttertoast.showToast(
|
||||
msg: "Added to cart successfully!",
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
backgroundColor: Colors.green,
|
||||
textColor: Colors.white,
|
||||
fontSize: 14.0,
|
||||
);
|
||||
notifyListeners(); // Update UI after adding to cart
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text("Something went wrong"),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
isLoading[productId] = false;
|
||||
notifyListeners(); // Ensure UI updates after operation
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool isWishListItemLoadingg = true;
|
||||
|
||||
List<WishListItem> wishListItem = [];
|
||||
@@ -427,30 +497,69 @@ class ProductProvider extends ChangeNotifier {
|
||||
}
|
||||
////////////////////////////// product increase ////////////////////////////////////
|
||||
|
||||
int _quantity = 1;
|
||||
int quantitys = 1;
|
||||
double _unitPrice = 0.0;
|
||||
double _totalPrice = 0.0;
|
||||
|
||||
int get quantity => _quantity;
|
||||
int get quantity => quantitys;
|
||||
double get totalPrice => _totalPrice;
|
||||
|
||||
void setProductPrice(double price) {
|
||||
_unitPrice = price;
|
||||
_totalPrice = _unitPrice * _quantity;
|
||||
_totalPrice = _unitPrice * quantitys;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
int productQuantity = 0;
|
||||
|
||||
// void increaseQuantity()
|
||||
// {
|
||||
// if(quantity<10)
|
||||
// if (_quantity < 10)
|
||||
// {
|
||||
// // Limit to 10
|
||||
// _quantity++;
|
||||
// _totalPrice = _unitPrice * _quantity;
|
||||
// notifyListeners();
|
||||
// }
|
||||
// {
|
||||
// Fluttertoast.showToast(
|
||||
// msg: "Sorry cart successfully!",
|
||||
// toastLength: Toast.LENGTH_SHORT,
|
||||
// gravity: ToastGravity.BOTTOM,
|
||||
// backgroundColor: Colors.green,
|
||||
// textColor: Colors.white,
|
||||
// fontSize: 14.0,
|
||||
// );
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
void increaseQuantity() {
|
||||
print("kjfgkhkdfhgkjdhfg");
|
||||
_quantity++;
|
||||
_totalPrice = _unitPrice * _quantity;
|
||||
notifyListeners();
|
||||
int maxAllowed = productQuantity >= 100
|
||||
? 10
|
||||
: productQuantity; // Max limit based on stock
|
||||
|
||||
if (quantitys < maxAllowed) {
|
||||
quantitys++;
|
||||
_totalPrice = _unitPrice * quantitys;
|
||||
notifyListeners();
|
||||
} else {
|
||||
Fluttertoast.showToast(
|
||||
msg: "Sorry, you can only add up to $maxAllowed items!",
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
backgroundColor: Colors.red,
|
||||
textColor: Colors.white,
|
||||
fontSize: 14.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void decreaseQuantity() {
|
||||
if (_quantity > 1) {
|
||||
_quantity--;
|
||||
_totalPrice = _unitPrice * _quantity;
|
||||
if (quantitys > 1) {
|
||||
quantitys--;
|
||||
_totalPrice = _unitPrice * quantitys;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
94
lib/src/logic/provider/profile_provider.dart
Normal file
94
lib/src/logic/provider/profile_provider.dart
Normal file
@@ -0,0 +1,94 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grocery_app/src/core/network_services/service_locator.dart';
|
||||
import 'package:grocery_app/src/core/utils/snack_bar.dart';
|
||||
import 'package:grocery_app/src/data/user_profile.dart';
|
||||
import 'package:grocery_app/src/logic/repo/auth_repo.dart';
|
||||
import 'package:grocery_app/src/logic/repo/product_repo.dart';
|
||||
import 'package:grocery_app/utils/extensions/extensions.dart';
|
||||
|
||||
class ProfileProvider extends ChangeNotifier {
|
||||
bool _isImageLoading = false;
|
||||
bool get isImageLoading => _isImageLoading;
|
||||
|
||||
String _uploadedUrl = '';
|
||||
|
||||
final _productRepo = getIt<ProductRepo>();
|
||||
|
||||
Future<bool> uploadImage(BuildContext context, File? _selectedImage) async {
|
||||
context.showLoader(show: true);
|
||||
_isImageLoading = false;
|
||||
final result = await _productRepo.uploadImage(_selectedImage!);
|
||||
context.showLoader(show: false);
|
||||
|
||||
return result.fold(
|
||||
(error) {
|
||||
_showSnackBar(context, error.message, Colors.red);
|
||||
return false;
|
||||
},
|
||||
(uploadImage) {
|
||||
_isImageLoading = true;
|
||||
_uploadedUrl = uploadImage.data!.url.toString();
|
||||
notifyListeners();
|
||||
|
||||
_showSnackBar(context, "Image uploaxded successfully!", Colors.green);
|
||||
return true;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _showSnackBar(BuildContext context, String message, Color color) {
|
||||
showTopSnackBar(context, message, color);
|
||||
}
|
||||
|
||||
Future<bool> createStore(
|
||||
BuildContext context, String firstName, String lastName) async {
|
||||
context.showLoader(show: true);
|
||||
|
||||
var data = {
|
||||
"firstName": firstName,
|
||||
"lastName": lastName,
|
||||
"img": _uploadedUrl
|
||||
};
|
||||
|
||||
try {
|
||||
var result = await _productRepo.updateProfile(data);
|
||||
|
||||
context.showLoader(show: false);
|
||||
|
||||
return result.fold(
|
||||
(error) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(error.message),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
return false;
|
||||
},
|
||||
(response) {
|
||||
Navigator.pop(context);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text("Profile updated"),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
return true;
|
||||
},
|
||||
);
|
||||
} catch (e)
|
||||
{
|
||||
context.showLoader(show: false);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text("Something went wrong. Please try again."),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import 'package:grocery_app/src/core/utils/response_type_def.dart';
|
||||
import 'package:grocery_app/src/data/OTPResponseModel.dart';
|
||||
import 'package:grocery_app/src/data/login_response.dart';
|
||||
import 'package:grocery_app/src/data/registration_response.dart';
|
||||
import 'package:grocery_app/src/data/user_profile.dart';
|
||||
import 'package:grocery_app/src/data/vendor_otpModel.dart';
|
||||
import 'package:grocery_app/src/logic/services/auth_service_locator.dart';
|
||||
import 'package:grocery_app/utils/constants/shared_pref_utils.dart';
|
||||
@@ -20,7 +21,6 @@ class AuthRepo {
|
||||
try {
|
||||
var response = await _authServices.sendOtp(data);
|
||||
final String model = response.toString();
|
||||
|
||||
|
||||
return right(model);
|
||||
} on DioException catch (e) {
|
||||
@@ -40,10 +40,10 @@ class AuthRepo {
|
||||
if (vendorOtpModel.data != null) {
|
||||
await SharedPrefUtils.setToken(
|
||||
authToken: vendorOtpModel.data!.accessToken ?? "");
|
||||
await SharedPrefUtils.setRefreshToken(
|
||||
refresh_token: vendorOtpModel.data!.refreshToken ?? "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
return right(vendorOtpModel);
|
||||
} on DioException catch (e) {
|
||||
var error = CustomDioExceptions.handleError(e);
|
||||
@@ -51,16 +51,17 @@ class AuthRepo {
|
||||
}
|
||||
}
|
||||
|
||||
FutureResult<LoginResponse> loginOtp(data) async {
|
||||
FutureResult<LoginResponse> loginOtp(data) async {
|
||||
try {
|
||||
var response = await _authServices.loginOtp(data);
|
||||
|
||||
LoginResponse loginResponse = loginResponseFromJson(response.toString());
|
||||
|
||||
if (loginResponse.accessToken != null)
|
||||
{
|
||||
if (loginResponse.accessToken != null) {
|
||||
await SharedPrefUtils.setToken(
|
||||
authToken: loginResponse.accessToken ?? "");
|
||||
await SharedPrefUtils.setRefreshToken(
|
||||
refresh_token: loginResponse.refreshToken ?? "");
|
||||
}
|
||||
|
||||
// final String model = response.toString();
|
||||
@@ -119,12 +120,9 @@ class AuthRepo {
|
||||
|
||||
await SharedPrefUtils.setToken(
|
||||
authToken: registrationResponse.accessToken ?? "");
|
||||
print("dsfklgjkfgbfgkfdgjkhkfdjg ${registrationResponse.accessToken}");
|
||||
// if (response.statCode) {
|
||||
// print("dsfklgjkfgbfgkfdgjkhkfdjg");
|
||||
// }
|
||||
|
||||
final String model = response.toString();
|
||||
await SharedPrefUtils.setRefreshToken(
|
||||
refresh_token: registrationResponse.refreshToken ?? "");
|
||||
final String model = response.toString();
|
||||
return right(registrationResponse);
|
||||
} on DioException catch (e) {
|
||||
var error = CustomDioExceptions.handleError(e);
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fpdart/fpdart.dart';
|
||||
import 'package:grocery_app/src/core/routes/routes.dart';
|
||||
import 'package:grocery_app/src/core/utils/custom_dio_exception.dart';
|
||||
import 'package:grocery_app/src/core/utils/response_type_def.dart';
|
||||
import 'package:grocery_app/src/data/address.dart';
|
||||
import 'package:grocery_app/src/data/allProduct_model.dart';
|
||||
import 'package:grocery_app/src/data/all_cart_items.dart';
|
||||
import 'package:grocery_app/src/data/banners.dart';
|
||||
import 'package:grocery_app/src/data/best_dealProduct.dart';
|
||||
import 'package:grocery_app/src/data/check_pin_response.dart';
|
||||
import 'package:grocery_app/src/data/login_response.dart';
|
||||
import 'package:grocery_app/src/data/product_category.dart';
|
||||
import 'package:grocery_app/src/data/product_details.dart';
|
||||
import 'package:grocery_app/src/data/upload_image.dart';
|
||||
import 'package:grocery_app/src/data/user_profile.dart';
|
||||
import 'package:grocery_app/src/data/wish_list_model.dart';
|
||||
import 'package:grocery_app/src/logic/services/home_locator.dart';
|
||||
import 'package:grocery_app/src/ui/productdetails/product_details.dart';
|
||||
import 'package:grocery_app/utils/constants/shared_pref_utils.dart';
|
||||
import 'package:grocery_app/utils/extensions/extensions.dart';
|
||||
|
||||
class ProductRepo {
|
||||
final ProductService _productService;
|
||||
@@ -36,12 +45,13 @@ class ProductRepo {
|
||||
}
|
||||
}
|
||||
|
||||
FutureResult<ProductDetailsData> getProductDetails(
|
||||
FutureResult<ProductDetailsData> getProductDetails(
|
||||
data, BuildContext context, id) async {
|
||||
try {
|
||||
var response = await _productService.getProductDetails(data, id);
|
||||
|
||||
ProductDetailsData loginResponse = productDetailsdataFromJson(response.toString());
|
||||
ProductDetailsData loginResponse =
|
||||
productDetailsdataFromJson(response.toString());
|
||||
|
||||
final String model = response.toString();
|
||||
|
||||
@@ -52,8 +62,6 @@ class ProductRepo {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
FutureResult<BestDealProduct> getBestDealProduct(
|
||||
data, BuildContext context) async {
|
||||
try {
|
||||
@@ -112,8 +120,19 @@ class ProductRepo {
|
||||
var response = await _productService.getItemCards(data);
|
||||
|
||||
AllCartItems allCartItems = allCartItemsFromJson(response.toString());
|
||||
return right(allCartItems);
|
||||
} on DioException catch (e) {
|
||||
var error = CustomDioExceptions.handleError(e);
|
||||
return left(error);
|
||||
}
|
||||
}
|
||||
|
||||
print("jdfgjkdf${allCartItems}");
|
||||
FutureResult<AddressResponse> getAddress(data) async {
|
||||
try {
|
||||
var response = await _productService.getAddress(data);
|
||||
|
||||
AddressResponse allCartItems =
|
||||
addressResponseFromJson(response.toString());
|
||||
|
||||
return right(allCartItems);
|
||||
} on DioException catch (e) {
|
||||
@@ -123,6 +142,47 @@ class ProductRepo {
|
||||
}
|
||||
}
|
||||
|
||||
FutureResult<UserProfile> getProfile(data) async {
|
||||
try {
|
||||
var response = await _productService.getProfile(data);
|
||||
|
||||
print("kdjfgkljfdkjlghflkgjh ${response}");
|
||||
UserProfile userProfile = userProfileFromJson(response.toString());
|
||||
print("kdjfgkljfdkjlghflkgjhrerrrerr ${userProfile.createdAt}");
|
||||
return right(userProfile);
|
||||
} on DioException catch (e) {
|
||||
var error = CustomDioExceptions.handleError(e);
|
||||
return left(error);
|
||||
}
|
||||
}
|
||||
FutureResult<String> updateProfile(data) async {
|
||||
try {
|
||||
var response = await _productService.updateProfile(data);
|
||||
|
||||
print("kdjfgkljfdkjlghflkgjh ${response}");
|
||||
final String model = response.toString();
|
||||
return right(model);
|
||||
} on DioException catch (e) {
|
||||
var error = CustomDioExceptions.handleError(e);
|
||||
return left(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
FutureResult<UploadImage> uploadImage(File imageFile)
|
||||
async {
|
||||
try {
|
||||
final response = await _productService.uploadImage(imageFile);
|
||||
UploadImage upload=uploadImageFromJson(response.toString());
|
||||
return right(upload);
|
||||
} on DioException catch (e) {
|
||||
final error = CustomDioExceptions.handleError(e);
|
||||
return left(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FutureResult<CheckPinResponse> checkPin(data, pin) async {
|
||||
try {
|
||||
var response = await _productService.checkPin(data, pin);
|
||||
@@ -148,6 +208,20 @@ class ProductRepo {
|
||||
}
|
||||
}
|
||||
|
||||
FutureResult<String> addAddress(data) async {
|
||||
try {
|
||||
var response = await _productService.addAddress(data);
|
||||
|
||||
final String model = response.toString();
|
||||
|
||||
return right(model);
|
||||
} on DioException catch (e) {
|
||||
print("djhgfjdfhjg ${e}");
|
||||
var error = CustomDioExceptions.handleError(e);
|
||||
return left(error);
|
||||
}
|
||||
}
|
||||
|
||||
FutureResult<String> addToWish(data) async {
|
||||
try {
|
||||
var response = await _productService.addToWish(data);
|
||||
@@ -175,6 +249,22 @@ class ProductRepo {
|
||||
return left(error);
|
||||
}
|
||||
}
|
||||
FutureResult<String> decreaseQuantity(data) async {
|
||||
try {
|
||||
var response = await _productService.decreaseQuantity(data);
|
||||
|
||||
final String model = response.toString();
|
||||
|
||||
return right(model);
|
||||
} on DioException catch (e) {
|
||||
print("djhgfjdfhjg ${e}");
|
||||
var error = CustomDioExceptions.handleError(e);
|
||||
return left(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
FutureResult<WishListModel> gettAllWishList(data) async {
|
||||
try {
|
||||
@@ -221,6 +311,32 @@ class ProductRepo {
|
||||
}
|
||||
}
|
||||
|
||||
FutureResult<String> refreshToken(data, BuildContext context) async {
|
||||
try {
|
||||
var response = await _productService.refresh_token(data);
|
||||
LoginResponse loginResponse = loginResponseFromJson(response.toString());
|
||||
|
||||
if (loginResponse.accessToken != null)
|
||||
{
|
||||
|
||||
await SharedPrefUtils.setToken(
|
||||
authToken: loginResponse.accessToken ?? "");
|
||||
await SharedPrefUtils.setRefreshToken(
|
||||
refresh_token: loginResponse.refreshToken ?? "");
|
||||
}
|
||||
|
||||
final String model = response.toString();
|
||||
|
||||
return right(model);
|
||||
} on DioException catch (e)
|
||||
{
|
||||
|
||||
|
||||
var error = CustomDioExceptions.handleError(e);
|
||||
return left(error);
|
||||
}
|
||||
}
|
||||
|
||||
// FutureResult<VendorModel> getMe(data) async {
|
||||
// try {
|
||||
// var response = await _homeService.getMe(data);
|
||||
|
||||
@@ -1,82 +1,58 @@
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:grocery_app/src/core/constant/api.dart';
|
||||
import 'package:grocery_app/src/core/network_services/api_services.dart';
|
||||
|
||||
|
||||
|
||||
class AuthServices extends ApiService {
|
||||
/// Login
|
||||
Future sendOtp(data) async
|
||||
{
|
||||
Future sendOtp(data) async {
|
||||
var response = await api.post(APIURL.sendOtp, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Future verifyOtp(data) async {
|
||||
Future verifyOtp(data) async {
|
||||
var response = await api.post(APIURL.verifyOtp, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
Future loginOtp(data) async {
|
||||
|
||||
Future loginOtp(data) async {
|
||||
var response = await api.post(APIURL.loginOtp, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
Future login(data) async
|
||||
{
|
||||
Future login(data) async {
|
||||
var response = await api.post(APIURL.login, data: jsonEncode(data));
|
||||
//response.statusCode
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Future userRegister(data) async
|
||||
{
|
||||
var response = await api.post(APIURL.customerRegister, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Future forgetPassword(data) async
|
||||
{
|
||||
var response = await api.post(APIURL.forgetPassword, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
Future verifyForgetPassword(data) async
|
||||
{
|
||||
var response = await api.post(APIURL.verifyForgetPassword, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
Future reset_password(data) async
|
||||
{
|
||||
var response = await api.post(APIURL.reset_password, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Future userRegister(data) async {
|
||||
var response =
|
||||
await api.post(APIURL.customerRegister, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
Future forgetPassword(data) async {
|
||||
var response =
|
||||
await api.post(APIURL.forgetPassword, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
Future verifyForgetPassword(data) async {
|
||||
var response =
|
||||
await api.post(APIURL.verifyForgetPassword, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Future reset_password(data) async {
|
||||
var response =
|
||||
await api.post(APIURL.reset_password, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
/// Login
|
||||
// Future profileUpdate(data) async {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:grocery_app/src/core/constant/api.dart';
|
||||
import 'package:grocery_app/src/core/network_services/api_services.dart';
|
||||
|
||||
@@ -76,7 +78,39 @@ class ProductService extends ApiService {
|
||||
await api.delete(APIURL.deleteItem + id, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
Future addAddress(data) async {
|
||||
var response = await api.post(APIURL.addAddress, data: jsonEncode(data));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
Future getProfile(data) async {
|
||||
var response = await api.get(APIURL.getprofile, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
Future updateProfile(data) async {
|
||||
var response = await api.patch(APIURL.updateProfile, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
Future<Response> uploadImage(File imageFile,
|
||||
{Map<String, dynamic>? additionalFields}) async {
|
||||
const String url = APIURL.uploadImage;
|
||||
return await api.uploadImage(
|
||||
url,
|
||||
imageFile,
|
||||
additionalFields: additionalFields,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future getAddress
|
||||
(data) async {
|
||||
var response =
|
||||
await api.get(APIURL.userAddress, data: jsonEncode(data));
|
||||
return response;
|
||||
}
|
||||
Future addToWish(data) async {
|
||||
var response = await api.post(APIURL.addToWish, data: jsonEncode(data));
|
||||
|
||||
@@ -89,6 +123,12 @@ class ProductService extends ApiService {
|
||||
return response;
|
||||
}
|
||||
|
||||
Future decreaseQuantity(data) async {
|
||||
var response = await api.patch(APIURL.addToCart, data: jsonEncode(data));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
Future gettAllWishList(data) async {
|
||||
var response =
|
||||
await api.get(APIURL.gettAllWishList, data: jsonEncode(data));
|
||||
|
||||
@@ -62,14 +62,21 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
],
|
||||
),
|
||||
floatingActionButton: floatingAction(),
|
||||
body: itemBestdeal());
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 100),
|
||||
child: itemBestdeal(),
|
||||
));
|
||||
}
|
||||
|
||||
Widget floatingAction() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.countList.isEmpty) {
|
||||
Widget floatingAction()
|
||||
{
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child)
|
||||
{
|
||||
if (provider.countList.isEmpty)
|
||||
{
|
||||
return Center();
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 30),
|
||||
child: Container(
|
||||
@@ -93,7 +100,7 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
color: Colors.white.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
const Positioned(
|
||||
Positioned(
|
||||
left: 20,
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
@@ -102,7 +109,7 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
height: 70,
|
||||
width: 70,
|
||||
radius: 10,
|
||||
imageUrl:
|
||||
imageUrl: provider.lastImageurl ??
|
||||
"https://5.imimg.com/data5/SELLER/Default/2024/2/385126988/OL/DA/VW/8627346/1l-fortune-sunflower-oil.jpg",
|
||||
backGroundColor: Colors.white,
|
||||
),
|
||||
@@ -113,15 +120,12 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
provider.countList.length.toString(),
|
||||
style: context.customRegular(Colors.white, 18),
|
||||
),
|
||||
],
|
||||
Text(
|
||||
provider.countList.length.toString(),
|
||||
style: context.customRegular(
|
||||
Colors.white,
|
||||
29,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
InkWell(
|
||||
@@ -306,8 +310,12 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
onTap: () async {
|
||||
if (await SharedPrefUtils.getToken() !=
|
||||
null) {
|
||||
await provider.addToWithCart(context,
|
||||
bestdealproduct.id!, bestdealproduct);
|
||||
await provider.addToWithCart(
|
||||
context,
|
||||
bestdealproduct.id!,
|
||||
bestdealproduct,
|
||||
bestdealproduct
|
||||
.productImages?.first.url);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:grocery_app/src/logic/provider/bottom_navbar_provider.dart';
|
||||
import 'package:grocery_app/src/logic/provider/home_provider.dart';
|
||||
import 'package:grocery_app/src/ui/cart/cartview_screen.dart';
|
||||
import 'package:grocery_app/src/ui/favourite/favourite_screen.dart';
|
||||
import 'package:grocery_app/src/ui/header.dart';
|
||||
@@ -38,6 +39,7 @@ class _BottomBarState extends State<BottomBarWidget> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
Provider.of<BottomNavProvider>(context, listen: false).getProfile(context);
|
||||
_currentIndex = 0;
|
||||
bottomWidgetPageController = PageController(
|
||||
initialPage: 0,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
135
lib/src/ui/coupons/coupons_screen.dart
Normal file
135
lib/src/ui/coupons/coupons_screen.dart
Normal file
@@ -0,0 +1,135 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CouponsScreen extends StatelessWidget {
|
||||
final List<Map<String, String>> coupons = [
|
||||
{
|
||||
"title": "Flat 10% OFF on Standard Chartered Digismart Credit Cards",
|
||||
"description": "No Minimum Order Value",
|
||||
"code": "DIGISMART"
|
||||
},
|
||||
{
|
||||
"title": "Flat 10% OFF upto \$10 on HSBC Cashback Credit Card",
|
||||
"description": "Total Value of Items Must be \$3 or More",
|
||||
"code": "HSBC10"
|
||||
},
|
||||
{
|
||||
"title": "Get Upto 50 OFF on Your First Payment",
|
||||
"description": "Total Value of Items Must be \$10 or More",
|
||||
"code": "PAYMENT50"
|
||||
}
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
title: Text("Coupons"),
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
TextField(
|
||||
cursorHeight: 20,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Enter Coupon Code",
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
suffixIcon: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.green,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text("Apply"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: coupons.length,
|
||||
itemBuilder: (context, index) {
|
||||
final coupon = coupons[index];
|
||||
return Card(
|
||||
color: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
elevation: 2,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
coupon["title"]!,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
coupon["description"]!,
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.green),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
coupon["code"]!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.green,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text("Apply"),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,19 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:grocery_app/src/common_widget/name_text_field.dart';
|
||||
import 'package:grocery_app/src/common_widget/network_image.dart';
|
||||
import 'package:grocery_app/src/logic/provider/profile_provider.dart';
|
||||
import 'package:grocery_app/utils/constants/assets_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/shared_pref_utils.dart';
|
||||
import 'package:grocery_app/utils/constants/string_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class EditProfileScreen extends StatefulWidget {
|
||||
const EditProfileScreen({super.key});
|
||||
@@ -15,6 +23,51 @@ class EditProfileScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _EditProfileScreenState extends State<EditProfileScreen> {
|
||||
String? name;
|
||||
String? email;
|
||||
String? profile;
|
||||
File? _image;
|
||||
final ImagePicker _picker = ImagePicker();
|
||||
|
||||
TextEditingController firstController = TextEditingController();
|
||||
TextEditingController lastController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
getUserDetails();
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
}
|
||||
|
||||
getUserDetails() async {
|
||||
firstController.text = APPSTRING.userName;
|
||||
lastController.text = APPSTRING.userLastName;
|
||||
profile = APPSTRING.userProfile;
|
||||
}
|
||||
|
||||
/// Pick image from gallery or camera
|
||||
Future<void> _pickImage() async {
|
||||
final XFile? pickedFile =
|
||||
await _picker.pickImage(source: ImageSource.gallery);
|
||||
|
||||
if (pickedFile != null) {
|
||||
setState(() {
|
||||
profile = pickedFile.path;
|
||||
_image = File(pickedFile.path);
|
||||
});
|
||||
|
||||
Provider.of<ProfileProvider>(context, listen: false)
|
||||
.uploadImage(context, _image);
|
||||
|
||||
await _saveProfileImage(pickedFile.path);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveProfileImage(String imagePath) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('KEY_PROFILE', imagePath);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -43,40 +96,50 @@ class _EditProfileScreenState extends State<EditProfileScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Container(
|
||||
color: Colors.transparent,
|
||||
height: 60,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
height: 50,
|
||||
decoration: BoxDecoration(color: APPCOLOR.lightGreen, borderRadius: BorderRadius.circular(10)),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Update",
|
||||
style: context.customRegular(Colors.white, 16),
|
||||
bottomNavigationBar:
|
||||
Consumer<ProfileProvider>(builder: (context, imageProvider, child) {
|
||||
return Container(
|
||||
color: Colors.transparent,
|
||||
height: 60,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
onTap: imageProvider.isImageLoading
|
||||
? () {
|
||||
imageProvider.createStore(context,
|
||||
firstController.text, lastController.text);
|
||||
}
|
||||
: null,
|
||||
child: Container(
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: imageProvider.isImageLoading
|
||||
? APPCOLOR.lightGreen
|
||||
: APPCOLOR.grey666666,
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Update",
|
||||
style: context.customRegular(Colors.white, 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
],
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
body: Padding(
|
||||
padding: context.bodyAllPadding,
|
||||
child: SingleChildScrollView(
|
||||
@@ -90,26 +153,37 @@ class _EditProfileScreenState extends State<EditProfileScreen> {
|
||||
Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
const AppNetworkImage(
|
||||
height: 80,
|
||||
width: 80,
|
||||
imageUrl: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTdQLwDqDwd2JfzifvfBTFT8I7iKFFevcedYg&s",
|
||||
radius: 90,
|
||||
backGroundColor: Colors.white,
|
||||
boxFit: BoxFit.fill,
|
||||
//
|
||||
CircleAvatar(
|
||||
radius: 40,
|
||||
backgroundColor: Colors.white,
|
||||
backgroundImage: _image != null
|
||||
? FileImage(_image!) as ImageProvider
|
||||
: (profile != null && profile!.isNotEmpty
|
||||
? NetworkImage(profile!)
|
||||
: const AssetImage("assets/default_profile.png")
|
||||
as ImageProvider),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 20,
|
||||
decoration: BoxDecoration(color: APPCOLOR.lightGreen, border: Border.all(color: Colors.white), borderRadius: BorderRadius.circular(5)),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
MdiIcons.pencil,
|
||||
size: 10,
|
||||
color: Colors.white,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
_pickImage();
|
||||
},
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
border: Border.all(color: Colors.white),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
MdiIcons.pencil,
|
||||
size: 10,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
@@ -120,34 +194,103 @@ class _EditProfileScreenState extends State<EditProfileScreen> {
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
const NameTextField(
|
||||
name: "Name",
|
||||
initText: "Smith Mate",
|
||||
Container(
|
||||
height: 60,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: APPCOLOR.lightGreen),
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"First Name",
|
||||
style: context.customMedium(APPCOLOR.lightGreen, 14),
|
||||
),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: firstController,
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none,
|
||||
isCollapsed: true,
|
||||
contentPadding: EdgeInsets.only(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 5,
|
||||
top: 5,
|
||||
)),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const NameTextField(
|
||||
name: "Email Address",
|
||||
initText: "SmithMate@example.com",
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const NameTextField(
|
||||
name: "Mobile Number",
|
||||
initText: "(205) 555-0100",
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const NameTextField(
|
||||
name: "Enter Address",
|
||||
initText: "8502 Preston Rd. inglewood, USA",
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
Container(
|
||||
height: 60,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: APPCOLOR.lightGreen),
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Last Name ",
|
||||
style: context.customMedium(APPCOLOR.lightGreen, 14),
|
||||
),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: lastController,
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none,
|
||||
isCollapsed: true,
|
||||
contentPadding: EdgeInsets.only(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 5,
|
||||
top: 5,
|
||||
)),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// const NameTextField(
|
||||
// name: "Last Name",
|
||||
// initText: "Smith Mate",
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// const NameTextField(
|
||||
// name: "Email Address",
|
||||
// initText: "SmithMate@example.com",
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// const NameTextField(
|
||||
// name: "Mobile Number",
|
||||
// initText: "(205) 555-0100",
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// const NameTextField(
|
||||
// name: "Enter Address",
|
||||
// initText: "8502 Preston Rd. inglewood, USA",
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
],
|
||||
)),
|
||||
),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
@@ -79,10 +80,25 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
|
||||
Widget productWidget() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.isLoadingg) {
|
||||
if (provider.isLoadingg)
|
||||
{
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 120),
|
||||
child: CircularProgressIndicator(),
|
||||
child: Center(
|
||||
child: Container(
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(
|
||||
color: APPCOLOR.bgGrey,
|
||||
width: 1,
|
||||
)),
|
||||
child: const Center(
|
||||
child: CupertinoActivityIndicator(),
|
||||
),
|
||||
)),
|
||||
);
|
||||
} else if (provider.products.isEmpty) {
|
||||
return Padding(
|
||||
@@ -106,8 +122,7 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
),
|
||||
itemBuilder: (context, index)
|
||||
{
|
||||
itemBuilder: (context, index) {
|
||||
var product = provider.products[index];
|
||||
|
||||
return InkWell(
|
||||
@@ -189,31 +204,31 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
// ),
|
||||
// ),
|
||||
|
||||
Positioned(
|
||||
right: 5,
|
||||
top: 5,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
if (await SharedPrefUtils
|
||||
.getToken() !=
|
||||
null) {
|
||||
provider.toggleWishlist(
|
||||
context, product.id!);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
},
|
||||
child: Icon(
|
||||
provider.wishlist.contains(product.id)
|
||||
? Icons.favorite
|
||||
: Icons.favorite_border,
|
||||
color: provider.wishlist
|
||||
.contains(product.id)
|
||||
? Colors.red
|
||||
: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Positioned(
|
||||
// right: 5,
|
||||
// top: 5,
|
||||
// child: InkWell(
|
||||
// onTap: () async {
|
||||
// if (await SharedPrefUtils
|
||||
// .getToken() !=
|
||||
// null) {
|
||||
// provider.toggleWishlist(
|
||||
// context, product.id!);
|
||||
// } else {
|
||||
// context.push(MyRoutes.SIGNUP);
|
||||
// }
|
||||
// },
|
||||
// child: Icon(
|
||||
// provider.wishlist.contains(product.id)
|
||||
// ? Icons.favorite
|
||||
// : Icons.favorite_border,
|
||||
// color: provider.wishlist
|
||||
// .contains(product.id)
|
||||
// ? Colors.red
|
||||
// : Colors.grey,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -221,7 +236,7 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
Text(
|
||||
product.name ?? " ",
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: context.customMedium(
|
||||
APPCOLOR.balck1A1A1A, 14),
|
||||
@@ -238,6 +253,7 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
Column(
|
||||
@@ -281,7 +297,7 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
if (await SharedPrefUtils.getToken() !=
|
||||
null) {
|
||||
await provider.addToCart(
|
||||
context, product.id!);
|
||||
context, product.id!, 1);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
@@ -327,6 +343,8 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -348,7 +366,21 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
final activeIndexProvider = Provider.of<ProductProvider>(context);
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.iscategroyloading) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
return Center(
|
||||
child: Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.bgGrey,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: APPCOLOR.bgGrey,
|
||||
width: 1,
|
||||
)),
|
||||
child: const Center(
|
||||
child: CupertinoActivityIndicator(),
|
||||
),
|
||||
));
|
||||
} else if (provider.categoryList.isEmpty) {
|
||||
return Center(child: Text('No products available'));
|
||||
} else {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
466
lib/src/ui/map/add_locations.dart
Normal file
466
lib/src/ui/map/add_locations.dart
Normal file
@@ -0,0 +1,466 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:grocery_app/src/logic/provider/addTocart_provider.dart';
|
||||
import 'package:grocery_app/src/logic/provider/address_provider.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
const String googleApiKey = "AIzaSyAi3_Dls63iGs7Nccgdm-4FkS0rhT03-4U";
|
||||
|
||||
class AddLocationAddress extends StatefulWidget {
|
||||
@override
|
||||
_AddLocationAddressState createState() => _AddLocationAddressState();
|
||||
}
|
||||
|
||||
class _AddLocationAddressState extends State<AddLocationAddress> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
late GoogleMapController mapController;
|
||||
LatLng _selectedLocation = LatLng(20.5937, 78.9629);
|
||||
|
||||
TextEditingController _pincodeController = TextEditingController();
|
||||
TextEditingController _fullNameController = TextEditingController();
|
||||
TextEditingController _PhoneNumberController = TextEditingController();
|
||||
TextEditingController _addressTypeController = TextEditingController();
|
||||
TextEditingController _HouseNoController = TextEditingController();
|
||||
TextEditingController _RoadController = TextEditingController();
|
||||
TextEditingController _AlterNativeNumberController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_determinePosition();
|
||||
}
|
||||
|
||||
Future<void> _determinePosition() async {
|
||||
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocationPermission permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
return;
|
||||
}
|
||||
|
||||
Position position = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.high,
|
||||
);
|
||||
LatLng currentLatLng = LatLng(position.latitude, position.longitude);
|
||||
|
||||
setState(() {
|
||||
_selectedLocation = currentLatLng;
|
||||
});
|
||||
|
||||
_getAddressFromLatLng(position.latitude, position.longitude);
|
||||
}
|
||||
|
||||
Future<void> _getAddressFromLatLng(double lat, double lng) async {
|
||||
final String url =
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=$googleApiKey";
|
||||
|
||||
try {
|
||||
final response = await http.get(Uri.parse(url));
|
||||
if (response.statusCode == 200) {
|
||||
final data = json.decode(response.body);
|
||||
if (data["status"] == "OK") {
|
||||
var result = data["results"][0]; // First result is most accurate
|
||||
|
||||
_RoadController.text = result["formatted_address"];
|
||||
List components = result["address_components"];
|
||||
|
||||
String roadName = "";
|
||||
String colony = "";
|
||||
String buildingName = "";
|
||||
String pincode = "";
|
||||
|
||||
for (var component in components) {
|
||||
List types = component["types"];
|
||||
if (types.contains("route")) {
|
||||
roadName = component["long_name"]; // Road Name
|
||||
} else if (types.contains("sublocality_level_1") ||
|
||||
types.contains("locality")) {
|
||||
colony = component["long_name"]; // Colony Name
|
||||
} else if (types.contains("premise") ||
|
||||
types.contains("street_number")) {
|
||||
buildingName = component["long_name"]; // Building Name
|
||||
} else if (types.contains("postal_code")) {
|
||||
pincode = component["long_name"]; // Extract Pin Code
|
||||
}
|
||||
}
|
||||
|
||||
// setState(() {
|
||||
// // _address = formattedAddress;
|
||||
// _roadName = roadName;
|
||||
// _colony = colony;
|
||||
// _buildingName = buildingName;
|
||||
// });
|
||||
|
||||
_pincodeController.text = pincode;
|
||||
_RoadController.text = result["formatted_address"];
|
||||
|
||||
print(
|
||||
"Full Address: ${result["formatted_address"]} ${response.body} sdfsgd ${pincode}");
|
||||
print("Road Name: $roadName");
|
||||
print("Colony: $colony");
|
||||
print("Building Name: $buildingName");
|
||||
} else {}
|
||||
} else {}
|
||||
} catch (e) {
|
||||
print("Error fetching address: $e");
|
||||
}
|
||||
}
|
||||
|
||||
void _onMapTapped(LatLng tappedPoint) {
|
||||
setState(() {
|
||||
_selectedLocation = tappedPoint;
|
||||
});
|
||||
_getAddressFromLatLng(tappedPoint.latitude, tappedPoint.longitude);
|
||||
}
|
||||
|
||||
Future<void> _updateLocationFromPincode(String enteredPincode) async {
|
||||
if (enteredPincode.isEmpty) return;
|
||||
|
||||
try {
|
||||
List<Location> locations = await locationFromAddress(enteredPincode);
|
||||
if (locations.isNotEmpty) {
|
||||
Location location = locations.first;
|
||||
LatLng newLatLng = LatLng(location.latitude, location.longitude);
|
||||
|
||||
setState(() {
|
||||
_selectedLocation = newLatLng;
|
||||
});
|
||||
|
||||
_getAddressFromLatLng(location.latitude, location.longitude);
|
||||
mapController.animateCamera(CameraUpdate.newLatLng(newLatLng));
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error fetching location from pincode: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text("Add Delivery address")),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 200.h,
|
||||
child: GoogleMap(
|
||||
initialCameraPosition: CameraPosition(
|
||||
target: _selectedLocation,
|
||||
zoom: 14,
|
||||
),
|
||||
onMapCreated: (controller) {
|
||||
mapController = controller;
|
||||
},
|
||||
|
||||
myLocationEnabled: true, // Enable current location button
|
||||
myLocationButtonEnabled: true,
|
||||
markers: {
|
||||
Marker(
|
||||
markerId: MarkerId("selected Location"),
|
||||
position: _selectedLocation,
|
||||
)
|
||||
},
|
||||
onTap: _onMapTapped,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10)],
|
||||
),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _fullNameController,
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Full Name (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Full Name";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
|
||||
// Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _PhoneNumberController,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 10,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Phone Number (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Phone Number ";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: _pincodeController,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 6,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Enter Pincode",
|
||||
border: OutlineInputBorder(),
|
||||
counterText: ""),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Please enter a pincode";
|
||||
} else if (value.length != 6) {
|
||||
return "Pincode must be exactly 6 digits";
|
||||
} else if (!RegExp(r'^[1-9][0-9]{5}$')
|
||||
.hasMatch(value)) {
|
||||
return "Enter a valid Indian pincode";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
// Expanded(
|
||||
// child: TextFormField(
|
||||
// controller: _addressTypeController,
|
||||
// keyboardType: TextInputType.text,
|
||||
// decoration: InputDecoration(
|
||||
// labelText: "Address Type",
|
||||
// border: OutlineInputBorder(),
|
||||
// ),
|
||||
// validator: (value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// return "Enter address Home or Work ";
|
||||
// }
|
||||
// return null; // ✅ Valid input
|
||||
// },
|
||||
// ),
|
||||
// ),\
|
||||
Expanded(
|
||||
child: DropdownButtonFormField<String>(
|
||||
value: _addressTypeController.text.isNotEmpty
|
||||
? _addressTypeController.text
|
||||
: null,
|
||||
items:
|
||||
["HOME", "WORK", "OTHER"].map((String type) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: type,
|
||||
child: Text(type),
|
||||
);
|
||||
}).toList(),
|
||||
decoration: InputDecoration(
|
||||
labelText: "Address Type",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
_addressTypeController.text = value;
|
||||
}
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Select Address Type (Home, Work, Other)";
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _HouseNoController,
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: InputDecoration(
|
||||
labelText: "House No, Building Name (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Enter House No, Building ";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _RoadController,
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Road Name, Area , Colony(Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Enter Road Name, Area , Colony(Required)";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Consumer<AddressProvider>(
|
||||
builder: (context, addressProvider, child)
|
||||
{
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
var status = await addressProvider.checkPin(
|
||||
context, _pincodeController.text);
|
||||
|
||||
if (status) {
|
||||
var state = await addressProvider.addAddress(
|
||||
context,
|
||||
_fullNameController.text,
|
||||
_pincodeController.text,
|
||||
_PhoneNumberController.text,
|
||||
_PhoneNumberController.text,
|
||||
_HouseNoController.text,
|
||||
_RoadController.text,
|
||||
_addressTypeController.text);
|
||||
if (state) {
|
||||
context .read<AddtocartProvider>()
|
||||
.getAddress(context);
|
||||
Fluttertoast.showToast(
|
||||
msg: "Address Added!",
|
||||
backgroundColor: Colors.lightGreen);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
} else {
|
||||
Fluttertoast.showToast(
|
||||
msg:
|
||||
"Delivery is not available for this pincode. Please try another pincode!",
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
backgroundColor: Colors.red,
|
||||
textColor: Colors.white,
|
||||
fontSize: 14.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(
|
||||
left: 15, right: 15, top: 10, bottom: 10),
|
||||
height: 50,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
if (addressProvider.ischeckpin)
|
||||
const CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
)
|
||||
else
|
||||
Text(
|
||||
"Save Address",
|
||||
style: context.customMedium(
|
||||
Colors.white, 20),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
// InkWell(
|
||||
// onTap: () async {
|
||||
// if (_formKey.currentState!.validate()) {
|
||||
// var status = await Provider.of<AddressProvider>(
|
||||
// context,
|
||||
// listen: false)
|
||||
// .checkPin(context, _pincodeController.text);
|
||||
// if (status) {
|
||||
// // var status = await Provider.of<AddressProvider>(
|
||||
// // context,
|
||||
// // listen: false)
|
||||
// // .addAddress(context, _pincodeController.text);
|
||||
// } else {
|
||||
// // Delivery is not available for this pincode. Please try another pincode.
|
||||
|
||||
// Fluttertoast.showToast(
|
||||
// msg:
|
||||
// "Delivery is not available for this pincode. Please try another pincode!",
|
||||
// toastLength: Toast.LENGTH_SHORT,
|
||||
// gravity: ToastGravity.BOTTOM,
|
||||
// backgroundColor: Colors.red,
|
||||
// textColor: Colors.white,
|
||||
// fontSize: 14.0,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// child: Container(
|
||||
// margin: const EdgeInsets.only(
|
||||
// left: 15, right: 15, top: 10, bottom: 10),
|
||||
// height: 50,
|
||||
// width: MediaQuery.sizeOf(context).width,
|
||||
// decoration: BoxDecoration(
|
||||
// color: APPCOLOR.lightGreen,
|
||||
// borderRadius: BorderRadius.circular(10)),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// const SizedBox(
|
||||
// width: 10,
|
||||
// ),
|
||||
// Text(
|
||||
// "Save Address",
|
||||
// style: context.customMedium(Colors.white, 20),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
|
||||
SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,330 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
|
||||
const String googleApiKey = "AIzaSyAi3_Dls63iGs7Nccgdm-4FkS0rhT03-4U";
|
||||
|
||||
class MapScreen extends StatefulWidget {
|
||||
@override
|
||||
_MapScreenState createState() => _MapScreenState();
|
||||
}
|
||||
|
||||
class _MapScreenState extends State<MapScreen> {
|
||||
late GoogleMapController mapController;
|
||||
LatLng _selectedLocation = LatLng(20.5937, 78.9629);
|
||||
|
||||
TextEditingController _pincodeController = TextEditingController();
|
||||
TextEditingController _fullNameController = TextEditingController();
|
||||
TextEditingController _PhoneNumberController = TextEditingController();
|
||||
TextEditingController _addressTypeController = TextEditingController();
|
||||
TextEditingController _HouseNoController = TextEditingController();
|
||||
TextEditingController _RoadController = TextEditingController();
|
||||
TextEditingController _AlterNativeNumberController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_determinePosition();
|
||||
}
|
||||
|
||||
Future<void> _determinePosition() async {
|
||||
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocationPermission permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
return;
|
||||
}
|
||||
|
||||
Position position = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.high,
|
||||
);
|
||||
LatLng currentLatLng = LatLng(position.latitude, position.longitude);
|
||||
|
||||
setState(() {
|
||||
_selectedLocation = currentLatLng;
|
||||
});
|
||||
|
||||
_getAddressFromLatLng(position.latitude, position.longitude);
|
||||
}
|
||||
|
||||
Future<void> _getAddressFromLatLng(double lat, double lng) async {
|
||||
final String url =
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=$googleApiKey";
|
||||
|
||||
try {
|
||||
final response = await http.get(Uri.parse(url));
|
||||
if (response.statusCode == 200) {
|
||||
final data = json.decode(response.body);
|
||||
if (data["status"] == "OK") {
|
||||
var result = data["results"][0]; // First result is most accurate
|
||||
|
||||
_RoadController.text = result["formatted_address"];
|
||||
List components = result["address_components"];
|
||||
|
||||
String roadName = "";
|
||||
String colony = "";
|
||||
String buildingName = "";
|
||||
String pincode = "";
|
||||
|
||||
for (var component in components) {
|
||||
List types = component["types"];
|
||||
if (types.contains("route")) {
|
||||
roadName = component["long_name"]; // Road Name
|
||||
} else if (types.contains("sublocality_level_1") ||
|
||||
types.contains("locality")) {
|
||||
colony = component["long_name"]; // Colony Name
|
||||
} else if (types.contains("premise") ||
|
||||
types.contains("street_number")) {
|
||||
buildingName = component["long_name"]; // Building Name
|
||||
} else if (types.contains("postal_code")) {
|
||||
pincode = component["long_name"]; // Extract Pin Code
|
||||
}
|
||||
}
|
||||
|
||||
// setState(() {
|
||||
// // _address = formattedAddress;
|
||||
// _roadName = roadName;
|
||||
// _colony = colony;
|
||||
// _buildingName = buildingName;
|
||||
// });
|
||||
|
||||
_pincodeController.text = pincode;
|
||||
_RoadController.text = result["formatted_address"];
|
||||
|
||||
print(
|
||||
"Full Address: ${result["formatted_address"]} ${response.body} sdfsgd ${pincode}");
|
||||
print("Road Name: $roadName");
|
||||
print("Colony: $colony");
|
||||
print("Building Name: $buildingName");
|
||||
} else {}
|
||||
} else {}
|
||||
} catch (e) {
|
||||
print("Error fetching address: $e");
|
||||
}
|
||||
}
|
||||
|
||||
// On map tapped
|
||||
void _onMapTapped(LatLng tappedPoint) {
|
||||
setState(() {
|
||||
_selectedLocation = tappedPoint;
|
||||
});
|
||||
_getAddressFromLatLng(tappedPoint.latitude, tappedPoint.longitude);
|
||||
}
|
||||
|
||||
// Update location based on entered pincode
|
||||
Future<void> _updateLocationFromPincode(String enteredPincode) async {
|
||||
if (enteredPincode.isEmpty) return;
|
||||
|
||||
try {
|
||||
List<Location> locations = await locationFromAddress(enteredPincode);
|
||||
if (locations.isNotEmpty) {
|
||||
Location location = locations.first;
|
||||
LatLng newLatLng = LatLng(location.latitude, location.longitude);
|
||||
|
||||
setState(() {
|
||||
_selectedLocation = newLatLng;
|
||||
});
|
||||
|
||||
_getAddressFromLatLng(location.latitude, location.longitude);
|
||||
mapController.animateCamera(CameraUpdate.newLatLng(newLatLng));
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error fetching location from pincode: $e");
|
||||
}
|
||||
}
|
||||
|
||||
// {
|
||||
// "name": "Socket Mall",
|
||||
// "pincode": "400001",
|
||||
// "phoneNumber": "+919876543210",
|
||||
// "alternatePhoneNumber": "+919876543211",
|
||||
// "addressLine": "123, Main Street, Apartment 4B",
|
||||
// "landmark": "Near Central Park",
|
||||
// "addressType": "HOME",
|
||||
// "isDefault": false,
|
||||
// "additionalInstructions": "Please ring doorbell twice"
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text("Add Delivery address")),
|
||||
body: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 200.h,
|
||||
child: GoogleMap(
|
||||
initialCameraPosition: CameraPosition(
|
||||
target: _selectedLocation,
|
||||
zoom: 14,
|
||||
),
|
||||
onMapCreated: (controller) {
|
||||
mapController = controller;
|
||||
},
|
||||
markers: {
|
||||
Marker(
|
||||
markerId: MarkerId("selected Location"),
|
||||
position: _selectedLocation,
|
||||
)
|
||||
},
|
||||
onTap: _onMapTapped,
|
||||
),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10)],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Text("Selected Address:",
|
||||
// style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
|
||||
// SizedBox(height: 5),
|
||||
// Text(_address, style: TextStyle(fontSize: 16)),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: _fullNameController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Full Name (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: _PhoneNumberController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Phone Number (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _pincodeController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Enter Pincode",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _addressTypeController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Address Type",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: _HouseNoController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "House No, Building Name (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: _RoadController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Road Name, Area , Colony(Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// print("fjnghkjfjghj");
|
||||
// Provider.of<ProductProvider>(context, listen: false)
|
||||
// .customerLogOut(context);
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(
|
||||
left: 15, right: 15, top: 10, bottom: 10),
|
||||
height: 50,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(
|
||||
"Save Address",
|
||||
style: context.customMedium(Colors.white, 20),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// ElevatedButton(
|
||||
// onPressed: () {
|
||||
// Navigator.pop(context, {
|
||||
// "location": _selectedLocation,
|
||||
// "address": _address,
|
||||
// "pincode": _pincode
|
||||
// });
|
||||
// },
|
||||
// child: Text("Confirm Location"),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:grocery_app/src/common_widget/network_image.dart';
|
||||
import 'package:grocery_app/src/core/routes/routes.dart';
|
||||
import 'package:grocery_app/src/data/allProduct_model.dart';
|
||||
import 'package:grocery_app/src/logic/provider/bottom_navbar_provider.dart';
|
||||
import 'package:grocery_app/src/logic/provider/home_provider.dart';
|
||||
import 'package:grocery_app/utils/constants/assets_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
@@ -18,6 +19,7 @@ import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:readmore/readmore.dart';
|
||||
import 'package:shimmer/shimmer.dart';
|
||||
|
||||
class ProductDetails extends StatefulWidget {
|
||||
String id;
|
||||
@@ -95,7 +97,6 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
prodectDtails(),
|
||||
Divider(),
|
||||
reviews(),
|
||||
Divider(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Text("Similar Products",
|
||||
@@ -110,20 +111,39 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
),
|
||||
),
|
||||
),
|
||||
// bottomNavigationBar: bottomBar(),
|
||||
bottomNavigationBar: bottomBar(),
|
||||
);
|
||||
}
|
||||
|
||||
double calculateDiscountPercentage(double basePrice, double discountPrice) {
|
||||
print(
|
||||
"Base Price (Before Discount): $basePrice, Discount Price (After Discount): $discountPrice");
|
||||
|
||||
if (basePrice <= 0 || discountPrice <= 0 || discountPrice > basePrice) {
|
||||
print("Error: Invalid price values.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
double discountAmount = basePrice - discountPrice;
|
||||
double discountPercentage = (discountAmount / basePrice) * 100;
|
||||
|
||||
return discountPercentage;
|
||||
}
|
||||
|
||||
Widget prodectDtails() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.isProductLoading) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.green,
|
||||
));
|
||||
return _buildSkeletonLoader();
|
||||
} else if (provider.productDetails.data == null) {
|
||||
return Center(child: Text('No products available'));
|
||||
} else {
|
||||
provider.setProductPrice(
|
||||
double.parse(provider.productDetails.data!.discountPrice));
|
||||
provider.productQuantity = provider.productDetails.data!.quantity;
|
||||
|
||||
if (provider.productDetails.data!.isInWishlist!) {
|
||||
provider.wishlist.contains(provider.productDetails.data!.id);
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
@@ -206,43 +226,13 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
color: Colors.green,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Text("10% OFF",
|
||||
child: Text(
|
||||
"${calculateDiscountPercentage(double.parse(provider.productDetails.data!.basePrice), double.parse(provider.productDetails.data!.discountPrice))}% OFF",
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 14)),
|
||||
),
|
||||
Spacer(),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
if (await SharedPrefUtils.getToken() != null) {
|
||||
provider.toggleWishlist(
|
||||
context, provider.productDetails.data!.id!);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
},
|
||||
child: Icon(
|
||||
provider.wishlist
|
||||
.contains(provider.productDetails.data!.id)
|
||||
? Icons.favorite
|
||||
: Icons.favorite_border,
|
||||
color: provider.wishlist
|
||||
.contains(provider.productDetails.data!.id)
|
||||
? Colors.red
|
||||
: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
ReadMoreText(
|
||||
provider.productDetails.data!.description ?? "",
|
||||
trimMode: TrimMode.Line,
|
||||
trimLines: 2,
|
||||
colorClickableText: APPCOLOR.appGreen,
|
||||
trimCollapsedText: 'Read More',
|
||||
trimExpandedText: 'Show less',
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -252,262 +242,320 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
});
|
||||
}
|
||||
|
||||
Widget reviews() {
|
||||
Widget _buildSkeletonLoader() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Reviews & Ratings",
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text("4.2",
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold)),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
RatingStars(
|
||||
value: value,
|
||||
onValueChanged: (v) {
|
||||
//
|
||||
setState(() {
|
||||
value = v;
|
||||
});
|
||||
},
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
valueLabelColor: const Color(0xff9b9b9b),
|
||||
valueLabelTextStyle: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontSize: 12.0),
|
||||
valueLabelRadius: 10,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration: Duration(milliseconds: 1000),
|
||||
valueLabelPadding:
|
||||
const EdgeInsets.symmetric(vertical: 1, horizontal: 8),
|
||||
valueLabelMargin: const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
highlightColor: Colors.grey[100]!,
|
||||
child: Container(
|
||||
height: 300,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start, // Align items at the top
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundImage: NetworkImage('https://via.placeholder.com/50'),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
|
||||
// Column for Text and RatingStars
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween, // Proper spacing
|
||||
children: [
|
||||
Text(
|
||||
"Johnson Smith",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
RatingStars(
|
||||
value: value,
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration: Duration(milliseconds: 1000),
|
||||
valueLabelPadding: const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin: const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
highlightColor: Colors.grey[100]!,
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: double.infinity,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
ReadMoreText(
|
||||
'Flutter is Google’s mobile UI open source framework to build high-quality native (super fast) interfaces for iOS and Android apps with the unified codebase.',
|
||||
trimMode: TrimMode.Line,
|
||||
trimLines: 2,
|
||||
colorClickableText: APPCOLOR.appGreen,
|
||||
trimCollapsedText: 'Read More',
|
||||
trimExpandedText: 'Show less',
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
highlightColor: Colors.grey[100]!,
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 150,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Widget similarProducts() {
|
||||
// return SizedBox(
|
||||
// height: 222,
|
||||
// child: ListView.builder(
|
||||
// itemCount: 5,
|
||||
// scrollDirection: Axis.horizontal,
|
||||
// itemBuilder: (context, index) {
|
||||
// return Padding(
|
||||
// padding: const EdgeInsets.only(right: 10, bottom: 5, top: 5),
|
||||
// child: Container(
|
||||
// height: 215,
|
||||
// width: 150,
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.white,
|
||||
// borderRadius: BorderRadius.circular(15),
|
||||
// boxShadow: [
|
||||
// BoxShadow(
|
||||
// color: Colors.grey.withOpacity(0.1),
|
||||
// blurRadius: 1,
|
||||
// offset: const Offset(5, 5),
|
||||
// ),
|
||||
// ]),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(5),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Container(
|
||||
// height: 100,
|
||||
// width: 150,
|
||||
// decoration: BoxDecoration(
|
||||
// color: APPCOLOR.bgGrey,
|
||||
// borderRadius: BorderRadius.circular(15)),
|
||||
// child: const Stack(
|
||||
// alignment: Alignment.center,
|
||||
// children: [
|
||||
// AppNetworkImage(
|
||||
// height: 70,
|
||||
// width: 70,
|
||||
// imageUrl:
|
||||
// "https://5.imimg.com/data5/SELLER/Default/2024/2/385126988/OL/DA/VW/8627346/1l-fortune-sunflower-oil.jpg",
|
||||
// backGroundColor: Colors.transparent),
|
||||
// Positioned(
|
||||
// right: 5,
|
||||
// top: 5,
|
||||
// child: Icon(Icons.favorite_border))
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// "Fortune Arhar Dal (Toor Dal)",
|
||||
// textAlign: TextAlign.left,
|
||||
// maxLines: 2,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 5,
|
||||
// ),
|
||||
// Text(
|
||||
// "500 ML",
|
||||
// textAlign: TextAlign.left,
|
||||
// maxLines: 1,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// style: context.customMedium(
|
||||
// Colors.grey.withOpacity(0.8), 12),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 3,
|
||||
// ),
|
||||
// Row(
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Text(
|
||||
// "\$12",
|
||||
// textAlign: TextAlign.left,
|
||||
// maxLines: 1,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// style: context.customSemiBold(Colors.black, 12),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// width: 5,
|
||||
// ),
|
||||
// Text(
|
||||
// "\$14",
|
||||
// textAlign: TextAlign.left,
|
||||
// maxLines: 1,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// style: context
|
||||
// .customMedium(
|
||||
// Colors.grey.withOpacity(0.8), 12)
|
||||
// .copyWith(
|
||||
// decoration: TextDecoration.lineThrough,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// )),
|
||||
// Expanded(
|
||||
// child: Align(
|
||||
// alignment: Alignment.centerRight,
|
||||
// child: Container(
|
||||
// height: 30,
|
||||
// width: 50,
|
||||
// decoration: BoxDecoration(
|
||||
// color: APPCOLOR.lightGreen,
|
||||
// borderRadius: BorderRadius.circular(5),
|
||||
// ),
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'Add',
|
||||
// style: context.customRegular(Colors.white, 12),
|
||||
// )),
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
Widget reviews() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.isProductLoading) {
|
||||
return SizedBox.shrink();
|
||||
} else if (provider.productDetails.data == null) {
|
||||
return Center(child: Text('No products available'));
|
||||
} else {
|
||||
return provider.productDetails.data!.productReview!.isNotEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Reviews & Ratings",
|
||||
style: TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text("4.2",
|
||||
style: TextStyle(
|
||||
fontSize: 30, fontWeight: FontWeight.bold)),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
RatingStars(
|
||||
value: value,
|
||||
onValueChanged: (v) {
|
||||
//
|
||||
setState(() {
|
||||
value = v;
|
||||
});
|
||||
},
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
valueLabelColor: const Color(0xff9b9b9b),
|
||||
valueLabelTextStyle: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontSize: 12.0),
|
||||
valueLabelRadius: 10,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration: Duration(milliseconds: 1000),
|
||||
valueLabelPadding: const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin: const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start, // Align items at the top
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundImage:
|
||||
NetworkImage('https://via.placeholder.com/50'),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
|
||||
// Column for Text and RatingStars
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment
|
||||
.spaceBetween, // Proper spacing
|
||||
children: [
|
||||
Text(
|
||||
"Johnson Smith",
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
RatingStars(
|
||||
value: value,
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration:
|
||||
Duration(milliseconds: 1000),
|
||||
valueLabelPadding:
|
||||
const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin:
|
||||
const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
ReadMoreText(
|
||||
'Flutter is Google’s mobile UI open source framework to build high-quality native (super fast) interfaces for iOS and Android apps with the unified codebase.',
|
||||
trimMode: TrimMode.Line,
|
||||
trimLines: 2,
|
||||
colorClickableText: APPCOLOR.appGreen,
|
||||
trimCollapsedText: 'Read More',
|
||||
trimExpandedText: 'Show less',
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Reviews & Ratings",
|
||||
style: TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text("4.2",
|
||||
style: TextStyle(
|
||||
fontSize: 30, fontWeight: FontWeight.bold)),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
RatingStars(
|
||||
value: value,
|
||||
onValueChanged: (v) {
|
||||
//
|
||||
setState(() {
|
||||
value = v;
|
||||
});
|
||||
},
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
valueLabelColor: const Color(0xff9b9b9b),
|
||||
valueLabelTextStyle: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontSize: 12.0),
|
||||
valueLabelRadius: 10,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration: Duration(milliseconds: 1000),
|
||||
valueLabelPadding: const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin: const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start, // Align items at the top
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundImage:
|
||||
NetworkImage('https://via.placeholder.com/50'),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
|
||||
// Column for Text and RatingStars
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment
|
||||
.spaceBetween, // Proper spacing
|
||||
children: [
|
||||
Text(
|
||||
"Johnson Smith",
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
RatingStars(
|
||||
value: value,
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration:
|
||||
Duration(milliseconds: 1000),
|
||||
valueLabelPadding:
|
||||
const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin:
|
||||
const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
ReadMoreText(
|
||||
'Flutter is Google’s mobile UI open source framework to build high-quality native (super fast) interfaces for iOS and Android apps with the unified codebase.',
|
||||
trimMode: TrimMode.Line,
|
||||
trimLines: 2,
|
||||
colorClickableText: APPCOLOR.appGreen,
|
||||
trimCollapsedText: 'Read More',
|
||||
trimExpandedText: 'Show less',
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget bestDeal() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
@@ -678,7 +726,7 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
false
|
||||
? null
|
||||
: () => provider.addToCart(
|
||||
context, bestdealproduct.id!);
|
||||
context, bestdealproduct.id!, 1);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
@@ -730,71 +778,90 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
}
|
||||
|
||||
Widget bottomBar() {
|
||||
return Consumer<ProductProvider>(
|
||||
builder: (context, cartProvider, child) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.grey.shade300, blurRadius: 10)],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.remove_circle_outline),
|
||||
onPressed: cartProvider.decreaseQuantity,
|
||||
),
|
||||
Text("${cartProvider.quantity}",
|
||||
style:
|
||||
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
IconButton(
|
||||
icon: Icon(Icons.add_circle_outline),
|
||||
onPressed: cartProvider.increaseQuantity,
|
||||
),
|
||||
],
|
||||
return Consumer<ProductProvider>(builder: (context, cartProvider, child) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.grey.shade300, blurRadius: 10)],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.remove_circle_outline),
|
||||
onPressed: cartProvider.decreaseQuantity,
|
||||
),
|
||||
Text("${cartProvider.quantity}",
|
||||
style:
|
||||
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
IconButton(
|
||||
icon: Icon(Icons.add_circle_outline),
|
||||
onPressed: cartProvider.increaseQuantity,
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
Container(
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Center(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'Add to Cart',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Container(
|
||||
width: 2, height: 50, color: APPCOLOR.whiteFBFEFB),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
"\$${cartProvider.totalPrice}",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Center(
|
||||
child: Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
cartProvider.addToCart(
|
||||
context,
|
||||
cartProvider.productDetails.data!.id!,
|
||||
cartProvider.quantity);
|
||||
},
|
||||
child: cartProvider.isLoadingCart
|
||||
? Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 40, right: 40),
|
||||
child: Container(
|
||||
height: 15,
|
||||
width: 15,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.white, strokeWidth: 2),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
'Add to Cart',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Container(
|
||||
width: 2, height: 50, color: APPCOLOR.whiteFBFEFB),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
"\$${cartProvider.totalPrice}",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,19 @@ import 'package:grocery_app/src/common_widget/network_image.dart';
|
||||
import 'package:grocery_app/src/logic/provider/home_provider.dart';
|
||||
import 'package:grocery_app/src/ui/card_checkout/card_checkout_screen.dart';
|
||||
import 'package:grocery_app/src/ui/edit_profile/edit_profile_screen.dart';
|
||||
import 'package:grocery_app/src/ui/map/google_map.dart';
|
||||
|
||||
import 'package:grocery_app/src/ui/mapscreen/map_screen.dart';
|
||||
import 'package:grocery_app/src/ui/message/message_screen.dart';
|
||||
import 'package:grocery_app/src/ui/notification/notification_screen.dart';
|
||||
import 'package:grocery_app/src/ui/rating_review/rating_review_screen.dart';
|
||||
import 'package:grocery_app/src/ui/static_page/static_page_screen.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/shared_pref_utils.dart';
|
||||
import 'package:grocery_app/utils/constants/string_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class ProfileScreen extends StatefulWidget {
|
||||
const ProfileScreen({super.key});
|
||||
@@ -25,7 +28,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
var top = 0.0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context)
|
||||
{
|
||||
return Scaffold(
|
||||
body: NestedScrollView(
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
@@ -69,34 +73,34 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
AppNetworkImage(
|
||||
height: top < 150 ? 30 : 50,
|
||||
width: top < 150 ? 30 : 50,
|
||||
imageUrl:
|
||||
imageUrl: "${APPSTRING.userProfile ?? ""}" ??
|
||||
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTdQLwDqDwd2JfzifvfBTFT8I7iKFFevcedYg&s",
|
||||
radius: 90,
|
||||
backGroundColor: Colors.white,
|
||||
boxFit: BoxFit.fill,
|
||||
),
|
||||
top > 100
|
||||
? Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 18,
|
||||
width: 18,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
border: Border.all(
|
||||
color: Colors.white),
|
||||
borderRadius:
|
||||
BorderRadius.circular(5)),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
MdiIcons.pencil,
|
||||
size: 10,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
))
|
||||
: const SizedBox(),
|
||||
// top > 100
|
||||
// ? Positioned(
|
||||
// bottom: 0,
|
||||
// right: 0,
|
||||
// child: Container(
|
||||
// height: 18,
|
||||
// width: 18,
|
||||
// decoration: BoxDecoration(
|
||||
// color: APPCOLOR.lightGreen,
|
||||
// border: Border.all(
|
||||
// color: Colors.white),
|
||||
// borderRadius:
|
||||
// BorderRadius.circular(5)),
|
||||
// child: Center(
|
||||
// child: Icon(
|
||||
// MdiIcons.pencil,
|
||||
// size: 10,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// ))
|
||||
// : const SizedBox(),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
@@ -108,13 +112,13 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Smith Mate",
|
||||
APPSTRING.userName ?? "",
|
||||
style: context.customExtraBold(
|
||||
top < 100 ? Colors.black : Colors.white,
|
||||
14),
|
||||
),
|
||||
Text(
|
||||
'smithmate@example.com',
|
||||
APPSTRING.emailName,
|
||||
style: context.customRegular(
|
||||
top < 100 ? Colors.black : Colors.white,
|
||||
10),
|
||||
@@ -196,30 +200,31 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
title: const Text('Notifications'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const RatingReviewScreen();
|
||||
},
|
||||
));
|
||||
},
|
||||
leading: Icon(MdiIcons.starOutline),
|
||||
title: const Text('Rating & Review'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const MessageScreen();
|
||||
},
|
||||
));
|
||||
},
|
||||
leading: Icon(MdiIcons.messageOutline),
|
||||
title: const Text('Driver Message'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
// ListTile(
|
||||
// onTap: () {
|
||||
// Navigator.of(context).push(MaterialPageRoute(
|
||||
// builder: (context) {
|
||||
// return const RatingReviewScreen();
|
||||
// },
|
||||
// ));
|
||||
// },
|
||||
// leading: Icon(MdiIcons.starOutline),
|
||||
// title: const Text('Rating & Review'),
|
||||
// trailing: Icon(MdiIcons.chevronRight),
|
||||
// ),
|
||||
// ListTile(
|
||||
// onTap: () {
|
||||
// Navigator.of(context).push(MaterialPageRoute(
|
||||
// builder: (context) {
|
||||
// return const MessageScreen();
|
||||
// },
|
||||
// ));
|
||||
// },
|
||||
// leading: Icon(MdiIcons.messageOutline),
|
||||
// title: const Text('Driver Message'),
|
||||
// trailing: Icon(MdiIcons.chevronRight),
|
||||
// ),
|
||||
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
@@ -248,24 +253,12 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
title: const Text('Term & Conditions'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {},
|
||||
leading: Icon(MdiIcons.basketOutline),
|
||||
title: const Text('Grocery List'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return MapScreen();
|
||||
},
|
||||
));
|
||||
},
|
||||
leading: Icon(MdiIcons.basketOutline),
|
||||
title: const Text('Map List'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
// ListTile(
|
||||
// onTap: () {},
|
||||
// leading: Icon(MdiIcons.basketOutline),
|
||||
// title: const Text('Grocery List'),
|
||||
// trailing: Icon(MdiIcons.chevronRight),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grocery_app/src/core/routes/routes.dart';
|
||||
import 'package:grocery_app/src/logic/provider/bottom_navbar_provider.dart';
|
||||
import 'package:grocery_app/src/ui/onboarding/on_boarding_screen.dart';
|
||||
import 'package:grocery_app/utils/constants/assets_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/shared_pref_utils.dart';
|
||||
import 'package:grocery_app/utils/extensions/extensions.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
const SplashScreen({super.key});
|
||||
@@ -14,6 +16,7 @@ class SplashScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SplashScreenState extends State<SplashScreen> {
|
||||
|
||||
couting() async {
|
||||
Future.delayed(const Duration(seconds: 3)).then((c) {
|
||||
Navigator.of(context).pushReplacement(MaterialPageRoute(
|
||||
@@ -27,6 +30,9 @@ class _SplashScreenState extends State<SplashScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
Future.delayed(const Duration(seconds: 2), () async {
|
||||
|
||||
Provider.of<BottomNavProvider>(context, listen: false)
|
||||
.refreshToken(context);
|
||||
if (await SharedPrefUtils.isFreshInstall()) {
|
||||
context.clearAndPush(routePath: MyRoutes.ONBOARDING);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user