1977 lines
106 KiB
Dart
1977 lines
106 KiB
Dart
import 'package:badges/badges.dart' as badges;
|
|
import 'package:customer/constant/constant.dart';
|
|
import 'package:customer/controllers/home_e_commerce_controller.dart';
|
|
import 'package:customer/controllers/theme_controller.dart';
|
|
import 'package:customer/models/advertisement_model.dart';
|
|
import 'package:customer/models/banner_model.dart';
|
|
import 'package:customer/models/brands_model.dart';
|
|
import 'package:customer/models/favourite_model.dart';
|
|
import 'package:customer/models/product_model.dart';
|
|
import 'package:customer/models/user_model.dart';
|
|
import 'package:customer/models/vendor_category_model.dart';
|
|
import 'package:customer/models/vendor_model.dart';
|
|
import 'package:customer/screen_ui/auth_screens/login_screen.dart';
|
|
import 'package:customer/screen_ui/ecommarce/all_brand_product_screen.dart';
|
|
import 'package:customer/screen_ui/ecommarce/all_category_product_screen.dart';
|
|
import 'package:customer/screen_ui/location_enable_screens/address_list_screen.dart';
|
|
import 'package:customer/screen_ui/multi_vendor_service/advertisement_screens/all_advertisement_screen.dart';
|
|
import 'package:customer/screen_ui/multi_vendor_service/cart_screen/cart_screen.dart';
|
|
import 'package:customer/screen_ui/multi_vendor_service/home_screen/category_restaurant_screen.dart';
|
|
import 'package:customer/screen_ui/multi_vendor_service/home_screen/restaurant_list_screen.dart'
|
|
show RestaurantListScreen;
|
|
import 'package:customer/screen_ui/multi_vendor_service/home_screen/view_all_category_screen.dart';
|
|
import 'package:customer/screen_ui/multi_vendor_service/restaurant_details_screen/restaurant_details_screen.dart';
|
|
import 'package:customer/screen_ui/multi_vendor_service/search_screen/search_screen.dart';
|
|
import 'package:customer/service/fire_store_utils.dart';
|
|
import 'package:customer/themes/app_them_data.dart';
|
|
import 'package:customer/themes/responsive.dart';
|
|
import 'package:customer/themes/round_button_border.dart';
|
|
import 'package:customer/themes/show_toast_dialog.dart';
|
|
import 'package:customer/themes/text_field_widget.dart';
|
|
import 'package:customer/utils/network_image_widget.dart';
|
|
import 'package:customer/widget/osm_map/map_picker_page.dart';
|
|
import 'package:customer/widget/place_picker/location_picker_screen.dart';
|
|
import 'package:customer/widget/place_picker/selected_location_model.dart';
|
|
import 'package:customer/widget/video_widget.dart';
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
import 'package:geocoding/geocoding.dart';
|
|
import 'package:geolocator/geolocator.dart';
|
|
import 'package:get/get.dart' hide Trans;
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
class HomeECommerceScreen extends StatelessWidget {
|
|
const HomeECommerceScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final themeController = Get.find<ThemeController>();
|
|
final isDark = themeController.isDark.value;
|
|
return GetX(
|
|
init: HomeECommerceController(),
|
|
builder: (controller) {
|
|
return Scaffold(
|
|
backgroundColor: isDark ? AppThemeData.grey900 : AppThemeData.grey50,
|
|
appBar: AppBar(
|
|
backgroundColor:
|
|
isDark ? AppThemeData.ecommerce300 : AppThemeData.ecommerce300,
|
|
titleSpacing: 0,
|
|
leading: InkWell(
|
|
onTap: () {
|
|
Get.back();
|
|
},
|
|
child: Icon(
|
|
Icons.arrow_back,
|
|
color: isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
|
size: 20,
|
|
),
|
|
),
|
|
title: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Constant.userModel == null
|
|
? InkWell(
|
|
onTap: () {
|
|
Get.offAll(const LoginScreen());
|
|
},
|
|
child: Text(
|
|
"Login".tr(),
|
|
textAlign: TextAlign.center,
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData.grey50
|
|
: AppThemeData.grey50,
|
|
fontSize: 12,
|
|
),
|
|
),
|
|
)
|
|
: Text(
|
|
Constant.userModel!.fullName(),
|
|
textAlign: TextAlign.center,
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
color:
|
|
isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
|
fontSize: 12,
|
|
),
|
|
),
|
|
InkWell(
|
|
onTap: () async {
|
|
if (Constant.userModel != null) {
|
|
Get.to(AddressListScreen())!.then((value) {
|
|
if (value != null) {
|
|
ShippingAddress shippingAddress = value;
|
|
Constant.selectedLocation = shippingAddress;
|
|
controller.getData();
|
|
}
|
|
});
|
|
} else {
|
|
Constant.checkPermission(
|
|
onTap: () async {
|
|
ShowToastDialog.showLoader("Please wait...".tr());
|
|
|
|
// ✅ declare it once here!
|
|
ShippingAddress shippingAddress = ShippingAddress();
|
|
|
|
try {
|
|
await Geolocator.requestPermission();
|
|
await Geolocator.getCurrentPosition();
|
|
ShowToastDialog.closeLoader();
|
|
|
|
if (Constant.selectedMapType == 'osm') {
|
|
final result = await Get.to(
|
|
() => MapPickerPage(),
|
|
);
|
|
if (result != null) {
|
|
final firstPlace = result;
|
|
final lat = firstPlace.coordinates.latitude;
|
|
final lng = firstPlace.coordinates.longitude;
|
|
final address = firstPlace.address;
|
|
|
|
shippingAddress.addressAs = "Home";
|
|
shippingAddress.locality = address.toString();
|
|
shippingAddress.location = UserLocation(
|
|
latitude: lat,
|
|
longitude: lng,
|
|
);
|
|
Constant.selectedLocation = shippingAddress;
|
|
controller.getData();
|
|
Get.back();
|
|
}
|
|
} else {
|
|
Get.to(LocationPickerScreen())!.then((
|
|
value,
|
|
) async {
|
|
if (value != null) {
|
|
SelectedLocationModel selectedLocationModel =
|
|
value;
|
|
|
|
shippingAddress.addressAs = "Home";
|
|
shippingAddress.location = UserLocation(
|
|
latitude:
|
|
selectedLocationModel.latLng!.latitude,
|
|
longitude:
|
|
selectedLocationModel.latLng!.longitude,
|
|
);
|
|
shippingAddress.locality =
|
|
"Picked from Map"; // You can reverse-geocode
|
|
|
|
Constant.selectedLocation = shippingAddress;
|
|
controller.getData();
|
|
}
|
|
});
|
|
}
|
|
} catch (e) {
|
|
await placemarkFromCoordinates(
|
|
19.228825,
|
|
72.854118,
|
|
).then((valuePlaceMaker) {
|
|
Placemark placeMark = valuePlaceMaker[0];
|
|
shippingAddress.location = UserLocation(
|
|
latitude: 19.228825,
|
|
longitude: 72.854118,
|
|
);
|
|
String currentLocation =
|
|
"${placeMark.name}, ${placeMark.subLocality}, ${placeMark.locality}, ${placeMark.administrativeArea}, ${placeMark.postalCode}, ${placeMark.country}";
|
|
shippingAddress.locality = currentLocation;
|
|
});
|
|
|
|
Constant.selectedLocation = shippingAddress;
|
|
ShowToastDialog.closeLoader();
|
|
controller.getData();
|
|
}
|
|
},
|
|
context: context,
|
|
);
|
|
}
|
|
},
|
|
child: Text.rich(
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
TextSpan(
|
|
children: [
|
|
TextSpan(
|
|
text: Constant.selectedLocation.getFullAddress(),
|
|
style: AppThemeData.boldTextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData.grey50
|
|
: AppThemeData.grey50,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
WidgetSpan(
|
|
child: SvgPicture.asset(
|
|
"assets/icons/ic_down.svg",
|
|
colorFilter: ColorFilter.mode(
|
|
AppThemeData.grey50,
|
|
BlendMode.srcIn,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
actions: [
|
|
Obx(
|
|
() => Padding(
|
|
padding: const EdgeInsets.only(right: 15.0, left: 10),
|
|
child: badges.Badge(
|
|
showBadge: true,
|
|
badgeContent: Text(
|
|
"${cartItem.length}",
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
overflow: TextOverflow.ellipsis,
|
|
fontFamily: AppThemeData.semiBold,
|
|
fontWeight: FontWeight.w600,
|
|
color:
|
|
isDark ? AppThemeData.grey50 : AppThemeData.grey50,
|
|
),
|
|
),
|
|
badgeStyle: badges.BadgeStyle(
|
|
shape: badges.BadgeShape.circle,
|
|
badgeColor: AppThemeData.info300,
|
|
),
|
|
child: InkWell(
|
|
onTap: () async {
|
|
(await Get.to(const CartScreen()));
|
|
controller.getCartData();
|
|
},
|
|
child: ClipOval(
|
|
child: Container(
|
|
width: 30,
|
|
height: 30,
|
|
decoration: ShapeDecoration(
|
|
shape: RoundedRectangleBorder(
|
|
side: BorderSide(
|
|
width: 1,
|
|
color:
|
|
isDark
|
|
? AppThemeData.grey700
|
|
: AppThemeData.grey200,
|
|
),
|
|
borderRadius: BorderRadius.circular(120),
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: SvgPicture.asset(
|
|
"assets/icons/ic_shoping_cart.svg",
|
|
colorFilter: ColorFilter.mode(
|
|
isDark
|
|
? AppThemeData.grey50
|
|
: AppThemeData.grey50,
|
|
BlendMode.srcIn,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
bottom: PreferredSize(
|
|
preferredSize: Size.fromHeight(
|
|
50.0,
|
|
), // height of the bottom widget
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 16,
|
|
vertical: 8,
|
|
),
|
|
child: InkWell(
|
|
onTap: () {
|
|
Get.to(
|
|
const SearchScreen(),
|
|
arguments: {
|
|
"vendorList": controller.allNearestRestaurant,
|
|
},
|
|
);
|
|
},
|
|
child: TextFieldWidget(
|
|
hintText: 'Search the store, item and more...'.tr(),
|
|
controller: null,
|
|
enable: false,
|
|
backgroundColor: AppThemeData.grey50,
|
|
hintColor:
|
|
isDark ? AppThemeData.grey400 : AppThemeData.grey400,
|
|
prefix: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: SvgPicture.asset(
|
|
"assets/icons/ic_search.svg",
|
|
colorFilter: ColorFilter.mode(
|
|
isDark ? AppThemeData.grey400 : AppThemeData.grey400,
|
|
BlendMode.srcIn,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
body:
|
|
controller.isLoading.value
|
|
? Constant.loader()
|
|
: SingleChildScrollView(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text(
|
|
"Category".tr(),
|
|
textAlign: TextAlign.start,
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark900
|
|
: AppThemeData.grey900,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
),
|
|
InkWell(
|
|
onTap: () {
|
|
Get.to(const ViewAllCategoryScreen());
|
|
},
|
|
child: Text(
|
|
"View all".tr(),
|
|
textAlign: TextAlign.start,
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
decoration: TextDecoration.underline,
|
|
color:
|
|
isDark
|
|
? AppThemeData.multiVendorDark300
|
|
: AppThemeData.multiVendor300,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: SizedBox(
|
|
height: 100,
|
|
child: ListView.builder(
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemCount:
|
|
controller.vendorCategoryModel.length,
|
|
scrollDirection: Axis.horizontal,
|
|
itemBuilder: (context, index) {
|
|
VendorCategoryModel vendorCategoryModel =
|
|
controller.vendorCategoryModel[index];
|
|
return InkWell(
|
|
onTap: () {
|
|
Get.to(
|
|
const CategoryRestaurantScreen(),
|
|
arguments: {
|
|
"vendorCategoryModel":
|
|
vendorCategoryModel,
|
|
"dineIn": false,
|
|
},
|
|
);
|
|
},
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(right: 18),
|
|
child: Column(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.start,
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.center,
|
|
children: [
|
|
NetworkImageWidget(
|
|
imageUrl:
|
|
vendorCategoryModel.photo
|
|
.toString(),
|
|
height: 60,
|
|
width: 60,
|
|
fit: BoxFit.cover,
|
|
),
|
|
const SizedBox(height: 5),
|
|
Text(
|
|
vendorCategoryModel.title
|
|
.toString(),
|
|
textAlign: TextAlign.center,
|
|
style: AppThemeData.mediumTextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark800
|
|
: AppThemeData.grey800,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child:
|
|
controller.bannerModel.isEmpty
|
|
? const SizedBox()
|
|
: BannerView(controller: controller),
|
|
),
|
|
Visibility(
|
|
visible:
|
|
(Constant.isEnableAdsFeature == true &&
|
|
controller.advertisementList.isNotEmpty),
|
|
child: const SizedBox(height: 20),
|
|
),
|
|
Visibility(
|
|
visible: Constant.isEnableAdsFeature == true,
|
|
child:
|
|
controller.advertisementList.isEmpty
|
|
? const SizedBox()
|
|
: Container(
|
|
color: AppThemeData.primary300.withAlpha(
|
|
40,
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 16,
|
|
vertical: 16,
|
|
),
|
|
child: Column(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.start,
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text(
|
|
"Highlights for you".tr(),
|
|
textAlign: TextAlign.start,
|
|
style: TextStyle(
|
|
fontFamily:
|
|
AppThemeData.semiBold,
|
|
fontSize: 16,
|
|
color:
|
|
isDark
|
|
? AppThemeData
|
|
.grey50
|
|
: AppThemeData
|
|
.grey900,
|
|
),
|
|
),
|
|
),
|
|
InkWell(
|
|
onTap: () {
|
|
Get.to(
|
|
AllAdvertisementScreen(),
|
|
)?.then((value) {
|
|
controller
|
|
.getFavouriteRestaurant();
|
|
});
|
|
},
|
|
child: Text(
|
|
"View all".tr(),
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(
|
|
fontFamily:
|
|
AppThemeData.regular,
|
|
color:
|
|
isDark
|
|
? AppThemeData
|
|
.primary300
|
|
: AppThemeData
|
|
.primary300,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
SizedBox(
|
|
height: 220,
|
|
child: ListView.builder(
|
|
physics:
|
|
const BouncingScrollPhysics(),
|
|
scrollDirection:
|
|
Axis.horizontal,
|
|
itemCount:
|
|
controller
|
|
.advertisementList
|
|
.length >=
|
|
10
|
|
? 10
|
|
: controller
|
|
.advertisementList
|
|
.length,
|
|
padding: EdgeInsets.all(0),
|
|
itemBuilder: (
|
|
BuildContext context,
|
|
int index,
|
|
) {
|
|
return AdvertisementHomeCard(
|
|
controller: controller,
|
|
model:
|
|
controller
|
|
.advertisementList[index],
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Text(
|
|
"New Arrivals".tr(),
|
|
textAlign: TextAlign.start,
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark900
|
|
: AppThemeData.grey900,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 20),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: SizedBox(
|
|
height: 380,
|
|
child: GridView.count(
|
|
crossAxisCount: 2,
|
|
// 2 columns
|
|
mainAxisSpacing: 0,
|
|
crossAxisSpacing: 20,
|
|
childAspectRatio: 1 / 1.1,
|
|
padding: EdgeInsets.zero,
|
|
physics: NeverScrollableScrollPhysics(),
|
|
children:
|
|
controller.newArrivalRestaurantList
|
|
.take(4)
|
|
.map(
|
|
(item) => NewArrivalCard(item: item),
|
|
)
|
|
.toList(),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 5),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: RoundedButtonBorder(
|
|
radius: 10,
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark100
|
|
: AppThemeData.grey100,
|
|
borderColor:
|
|
isDark
|
|
? AppThemeData.greyDark200
|
|
: AppThemeData.grey200,
|
|
title: 'View All Arrivals'.tr(),
|
|
onPress: () {
|
|
Get.to(
|
|
RestaurantListScreen(),
|
|
arguments: {
|
|
"vendorList":
|
|
controller.newArrivalRestaurantList,
|
|
"title": "New Arrivals".tr(),
|
|
},
|
|
);
|
|
},
|
|
),
|
|
),
|
|
SizedBox(height: 20),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Top Brands".tr(),
|
|
textAlign: TextAlign.start,
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark900
|
|
: AppThemeData.grey900,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
GridView.builder(
|
|
padding: EdgeInsets.zero,
|
|
gridDelegate:
|
|
const SliverGridDelegateWithFixedCrossAxisCount(
|
|
crossAxisCount: 4,
|
|
childAspectRatio: 4.5 / 6,
|
|
crossAxisSpacing: 2,
|
|
),
|
|
itemCount: controller.brandList.length,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
shrinkWrap: true,
|
|
itemBuilder: (context, index) {
|
|
BrandsModel brandModel =
|
|
controller.brandList[index];
|
|
return InkWell(
|
|
onTap: () {
|
|
Get.to(
|
|
AllBrandProductScreen(),
|
|
arguments: {"brandModel": brandModel},
|
|
);
|
|
},
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
width: 80,
|
|
height: 80,
|
|
decoration: ShapeDecoration(
|
|
color:
|
|
isDark
|
|
? AppThemeData.grey900
|
|
: AppThemeData.grey50,
|
|
shape: RoundedRectangleBorder(
|
|
side: BorderSide(
|
|
width: 1,
|
|
strokeAlign:
|
|
BorderSide
|
|
.strokeAlignOutside,
|
|
color:
|
|
isDark
|
|
? AppThemeData.grey800
|
|
: AppThemeData
|
|
.grey100,
|
|
),
|
|
borderRadius:
|
|
BorderRadius.circular(10),
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(10),
|
|
child: ClipOval(
|
|
child: NetworkImageWidget(
|
|
imageUrl:
|
|
brandModel.photo
|
|
.toString(),
|
|
fit: BoxFit.cover,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 5),
|
|
Text(
|
|
'${brandModel.title}',
|
|
textAlign: TextAlign.center,
|
|
maxLines: 2,
|
|
style: AppThemeData.mediumTextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData.grey50
|
|
: AppThemeData.grey900,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
ListView.builder(
|
|
shrinkWrap: true,
|
|
physics: const BouncingScrollPhysics(),
|
|
padding: EdgeInsets.zero,
|
|
itemCount:
|
|
controller.categoryWiseProductList.length,
|
|
itemBuilder: (context, index) {
|
|
VendorCategoryModel item =
|
|
controller.categoryWiseProductList[index];
|
|
String imagePath =
|
|
[
|
|
"assets/images/ic_product_bg_1.png",
|
|
"assets/images/ic_product_bg_2.png",
|
|
"assets/images/ic_product_bg_3.png",
|
|
][index % ["", "", ""].length];
|
|
return Container(
|
|
width: Responsive.width(100, context),
|
|
decoration: BoxDecoration(
|
|
image: DecorationImage(
|
|
image: AssetImage(imagePath),
|
|
fit: BoxFit.fill,
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(
|
|
left: 16,
|
|
right: 16,
|
|
top: 10,
|
|
bottom: 20,
|
|
),
|
|
child: FutureBuilder<List<ProductModel>>(
|
|
future:
|
|
FireStoreUtils.getProductListByCategoryId(
|
|
item.id.toString(),
|
|
),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState ==
|
|
ConnectionState.waiting) {
|
|
return Center(
|
|
child:
|
|
CircularProgressIndicator.adaptive(
|
|
valueColor:
|
|
AlwaysStoppedAnimation(
|
|
AppThemeData.primary300,
|
|
),
|
|
),
|
|
);
|
|
} else if ((snapshot.hasData ||
|
|
(snapshot.data?.isNotEmpty ??
|
|
false))) {
|
|
List<ProductModel> productList =
|
|
snapshot.data!;
|
|
return snapshot.data!.isEmpty
|
|
? Container()
|
|
: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
item.title.toString(),
|
|
textAlign: TextAlign.start,
|
|
style:
|
|
AppThemeData.boldTextStyle(
|
|
color:
|
|
AppThemeData
|
|
.grey900,
|
|
fontSize: 18,
|
|
),
|
|
),
|
|
Text(
|
|
"Style up with the latest fits, now at unbeatable prices."
|
|
.tr(),
|
|
textAlign: TextAlign.start,
|
|
style:
|
|
AppThemeData.regularTextStyle(
|
|
color:
|
|
AppThemeData
|
|
.grey900,
|
|
fontSize: 12,
|
|
),
|
|
),
|
|
SizedBox(height: 20),
|
|
GridView.builder(
|
|
shrinkWrap: true,
|
|
gridDelegate:
|
|
const SliverGridDelegateWithFixedCrossAxisCount(
|
|
crossAxisCount: 3,
|
|
childAspectRatio:
|
|
3.5 / 6,
|
|
crossAxisSpacing: 10,
|
|
),
|
|
padding: EdgeInsets.zero,
|
|
physics:
|
|
NeverScrollableScrollPhysics(),
|
|
itemCount:
|
|
productList.length > 6
|
|
? 6
|
|
: productList.length,
|
|
itemBuilder: (
|
|
context,
|
|
index,
|
|
) {
|
|
ProductModel productModel =
|
|
productList[index];
|
|
return FutureBuilder(
|
|
future:
|
|
FireStoreUtils.getVendorById(
|
|
productModel
|
|
.vendorID
|
|
.toString(),
|
|
),
|
|
builder: (
|
|
context,
|
|
vendorSnapshot,
|
|
) {
|
|
if (!vendorSnapshot
|
|
.hasData ||
|
|
vendorSnapshot
|
|
.connectionState ==
|
|
ConnectionState
|
|
.waiting) {
|
|
return const SizedBox(); // Show placeholder or loader
|
|
}
|
|
VendorModel?
|
|
vendorModel =
|
|
vendorSnapshot.data;
|
|
String price = "0.0";
|
|
String disPrice = "0.0";
|
|
List<String>
|
|
selectedVariants = [];
|
|
List<String>
|
|
selectedIndexVariants =
|
|
[];
|
|
List<String>
|
|
selectedIndexArray = [];
|
|
if (productModel
|
|
.itemAttribute !=
|
|
null) {
|
|
if (productModel
|
|
.itemAttribute!
|
|
.attributes!
|
|
.isNotEmpty) {
|
|
for (var element
|
|
in productModel
|
|
.itemAttribute!
|
|
.attributes!) {
|
|
if (element
|
|
.attributeOptions!
|
|
.isNotEmpty) {
|
|
selectedVariants.add(
|
|
productModel
|
|
.itemAttribute!
|
|
.attributes![productModel
|
|
.itemAttribute!
|
|
.attributes!
|
|
.indexOf(
|
|
element,
|
|
)]
|
|
.attributeOptions![0]
|
|
.toString(),
|
|
);
|
|
selectedIndexVariants
|
|
.add(
|
|
'${productModel.itemAttribute!.attributes!.indexOf(element)} _${productModel.itemAttribute!.attributes![0].attributeOptions![0].toString()}',
|
|
);
|
|
selectedIndexArray
|
|
.add(
|
|
'${productModel.itemAttribute!.attributes!.indexOf(element)}_0',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (productModel
|
|
.itemAttribute!
|
|
.variants!
|
|
.where(
|
|
(element) =>
|
|
element
|
|
.variantSku ==
|
|
selectedVariants
|
|
.join(
|
|
'-',
|
|
),
|
|
)
|
|
.isNotEmpty) {
|
|
price = Constant.productCommissionPrice(
|
|
vendorModel!,
|
|
productModel
|
|
.itemAttribute!
|
|
.variants!
|
|
.where(
|
|
(
|
|
element,
|
|
) =>
|
|
element.variantSku ==
|
|
selectedVariants.join(
|
|
'-',
|
|
),
|
|
)
|
|
.first
|
|
.variantPrice ??
|
|
'0',
|
|
);
|
|
disPrice = "0";
|
|
}
|
|
} else {
|
|
price =
|
|
Constant.productCommissionPrice(
|
|
vendorModel!,
|
|
productModel
|
|
.price
|
|
.toString(),
|
|
);
|
|
disPrice =
|
|
double.parse(
|
|
productModel
|
|
.disPrice
|
|
.toString(),
|
|
) <=
|
|
0
|
|
? "0"
|
|
: Constant.productCommissionPrice(
|
|
vendorModel,
|
|
productModel
|
|
.disPrice
|
|
.toString(),
|
|
);
|
|
}
|
|
return GestureDetector(
|
|
onTap: () async {
|
|
Get.to(
|
|
const RestaurantDetailsScreen(),
|
|
arguments: {
|
|
"vendorModel":
|
|
vendorModel,
|
|
},
|
|
);
|
|
},
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment
|
|
.start,
|
|
children: [
|
|
ClipRRect(
|
|
borderRadius:
|
|
BorderRadius.circular(
|
|
10,
|
|
),
|
|
child: SizedBox(
|
|
height: 90,
|
|
width:
|
|
Responsive.width(
|
|
100,
|
|
context,
|
|
),
|
|
child: NetworkImageWidget(
|
|
imageUrl:
|
|
productModel
|
|
.photo
|
|
.toString(),
|
|
fit:
|
|
BoxFit
|
|
.cover,
|
|
),
|
|
),
|
|
),
|
|
Column(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment
|
|
.start,
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment
|
|
.start,
|
|
children: [
|
|
Text(
|
|
productModel
|
|
.name!
|
|
.capitalizeString(),
|
|
textAlign:
|
|
TextAlign
|
|
.start,
|
|
maxLines: 1,
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
fontSize:
|
|
18,
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark600
|
|
: AppThemeData.grey600,
|
|
),
|
|
),
|
|
disPrice ==
|
|
"" ||
|
|
disPrice ==
|
|
"0"
|
|
? Text(
|
|
Constant.amountShow(
|
|
amount:
|
|
price,
|
|
),
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
fontSize:
|
|
16,
|
|
color:
|
|
AppThemeData.primary300,
|
|
),
|
|
)
|
|
: Column(
|
|
children: [
|
|
Text(
|
|
Constant.amountShow(
|
|
amount:
|
|
price,
|
|
),
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
fontSize:
|
|
14,
|
|
color:
|
|
Colors.grey,
|
|
decoration:
|
|
TextDecoration.lineThrough,
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width:
|
|
5,
|
|
),
|
|
Text(
|
|
Constant.amountShow(
|
|
amount:
|
|
disPrice,
|
|
),
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
fontSize:
|
|
14,
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark900
|
|
: AppThemeData.grey900,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color:
|
|
isDark
|
|
? AppThemeData.warning50
|
|
: AppThemeData.warning50,
|
|
borderRadius:
|
|
BorderRadius.circular(
|
|
30,
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal:
|
|
10,
|
|
vertical:
|
|
6,
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.center,
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.center,
|
|
mainAxisSize:
|
|
MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
Icons.star,
|
|
size:
|
|
18,
|
|
color:
|
|
AppThemeData.warning400,
|
|
),
|
|
Text(
|
|
"${Constant.calculateReview(reviewCount: productModel.reviewsCount.toString(), reviewSum: productModel.reviewsSum.toString())} (${productModel.reviewsSum})",
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
fontSize:
|
|
12,
|
|
color:
|
|
AppThemeData.warning400,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
RoundedButtonBorder(
|
|
radius: 10,
|
|
color:
|
|
isDark
|
|
? AppThemeData
|
|
.greyDark100
|
|
: AppThemeData
|
|
.grey100,
|
|
borderColor:
|
|
isDark
|
|
? AppThemeData
|
|
.greyDark200
|
|
: AppThemeData
|
|
.grey200,
|
|
title: 'View All Products',
|
|
onPress: () {
|
|
Get.to(
|
|
AllCategoryProductScreen(),
|
|
arguments: {
|
|
"categoryModel": item,
|
|
},
|
|
);
|
|
},
|
|
),
|
|
],
|
|
);
|
|
} else {
|
|
return SizedBox();
|
|
}
|
|
},
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
SizedBox(height: 10),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child:
|
|
controller.bannerModel.isEmpty
|
|
? const SizedBox()
|
|
: BannerBottomView(controller: controller),
|
|
),
|
|
// Visibility(
|
|
// visible: (Constant.isEnableAdsFeature == true && controller.advertisementList.isNotEmpty),
|
|
// child: const SizedBox(height: 20),
|
|
// ),
|
|
// Visibility(
|
|
// visible: Constant.isEnableAdsFeature == true,
|
|
// child:
|
|
// controller.advertisementList.isEmpty
|
|
// ? const SizedBox()
|
|
// : Container(
|
|
// color: AppThemeData.primary300.withAlpha(40),
|
|
// child: Padding(
|
|
// padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
|
// child: Column(
|
|
// mainAxisAlignment: MainAxisAlignment.start,
|
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
|
// children: [
|
|
// Row(
|
|
// children: [
|
|
// Expanded(
|
|
// child: Text(
|
|
// "Highlights for you".tr(),
|
|
// textAlign: TextAlign.start,
|
|
// style: TextStyle(
|
|
// fontFamily: AppThemeData.semiBold,
|
|
// fontSize: 16,
|
|
// color: isDark ? AppThemeData.grey50 : AppThemeData.grey900,
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// InkWell(
|
|
// onTap: () {
|
|
// Get.to(AllAdvertisementScreen())?.then((value) {
|
|
// controller.getFavouriteRestaurant();
|
|
// });
|
|
// },
|
|
// child: Text(
|
|
// "View all".tr(),
|
|
// textAlign: TextAlign.center,
|
|
// style: TextStyle(
|
|
// fontFamily: AppThemeData.regular,
|
|
// color: isDark ? AppThemeData.primary300 : AppThemeData.primary300,
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// const SizedBox(height: 16),
|
|
// SizedBox(
|
|
// height: 220,
|
|
// child: ListView.builder(
|
|
// physics: const BouncingScrollPhysics(),
|
|
// scrollDirection: Axis.horizontal,
|
|
// itemCount:
|
|
// controller.advertisementList.length >= 10
|
|
// ? 10
|
|
// : controller.advertisementList.length,
|
|
// padding: EdgeInsets.all(0),
|
|
// itemBuilder: (BuildContext context, int index) {
|
|
// return AdvertisementHomeCard(
|
|
// controller: controller,
|
|
// model: controller.advertisementList[index],
|
|
// );
|
|
// },
|
|
// ),
|
|
// ),
|
|
// ],
|
|
// ),
|
|
// ),
|
|
// ),
|
|
// ),
|
|
const SizedBox(height: 20),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"All Store".tr(),
|
|
textAlign: TextAlign.start,
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark900
|
|
: AppThemeData.grey900,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
ListView.builder(
|
|
padding: EdgeInsets.zero,
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
itemCount:
|
|
controller.allNearestRestaurant.length > 8
|
|
? 8
|
|
: controller
|
|
.allNearestRestaurant
|
|
.length,
|
|
itemBuilder: (context, index) {
|
|
VendorModel item =
|
|
controller.allNearestRestaurant[index];
|
|
return InkWell(
|
|
onTap: () {
|
|
Get.to(
|
|
const RestaurantDetailsScreen(),
|
|
arguments: {"vendorModel": item},
|
|
);
|
|
},
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(
|
|
bottom: 20,
|
|
),
|
|
child: Row(
|
|
children: [
|
|
ClipRRect(
|
|
borderRadius:
|
|
BorderRadius.circular(10),
|
|
child: NetworkImageWidget(
|
|
imageUrl: item.photo.toString(),
|
|
height: 80,
|
|
width: 130,
|
|
fit: BoxFit.cover,
|
|
),
|
|
),
|
|
SizedBox(width: 10),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
item.title.toString(),
|
|
style:
|
|
AppThemeData.semiBoldTextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData
|
|
.greyDark900
|
|
: AppThemeData
|
|
.grey900,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
Icons.location_on,
|
|
size: 14,
|
|
color: Colors.grey,
|
|
),
|
|
SizedBox(width: 4),
|
|
Expanded(
|
|
child: Text(
|
|
item.location
|
|
.toString(),
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
fontSize: 12,
|
|
color:
|
|
isDark
|
|
? AppThemeData
|
|
.greyDark500
|
|
: AppThemeData
|
|
.grey500,
|
|
),
|
|
overflow:
|
|
TextOverflow
|
|
.ellipsis,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color:
|
|
isDark
|
|
? AppThemeData
|
|
.warning50
|
|
: AppThemeData
|
|
.warning50,
|
|
borderRadius:
|
|
BorderRadius.circular(
|
|
30,
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding:
|
|
const EdgeInsets.symmetric(
|
|
horizontal: 10,
|
|
vertical: 6,
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment
|
|
.center,
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment
|
|
.center,
|
|
mainAxisSize:
|
|
MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
Icons.star,
|
|
size: 18,
|
|
color:
|
|
AppThemeData
|
|
.warning400,
|
|
),
|
|
Text(
|
|
"${Constant.calculateReview(reviewCount: item.reviewsCount.toString(), reviewSum: item.reviewsSum.toString())} (${item.reviewsSum})",
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
fontSize: 12,
|
|
color:
|
|
AppThemeData
|
|
.warning400,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
RoundedButtonBorder(
|
|
radius: 10,
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark100
|
|
: AppThemeData.grey100,
|
|
borderColor:
|
|
isDark
|
|
? AppThemeData.greyDark200
|
|
: AppThemeData.grey200,
|
|
title: 'View All Stores'.tr(),
|
|
onPress: () {
|
|
Get.to(
|
|
const RestaurantListScreen(),
|
|
arguments: {
|
|
"vendorList":
|
|
controller.allNearestRestaurant,
|
|
},
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class NewArrivalCard extends StatelessWidget {
|
|
final VendorModel item;
|
|
|
|
const NewArrivalCard({super.key, required this.item});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final themeController = Get.find<ThemeController>();
|
|
final isDark = themeController.isDark.value;
|
|
return InkWell(
|
|
onTap: () {
|
|
Get.to(
|
|
const RestaurantDetailsScreen(),
|
|
arguments: {"vendorModel": item},
|
|
);
|
|
},
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
ClipRRect(
|
|
borderRadius: BorderRadius.circular(10),
|
|
child: NetworkImageWidget(
|
|
height: 100,
|
|
width: double.infinity,
|
|
fit: BoxFit.cover,
|
|
imageUrl:
|
|
item.photo != null && item.photo!.isNotEmpty
|
|
? item.photo.toString()
|
|
: Constant.placeHolderImage.toString(),
|
|
),
|
|
),
|
|
SizedBox(height: 5),
|
|
Text(
|
|
item.title.toString(),
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
color: isDark ? AppThemeData.greyDark900 : AppThemeData.grey900,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
Row(
|
|
children: [
|
|
Icon(Icons.location_on, size: 14, color: Colors.grey),
|
|
SizedBox(width: 4),
|
|
Expanded(
|
|
child: Text(
|
|
item.location.toString(),
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
fontSize: 12,
|
|
color:
|
|
isDark
|
|
? AppThemeData.greyDark500
|
|
: AppThemeData.grey500,
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: isDark ? AppThemeData.warning50 : AppThemeData.warning50,
|
|
borderRadius: BorderRadius.circular(30),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(Icons.star, size: 18, color: AppThemeData.warning400),
|
|
Text(
|
|
"${Constant.calculateReview(reviewCount: item.reviewsCount.toString(), reviewSum: item.reviewsSum.toString())} (${item.reviewsSum})",
|
|
style: AppThemeData.semiBoldTextStyle(
|
|
fontSize: 12,
|
|
color: AppThemeData.warning400,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class BannerView extends StatelessWidget {
|
|
final HomeECommerceController controller;
|
|
|
|
const BannerView({super.key, required this.controller});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
children: [
|
|
SizedBox(
|
|
height: 160,
|
|
child: PageView.builder(
|
|
physics: const BouncingScrollPhysics(),
|
|
controller: controller.pageController.value,
|
|
scrollDirection: Axis.horizontal,
|
|
itemCount: controller.bannerModel.length,
|
|
padEnds: false,
|
|
pageSnapping: true,
|
|
allowImplicitScrolling: true,
|
|
onPageChanged: (value) {
|
|
controller.currentPage.value = value;
|
|
},
|
|
itemBuilder: (BuildContext context, int index) {
|
|
BannerModel bannerModel = controller.bannerModel[index];
|
|
return InkWell(
|
|
onTap: () async {
|
|
if (bannerModel.redirect_type == "store") {
|
|
ShowToastDialog.showLoader("Please wait...".tr());
|
|
VendorModel? vendorModel =
|
|
await FireStoreUtils.getVendorById(
|
|
bannerModel.redirect_id.toString(),
|
|
);
|
|
|
|
ShowToastDialog.closeLoader();
|
|
Get.to(
|
|
const RestaurantDetailsScreen(),
|
|
arguments: {"vendorModel": vendorModel},
|
|
);
|
|
} else if (bannerModel.redirect_type == "product") {
|
|
ShowToastDialog.showLoader("Please wait...".tr());
|
|
ProductModel? productModel =
|
|
await FireStoreUtils.getProductById(
|
|
bannerModel.redirect_id.toString(),
|
|
);
|
|
VendorModel? vendorModel =
|
|
await FireStoreUtils.getVendorById(
|
|
productModel!.vendorID.toString(),
|
|
);
|
|
|
|
ShowToastDialog.closeLoader();
|
|
Get.to(
|
|
const RestaurantDetailsScreen(),
|
|
arguments: {"vendorModel": vendorModel},
|
|
);
|
|
} else if (bannerModel.redirect_type == "external_link") {
|
|
final uri = Uri.parse(bannerModel.redirect_id.toString());
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(uri);
|
|
} else {
|
|
ShowToastDialog.showToast("Could not launch".tr());
|
|
}
|
|
}
|
|
},
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(right: 14),
|
|
child: ClipRRect(
|
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
|
child: NetworkImageWidget(
|
|
imageUrl: bannerModel.photo.toString(),
|
|
fit: BoxFit.cover,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: List.generate(controller.bannerModel.length, (index) {
|
|
return Obx(
|
|
() => Container(
|
|
margin: const EdgeInsets.only(right: 5),
|
|
alignment: Alignment.centerLeft,
|
|
height: 9,
|
|
width: 9,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color:
|
|
controller.currentPage.value == index
|
|
? AppThemeData.primary300
|
|
: Colors.black12,
|
|
),
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class BannerBottomView extends StatelessWidget {
|
|
final HomeECommerceController controller;
|
|
|
|
const BannerBottomView({super.key, required this.controller});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
children: [
|
|
SizedBox(
|
|
height: 150,
|
|
child: PageView.builder(
|
|
physics: const BouncingScrollPhysics(),
|
|
controller: controller.pageBottomController.value,
|
|
scrollDirection: Axis.horizontal,
|
|
itemCount: controller.bannerBottomModel.length,
|
|
padEnds: false,
|
|
pageSnapping: true,
|
|
allowImplicitScrolling: true,
|
|
onPageChanged: (value) {
|
|
controller.currentBottomPage.value = value;
|
|
},
|
|
itemBuilder: (BuildContext context, int index) {
|
|
BannerModel bannerModel = controller.bannerBottomModel[index];
|
|
return InkWell(
|
|
onTap: () async {
|
|
if (bannerModel.redirect_type == "store") {
|
|
ShowToastDialog.showLoader("Please wait...".tr());
|
|
VendorModel? vendorModel =
|
|
await FireStoreUtils.getVendorById(
|
|
bannerModel.redirect_id.toString(),
|
|
);
|
|
|
|
ShowToastDialog.closeLoader();
|
|
Get.to(
|
|
const RestaurantDetailsScreen(),
|
|
arguments: {"vendorModel": vendorModel},
|
|
);
|
|
} else if (bannerModel.redirect_type == "product") {
|
|
ShowToastDialog.showLoader("Please wait...".tr());
|
|
ProductModel? productModel =
|
|
await FireStoreUtils.getProductById(
|
|
bannerModel.redirect_id.toString(),
|
|
);
|
|
VendorModel? vendorModel =
|
|
await FireStoreUtils.getVendorById(
|
|
productModel!.vendorID.toString(),
|
|
);
|
|
|
|
ShowToastDialog.closeLoader();
|
|
Get.to(
|
|
const RestaurantDetailsScreen(),
|
|
arguments: {"vendorModel": vendorModel},
|
|
);
|
|
} else if (bannerModel.redirect_type == "external_link") {
|
|
final uri = Uri.parse(bannerModel.redirect_id.toString());
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(uri);
|
|
} else {
|
|
ShowToastDialog.showToast("Could not launch".tr());
|
|
}
|
|
}
|
|
},
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(right: 14),
|
|
child: ClipRRect(
|
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
|
child: NetworkImageWidget(
|
|
imageUrl: bannerModel.photo.toString(),
|
|
fit: BoxFit.cover,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 10),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: List.generate(controller.bannerBottomModel.length, (
|
|
index,
|
|
) {
|
|
return Obx(
|
|
() => Container(
|
|
margin: const EdgeInsets.only(right: 5),
|
|
alignment: Alignment.centerLeft,
|
|
height: 9,
|
|
width: 9,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color:
|
|
controller.currentBottomPage.value == index
|
|
? AppThemeData.primary300
|
|
: Colors.black12,
|
|
),
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class AdvertisementHomeCard extends StatelessWidget {
|
|
final AdvertisementModel model;
|
|
final HomeECommerceController controller;
|
|
|
|
const AdvertisementHomeCard({
|
|
super.key,
|
|
required this.controller,
|
|
required this.model,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final themeController = Get.find<ThemeController>();
|
|
final isDark = themeController.isDark.value;
|
|
return InkWell(
|
|
onTap: () async {
|
|
ShowToastDialog.showLoader("Please wait...".tr());
|
|
VendorModel? vendorModel = await FireStoreUtils.getVendorById(
|
|
model.vendorId!,
|
|
);
|
|
ShowToastDialog.closeLoader();
|
|
Get.to(
|
|
const RestaurantDetailsScreen(),
|
|
arguments: {"vendorModel": vendorModel},
|
|
);
|
|
},
|
|
child: Container(
|
|
margin: EdgeInsets.only(right: 16),
|
|
width: Responsive.width(70, context),
|
|
decoration: BoxDecoration(
|
|
color: isDark ? AppThemeData.info600 : AppThemeData.surface,
|
|
borderRadius: BorderRadius.circular(16),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.1),
|
|
blurRadius: isDark ? 6 : 2,
|
|
spreadRadius: 0,
|
|
offset: Offset(0, isDark ? 3 : 1),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Stack(
|
|
children: [
|
|
model.type == 'restaurant_promotion'
|
|
? ClipRRect(
|
|
borderRadius: BorderRadius.vertical(
|
|
top: Radius.circular(16),
|
|
),
|
|
child: NetworkImageWidget(
|
|
imageUrl: model.coverImage ?? '',
|
|
height: 135,
|
|
width: double.infinity,
|
|
fit: BoxFit.cover,
|
|
),
|
|
)
|
|
: VideoAdvWidget(
|
|
url: model.video ?? '',
|
|
height: 135,
|
|
width: double.infinity,
|
|
),
|
|
if (model.type != 'video_promotion' &&
|
|
model.vendorId != null &&
|
|
(model.showRating == true || model.showReview == true))
|
|
Positioned(
|
|
bottom: 8,
|
|
right: 8,
|
|
child: FutureBuilder(
|
|
future: FireStoreUtils.getVendorById(model.vendorId!),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState ==
|
|
ConnectionState.waiting) {
|
|
return const SizedBox();
|
|
} else {
|
|
if (snapshot.hasError) {
|
|
return const SizedBox();
|
|
} else if (snapshot.data == null) {
|
|
return const SizedBox();
|
|
} else {
|
|
VendorModel vendorModel = snapshot.data!;
|
|
return Container(
|
|
decoration: ShapeDecoration(
|
|
color:
|
|
isDark
|
|
? AppThemeData.primary600
|
|
: AppThemeData.primary50,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(120),
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 12,
|
|
vertical: 8,
|
|
),
|
|
child: Row(
|
|
children: [
|
|
if (model.showRating == true)
|
|
SvgPicture.asset(
|
|
"assets/icons/ic_star.svg",
|
|
colorFilter: ColorFilter.mode(
|
|
AppThemeData.primary300,
|
|
BlendMode.srcIn,
|
|
),
|
|
),
|
|
if (model.showRating == true)
|
|
const SizedBox(width: 5),
|
|
Text(
|
|
"${model.showRating == true ? Constant.calculateReview(reviewCount: vendorModel.reviewsCount!.toStringAsFixed(0), reviewSum: vendorModel.reviewsSum.toString()) : ''} ${model.showReview == true ? '(${vendorModel.reviewsCount!.toStringAsFixed(0)})' : ''}",
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
color:
|
|
isDark
|
|
? AppThemeData.primary300
|
|
: AppThemeData.primary300,
|
|
fontFamily: AppThemeData.semiBold,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
Padding(
|
|
padding: EdgeInsets.all(12),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
if (model.type == 'restaurant_promotion')
|
|
ClipRRect(
|
|
borderRadius: BorderRadius.circular(30),
|
|
child: NetworkImageWidget(
|
|
imageUrl: model.profileImage ?? '',
|
|
height: 50,
|
|
width: 50,
|
|
fit: BoxFit.cover,
|
|
),
|
|
),
|
|
SizedBox(width: 8),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
model.title ?? '',
|
|
style: TextStyle(
|
|
color:
|
|
isDark
|
|
? AppThemeData.grey50
|
|
: AppThemeData.grey900,
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
Text(
|
|
model.description ?? '',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontFamily: AppThemeData.medium,
|
|
color:
|
|
isDark
|
|
? AppThemeData.grey400
|
|
: AppThemeData.grey600,
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 2,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
model.type == 'restaurant_promotion'
|
|
? IconButton(
|
|
icon: Obx(
|
|
() =>
|
|
controller.favouriteList
|
|
.where(
|
|
(p0) =>
|
|
p0.restaurantId == model.vendorId,
|
|
)
|
|
.isNotEmpty
|
|
? SvgPicture.asset(
|
|
"assets/icons/ic_like_fill.svg",
|
|
)
|
|
: SvgPicture.asset(
|
|
"assets/icons/ic_like.svg",
|
|
colorFilter: ColorFilter.mode(
|
|
isDark
|
|
? AppThemeData.grey400
|
|
: AppThemeData.grey600,
|
|
BlendMode.srcIn,
|
|
),
|
|
),
|
|
),
|
|
onPressed: () async {
|
|
if (controller.favouriteList
|
|
.where((p0) => p0.restaurantId == model.vendorId)
|
|
.isNotEmpty) {
|
|
FavouriteModel favouriteModel = FavouriteModel(
|
|
restaurantId: model.vendorId,
|
|
userId: FireStoreUtils.getCurrentUid(),
|
|
);
|
|
controller.favouriteList.removeWhere(
|
|
(item) => item.restaurantId == model.vendorId,
|
|
);
|
|
await FireStoreUtils.removeFavouriteRestaurant(
|
|
favouriteModel,
|
|
);
|
|
} else {
|
|
FavouriteModel favouriteModel = FavouriteModel(
|
|
restaurantId: model.vendorId,
|
|
userId: FireStoreUtils.getCurrentUid(),
|
|
);
|
|
controller.favouriteList.add(favouriteModel);
|
|
await FireStoreUtils.setFavouriteRestaurant(
|
|
favouriteModel,
|
|
);
|
|
}
|
|
controller.update();
|
|
},
|
|
)
|
|
: Container(
|
|
decoration: ShapeDecoration(
|
|
color:
|
|
isDark
|
|
? AppThemeData.primary600
|
|
: AppThemeData.primary50,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(5),
|
|
),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 10,
|
|
vertical: 4,
|
|
),
|
|
child: Icon(
|
|
Icons.arrow_forward,
|
|
size: 20,
|
|
color: AppThemeData.primary300,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|