updateProfile

This commit is contained in:
2025-02-03 01:29:42 +05:30
parent 42aaa7cdad
commit 1f7254ecaa
48 changed files with 6088 additions and 2473 deletions

View File

@@ -3,9 +3,11 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:grocery_app/src/core/network_services/service_locator.dart';
import 'package:grocery_app/src/core/routes/routes.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/src/logic/provider/auth_provider.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/logic/provider/profile_provider.dart';
import 'package:grocery_app/src/ui/splash/splash_screen.dart';
import 'package:grocery_app/utils/constants/color_constant.dart';
import 'package:grocery_app/utils/constants/string_constant.dart';
@@ -30,21 +32,23 @@ class MyApplication extends StatelessWidget {
splitScreenMode: true,
builder: (context, child) => GlobalLoaderOverlay(
overlayColor: APPCOLOR.whiteFBFEFB.withOpacity(0.5),
useDefaultLoading: false,
// overlayWidgetBuilder: (progress) => const GlobalLoader(),
child: MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AuthProvider()),
ChangeNotifierProvider(create: (_) => ProductProvider()),
ChangeNotifierProvider(create: (_) => ProductProvider()),
ChangeNotifierProvider(create: (_) => AddtocartProvider()),
ChangeNotifierProvider(create: (_) => BottomNavProvider()),
// ChangeNotifierProvider(create: (_) => HomeProvider()),
ChangeNotifierProvider(create: (_) => BottomNavProvider()),
ChangeNotifierProvider(create: (_) => AddressProvider()),
ChangeNotifierProvider(create: (_) => ProfileProvider()),
],
child: MaterialApp.router(
routerConfig: MyRoutes.router,
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightGreen),
scaffoldBackgroundColor: Colors.white,
canvasColor: const Color.fromRGBO(255, 255, 255, 1),
fontFamily: 'GoogleSans',

View File

@@ -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 {
),
),
);
}
}

View File

@@ -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,

View File

@@ -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/";
}

View File

@@ -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
View 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,
};
}

View 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,
};
}

View 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,
};
}

View File

@@ -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"],

View File

@@ -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
}
}
}

View 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;
}
}
}

View File

@@ -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;
},
);
}
}

View File

@@ -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();
}
}

View 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;
}
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 {

View File

@@ -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));

View File

@@ -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);
}

View File

@@ -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

View 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"),
)
],
)
],
),
),
);
},
),
),
],
),
),
);
}
}

View File

@@ -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

View File

@@ -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

View 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),
],
),
),
),
],
),
),
),
);
}
}

View File

@@ -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"),
// ),
],
),
),
),
],
),
);
}
}

View File

@@ -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 Googles 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 Googles 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 Googles 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),
),
],
),
),
)
],
),
);
},
);
),
)
],
),
);
});
}
}

View File

@@ -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),
// ),
],
),
),

View File

@@ -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 {

View File

@@ -1,5 +1,6 @@
// ignore_for_file: constant_identifier_names
import 'package:grocery_app/src/data/user_profile.dart';
import 'package:shared_preferences/shared_preferences.dart';
// Shared preference for the app to store data locally
@@ -35,7 +36,43 @@ class SharedPrefUtils {
static const String STORE_ID = "STORE_ID";
static const String REFRESH_TOKEN = "REFRESH_TOKEN";
/// Set bearer authorization token
static const String KEY_NAME = "user_name";
static const String KEY_LAST_NAME = "user_name";
static const String KEY_EMAIL = "user_email";
static const String KEY_PROFILE = "user_profile";
static Future<void> saveUser({
required UserProfile user,
}) async {
print("jdhsfhjdjfhg ${user.img}");
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString(KEY_NAME, user.firstName ?? "");
await prefs.setString(KEY_LAST_NAME, user.lastName ?? "");
await prefs.setString(KEY_EMAIL, user.email ?? " ");
await prefs.setString(KEY_PROFILE, user.img ?? " ");
}
static Future<String?> getUserName() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(KEY_NAME);
}
static Future<String?> getLastName() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(KEY_LAST_NAME);
}
/// Get user email
static Future<String?> getUserEmail() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(KEY_EMAIL);
}
/// Get user profile URL
static Future<String?> getUserProfile() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(KEY_PROFILE);
}
static Future<bool> setToken({required String authToken}) {
_token = authToken;
return SharedPreferences.getInstance()
@@ -232,10 +269,7 @@ class SharedPrefUtils {
return firstName!;
}
static Future<String> getLastName() async {
final sp = await SharedPreferences.getInstance();
return sp.getString(LAST_NAME) ?? "";
}
static Future<String> getEmail() async {
final sp = await SharedPreferences.getInstance();
@@ -247,11 +281,6 @@ class SharedPrefUtils {
return sp.getString(PASSWORD) ?? "";
}
static Future<String> getUsername() async {
final sp = await SharedPreferences.getInstance();
return sp.getString(USER_NAME) ?? "";
}
static Future<bool> getRandomInstruction() async {
final sp = await SharedPreferences.getInstance();
return sp.getBool(INS_RANDOM) ?? true;

View File

@@ -2,10 +2,12 @@ class APPSTRING {
//title
static const String enterYourMobileNumber = "Enter Your Mobile Number";
static const String whatYourPhoneNumber = "What's your phone number?";
static const String codeSentText = "A code will be send to verify your phone number";
static const String codeSentText =
"A code will be send to verify your phone number";
static const String enterVerificationCode = "Enter Verification Code";
static const String enterCode = "Enter the 6-digit code sent to you at ********8902";
static const String enterCode =
"Enter the 6-digit code sent to you at ********8902";
static const String pleaseEnterYourFullName = "Please Enter Your Full Name";
//hint
@@ -13,11 +15,16 @@ class APPSTRING {
static const String firstNameHint = "First Name";
static const String lastNameHint = "last Name";
static const String emailHint = "Email-ID";
static const String emailHint = "Email-ID";
static const String addressHint = "Address";
//button
static const String verifyButton = "Verify";
static const String continueBtn = "Continue";
static const String appName = "Customer App";
static const String appName = "Customer App";
static String userName = "user_name";
static String userLastName = "user_name";
static String emailName = "user_email";
static String userProfile = "user_profile";
}