change category flow

This commit is contained in:
2025-05-10 01:14:10 +05:30
parent 873c73143b
commit bf7a7a96bd
11 changed files with 1405 additions and 1132 deletions

View File

@@ -9,6 +9,7 @@ import 'package:grocery_app/src/ui/bottomnavigation/bottom_bar_widget.dart';
import 'package:grocery_app/src/ui/card_checkout/card_checkout_screen.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/category_product.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';
@@ -151,108 +152,19 @@ class MyRoutes {
return OrderDetailsScreen(order: order);
},
),
animatedGoRoute(
path: CATEGORYPRODUCT,
name: CATEGORYPRODUCT,
pageBuilder: (context, state) {
final args = state.extra as Map<String, dynamic>;
// animatedGoRoute(
// path: UPDATESTORE,
// name: UPDATESTORE,
// pageBuilder: (context, state) {
// final extra = state.extra as Map<String, dynamic>?;
// final String status = extra?['storeId'] ?? '';
// return UpdateStoreScreen(storeId: status);
// }
return CtegoryProduct(categoryId: args["id"],
name: args["name"],);
},
),
// ),
// animatedGoRoute(
// path: SUBMITSCREEN,
// name: SUBMITSCREEN,
// pageBuilder: (context, state) => const PinCreated(),
// ),
// animatedGoRoute(
// path: APPROVEDSTATUS,
// name: APPROVEDSTATUS,
// pageBuilder: (context, state) => const ApprovalScreen(),
// ),
// animatedGoRoute(
// path: SIGNUP,
// name: SIGNUP,
// pageBuilder: (context, state) => LoginHostScreen(),
// ),
// animatedGoRoute(
// path: DASHBOARDSCREEN,
// name: DASHBOARDSCREEN,
// pageBuilder: (context, state) => DashboardScree(),
// ),
// animatedGoRoute(
// path: CUSTOMERORDER,
// name: CUSTOMERORDER,
// pageBuilder: (context, state) {
// // Extract data from `state.extra`
// final Map<String, dynamic> orderDetails =
// state.extra as Map<String, dynamic>;
// return CustomerOrder(
// orderDetails:
// orderDetails, // Pass the data to the destination widget
// );
// },
// ),
// animatedGoRoute(
// path: PRODUCTFORMSCREEN,
// name: PRODUCTFORMSCREEN,
// pageBuilder: (context, state) => ProductFormScreen(),
// ),
// animatedGoRoute(
// path: PRODUCTDETAILS,
// name: PRODUCTDETAILS,
// pageBuilder: (context, state) {
// final Product product = state.extra as Product;
// return Productdetails(
// product: product, // Pass the `Product` object directly
// );
// },
// ),
// animatedGoRoute(
// path: TRANSACTIONHISTORY,
// name: TRANSACTIONHISTORY,
// pageBuilder: (context, state) => TransactionHistory(),
// ),
// animatedGoRoute(
// path: INSIGHTSHISTORY,
// name: INSIGHTSHISTORY,
// pageBuilder: (context, state) => InsightsHistory(),
// ),
// animatedGoRoute(
// path: DETAILSBUSSINESS,
// name: DETAILSBUSSINESS,
// pageBuilder: (context, state) => DetailsBussiness(),
// ),
// animatedGoRoute(
// path: STOREMANAGEMENT,
// name: STOREMANAGEMENT,
// pageBuilder: (context, state) => StoreManagement(),
// ),
// animatedGoRoute(
// path: SETTING,
// name: SETTING,
// pageBuilder: (context, state) => Settings(),
// ),
// animatedGoRoute(
// path: FORGETPASSWORD,
// name: FORGETPASSWORD,
// pageBuilder: (context, state) => ForgetPassword(),
// ),
// animatedGoRoute(
// path: VERIFYPASSWORD,
// name: VERIFYPASSWORD,
// pageBuilder: (context, state) => VerifyOtpForgetPassword(),
// ),
// animatedGoRoute(
// path: FORGETNEWPASSWORD,
// name: FORGETNEWPASSWORD,
// pageBuilder: (context, state) => ForgetNewPassword(),
// ),
// ],
]);
/// Route constants
@@ -279,33 +191,10 @@ class MyRoutes {
static const PRIVACY = "/privacyandpolicy";
// static const SETUPBUSSINESS = "/setupbussiness";
// static const CREATESTORE = "/createStore";
// static const SUBMITSCREEN = "/submitscreen";
// static const APPROVEDSTATUS = "/approvedstatus";
static const OTPSCREEN = "/otpscreen";
static const CATEGORYPRODUCT = "/CtegoryProduct";
// static const DASHBOARDSCREEN = "/dashboardscreen";
// static const CUSTOMERORDER = "/customerorder";
// static const PRODUCTFORMSCREEN = "/productformscreen";
// static const TRANSACTIONHISTORY = "/transationhistory";
// static const INSIGHTSHISTORY = "/insightshistory";
// static const DETAILSBUSSINESS = "/detailsbussiness";
// static const STOREMANAGEMENT = "/storemanagement";
// static const SETTING = "/settings";
// static const FORGETPASSWORD = "/forgetpassword";
// static const VERIFYPASSWORD = "/verifypassword";
// static const FORGETNEWPASSWORD = "/forgetnewpassword";
// static const UPDATESTORE = "/updatestore";
static const OTPSCREEN = "/otpscreen";
}
GoRoute animatedGoRoute({

View File

@@ -1,77 +1,4 @@
// // To parse this JSON data, do
// //
// // final productCategoryModel = productCategoryModelFromJson(jsondynamic);
// import 'dart:convert';
// List<ProductCategoryModel> productCategoryModelFromJson(dynamic str) => List<ProductCategoryModel>.from(json.decode(str).map((x) => ProductCategoryModel.fromJson(x)));
// dynamic productCategoryModelToJson(List<ProductCategoryModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
// class ProductCategoryModel
// {
// dynamic id;
// dynamic name;
// dynamic description;
// dynamic image;
// dynamic slug;
// dynamic level;
// bool? isActive;
// DateTime? createdAt;
// DateTime? updatedAt;
// dynamic parentCategoryId;
// dynamic path;
// dynamic parentCategory;
// List<ProductCategoryModel>? childCategories;
// ProductCategoryModel({
// this.id,
// this.name,
// this.description,
// this.image,
// this.slug,
// this.level,
// this.isActive,
// this.createdAt,
// this.updatedAt,
// this.parentCategoryId,
// this.path,
// this.parentCategory,
// this.childCategories,
// });
// factory ProductCategoryModel.fromJson(Map<dynamic, dynamic> json) => ProductCategoryModel(
// 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"],
// parentCategory: json["parentCategory"],
// childCategories: List<ProductCategoryModel>.from(json["childCategories"].map((x) => ProductCategoryModel.fromJson(x))),
// );
// 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,
// "parentCategory": parentCategory,
// "childCategories": List<dynamic>.from(childCategories!.map((x) => x.toJson())),
// };
// }
import 'dart:convert';

View File

@@ -0,0 +1,30 @@
// // models/product_category_model.dart
// class ProductCategoryModel {
// final String id;
// final String name;
// final String image;
// final int level;
// final List<ProductCategoryModel> childCategories;
// ProductCategoryModel({
// required this.id,
// required this.name,
// required this.image,
// required this.level,
// required this.childCategories,
// });
// factory ProductCategoryModel.fromJson(Map<String, dynamic> json) {
// return ProductCategoryModel(
// id: json['id'],
// name: json['name'],
// image: json['image'] ?? '',
// level: json['level'] ?? 1,
// childCategories: json['childCategories'] != null
// ? List<ProductCategoryModel>.from(
// json['childCategories'].map((x) => ProductCategoryModel.fromJson(x)))
// : [],
// );
// }
// }

View File

@@ -25,12 +25,6 @@ import 'package:http/http.dart' as http;
class ProductProvider extends ChangeNotifier {
final _homeRepo = getIt<ProductRepo>();
String searchValue = '';
bool isLoadingg = false;
@@ -45,8 +39,7 @@ class ProductProvider extends ChangeNotifier {
bool iscroll = true;
Future<void> gettAllProduct(BuildContext context, String id, bool status,
String search, bool first) async
{
String search, bool first) async {
print("kdjfhgkfkjdghkjkdfg");
// if (isLoadingg || !hasMore) return;
@@ -181,6 +174,7 @@ class ProductProvider extends ChangeNotifier {
},
);
}
int selectedImage = 0;
ProductDetailsData productDetails = ProductDetailsData();
@@ -289,13 +283,12 @@ class ProductProvider extends ChangeNotifier {
print("Error fetching categories: $error");
notifyListeners();
},
(categoryList)
{
(categoryList) {
if (categoryList.isNotEmpty) {
final categories = [ProductCategoryModel(id: "all", name: "ALL")];
categories.addAll(categoryList.cast<ProductCategoryModel>());
// final categories = [ProductCategoryModel(id: "all", name: "ALL")];
// categories.addAll(categoryList.cast<ProductCategoryModel>());
categoriesss = categories;
categoriesss = categoryList;
} else {
print("No categories found.");
}

View File

@@ -0,0 +1,638 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertoast/fluttertoast.dart';
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/ProductCategoryModel.dart';
import 'package:grocery_app/src/data/product_category.dart';
import 'package:grocery_app/src/logic/provider/home_provider.dart';
import 'package:grocery_app/src/ui/data_notfound.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/extensions/uicontext.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:provider/provider.dart';
class CtegoryProduct extends StatefulWidget {
String categoryId;
String name;
CtegoryProduct({super.key, required this.categoryId, required this.name});
@override
State<CtegoryProduct> createState() => _CtegoryProductState();
}
class _CtegoryProductState extends State<CtegoryProduct> {
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
final productProvider =
Provider.of<ProductProvider>(context, listen: false);
productProvider.page = 1;
// productProvider.gettAllProduct(context, "", true, '', true);
productProvider.gettAllProduct(
context, "/category/${widget.categoryId}", true, '', false);
// productProvider.getAllcategory(context);
// productProvider.getCategoryByLevel();
// productProvider.setActiveIndex(0);
});
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
final productProvider =
Provider.of<ProductProvider>(context, listen: false);
productProvider.gettAllProduct(context, "", false, '', false);
}
});
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
leading: Center(
child: SizedBox(
height: 20,
width: 20,
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: SvgPicture.asset(
APPASSETS.back,
height: 20,
width: 20,
)),
),
),
title: Text(
widget.name ?? "",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
),
),
actions: [],
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: productWidget(),
),
);
}
Widget productWidget() {
return Consumer<ProductProvider>(builder: (context, provider, child) {
if (provider.isLoadingg) {
return 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 Center(
child: DataNotFound(
imagePath: 'assets/images/cart.jpg',
message: "",
width: 220.w,
height: 250.h,
),
);
} else {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: LayoutBuilder(
builder: (context, constraints) {
final itemWidth = (constraints.maxWidth - 20) / 2;
final itemHeight = itemWidth * 1.4;
return GridView.builder(
controller: _scrollController,
itemCount:
provider.products.length + (provider.hasMore ? 1 : 0),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: itemWidth / itemHeight,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
if (index == provider.products.length) {
return SizedBox.shrink();
}
var product = provider.products[index];
return InkWell(
onTap: () {
context.push(
MyRoutes.PRODUCTDETAILS,
extra: {
"id": product.id,
"quantity": 1,
"price": product.discountPrice,
},
);
},
child: Container(
height: itemHeight,
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: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: itemWidth *
0.9, // Adjust height for image container
// width: itemWidth,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
),
child: Stack(
alignment: Alignment.center,
children: [
AppNetworkImage(
imageUrl: product
.productImages!.first.url ??
"https://5.imimg.com/data5/SELLER/Default/2024/2/385126988/OL/DA/VW/8627346/1l-fortune-sunflower-oil.jpg",
backGroundColor: Colors.transparent,
radius: 10,
boxFit: BoxFit.fill),
Positioned(
right: 1,
bottom: 0,
child: Container(
height: 35,
width: 35,
padding: EdgeInsets.symmetric(
horizontal: 1, vertical: 1),
decoration: BoxDecoration(
color: Colors.red,
borderRadius:
BorderRadius.circular(100),
),
child: Center(
child: Text(
"${calculateDiscountPercentage(double.parse(product.basePrice), double.parse(product!.discountPrice))}%\nOFF",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 10)),
),
),
)
],
),
),
const SizedBox(height: 5),
Text(
product.name ?? " ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
APPCOLOR.balck1A1A1A,
15,
)
.copyWith(fontWeight: FontWeight.bold),
),
const SizedBox(height: 2),
Text(
product.unit ?? " ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
13,
),
),
const SizedBox(height: 1),
Spacer(),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${product.discountPrice ?? " "}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customSemiBold(
Colors.black, 15),
),
const SizedBox(width: 5),
Text(
"${product.basePrice ?? " "}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
15,
)
.copyWith(
decoration:
TextDecoration.lineThrough,
),
),
],
),
Spacer(),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: () async {
print(
"Add to Cart Pressed for ${product.id}");
if (await SharedPrefUtils.getToken() !=
null) {
await provider.addToCart(
context, product.id!, 1);
} else {
context.push(MyRoutes.SIGNUP);
}
},
child: Container(
height:
MediaQuery.of(context).size.height *
0.038,
width: MediaQuery.of(context).size.width *
0.1,
decoration: BoxDecoration(
color: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: provider.isLoading[product.id] ??
false
? Padding(
padding:
const EdgeInsets.all(8.0),
child: Container(
height: 10,
width: 10,
child:
CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2),
),
)
: Text(
// provider.cartItems
// .contains(bestdealproduct.id)
// ? 'Added'
// :
'Add',
style: context.customRegular(
Colors.white, 12),
),
),
),
),
),
],
),
],
),
),
);
},
);
},
),
),
);
}
});
}
int calculateDiscountPercentage(double basePrice, double discountPrice) {
if (basePrice <= 0 || discountPrice <= 0 || discountPrice > basePrice) {
return 0;
}
double discountAmount = basePrice - discountPrice;
double discountPercentage = (discountAmount / basePrice) * 100;
return discountPercentage.round();
}
Widget filterCategory() {
final activeIndexProvider = Provider.of<ProductProvider>(context);
return Consumer<ProductProvider>(builder: (context, provider, child) {
if (provider.iscategroyloading) {
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 {
final categories = [DatumCategory(id: "all", name: "ALL")];
categories.addAll(provider.categoryList.cast<DatumCategory>());
return Container(
decoration: const BoxDecoration(color: Colors.white),
width: 70,
child: ListView.builder(
itemCount: categories.length,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
var category = categories[index];
return Padding(
padding: const EdgeInsets.only(bottom: 0),
child: InkWell(
onTap: () {
provider.iscroll = true;
provider.products.clear();
provider.isLoadingg = false;
provider.hasMore = true;
provider.page = 1;
provider.notifyListeners();
if (category.id == "all") {
provider.gettAllProduct(context, "", true, '', false);
} else {
provider.gettAllProduct(
context, "/category/${category.id}", true, '', false);
}
activeIndexProvider.setActiveIndex(index);
},
child: Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Container(
decoration: BoxDecoration(
color: activeIndexProvider.activeIndex == index
? Colors.greenAccent.withOpacity(0.3)
: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(5)),
child: Padding(
padding: const EdgeInsets.only(top: 0, bottom: 0),
child: SizedBox(
width: 70,
child: Column(
children: [
if (category.name == "ALL") ...{
if (provider.categoriesss.isNotEmpty)
PopupMenuButton<ProductCategoryModel>(
onSelected: (ProductCategoryModel value) {
activeIndexProvider.setActiveIndex(0);
if (value.id == "all") {
provider.iscroll = true;
provider.products.clear();
provider.isLoadingg = false;
provider.hasMore = true;
provider.page = 1;
provider.gettAllProduct(
context, "", true, '', false);
provider.getAllcategory(context);
} else {
provider.categoryList.clear();
provider.getSubcategory(
context, value.id);
}
provider.setSelectedCategory(value);
},
itemBuilder: (BuildContext context) =>
provider.categoriesss
.map(
(category) => PopupMenuItem(
value: category,
child: Text(category.name ??
"Unknown"),
),
)
.toList(),
child: Center(
child: Column(
children: [
const Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Text("All"),
Icon(Icons.arrow_drop_down)
],
),
CachedNetworkImage(
errorWidget:
(context, url, error) {
return Container(
height: 40,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius:
BorderRadius
.circular(10),
border: Border.all(
color: Colors
.transparent,
width: 1,
)),
child: Center(
child: Image.asset(
APPASSETS.placeHolder,
height: 50 * 0.4,
color: APPCOLOR.bgGrey,
)),
);
},
placeholder: (context, url) {
return Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius:
BorderRadius
.circular(10),
border: Border.all(
color:
APPCOLOR.bgGrey,
width: 1,
)),
child: const Center(
child:
CupertinoActivityIndicator(),
),
);
},
imageBuilder:
(context, cIMage) {
return Container(
// width: 60,
height: 70,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(
Radius.circular(5!),
),
image: DecorationImage(
fit: BoxFit.fill,
image: cIMage,
)),
);
},
imageUrl: provider
.selectedCategory
?.image ??
'https://i.pinimg.com/originals/a5/f3/5f/a5f35fb23e942809da3df91b23718e8d.png'),
],
),
)),
} else ...{
Column(
children: [
CachedNetworkImage(
errorWidget: (context, url, error) {
return Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius:
BorderRadius.circular(10),
border: Border.all(
color: Colors.transparent,
width: 1,
)),
child: Center(
child: Image.asset(
APPASSETS.placeHolder,
height: 50 * 0.4,
color: APPCOLOR.bgGrey,
)),
);
},
placeholder: (context, url) {
return Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius:
BorderRadius.circular(10),
border: Border.all(
color: APPCOLOR.bgGrey,
width: 1,
)),
child: const Center(
child:
CupertinoActivityIndicator(),
),
);
},
imageBuilder: (context, cIMage) {
return Container(
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(5!),
),
image: DecorationImage(
fit: BoxFit.fill,
image: cIMage,
)),
);
},
imageUrl: category.image),
SizedBox(
height: 5,
),
Container(
width: 50,
child: Text(
category.name,
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style:
activeIndexProvider.activeIndex ==
index
? context.customExtraBold(
APPCOLOR.balck1A1A1A, 9)
: context.customMedium(
APPCOLOR.balck1A1A1A, 10),
),
),
],
),
},
],
),
),
),
),
),
),
);
},
),
);
}
});
}
}

View File

@@ -2,21 +2,15 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:flutter_svg/svg.dart';
import 'package:gap/gap.dart';
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/ProductCategoryModel.dart';
import 'package:grocery_app/src/data/product_category.dart';
import 'package:grocery_app/src/logic/provider/home_provider.dart';
import 'package:grocery_app/src/ui/data_notfound.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/extensions/uicontext.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:provider/provider.dart';
class FruitVeggieDetail extends StatefulWidget {
@@ -38,7 +32,7 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
Provider.of<ProductProvider>(context, listen: false);
productProvider.page = 1;
productProvider.gettAllProduct(context, "", true, '', true);
// productProvider.gettAllProduct(context, "", true, '', true);
productProvider.getAllcategory(context);
productProvider.getCategoryByLevel();
@@ -46,22 +40,22 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
productProvider.setActiveIndex(0);
});
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
final productProvider =
Provider.of<ProductProvider>(context, listen: false);
// _scrollController.addListener(() {
// if (_scrollController.position.pixels ==
// _scrollController.position.maxScrollExtent) {
// final productProvider =
// Provider.of<ProductProvider>(context, listen: false);
productProvider.gettAllProduct(context, "", false, '', false);
}
});
// productProvider.gettAllProduct(context, "", false, '', false);
// }
// });
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
// @override
// void dispose() {
// _scrollController.dispose();
// super.dispose();
// }
@override
Widget build(BuildContext context) {
@@ -96,275 +90,73 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [filterCategory(), productWidget()],
children: [
filterCategory(),
Gap(10.w),
Expanded(child: expendablecategory()),
],
),
),
);
}
Widget productWidget() {
return Consumer<ProductProvider>(builder: (context, provider, child) {
if (provider.isLoadingg) {
return Padding(
padding: const EdgeInsets.only(left: 120),
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 Center(
child: Padding(
padding: const EdgeInsets.only(left: 40),
child: DataNotFound(
imagePath: 'assets/images/cart.jpg',
message: "",
width: 220.w,
height: 250.h,
),
),
);
} else {
Widget expendablecategory() {
return Consumer<ProductProvider>(
builder: (context, provider, child) {
if (provider.iscategroyloading) {
return const Center(child: CupertinoActivityIndicator());
}
return Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: LayoutBuilder(
builder: (context, constraints) {
final itemWidth = (constraints.maxWidth - 20) / 2;
final itemHeight = itemWidth * 1.7;
child: ListView.builder(
itemCount: provider.categoriesss.length,
itemBuilder: (context, index) {
final category = provider.categoriesss[index];
return GridView.builder(
controller: _scrollController,
itemCount:
provider.products.length + (provider.hasMore ? 1 : 0),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: itemWidth / itemHeight,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
if (index == provider.products.length) {
return SizedBox.shrink();
}
var product = provider.products[index];
return InkWell(
onTap: () {
context.push(
MyRoutes.PRODUCTDETAILS,
extra: {
"id": product.id,
"quantity": 1,
"price": product.discountPrice,
},
);
},
child: Container(
height: itemHeight,
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: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: itemWidth *
0.9, // Adjust height for image container
// width: itemWidth,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
),
child: Stack(
alignment: Alignment.center,
children: [
AppNetworkImage(
imageUrl: product
.productImages!.first.url ??
"https://5.imimg.com/data5/SELLER/Default/2024/2/385126988/OL/DA/VW/8627346/1l-fortune-sunflower-oil.jpg",
backGroundColor: Colors.transparent,
radius: 10,
boxFit: BoxFit.fill),
Positioned(
right: 1,
bottom: 0,
child: Container(
height: 35,
width: 35,
padding: EdgeInsets.symmetric(
horizontal: 1, vertical: 1),
decoration: BoxDecoration(
color: Colors.red,
borderRadius:
BorderRadius.circular(100),
),
child: Center(
child: Text(
"${calculateDiscountPercentage(double.parse(product.basePrice), double.parse(product!.discountPrice))}%\nOFF",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 10)),
),
),
)
],
),
),
const SizedBox(height: 5),
Text(
product.name ?? " ",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
APPCOLOR.balck1A1A1A,
15,
)
.copyWith(fontWeight: FontWeight.bold),
),
const SizedBox(height: 2),
Text(
product.unit ?? " ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
13,
),
),
const SizedBox(height: 1),
Spacer(),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${product.discountPrice ?? " "}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customSemiBold(
Colors.black, 15),
),
const SizedBox(width: 5),
Text(
"${product.basePrice ?? " "}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
15,
)
.copyWith(
decoration:
TextDecoration.lineThrough,
),
),
],
),
Spacer(),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: () async {
print(
"Add to Cart Pressed for ${product.id}");
print("kdfjgkjhghk ${category.name}");
if (await SharedPrefUtils.getToken() !=
null) {
await provider.addToCart(
context, product.id!, 1);
} else {
context.push(MyRoutes.SIGNUP);
}
},
child: Container(
height:
MediaQuery.of(context).size.height *
0.038,
width: MediaQuery.of(context).size.width *
0.1,
decoration: BoxDecoration(
color: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: provider.isLoading[product.id] ??
false
? Padding(
padding:
const EdgeInsets.all(8.0),
child: Container(
height: 10,
width: 10,
child:
CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2),
),
)
: Text(
// provider.cartItems
// .contains(bestdealproduct.id)
// ? 'Added'
// :
'Add',
style: context.customRegular(
Colors.white, 12),
),
),
),
),
),
],
),
],
),
),
);
},
);
},
),
return _buildExpandableTile(category);
},
),
);
}
});
},
);
}
int calculateDiscountPercentage(double basePrice, double discountPrice) {
if (basePrice <= 0 || discountPrice <= 0 || discountPrice > basePrice) {
return 0;
Widget _buildExpandableTile(ProductCategoryModel category) {
if (category.childCategories!.isEmpty) {
return ListTile(
leading: CachedNetworkImage(
imageUrl: category.image!,
width: 40,
height: 40,
errorWidget: (context, url, error) => const Icon(Icons.error),
),
title: Text(category.name!),
onTap: () {
context.push(MyRoutes.CATEGORYPRODUCT,
extra: {"id":category.id,"name": category.name});
},
);
}
double discountAmount = basePrice - discountPrice;
double discountPercentage = (discountAmount / basePrice) * 100;
return discountPercentage.round();
return Theme(
data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
child: Card(
color: Colors.grey.shade100,
child: ExpansionTile(
leading: CachedNetworkImage(
imageUrl: category.image!,
width: 40,
height: 40,
errorWidget: (context, url, error) => const Icon(Icons.error),
),
title: Text(category.name!),
children:
category.childCategories!.map(_buildExpandableTile).toList(),
),
),
);
}
Widget filterCategory() {
@@ -389,35 +181,39 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
),
);
} else {
final categories = [DatumCategory(id: "all", name: "ALL")];
categories.addAll(provider.categoryList.cast<DatumCategory>());
// final categories = [DatumCategory(id: "all", name: "ALL")];
// categories.addAll(provider.categoryList.cast<DatumCategory>());
return Container(
decoration: const BoxDecoration(color: Colors.white),
width: 70,
child: ListView.builder(
itemCount: categories.length,
physics: BouncingScrollPhysics(),
itemCount: provider.categoryList.length,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
var category = categories[index];
var category = provider.categoryList[index];
return Padding(
padding: const EdgeInsets.only(bottom: 0),
child: InkWell(
onTap: () {
provider.iscroll = true;
provider.products.clear();
provider.isLoadingg = false;
provider.hasMore = true;
provider.page = 1;
provider.notifyListeners();
context.push(MyRoutes.CATEGORYPRODUCT,
extra: {"id":category.id,"name": category.name});
// provider.iscroll = true;
// provider.products.clear();
// provider.isLoadingg = false;
// provider.hasMore = true;
// provider.page = 1;
// provider.notifyListeners();
if (category.id == "all") {
provider.gettAllProduct(context, "", true, '', false);
} else {
provider.gettAllProduct(
context, "/category/${category.id}", true, '', false);
}
// if (category.id == "all")
// {
// provider.gettAllProduct(context, "", true, '', false);
// } else
// {
// provider.gettAllProduct( context, "/category/${category.id}", true, '', false);
// }
activeIndexProvider.setActiveIndex(index);
},