productdetails

This commit is contained in:
2025-01-31 19:02:20 +05:30
parent 028155a1d7
commit 42aaa7cdad
32 changed files with 2803 additions and 1987 deletions

View File

@@ -1,9 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/flutter_svg.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/all_cart_items.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';
@@ -58,7 +61,16 @@ class _BestDealScreenState extends State<BestDealScreen> {
)
],
),
floatingActionButton: Padding(
floatingActionButton: floatingAction(),
body: itemBestdeal());
}
Widget floatingAction() {
return Consumer<ProductProvider>(builder: (context, provider, child) {
if (provider.countList.isEmpty) {
return Center();
} else {
return Padding(
padding: const EdgeInsets.only(left: 30),
child: Container(
height: 80,
@@ -106,34 +118,41 @@ class _BestDealScreenState extends State<BestDealScreen> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'2 Items',
provider.countList.length.toString(),
style: context.customRegular(Colors.white, 18),
),
Text(
'\$25',
style: context.customExtraBold(Colors.white, 20),
)
],
),
const Spacer(),
Text(
'View Cart',
style: context.customMedium(Colors.white, 24),
),
const SizedBox(
width: 10,
),
const Icon(
Icons.arrow_forward,
color: Colors.white,
size: 35,
),
InkWell(
onTap: () {
context.read<BottomNavProvider>().setIndex(2);
Navigator.pop(context);
},
child: Row(
children: [
Text(
'View Cart',
style: context.customMedium(Colors.white, 24),
),
const SizedBox(
width: 10,
),
const Icon(
Icons.arrow_forward,
color: Colors.white,
size: 35,
),
],
),
)
],
),
),
),
),
body: itemBestdeal());
);
}
});
}
Widget itemBestdeal() {
@@ -156,182 +175,183 @@ class _BestDealScreenState extends State<BestDealScreen> {
),
itemBuilder: (context, index) {
var bestdealproduct = provider.bestdeal[index];
return Container(
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: MediaQuery.of(context).size.height *
0.15, // Dynamic height
width: MediaQuery.of(context).size.width *
0.4, // Dynamic width
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
),
child: Stack(
alignment: Alignment.center,
children: [
Center(
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,
return InkWell(
onTap: () {
context.push(MyRoutes.PRODUCTDETAILS,
extra: bestdealproduct.id);
},
child: Container(
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: MediaQuery.of(context).size.height *
0.15, // Dynamic height
width: MediaQuery.of(context).size.width *
0.4, // Dynamic width
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
),
child: Stack(
alignment: Alignment.center,
children: [
Center(
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,
),
),
// Positioned(
// right: 5,
// top: 5,
// child: InkWell(
// onTap: () async {
// if (await SharedPrefUtils.getToken() !=
// null) {
// provider.toggleWishlist(
// context, bestdealproduct.id!);
// } else {
// context.push(MyRoutes.LOGIN);
// }
// },
// child: Icon(
// provider.wishlist
// .contains(bestdealproduct.id)
// ? Icons.favorite
// : Icons.favorite_border,
// color: provider.wishlist
// .contains(bestdealproduct.id)
// ? Colors.red
// : Colors.grey,
// ),
// ),
// ),
],
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005),
Text(
bestdealproduct.name ?? "",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: context.customMedium(APPCOLOR.balck1A1A1A, 16),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005),
Text(
bestdealproduct.unit ?? "",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
12,
),
),
Spacer(),
Row(
children: [
Row(
children: [
Text(
"\$${bestdealproduct.discountPrice ?? ""} ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style:
context.customSemiBold(Colors.black, 12),
),
Text(
"\$${bestdealproduct.basePrice ?? ""}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
12,
)
.copyWith(
decoration: TextDecoration.lineThrough,
),
),
],
),
Positioned(
right: 5,
top: 5,
child: InkWell(
Spacer(),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: () async {
if (await SharedPrefUtils.getToken() !=
null) {
provider.toggleWishlist(
context, bestdealproduct.id!);
await provider.addToWithCart(context,
bestdealproduct.id!, bestdealproduct);
} else {
context.push(MyRoutes.LOGIN);
context.push(MyRoutes.SIGNUP);
}
},
child: Icon(
provider.wishlist.contains(bestdealproduct.id)
? Icons.favorite
: Icons.favorite_border,
color: provider.wishlist
.contains(bestdealproduct.id)
? Colors.red
: Colors.grey,
child: Container(
height: MediaQuery.of(context).size.height *
0.035,
width:
MediaQuery.of(context).size.width * 0.1,
decoration: BoxDecoration(
color: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: provider.isLoading[
bestdealproduct.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),
),
),
),
),
),
],
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005),
Text(
bestdealproduct.name ?? "",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: context.customMedium(APPCOLOR.balck1A1A1A, 16),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005),
Text(
bestdealproduct.unit ?? "",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
12,
),
),
Spacer(),
Row(
children: [
Row(
children: [
Text(
"\$${bestdealproduct.discountPrice ?? ""} ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customSemiBold(Colors.black, 12),
),
Text(
"\$${bestdealproduct.basePrice ?? ""}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
12,
)
.copyWith(
decoration: TextDecoration.lineThrough,
),
),
],
),
Spacer(),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: () async {
print(
"Add to Cart Pressed for ${bestdealproduct.id}");
if (await SharedPrefUtils.getToken() != null) {
// if (!(provider
// .isLoading[bestdealproduct.id] ??
// false))
// {
await provider.addToCart(
context, bestdealproduct.id!);
// }
} else {
context.push(MyRoutes.LOGIN);
}
},
child: Container(
height:
MediaQuery.of(context).size.height * 0.035,
width: MediaQuery.of(context).size.width * 0.1,
decoration: BoxDecoration(
color: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: provider
.isLoading[bestdealproduct.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),
),
),
),
),
),
],
),
],
],
),
),
),
);

View File

@@ -2,12 +2,14 @@
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/ui/cart/cartview_screen.dart';
import 'package:grocery_app/src/ui/favourite/favourite_screen.dart';
import 'package:grocery_app/src/ui/header.dart';
import 'package:grocery_app/src/ui/home/home_screen.dart';
import 'package:grocery_app/src/ui/profilepage/profile_screen.dart';
import 'package:grocery_app/utils/constants/color_constant.dart';
import 'package:provider/provider.dart';
class BottomBarWidget extends StatefulWidget {
const BottomBarWidget({super.key});
@@ -69,10 +71,11 @@ class _BottomBarState extends State<BottomBarWidget> {
@override
Widget build(BuildContext context) {
SizeConfig().init(context);
final bottomNavProvider = Provider.of<BottomNavProvider>(context);
return Scaffold(
body: PageView(
controller: bottomWidgetPageController,
controller: bottomNavProvider.pageController,
physics: const NeverScrollableScrollPhysics(),
children: <Widget>[
HomeScreen(),
@@ -89,7 +92,10 @@ class _BottomBarState extends State<BottomBarWidget> {
duration: const Duration(milliseconds: 300),
curve: Curves.decelerate,
top: 0,
left: (_currentIndex * MediaQuery.sizeOf(context).width / 4) + 42,
left: (bottomNavProvider.currentIndex *
MediaQuery.sizeOf(context).width /
4) +
42,
child: Column(
children: [
ClipPath(
@@ -119,26 +125,26 @@ class _BottomBarState extends State<BottomBarWidget> {
BottomNavButton(
icon: Icons.home,
index: 0,
currentIndex: _currentIndex,
onPressed: _onNavButtonTapped,
currentIndex: bottomNavProvider.currentIndex,
onPressed: bottomNavProvider.setIndex,
),
BottomNavButton(
icon: Icons.favorite,
index: 1,
currentIndex: _currentIndex,
onPressed: _onNavButtonTapped,
currentIndex: bottomNavProvider.currentIndex,
onPressed: bottomNavProvider.setIndex,
),
BottomNavButton(
icon: Icons.shopping_bag,
index: 2,
currentIndex: _currentIndex,
onPressed: _onNavButtonTapped,
currentIndex: bottomNavProvider.currentIndex,
onPressed: bottomNavProvider.setIndex,
),
BottomNavButton(
icon: Icons.person,
index: 3,
currentIndex: _currentIndex,
onPressed: _onNavButtonTapped,
currentIndex: bottomNavProvider.currentIndex,
onPressed: bottomNavProvider.setIndex,
),
],
),

View File

@@ -1,99 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/svg.dart';
import 'package:grocery_app/src/common_widget/network_image.dart';
import 'package:grocery_app/src/ui/widgets/custom_icon_button.dart';
import 'package:grocery_app/utils/constants/assets_constant.dart';
import 'package:grocery_app/utils/constants/color_constant.dart';
import 'package:grocery_app/utils/extensions/uicontext.dart';
class CartItem extends StatelessWidget {
// final ProductModel product;
const CartItem({
Key? key,
// required this.product,
}) : super(key: key);
@override
Widget build(BuildContext context)
{
return
Padding(
padding: EdgeInsets.symmetric(horizontal: 24.w),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
color: Colors.greenAccent.withOpacity(0.1),
borderRadius: BorderRadius.circular(5),
),
child: AppNetworkImage(
width: 50.w,
height: 40.h,
imageUrl:
'https://i.pinimg.com/originals/a5/f3/5f/a5f35fb23e942809da3df91b23718e8d.png',
backGroundColor: APPCOLOR.bgGrey,
radius: 10,
),
),
// Image.asset(product.image, width: 50.w, height: 40.h),
16.horizontalSpace,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Vegitables and Fruits",
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
5.verticalSpace,
Text(
'1kg, 10\$',
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
],
),
const Spacer(),
Row(
children: [
CustomIconButton(
width: 20.w,
height: 20.h,
onPressed: () {},
icon: SvgPicture.asset(
APPASSETS.removeIcon,
fit: BoxFit.none,
),
backgroundColor: APPCOLOR.appGreen,
),
16.horizontalSpace,
Text(
"10",
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
16.horizontalSpace,
CustomIconButton(
width: 20.w,
height: 20.h,
onPressed: () {},
icon: SvgPicture.asset(
APPASSETS.addIcon,
fit: BoxFit.none,
),
backgroundColor: APPCOLOR.appGreen,
),
],
)
],
),
);
}
}

View File

@@ -9,7 +9,7 @@ import 'package:grocery_app/src/common_widget/textfield_widget.dart';
import 'package:grocery_app/src/logic/provider/addTocart_provider.dart';
import 'package:grocery_app/src/logic/provider/home_provider.dart';
import 'package:grocery_app/src/ui/bestdeal/bestdeal_screen.dart';
import 'package:grocery_app/src/ui/cart/cart_item.dart';
import 'package:grocery_app/src/ui/widgets/custom_icon_button.dart';
import 'package:grocery_app/src/ui/widgets/elevated_button.dart';
import 'package:grocery_app/utils/constants/assets_constant.dart';
@@ -32,6 +32,7 @@ class _MycartState extends State<Mycart> {
void initState() {
Provider.of<AddtocartProvider>(context, listen: false)
.getItemCards(context);
Provider.of<AddtocartProvider>(context, listen: false)
.getCurrentLocation(context);
@@ -213,15 +214,16 @@ class _MycartState extends State<Mycart> {
Widget cartItems() {
return Consumer<AddtocartProvider>(builder: (context, provider, child) {
print("djkhsfjh ${provider.allitem.items}");
if (provider.isLoaddcartItem) {
return Padding(
padding: const EdgeInsets.only(left: 120),
child: CircularProgressIndicator(),
return Center(
child: CircularProgressIndicator(
color: Colors.green,
),
);
} else if (provider.allitem == null) {
return Center(child: Text('🛒 Your Front Shop Cart is empty'));
} else if (provider.allitem.items == null) {
} else if (provider.allitem.items == null ||
provider.allitem.items!.isEmpty) {
return Center(child: Text('🛒 Your Front Shop Cart is empty'));
} else {
return ListView.separated(
@@ -235,7 +237,6 @@ class _MycartState extends State<Mycart> {
itemBuilder: (context, index) {
var items = provider.allitem.items![index];
print("kdfgdjfgkj ${items}");
return Padding(
padding: EdgeInsets.symmetric(horizontal: 10.w),
child: Row(
@@ -303,38 +304,76 @@ class _MycartState extends State<Mycart> {
),
),
const Spacer(),
Row(
Column(
children: [
CustomIconButton(
width: 14.w,
height: 14.h,
onPressed: () {
// provider.decreaseQuantity(items);
Row(
children: [
CustomIconButton(
width: 14.w,
height: 14.h,
onPressed: () {
// provider.decreaseQuantity(items);
},
icon: SvgPicture.asset(
APPASSETS.removeIcon,
fit: BoxFit.none,
),
backgroundColor: APPCOLOR.appGreen,
),
5.horizontalSpace,
Text(
items.quantity.toString(),
style:
context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
5.horizontalSpace,
CustomIconButton(
width: 14.w,
height: 14.h,
onPressed: () {
// provider..increaseQuantity(items);
},
icon: SvgPicture.asset(
APPASSETS.addIcon,
fit: BoxFit.none,
),
backgroundColor: APPCOLOR.appGreen,
),
],
),
Gap(20),
InkWell(
onTap: () {
provider.deleteItem(context, items.id);
},
icon: SvgPicture.asset(
APPASSETS.removeIcon,
fit: BoxFit.none,
child: Container(
height: 25,
width: 70,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
shape: BoxShape.rectangle,
border: Border.all(
color: Colors
.blue, // Replace with your desired border color
width: 2, // Border width
),
),
child: provider.isRemoveItem[items.id] ?? false
? Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 5,
width: 5,
child: CircularProgressIndicator(
color: Colors.green, strokeWidth: 1),
),
),
)
: Center(child: Text("Delete")),
),
backgroundColor: APPCOLOR.appGreen,
),
5.horizontalSpace,
Text(
items.quantity.toString(),
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
5.horizontalSpace,
CustomIconButton(
width: 14.w,
height: 14.h,
onPressed: () {
// provider..increaseQuantity(items);
},
icon: SvgPicture.asset(
APPASSETS.addIcon,
fit: BoxFit.none,
),
backgroundColor: APPCOLOR.appGreen,
),
)
],
)
],
@@ -356,7 +395,9 @@ class _MycartState extends State<Mycart> {
if (provider.isLoaddcartItem) {
return Padding(
padding: const EdgeInsets.only(left: 120),
child: CircularProgressIndicator(),
child: CircularProgressIndicator(
color: Colors.white,
),
);
} else if (provider.allitem == null) {
return Center(child: Text('🛒 Your Front Shop Cart is empty'));
@@ -384,9 +425,7 @@ class _MycartState extends State<Mycart> {
trailing: Icon(Icons.arrow_forward_ios),
onTap: () {},
),
SummaryRow(
label: 'Item Total',
value: '\$22'),
SummaryRow(label: 'Item Total', value: '\$22'),
SummaryRow(label: 'Discount', value: '\$2'),
SummaryRow(label: 'Delivery Free', value: 'Free', isGreen: true),
Divider(),

View File

@@ -106,219 +106,231 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
itemBuilder: (context, index)
{
var product = provider.products[index];
return 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: Padding(
padding: const EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: itemWidth *
0.6, // Adjust height for image container
width: itemWidth,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
),
child: Stack(
alignment: Alignment.center,
children: [
AppNetworkImage(
height: 70,
width: 70,
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,
),
// Positioned(
// right: 5,
// top: 5,
// child: InkWell(
// onTap: () async {
// if (await SharedPrefUtils.getToken() !=
// null) {
// if (product.isInWishlist) {
// Fluttertoast.showToast(
// msg: "Item already added!",
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.BOTTOM,
// backgroundColor: Colors.green,
// textColor: Colors.white,
// fontSize: 14.0,
// );
// } else {
// //product.isInWishlist=ture;
// provider
// .toggleWishlist1(product.id!);
// }
// } else {
// context.push(MyRoutes.LOGIN);
// }
// },
// child: Icon(
// product.isInWishlist
// ? Icons.favorite
// : Icons.favorite_border,
// color: product.isInWishlist
// ? Colors.red
// : Colors.grey,
// ),
// ),
// ),
return InkWell(
onTap: ()
{
context.push(MyRoutes.PRODUCTDETAILS,
extra: product.id);
},
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: Padding(
padding: const EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: itemWidth *
0.6, // Adjust height for image container
width: itemWidth,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
),
child: Stack(
alignment: Alignment.center,
children: [
AppNetworkImage(
height: 70,
width: 70,
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,
),
// Positioned(
// right: 5,
// top: 5,
// child: InkWell(
// onTap: () async {
// if (await SharedPrefUtils.getToken() !=
// null) {
// if (product.isInWishlist) {
// Fluttertoast.showToast(
// msg: "Item already added!",
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.BOTTOM,
// backgroundColor: Colors.green,
// textColor: Colors.white,
// fontSize: 14.0,
// );
// } else {
// //product.isInWishlist=ture;
// provider
// .toggleWishlist1(product.id!);
// }
// } else {
// context.push(MyRoutes.LOGIN);
// }
// },
// child: Icon(
// product.isInWishlist
// ? Icons.favorite
// : Icons.favorite_border,
// color: product.isInWishlist
// ? Colors.red
// : Colors.grey,
// ),
// ),
// ),
Positioned(
right: 5,
top: 5,
child: InkWell(
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,
),
),
),
],
),
),
const SizedBox(height: 5),
Text(
product.name ?? " ",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
APPCOLOR.balck1A1A1A, 14),
),
const SizedBox(height: 5),
Text(
product.unit ?? " ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
12,
),
),
const SizedBox(height: 3),
Row(
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"\$${product.discountPrice ?? " "}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customSemiBold(
Colors.black, 12),
),
const SizedBox(width: 5),
Text(
"\$${product.basePrice ?? " "}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
12,
)
.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) {
provider.toggleWishlist(
await provider.addToCart(
context, product.id!);
} else {
context.push(MyRoutes.LOGIN);
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,
child: Container(
height:
MediaQuery.of(context).size.height *
0.035,
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),
),
),
),
),
),
],
),
),
const SizedBox(height: 5),
Text(
product.name ?? " ",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
APPCOLOR.balck1A1A1A, 14),
),
const SizedBox(height: 5),
Text(
product.unit ?? " ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
12,
),
),
const SizedBox(height: 3),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"\$${product.discountPrice ?? " "}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customSemiBold(
Colors.black, 12),
),
const SizedBox(width: 5),
Text(
"\$${product.basePrice ?? " "}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
12,
)
.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!);
} else {
context.push(MyRoutes.LOGIN);
}
},
child: Container(
height:
MediaQuery.of(context).size.height *
0.035,
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),
),
),
),
),
),
],
),
],
],
),
),
),
);

View File

@@ -190,192 +190,198 @@ class _HomeScreenState extends State<HomeScreen> {
double cardWidth =
MediaQuery.of(context).size.width * 0.4; // Dynamic width
return Padding(
padding: const EdgeInsets.only(right: 10, bottom: 5, top: 5),
child: Container(
width: cardWidth,
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: [
Center(
child: Container(
height: MediaQuery.of(context).size.height * 0.12,
width: cardWidth * 0.9,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
return InkWell(
onTap: () {
context.push(MyRoutes.PRODUCTDETAILS,
extra: bestdealproduct.id);
},
child: Padding(
padding: const EdgeInsets.only(right: 10, bottom: 5, top: 5),
child: Container(
width: cardWidth,
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: [
Center(
child: Container(
height: MediaQuery.of(context).size.height * 0.12,
width: cardWidth * 0.9,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
),
child: Stack(
alignment: Alignment.center,
children: [
AppNetworkImage(
height: MediaQuery.of(context).size.height *
0.08,
width: cardWidth * 0.7,
imageUrl: bestdealproduct
.productImages?.first?.url ??
"",
backGroundColor: Colors.transparent,
),
// Positioned(
// right: 5,
// top: 5,
// child: InkWell(
// onTap: () async {
// if (await SharedPrefUtils.getToken() !=
// null) {
// provider.toggleWishlist(
// context, bestdealproduct.id!);
// } else {
// context.push(MyRoutes.LOGIN);
// }
// },
// child: Icon(
// provider.wishlist
// .contains(bestdealproduct.id)
// ? Icons.favorite
// : Icons.favorite_border,
// color: provider.wishlist
// .contains(bestdealproduct.id)
// ? Colors.red
// : Colors.grey,
// ),
// ),
// ),
],
),
),
child: Stack(
alignment: Alignment.center,
children: [
AppNetworkImage(
height:
MediaQuery.of(context).size.height * 0.08,
width: cardWidth * 0.7,
imageUrl: bestdealproduct
.productImages?.first?.url ??
"",
backGroundColor: Colors.transparent,
),
Positioned(
right: 5,
top: 5,
child: InkWell(
onTap: () async {
if (await SharedPrefUtils.getToken() !=
null) {
provider.toggleWishlist(
context, bestdealproduct.id!);
} else {
context.push(MyRoutes.LOGIN);
}
},
child: Icon(
provider.wishlist
.contains(bestdealproduct.id)
? Icons.favorite
: Icons.favorite_border,
color: provider.wishlist
.contains(bestdealproduct.id)
? Colors.red
: Colors.grey,
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.01,
),
Text(
bestdealproduct.name ?? "",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style:
context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005,
),
Text(
bestdealproduct.unit ?? "",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
12,
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005,
),
const Spacer(),
Row(
children: [
Row(
children: [
Text(
"\$${bestdealproduct.discountPrice ?? ""} ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customSemiBold(
Colors.black, 12),
),
Text(
"\$${bestdealproduct.basePrice ?? ""}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
12,
)
.copyWith(
decoration:
TextDecoration.lineThrough,
),
),
],
),
const Spacer(),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: () async {
print(
"Add to Cart Pressed for ${bestdealproduct.id}");
if (await SharedPrefUtils.getToken() !=
null) {
// if (!(provider
// .isLoading[bestdealproduct.id] ??
// false))
// {
await provider.addToCart(
context, bestdealproduct.id!);
// }
} else {
context.push(MyRoutes.SIGNUP);
}
},
child: Container(
height: MediaQuery.of(context).size.height *
0.035,
width:
MediaQuery.of(context).size.width * 0.1,
decoration: BoxDecoration(
color: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: provider.isLoading[
bestdealproduct.id] ??
false
? Padding(
padding:
const EdgeInsets.all(8.0),
child: Container(
height: 10,
width: 10,
child:
CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2),
),
)
: Text(
'Add',
style: context.customRegular(
Colors.white, 12),
),
),
),
),
],
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.01,
),
Text(
bestdealproduct.name ?? "",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005,
),
Text(
bestdealproduct.unit ?? "",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
12,
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005,
),
const Spacer(),
Row(
children: [
Row(
children: [
Text(
"\$${bestdealproduct.discountPrice ?? ""} ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style:
context.customSemiBold(Colors.black, 12),
),
Text(
"\$${bestdealproduct.basePrice ?? ""}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
12,
)
.copyWith(
decoration: TextDecoration.lineThrough,
),
),
],
),
const Spacer(),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: () async {
print(
"Add to Cart Pressed for ${bestdealproduct.id}");
if (await SharedPrefUtils.getToken() !=
null) {
// if (!(provider
// .isLoading[bestdealproduct.id] ??
// false))
// {
await provider.addToCart(
context, bestdealproduct.id!);
// }
} else {
context.push(MyRoutes.LOGIN);
}
},
child: Container(
height: MediaQuery.of(context).size.height *
0.035,
width:
MediaQuery.of(context).size.width * 0.1,
decoration: BoxDecoration(
color: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: provider.isLoading[
bestdealproduct.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),
),
),
),
),
),
],
),
],
],
),
],
),
),
),
),
@@ -505,7 +511,7 @@ class _HomeScreenState extends State<HomeScreen> {
var product = provider.products[index];
return InkWell(
onTap: () {
context.push(MyRoutes.PRODUCTDETAILS, extra: product);
context.push(MyRoutes.PRODUCTDETAILS, extra: product.id);
},
child: SizedBox(
child: Column(

View File

@@ -92,7 +92,7 @@ class _LoginScreenState extends State<LoginScreen> {
await pageNotifier.sendOtp(phoneController.text, context);
if (success) {
context.push(MyRoutes.OTPSCREEN);
context.push(MyRoutes.LOGINOTPSCREEN);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(

View File

@@ -0,0 +1,154 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:grocery_app/src/common_widget/textfield_widget.dart';
import 'package:grocery_app/src/core/routes/routes.dart';
import 'package:grocery_app/src/logic/provider/auth_provider.dart';
import 'package:grocery_app/src/ui/otp/otp_screen.dart';
import 'package:grocery_app/utils/constants/color_constant.dart';
import 'package:grocery_app/utils/constants/string_constant.dart';
import 'package:grocery_app/utils/extensions/uicontext.dart';
import 'package:provider/provider.dart';
class SingnuScreen extends StatefulWidget {
const SingnuScreen({super.key});
@override
State<SingnuScreen> createState() => _SingnuScreenState();
}
class _SingnuScreenState extends State<SingnuScreen> {
TextEditingController phoneController = TextEditingController();
String? validatePhoneNumber(String? value) {
if (value == null || value.isEmpty) {
return 'Phone number cannot be empty';
} else if (!RegExp(r'^\d{10}$').hasMatch(value)) {
return 'Enter a valid 10-digit phone number';
}
return null;
}
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
final pageNotifier = Provider.of<AuthProvider>(context, listen: false);
return Scaffold(
body: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
decoration: BoxDecoration(
color: Colors.greenAccent.withOpacity(0.1),
),
child: Padding(
padding: context.bodyAllPadding,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 30),
Text(
APPSTRING.enterYourMobileNumber,
style: context.customMedium(APPCOLOR.balck1A1A1A, 18),
),
const SizedBox(height: 40),
Text(
APPSTRING.whatYourPhoneNumber,
style: context.customMedium(APPCOLOR.black333333, 18),
),
SizedBox(
width: 200,
child: Text(
APPSTRING.codeSentText,
style: context.customMedium(APPCOLOR.grey666666, 14),
),
),
const SizedBox(height: 40),
Form(
key: _formKey,
child: AppTextFieldWidget(
length: 10,
controller: phoneController,
hintText: APPSTRING.phoneNumberHint,
onValidate: (value) => validatePhoneNumber(value),
),
),
RichText(
text: TextSpan(
text: "Already have an account? ",
style: TextStyle(color: Colors.black, fontSize: 16),
children: [
TextSpan(
text: "Login",
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
decoration: TextDecoration.underline,
),
// Navigate to Login Screen when tapped
recognizer: TapGestureRecognizer()
..onTap = () {
context.push(MyRoutes.LOGIN);
},
),
])),
Text(
"",
style: context.customMedium(APPCOLOR.balck1A1A1A, 18),
),
],
),
),
),
bottomNavigationBar: Container(
decoration: BoxDecoration(
color: Colors.greenAccent.withOpacity(0.1),
),
height: 100,
child: Padding(
padding: context.bodyAllPadding.copyWith(bottom: 20),
child: Center(
child: InkWell(
onTap: () async {
if (_formKey.currentState?.validate() ?? false) {
final success =
await pageNotifier.sendOtp(phoneController.text, context);
if (success) {
context.push(MyRoutes.OTPSCREEN);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Failed to send OTP. Please try again."),
),
);
}
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Enter a valid 10-digit phone number."),
),
);
}
},
child: Container(
height: 50,
width: MediaQuery.sizeOf(context).width,
decoration: BoxDecoration(
color: APPCOLOR.appGreen,
borderRadius: BorderRadius.circular(4)),
child: Center(
child: Text(
APPSTRING.verifyButton,
style: context.customMedium(Colors.white, 16),
),
),
),
),
),
),
),
);
}
}

View File

@@ -33,7 +33,7 @@ class _OnBoardingScreenState extends State<OnBoardingScreen> {
skipbyarrowFunction() {
SharedPrefUtils.setFreshInstall(isFresh: false).then(
(value) => context.clearAndPush(routePath: MyRoutes.LOGIN, args: 0),
(value) => context.clearAndPush(routePath: MyRoutes.SIGNUP, args: 0),
);
}

View File

@@ -0,0 +1,123 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:go_router/go_router.dart';
import 'package:grocery_app/src/logic/provider/auth_provider.dart';
import 'package:grocery_app/src/ui/entername/enter_fullname_screen.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/string_constant.dart';
import 'package:grocery_app/utils/extensions/color_ex.dart';
import 'package:grocery_app/utils/extensions/extensions.dart';
import 'package:grocery_app/utils/extensions/uicontext.dart';
import 'package:otp_text_field/otp_text_field.dart';
import 'package:otp_text_field/style.dart';
import 'package:provider/provider.dart';
import '../../core/routes/routes.dart';
class LoginOtpScreen extends StatefulWidget {
const LoginOtpScreen({super.key});
@override
State<LoginOtpScreen> createState() => _LoginOtpScreenState();
}
class _LoginOtpScreenState extends State<LoginOtpScreen> {
String maskNumber(String number) {
// Ensure the input has at least 4 digits to avoid errors
if (number.length < 4) {
throw Exception('Number is too short to mask');
}
// Replace all characters except the last 4 with '*'
String maskedPart = '*' * (number.length - 4);
String visiblePart = number.substring(number.length - 4);
return maskedPart + visiblePart;
}
@override
Widget build(BuildContext context) {
final pageNotifier = Provider.of<AuthProvider>(context, listen: false);
return Scaffold(
body: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
decoration: BoxDecoration(
color: Colors.greenAccent.withOpacity(0.1),
),
child: Padding(
padding: context.bodyAllPadding,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 30),
InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: SvgPicture.asset(APPASSETS.back)),
const SizedBox(height: 30),
Text(
APPSTRING.enterVerificationCode,
style: context.customMedium(APPCOLOR.black333333, 18),
),
SizedBox(
width: 300,
child: Text(
"Enter the 6-digit code sent to you at ${maskNumber(pageNotifier.numberwithCode)}",
style: context.customRegular(APPCOLOR.grey666666, 16),
),
),
const SizedBox(height: 20),
OTPTextField(
length: 6,
onChanged: (c)
{
},
width: MediaQuery.of(context).size.width,
fieldWidth: 50,
otpFieldStyle: OtpFieldStyle(
backgroundColor: HexColor('F4F5F5'),
),
style: const TextStyle(fontSize: 17),
textFieldAlignment: MainAxisAlignment.spaceBetween,
fieldStyle: FieldStyle.box,
onCompleted: (pin) async {
final success = await pageNotifier.loginOtp(pin, context);
if (success)
{
context.clearAndPush(routePath: MyRoutes.BOTTOMNAV);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: Colors.grey,
content: Text("Failed to send OTP. Please try again."),
),
);
}
},
),
const SizedBox(
height: 10,
),
RichText(
text: TextSpan(
text: 'Didnt get the code? ',
style: context.customRegular(APPCOLOR.gery48514D, 14),
children: [
TextSpan(
text: 'Resend',
style: context.customRegular(APPCOLOR.appGreen, 14),
)
]))
],
),
),
),
);
}
}

View File

@@ -20,8 +20,8 @@ import 'package:provider/provider.dart';
import 'package:readmore/readmore.dart';
class ProductDetails extends StatefulWidget {
Product product;
ProductDetails({super.key, required this.product});
String id;
ProductDetails({super.key, required this.id});
@override
State<ProductDetails> createState() => _ProductDetailsState();
@@ -35,22 +35,24 @@ class _ProductDetailsState extends State<ProductDetails> {
@override
void initState() {
super.initState();
Provider.of<ProductProvider>(context, listen: false)
.getProduuctDetails(context, widget.id);
productId = widget.product.id;
Future.delayed(Duration.zero, () {
Provider.of<ProductProvider>(context, listen: false)
.setProductPrice(double.parse(widget.product.discountPrice));
// productId = widget.product.id;
// Future.delayed(Duration.zero, () {
// Provider.of<ProductProvider>(context, listen: false)
// .setProductPrice(double.parse(widget.product.discountPrice));
Provider.of<ProductProvider>(context, listen: false)
.similarProductprovider(context, widget.product.id);
});
// Provider.of<ProductProvider>(context, listen: false)
// .similarProductprovider(context, widget.product.id);
// });
Timer.periodic(Duration(seconds: 3), (timer) {
setState(() {
selectedImage =
(selectedImage + 1) % widget.product.productImages!.length;
});
});
// Timer.periodic(Duration(seconds: 3), (timer) {
// setState(() {
// selectedImage =
// (selectedImage + 1) % widget.product.productImages!.length;
// });
// });
}
double value = 3.5;
@@ -90,102 +92,7 @@ class _ProductDetailsState extends State<ProductDetails> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 300,
child: CarouselSlider.builder(
itemCount: widget.product.productImages!.length,
itemBuilder: (context, index, realIndex) {
var productImage = widget.product.productImages![index];
return Image.network(productImage.url ??
'https://i.pinimg.com/originals/a5/f3/5f/a5f35fb23e942809da3df91b23718e8d.png');
},
options: CarouselOptions(
height: 300,
initialPage: selectedImage,
enableInfiniteScroll: true,
autoPlay: true,
autoPlayInterval: Duration(seconds: 3),
autoPlayAnimationDuration: Duration(milliseconds: 800),
enlargeCenterPage: true,
onPageChanged: (index, reason) {
setState(() {
selectedImage = index;
});
},
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: widget.product.productImages!.map((url) {
int index = widget.product.productImages!.indexOf(url);
return Container(
margin: EdgeInsets.symmetric(horizontal: 5),
width: 8,
height: 8,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: selectedImage == index ? Colors.red : Colors.grey,
),
);
}).toList(),
),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.product.name ?? "",
style: context.customExtraBold(Colors.black, 18),
),
Row(
children: [
Text(
"\$${widget.product.discountPrice}",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.green),
),
SizedBox(width: 10),
Text(
"\$${widget.product.basePrice}",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
decoration: TextDecoration.lineThrough,
color: Colors.grey,
),
),
SizedBox(width: 10),
Container(
padding:
EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(5),
),
child: Text("10% OFF",
style:
TextStyle(color: Colors.white, fontSize: 14)),
)
],
),
SizedBox(height: 10),
ReadMoreText(
widget.product.description ?? "",
trimMode: TrimMode.Line,
trimLines: 2,
colorClickableText: APPCOLOR.appGreen,
trimCollapsedText: 'Read More',
trimExpandedText: 'Show less',
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
],
),
),
prodectDtails(),
Divider(),
reviews(),
Divider(),
@@ -203,10 +110,148 @@ class _ProductDetailsState extends State<ProductDetails> {
),
),
),
bottomNavigationBar: bottomBar(),
// bottomNavigationBar: bottomBar(),
);
}
Widget prodectDtails() {
return Consumer<ProductProvider>(builder: (context, provider, child) {
if (provider.isProductLoading) {
return Center(
child: CircularProgressIndicator(
color: Colors.green,
));
} else if (provider.productDetails.data == null) {
return Center(child: Text('No products available'));
} else {
return Column(
children: [
SizedBox(
height: 300,
child: CarouselSlider.builder(
itemCount:
provider.productDetails.data!.productImages!.length ?? 0,
itemBuilder: (context, index, realIndex) {
var productImage =
provider.productDetails.data!.productImages![index];
return Image.network(productImage.url ??
'https://i.pinimg.com/originals/a5/f3/5f/a5f35fb23e942809da3df91b23718e8d.png');
},
options: CarouselOptions(
height: 300,
initialPage: selectedImage,
enableInfiniteScroll: true,
autoPlay: true,
autoPlayInterval: Duration(seconds: 3),
autoPlayAnimationDuration: Duration(milliseconds: 800),
enlargeCenterPage: true,
onPageChanged: (index, reason) {
setState(() {
selectedImage = index;
});
},
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: provider.productDetails.data!.productImages!.map((url) {
int index =
provider.productDetails.data!.productImages!.indexOf(url);
return Container(
margin: EdgeInsets.symmetric(horizontal: 5),
width: 8,
height: 8,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: selectedImage == index ? Colors.red : Colors.grey,
),
);
}).toList(),
),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
provider.productDetails.data!.name ?? "",
style: context.customExtraBold(Colors.black, 18),
),
Row(
children: [
Text(
"\$${provider.productDetails.data!.discountPrice}",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.green),
),
SizedBox(width: 10),
Text(
"\$${provider.productDetails.data!.basePrice}",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
decoration: TextDecoration.lineThrough,
color: Colors.grey,
),
),
SizedBox(width: 10),
Container(
padding:
EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(5),
),
child: Text("10% 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),
),
],
),
),
],
);
}
});
}
Widget reviews() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
@@ -481,215 +526,198 @@ class _ProductDetailsState extends State<ProductDetails> {
double cardWidth =
MediaQuery.of(context).size.width * 0.4; // Dynamic width
return Padding(
padding: const EdgeInsets.only(right: 10, bottom: 5, top: 5),
child: Container(
width: cardWidth,
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: [
Center(
child: Container(
height: MediaQuery.of(context).size.height * 0.12,
width: cardWidth * 0.9,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
return InkWell(
onTap: () {
provider.getProduuctDetails(context, bestdealproduct.id);
},
child: Padding(
padding: const EdgeInsets.only(right: 10, bottom: 5, top: 5),
child: Container(
width: cardWidth,
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: [
Center(
child: Container(
height: MediaQuery.of(context).size.height * 0.12,
width: cardWidth * 0.9,
decoration: BoxDecoration(
color: APPCOLOR.bgGrey,
borderRadius: BorderRadius.circular(15),
),
child: Stack(
alignment: Alignment.center,
children: [
AppNetworkImage(
height: MediaQuery.of(context).size.height *
0.08,
width: cardWidth * 0.7,
imageUrl: bestdealproduct
.productImages?.first?.url ??
"",
backGroundColor: Colors.transparent,
),
],
),
),
child: Stack(
alignment: Alignment.center,
children: [
AppNetworkImage(
height:
MediaQuery.of(context).size.height * 0.08,
width: cardWidth * 0.7,
imageUrl: bestdealproduct
.productImages?.first?.url ??
"",
backGroundColor: Colors.transparent,
),
Positioned(
right: 5,
top: 5,
child: InkWell(
onTap: () async {
if (await SharedPrefUtils.getToken() !=
null) {
provider.toggleWishlist(
context, bestdealproduct.id!);
} else {
context.push(MyRoutes.LOGIN);
}
},
child: Icon(
provider.wishlist
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.01,
),
Text(
bestdealproduct.name ?? "",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style:
context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005,
),
Text(
bestdealproduct.unit ?? "",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
12,
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005,
),
const Spacer(),
Row(
children: [
Row(
children: [
Text(
"\$${bestdealproduct.discountPrice ?? ""} ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customSemiBold(
Colors.black, 12),
),
Text(
"\$${bestdealproduct.basePrice ?? ""}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
12,
)
.copyWith(
decoration:
TextDecoration.lineThrough,
),
),
],
),
// Align(
// alignment: Alignment.centerRight,
// child: InkWell(
// onTap: () async {
// bool success = await provider.addToCart(context, bestdealproduct.id!);
// if (success) {
// Fluttertoast.showToast(
// msg: "Product added to cart!",
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.BOTTOM,
// backgroundColor: Colors.green,
// textColor: Colors.white,
// fontSize: 14.0,
// );
// }
// },
// child: Container(
// height:
// MediaQuery.of(context).size.height * 0.035,
// width: MediaQuery.of(context).size.width * 0.1,
// decoration: BoxDecoration(
// color: APPCOLOR.lightGreen,
// borderRadius: BorderRadius.circular(5),
// ),
// child: Center(
// child: Text(
// 'Add',
// style:
// context.customRegular(Colors.white, 12),
// ),
// ),
// ),
// ),
// ),
const Spacer(),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: () async {
if (await SharedPrefUtils.getToken() !=
null) {
provider.isLoading[bestdealproduct.id] ??
false
? null
: () => provider.addToCart(
context, bestdealproduct.id!);
} else {
context.push(MyRoutes.SIGNUP);
}
},
child: Container(
height: MediaQuery.of(context).size.height *
0.035,
width:
MediaQuery.of(context).size.width * 0.1,
decoration: BoxDecoration(
color: provider.cartItems
.contains(bestdealproduct.id)
? Icons.favorite
: Icons.favorite_border,
color: provider.wishlist
.contains(bestdealproduct.id)
? Colors.red
: Colors.grey,
? Colors.grey
: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: provider.isLoading[
bestdealproduct.id] ??
false
? CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2)
: Text(
provider.cartItems.contains(
bestdealproduct.id)
? 'Added'
: 'Add',
style: context.customRegular(
Colors.white, 12),
),
),
),
),
],
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.01,
),
Text(
bestdealproduct.name ?? "",
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005,
),
Text(
bestdealproduct.unit ?? "",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context.customMedium(
Colors.grey.withOpacity(0.8),
12,
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.005,
),
const Spacer(),
Row(
children: [
Row(
children: [
Text(
"\$${bestdealproduct.discountPrice ?? ""} ",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style:
context.customSemiBold(Colors.black, 12),
),
Text(
"\$${bestdealproduct.basePrice ?? ""}",
textAlign: TextAlign.left,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: context
.customMedium(
Colors.grey.withOpacity(0.8),
12,
)
.copyWith(
decoration: TextDecoration.lineThrough,
),
),
],
),
// Align(
// alignment: Alignment.centerRight,
// child: InkWell(
// onTap: () async {
// bool success = await provider.addToCart(context, bestdealproduct.id!);
// if (success) {
// Fluttertoast.showToast(
// msg: "Product added to cart!",
// toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.BOTTOM,
// backgroundColor: Colors.green,
// textColor: Colors.white,
// fontSize: 14.0,
// );
// }
// },
// child: Container(
// height:
// MediaQuery.of(context).size.height * 0.035,
// width: MediaQuery.of(context).size.width * 0.1,
// decoration: BoxDecoration(
// color: APPCOLOR.lightGreen,
// borderRadius: BorderRadius.circular(5),
// ),
// child: Center(
// child: Text(
// 'Add',
// style:
// context.customRegular(Colors.white, 12),
// ),
// ),
// ),
// ),
// ),
const Spacer(),
Align(
alignment: Alignment.centerRight,
child: GestureDetector(
onTap: () async {
if (await SharedPrefUtils.getToken() !=
null) {
provider.isLoading[bestdealproduct.id] ??
false
? null
: () => provider.addToCart(
context, bestdealproduct.id!);
} else {
context.push(MyRoutes.LOGIN);
}
},
child: Container(
height: MediaQuery.of(context).size.height *
0.035,
width:
MediaQuery.of(context).size.width * 0.1,
decoration: BoxDecoration(
color: provider.cartItems
.contains(bestdealproduct.id)
? Colors.grey
: APPCOLOR.lightGreen,
borderRadius: BorderRadius.circular(5),
),
child: Center(
child: provider.isLoading[
bestdealproduct.id] ??
false
? CircularProgressIndicator(
color: Colors.white, strokeWidth: 2)
: Text(
provider.cartItems.contains(
bestdealproduct.id)
? 'Added'
: 'Add',
style: context.customRegular(
Colors.white, 12),
),
),
),
),
),
],
),
],
],
),
],
),
),
),
),
@@ -770,7 +798,6 @@ class _ProductDetailsState extends State<ProductDetails> {
}
}
// Widget _slider(BuildContext context) {
// double height = MediaQuery.of(context).size.height * .43;
// double statusBarHeight = MediaQuery.of(context).padding.top;
@@ -856,5 +883,3 @@ class _ProductDetailsState extends State<ProductDetails> {
// ),
// );
// }