pagination

This commit is contained in:
2025-02-14 18:52:46 +05:30
parent 9874c094a9
commit e3b601ee7d
9 changed files with 504 additions and 191 deletions

View File

@@ -992,7 +992,7 @@
"languageVersion": "3.4"
}
],
"generated": "2025-02-13T11:54:46.039722Z",
"generated": "2025-02-14T13:22:19.642868Z",
"generator": "pub",
"generatorVersion": "3.4.4",
"flutterRoot": "file:///Users/rajeevsingh/Documents/allSoftwares/flutter",

File diff suppressed because one or more lines are too long

View File

@@ -30,9 +30,6 @@ class APIURL {
static const String myOrder = "${BASE_URL}orders/my-orders";
static const String offerCoupon = "${BASE_URL}coupons";
static const String applyCoupon = "${BASE_URL}coupons/validate";
static const String forgetPassword = "${BASE_URL}auth/forgot-password/vendor";
static const String verifyForgetPassword =
"${BASE_URL}auth/forgot-password-verify-otp/vendor";

View File

@@ -29,8 +29,10 @@ class DioClient {
CancelToken? cancelToken,
ProgressCallback? onReceiveProgress,
bool hideSoftKeyboard = true,
required data}) async {
if (hideSoftKeyboard) {
required data}) async
{
if (hideSoftKeyboard)
{
// hideKeyBoard();
}
@@ -41,7 +43,8 @@ class DioClient {
url,
queryParameters: queryParameters,
options: options ??
Options(headers: {
Options(headers:
{
"authorization": "Bearer ${await SharedPrefUtils.getToken()}"
}),
cancelToken: cancelToken,

View File

@@ -16,15 +16,41 @@ import 'package:grocery_app/utils/extensions/extensions.dart';
class ProductProvider extends ChangeNotifier {
final _homeRepo = getIt<ProductRepo>();
bool isLoadingg = true;
String searchValue = '';
bool isLoadingg = false;
List<Product> products = [];
Future<void> gettAllProduct(BuildContext context, String id) async {
var data = {};
int page = 1;
final int limit = 8;
print("skdjhfgkf ${id}");
bool hasMore = true;
bool iscroll = true;
Future<void> gettAllProduct(
BuildContext context, String id, bool status, String search) async {
if (isLoadingg || !hasMore) return;
print("kjldfgjklfjkdgjkhlfg");
if (id.isNotEmpty) {
products.clear();
hasMore = true;
}
if (status) {
isLoadingg = true;
}
;
notifyListeners();
var data = {
"page": page,
"limit": limit,
"minPrice": "",
"minPrice": "",
"search": search
};
var result = await _homeRepo.getAllProduct(data, context, id);
return result.fold(
(error) {
@@ -32,13 +58,66 @@ class ProductProvider extends ChangeNotifier {
notifyListeners();
},
(response) {
products = response.data!;
// products = response.data!;
// page++;
// print(
// "jksdhfgkjdfkhjghkjdfhgkjdf ${response.data} ${response.data!.isNotEmpty}");
// if (response.data != null && response.data!.isNotEmpty) {
// products.addAll(response.data!);
// // products = response.data!;
// page++;
// } else {
// hasMore = false;
// }
if (response.data != null && response.data!.isNotEmpty) {
if (id.isNotEmpty) {
products = response.data!;
} else {
products.addAll(response.data!);
}
page++;
if (response.data!.length < limit) {
hasMore = false;
}
} else {
hasMore = false;
}
isLoadingg = false;
notifyListeners();
},
);
}
bool isHomeLoadingg = false;
List<Product> homeproducts = [];
Future<void> getHomeProduct(BuildContext context,String id, String search) async
{
isHomeLoadingg = true;
notifyListeners();
var data = {"minPrice": "", "minPrice": "", "search": search};
var result = await _homeRepo.getAllProduct(data, context,id);
return result.fold(
(error) {
isLoadingg = false;
notifyListeners();
},
(response)
{
homeproducts = response.data!;
isHomeLoadingg = false;
notifyListeners();
},
);
}
ProductDetailsData productDetails = ProductDetailsData();
bool isProductLoading = true;
@@ -68,11 +147,11 @@ class ProductProvider extends ChangeNotifier {
bool isBestdealingloading = true;
Future<void> getBestDealProduct(BuildContext context) async {
isBestdealingloading = true;
notifyListeners();
var data = {};
Future<void> getBestDealProduct(BuildContext context,String search) async
{
isBestdealingloading = true;
notifyListeners();
var data = {"minPrice": "", "minPrice": "", "search": search};
var result = await _homeRepo.getBestDealProduct(data, context);
return result.fold(
(error) {
@@ -87,6 +166,9 @@ class ProductProvider extends ChangeNotifier {
);
}
List<Datum> categoryList = [];
bool iscategroyloading = true;
@@ -396,8 +478,7 @@ class ProductProvider extends ChangeNotifier {
notifyListeners(); // Update UI after adding to cart
},
);
} catch (e)
{
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Product already added"),
@@ -584,5 +665,14 @@ class ProductProvider extends ChangeNotifier {
);
}
///////////////////////////////////////////////////// all carts////////////////////////
///////////////////////////////////////////////////// all filter ////////////////////////
int _selectedIndex = 0;
int get selectedIndex => _selectedIndex;
void setSelectedIndex(BuildContext context, int index) {
_selectedIndex = index;
notifyListeners();
}
}

View File

@@ -23,7 +23,8 @@ class ProductService extends ApiService {
var response;
if (id.isEmpty) {
response = await api.get(APIURL.getAllProduct, data: jsonEncode(data));
response = await api.get(APIURL.getAllProduct,
queryParameters: data, data: data);
} else {
response =
await api.get(APIURL.getAllProduct + id, data: jsonEncode(data));
@@ -42,8 +43,8 @@ class ProductService extends ApiService {
//
Future getBestDealProduct(data) async {
var response =
await api.get(APIURL.getBestDealProduct, data: jsonEncode(data));
var response = await api.get(APIURL.getBestDealProduct,
queryParameters: data, data: jsonEncode(data));
return response;
}
@@ -80,23 +81,19 @@ class ProductService extends ApiService {
return response;
}
Future offerCoupon(data) async {
Future offerCoupon(data) async {
var response = await api.get(APIURL.offerCoupon, data: jsonEncode(data));
return response;
}
Future applyCoupon(data) async {
Future applyCoupon(data) async {
var response = await api.post(APIURL.applyCoupon, data: jsonEncode(data));
return response;
}
Future checkPin(data, pin) async {
var response = await api.get(APIURL.checkPin + pin, data: jsonEncode(data));

View File

@@ -14,6 +14,7 @@ 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';
import 'package:shimmer/shimmer.dart';
class BestDealScreen extends StatefulWidget {
const BestDealScreen({super.key});
@@ -23,10 +24,12 @@ class BestDealScreen extends StatefulWidget {
}
class _BestDealScreenState extends State<BestDealScreen> {
bool _isSearching = false;
TextEditingController _searchController = TextEditingController();
@override
void initState() {
Provider.of<ProductProvider>(context, listen: false)
.getBestDealProduct(context);
.getBestDealProduct(context, '');
super.initState();
}
@@ -56,31 +59,69 @@ class _BestDealScreenState extends State<BestDealScreen> {
height: 20,
width: 20,
child: InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: SvgPicture.asset(
APPASSETS.back,
height: 20,
width: 20,
)),
),
),
title: const Text(
"Best Deal",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
),
),
actions: [
InkWell(
onTap: () {},
child: Icon(
MdiIcons.magnify,
size: 35,
onTap: () {
Navigator.of(context).pop();
},
child: SvgPicture.asset(
APPASSETS.back,
height: 20,
width: 20,
),
),
)
),
),
title: _isSearching
? TextField(
controller: _searchController,
autofocus: true, // Focus on search field when opened
decoration: InputDecoration(
hintText: "Search...",
border: InputBorder.none,
),
style: TextStyle(fontSize: 18),
onChanged: (query) {
// You can call a search function here
},
)
: const Text(
"Best Deal",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
),
),
actions: [
if (_isSearching) // Show search icon only when searching
InkWell(
onTap: () {
Provider.of<ProductProvider>(context, listen: false)
.getBestDealProduct(context, _searchController.text);
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Icon(
MdiIcons.magnify,
size: 35,
),
),
),
InkWell(
onTap: () {
setState(() {
_isSearching = !_isSearching;
if (!_isSearching) {
_searchController.clear(); // Clear search when closed
}
});
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Icon(
_isSearching ? Icons.close : MdiIcons.magnify,
size: 35,
),
),
),
],
),
floatingActionButton: floatingAction(),
@@ -180,11 +221,68 @@ class _BestDealScreenState extends State<BestDealScreen> {
Widget itemBestdeal() {
return Consumer<ProductProvider>(builder: (context, provider, child) {
if (provider.isBestdealingloading) {
return Center(child: CircularProgressIndicator());
return Padding(
padding: const EdgeInsets.all(15),
child: GridView.builder(
itemCount: 6, // Number of shimmer items
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.5),
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
return Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
child: Padding(
padding: const EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: MediaQuery.of(context).size.height * 0.15,
width: MediaQuery.of(context).size.width * 0.4,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius: BorderRadius.circular(15),
),
),
SizedBox(height: 8),
Container(
height: 10,
width: MediaQuery.of(context).size.width * 0.35,
color: Colors.grey[300],
),
SizedBox(height: 5),
Container(
height: 10,
width: MediaQuery.of(context).size.width * 0.25,
color: Colors.grey[300],
),
SizedBox(height: 10),
Container(
height: 15,
width: MediaQuery.of(context).size.width * 0.3,
color: Colors.grey[300],
),
],
),
),
),
);
},
),
);
} else if (provider.bestdeal.isEmpty) {
return Center(child: Text('No products available'));
} else {
print("kjhfgjkdfkjghdhjfgk ${provider.bestdeal.first.additionalInfo}");
return Padding(
padding: const EdgeInsets.all(15),
child: GridView.builder(
@@ -380,6 +478,75 @@ class _BestDealScreenState extends State<BestDealScreen> {
},
),
);
// Padding(
// padding: const EdgeInsets.all(15),
// child: GridView.builder(
// itemCount: provider.bestdeal.length,
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 2,
// childAspectRatio: MediaQuery.of(context).size.width /
// (MediaQuery.of(context).size.height / 1.5),
// crossAxisSpacing: 10,
// mainAxisSpacing: 10,
// ),
// itemBuilder: (context, index) {
// var bestdealproduct = provider.bestdeal[index];
// return InkWell(
// onTap: () {
// context.push(MyRoutes.PRODUCTDETAILS,
// extra: bestdealproduct.id);
// },
// child: Container(
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(15),
// ),
// child: Padding(
// padding: const EdgeInsets.all(5),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Container(
// height: MediaQuery.of(context).size.height * 0.15,
// width: MediaQuery.of(context).size.width * 0.4,
// decoration: BoxDecoration(
// color: APPCOLOR.bgGrey,
// borderRadius: BorderRadius.circular(15),
// ),
// child: AppNetworkImage(
// height: MediaQuery.of(context).size.height * 0.13,
// width: MediaQuery.of(context).size.width * 0.35,
// imageUrl:
// bestdealproduct.productImages?.first.url ?? "",
// backGroundColor: Colors.transparent,
// ),
// ),
// SizedBox(height: 8),
// Text(bestdealproduct.name ?? ""),
// Text(bestdealproduct.unit ?? ""),
// Text(bestdealproduct.quantity > 0
// ? "In Stock"
// : "Out of Stock"),
// Row(
// children: [
// Text("₹${bestdealproduct.discountPrice ?? ""}"),
// Text(
// "₹${bestdealproduct.basePrice ?? ""}",
// style: TextStyle(
// decoration: TextDecoration.lineThrough,
// ),
// ),
// ],
// ),
// ],
// ),
// ),
// ),
// );
// },
// ),
// );
}
});
}

View File

@@ -21,14 +21,36 @@ class FruitVeggieDetail extends StatefulWidget {
}
class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
final ScrollController _scrollController = ScrollController();
@override
void initState() {
Provider.of<ProductProvider>(context, listen: false)
.getAllcategory(context);
// Ensuring the context is available before accessing the provider
WidgetsBinding.instance.addPostFrameCallback((_) {
final productProvider =
Provider.of<ProductProvider>(context, listen: false);
productProvider.getAllcategory(context);
productProvider.gettAllProduct(context, "", true, '');
});
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
final productProvider =
Provider.of<ProductProvider>(context, listen: false);
productProvider.gettAllProduct(context, "", false, '');
}
});
super.initState();
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -41,8 +63,6 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
width: 20,
child: InkWell(
onTap: () {
Provider.of<ProductProvider>(context, listen: false)
.gettAllProduct(context, "");
Navigator.of(context).pop();
},
child: SvgPicture.asset(
@@ -60,16 +80,16 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
),
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 10),
child: InkWell(
onTap: () {},
child: Icon(
MdiIcons.magnify,
size: 35,
),
),
)
// Padding(
// padding: const EdgeInsets.only(right: 10),
// child: InkWell(
// onTap: () {},
// child: Icon(
// MdiIcons.magnify,
// size: 35,
// ),
// ),
// )
],
),
body: Row(
@@ -114,7 +134,11 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
final itemHeight = itemWidth * 1.5;
return GridView.builder(
itemCount: provider.products.length,
controller: _scrollController,
// itemCount: provider.products.length,
itemCount:
provider.products.length + (provider.hasMore ? 1 : 0),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: itemWidth / itemHeight,
@@ -122,8 +146,30 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
if (index == provider.products.length) {
return SizedBox.shrink();
// return Center(
// child: 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(),
// ),
// )),
// )
// ); // Show loader when fetching more data
}
var product = provider.products[index];
return InkWell(
onTap: () {
context.push(MyRoutes.PRODUCTDETAILS,
@@ -425,9 +471,20 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
var category = provider.categoryList[index];
return InkWell(
onTap: () {
provider.isLoadingg = true;
provider.gettAllProduct(context, "/category/${category.id}");
provider.iscroll = true;
provider.products.clear(); // Clear existing products
provider.isLoadingg = false;
provider.hasMore = true;
provider.page = 1; // Reset page for new category
provider
.notifyListeners(); // Notify listeners before fetching data
provider.gettAllProduct(
context, "/category/${category.id}", true, '');
activeIndexProvider.setActiveIndex(index);
// provider.isLoadingg = false;
// provider.hasMore = false;
// provider.gettAllProduct(context, "/category/${category.id}");
// activeIndexProvider.setActiveIndex(index);
},
child: SizedBox(
height: 150,

View File

@@ -30,21 +30,22 @@ class _HomeScreenState extends State<HomeScreen> {
void initState() {
super.initState();
Provider.of<ProductProvider>(context, listen: false).getBanners(context);
Provider.of<ProductProvider>(context, listen: false)
.gettAllProduct(context, "");
Provider.of<ProductProvider>(context, listen: false)
.getBestDealProduct(context);
Provider.of<ProductProvider>(context, listen: false)
.getAllcategory(context);
getUserDetails();
WidgetsBinding.instance.addPostFrameCallback((_) {
final productProvider =
Provider.of<ProductProvider>(context, listen: false);
productProvider.getBanners(context);
productProvider.getHomeProduct(context, "", '');
productProvider.getBestDealProduct(context,'');
productProvider.getAllcategory(context);
getUserDetails();
});
}
getUserDetails() async {
APPSTRING.userName = (await SharedPrefUtils.getFirstName())!;
print("kdjfkgjhdkfgj ${await SharedPrefUtils.getFirstName()}");
APPSTRING.emailName = (await SharedPrefUtils.getUserEmail())!;
APPSTRING.userProfile = (await SharedPrefUtils.getUserProfile())!;
APPSTRING.userLastName = (await SharedPrefUtils.getLastName())!;
@@ -67,42 +68,58 @@ class _HomeScreenState extends State<HomeScreen> {
),
Row(
children: [
Expanded(
child: Container(
height: 50,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
decoration: InputDecoration(
border: InputBorder.none,
fillColor: Colors.transparent,
prefixIcon: Icon(MdiIcons.magnify),
hintText: 'Search',
hintStyle:
context.customRegular(APPCOLOR.grey666666, 18),
isCollapsed: true,
contentPadding: const EdgeInsets.symmetric(
vertical: 10, horizontal: 10),
Consumer<ProductProvider>(
builder: (context, provider, child) {
return Expanded(
child: Container(
height: 50,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
onChanged: (value) {
provider.searchValue = value;
},
decoration: InputDecoration(
border: InputBorder.none,
fillColor: Colors.transparent,
suffixIcon: InkWell(
onTap: () {
provider.getHomeProduct(
context, "", provider.searchValue);
},
child: Icon(MdiIcons.magnify)),
hintText: 'Search',
hintStyle: context.customRegular(
APPCOLOR.grey666666, 18),
isCollapsed: true,
contentPadding: const EdgeInsets.symmetric(
vertical: 10, horizontal: 10),
),
),
),
),
),
);
}),
const SizedBox(
width: 10,
),
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: Icon(
MdiIcons.tuneVariant,
color: Colors.white,
InkWell(
onTap: () {
showSortBottomSheet(context);
},
child: Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: Icon(
MdiIcons.tuneVariant,
color: Colors.white,
),
),
),
),
@@ -594,11 +611,6 @@ class _HomeScreenState extends State<HomeScreen> {
});
}
// Future<void> _launchUrl(url) async {
// if (!await launchUrl(url)) {
// throw Exception('Could not launch $url');
// }
// }
Future<void> _launchUrl(url) async {
print("jdhfjkgh ${url}");
final Uri uri = Uri.parse(url);
@@ -607,71 +619,9 @@ class _HomeScreenState extends State<HomeScreen> {
}
}
// Widget categoriesProduct() {
// return Consumer<ProductProvider>(builder: (context, provider, child) {
// if (provider.isLoadingg) {
// return Center(child: CircularProgressIndicator());
// } else if (provider.products.isEmpty) {
// return Center(child: Text('No products available'));
// } else {
// return GridView.builder(
// shrinkWrap: true,
// itemCount: provider.products.length,
// physics: const NeverScrollableScrollPhysics(),
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 4,
// crossAxisSpacing: 5,
// mainAxisSpacing: 5,
// childAspectRatio: MediaQuery.of(context).size.width /
// (MediaQuery.of(context).size.height / 1.2),
// ),
// itemBuilder: (context, index) {
// var product = provider.products[index];
// return InkWell(
// onTap: () {
// context.push(MyRoutes.PRODUCTDETAILS, extra: product.id);
// },
// child: SizedBox(
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Container(
// decoration: BoxDecoration(
// color: APPCOLOR.bgGrey,
// borderRadius: BorderRadius.circular(5),
// ),
// child: AppNetworkImage(
// height: 80,
// width: 80,
// imageUrl: product.productImages!.first.url,
// //'https://i.pinimg.com/originals/a5/f3/5f/a5f35fb23e942809da3df91b23718e8d.png',
// backGroundColor: APPCOLOR.bgGrey,
// radius: 10,
// ),
// ),
// const SizedBox(
// height: 10,
// ),
// Text(
// product.name ?? "",
// textAlign: TextAlign.center,
// maxLines: 2,
// overflow: TextOverflow.ellipsis,
// style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
// )
// ],
// ),
// ),
// );
// },
// );
// }
// });
// }
Widget categoriesProduct() {
return Consumer<ProductProvider>(builder: (context, provider, child) {
return provider.isLoadingg
return provider.isHomeLoadingg
? GridView.builder(
shrinkWrap: true,
itemCount: 8,
@@ -685,7 +635,7 @@ class _HomeScreenState extends State<HomeScreen> {
),
itemBuilder: (context, index) {
return Skeletonizer(
enabled: provider.isLoadingg,
enabled: provider.isHomeLoadingg,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
@@ -708,11 +658,11 @@ class _HomeScreenState extends State<HomeScreen> {
);
},
)
: provider.products.isEmpty
: provider.homeproducts.isEmpty
? Center(child: Text('No products available'))
: GridView.builder(
shrinkWrap: true,
itemCount: provider.products.length,
itemCount: provider.homeproducts.length,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
@@ -722,7 +672,7 @@ class _HomeScreenState extends State<HomeScreen> {
(MediaQuery.of(context).size.height / 1.2),
),
itemBuilder: (context, index) {
var product = provider.products[index];
var product = provider.homeproducts[index];
return InkWell(
onTap: () {
context.push(MyRoutes.PRODUCTDETAILS,
@@ -762,4 +712,56 @@ class _HomeScreenState extends State<HomeScreen> {
);
});
}
void showSortBottomSheet(BuildContext context) {
showModalBottomSheet(
context: context,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(50)),
),
builder: (context) {
return Consumer<ProductProvider>(
builder: (context, sortProvider, child) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Sort By",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
Divider(
thickness: 0.2,
),
_buildSortOption(context, sortProvider, 0, "Relevance"),
_buildSortOption(context, sortProvider, 1, "Popularity"),
_buildSortOption(
context, sortProvider, 2, "Price: Low to High"),
],
),
);
},
);
},
);
}
Widget _buildSortOption(
BuildContext context, ProductProvider provider, int index, String title) {
bool isSelected = provider.selectedIndex == index;
return ListTile(
title: Text(title),
trailing: isSelected
? Icon(Icons.check_circle, color: Colors.green)
: Icon(Icons.radio_button_unchecked, color: Colors.grey),
onTap: () {
provider.getHomeProduct(context, '', '');
provider.setSelectedIndex(context, index);
Navigator.pop(context); // Close the bottom sheet
},
);
}
}