|
|
|
import 'package:after_layout/after_layout.dart';
|
|
|
|
import 'package:carousel_slider/carousel_slider.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/model/packages_offers/requests/AddProductToCartRequestModel.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/model/packages_offers/requests/CreateCustomerRequestModel.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/model/packages_offers/requests/OffersCategoriesRequestModel.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/model/packages_offers/requests/OffersProductsRequestModel.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesCustomerResponseModel.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesResponseModel.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/viewModels/packages_offers/PackagesOffersViewModel.dart';
|
|
|
|
import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/order_model_view_model.dart';
|
|
|
|
import 'package:diplomaticquarterapp/locator.dart';
|
|
|
|
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
|
|
|
|
import 'package:diplomaticquarterapp/pages/packages_offers/ClinicOfferAndPackagesPage.dart';
|
|
|
|
import 'package:diplomaticquarterapp/pages/packages_offers/CreateCustomerDailogPage.dart';
|
|
|
|
import 'package:diplomaticquarterapp/pages/packages_offers/OfferAndPackageDetailPage.dart';
|
|
|
|
import 'package:diplomaticquarterapp/pages/packages_offers/OfferAndPackagesCartPage.dart';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/utils.dart' as utils;
|
|
|
|
import 'package:diplomaticquarterapp/widgets/Loader/gif_loader_container.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/carousel_indicator/carousel_indicator.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/loadings/ShimmerLoading.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/offers_packages/PackagesOfferCard.dart';
|
|
|
|
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
|
|
|
|
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
|
|
|
|
import 'package:flutter/rendering.dart';
|
|
|
|
import 'package:flutter_material_pickers/flutter_material_pickers.dart';
|
|
|
|
|
|
|
|
dynamic languageID;
|
|
|
|
|
|
|
|
class PackagesHomePage extends StatefulWidget {
|
|
|
|
dynamic offersModel;
|
|
|
|
PackagesHomePage({@required this.offersModel});
|
|
|
|
|
|
|
|
@override
|
|
|
|
_PackagesHomePageState createState() => _PackagesHomePageState();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class _PackagesHomePageState extends State<PackagesHomePage> with AfterLayoutMixin<PackagesHomePage>{
|
|
|
|
getLanguageID() async {
|
|
|
|
languageID = await sharedPref.getString(APP_LANGUAGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
getLanguageID();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void afterFirstLayout(BuildContext context) async{
|
|
|
|
viewModel.service.loadOffersPackagesDataForMainPage(context: context, completion: (){
|
|
|
|
setState((){});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Controllers
|
|
|
|
var _searchTextController = TextEditingController();
|
|
|
|
var _filterTextController = TextEditingController();
|
|
|
|
var _carouselController = CarouselController();
|
|
|
|
|
|
|
|
|
|
|
|
int carouselIndicatorIndex = 0;
|
|
|
|
CarouselSlider _bannerCarousel;
|
|
|
|
TextField _textFieldSearch;
|
|
|
|
TextField _textFieldFilterSelection;
|
|
|
|
|
|
|
|
ListView _listViewLatestOffers;
|
|
|
|
ListView _listViewBestSeller;
|
|
|
|
|
|
|
|
PackagesViewModel viewModel;
|
|
|
|
|
|
|
|
onCartClick(){
|
|
|
|
if (viewModel.service.customer == null){
|
|
|
|
utils.Utils.showErrorToast("Cart is empty for your current session");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Navigator.of(context).push(
|
|
|
|
MaterialPageRoute(
|
|
|
|
builder: (BuildContext context) => PackagesCartPage()
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
onProductCartClick(PackagesResponseModel product) async {
|
|
|
|
if(viewModel.service.customer == null)
|
|
|
|
viewModel.service.customer = await CreateCustomerDialogPage(context: context).show();
|
|
|
|
|
|
|
|
if(viewModel.service.customer != null) {
|
|
|
|
var request = AddProductToCartRequestModel(product_id: product.id, customer_id: viewModel.service.customer.id);
|
|
|
|
await viewModel.service.addProductToCart(request, context: context).then((response){
|
|
|
|
appScaffold.appBar.badgeUpdater(viewModel.service.cartItemCount);
|
|
|
|
}).catchError((error) {
|
|
|
|
utils.Utils.showErrorToast(error);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AppScaffold appScaffold;
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return BaseView<PackagesViewModel>(
|
|
|
|
allowAny: true,
|
|
|
|
onModelReady: (model) => viewModel = model,
|
|
|
|
builder: (_, model, wi){
|
|
|
|
return
|
|
|
|
appScaffold =
|
|
|
|
AppScaffold(
|
|
|
|
appBarTitle: TranslationBase.of(context).offerAndPackages,
|
|
|
|
isShowAppBar: true,
|
|
|
|
isPharmacy: false,
|
|
|
|
showPharmacyCart: false,
|
|
|
|
showHomeAppBarIcon: false,
|
|
|
|
isOfferPackages: true,
|
|
|
|
showOfferPackagesCart: true,
|
|
|
|
isShowDecPage: false,
|
|
|
|
body: ListView(
|
|
|
|
children: [
|
|
|
|
|
|
|
|
// Top Banner Carousel
|
|
|
|
AspectRatio(
|
|
|
|
aspectRatio: 2.2/1,
|
|
|
|
child: bannerCarousel()
|
|
|
|
),
|
|
|
|
|
|
|
|
Center(
|
|
|
|
child: CarouselIndicator(
|
|
|
|
activeColor: Theme.of(context).appBarTheme.color,
|
|
|
|
color: Colors.grey[300],
|
|
|
|
cornerRadius: 15,
|
|
|
|
width: 15, height: 15,
|
|
|
|
count: _bannerCarousel.itemCount,
|
|
|
|
index: carouselIndicatorIndex,
|
|
|
|
onClick: (index){
|
|
|
|
debugPrint('onClick at ${index}');
|
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
|
|
|
|
SizedBox(height: 10,),
|
|
|
|
|
|
|
|
Padding(
|
|
|
|
padding: const EdgeInsets.all(15),
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
// Search Textfield
|
|
|
|
searchTextField(),
|
|
|
|
|
|
|
|
SizedBox(height: 10,),
|
|
|
|
|
|
|
|
// Filter Selection
|
|
|
|
filterOptionSelection(),
|
|
|
|
|
|
|
|
SizedBox(height: 20,),
|
|
|
|
|
|
|
|
// Horizontal Scrollable Cards
|
|
|
|
Texts(
|
|
|
|
"Latest offers",
|
|
|
|
fontWeight: FontWeight.bold,
|
|
|
|
color: Colors.black87,
|
|
|
|
fontSize: 20
|
|
|
|
),
|
|
|
|
|
|
|
|
// Latest Offers Horizontal Scrollable List
|
|
|
|
AspectRatio(
|
|
|
|
aspectRatio: 1.3/1,
|
|
|
|
child: LayoutBuilder(builder: (context, constraints){
|
|
|
|
double itemContentPadding = 10;
|
|
|
|
double itemWidth = (constraints.maxWidth/2) - (itemContentPadding*2);
|
|
|
|
return latestOfferListView(itemWidth: itemWidth, itemContentPadding: itemContentPadding);
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
|
|
|
|
SizedBox(height: 10,),
|
|
|
|
|
|
|
|
Texts(
|
|
|
|
"Best sellers",
|
|
|
|
fontWeight: FontWeight.bold,
|
|
|
|
color: Colors.black87,
|
|
|
|
fontSize: 20
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
// Best Seller Horizontal Scrollable List
|
|
|
|
AspectRatio(
|
|
|
|
aspectRatio: 1.3/1,
|
|
|
|
child: LayoutBuilder(builder: (context, constraints){
|
|
|
|
double itemContentPadding = 10; // 10 is content padding in each item
|
|
|
|
double itemWidth = (constraints.maxWidth/2) - (itemContentPadding*2 /* 2 = LeftRight */);
|
|
|
|
return bestSellerListView(itemWidth: itemWidth, itemContentPadding: itemContentPadding);
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
|
|
|
|
],),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
.setOnAppBarCartClick(onCartClick);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
showClinicSelectionList() async {
|
|
|
|
var clinics = viewModel.service.categoryList;
|
|
|
|
if(clinics.isEmpty) {
|
|
|
|
GifLoaderDialogUtils.showMyDialog(context);
|
|
|
|
clinics = await viewModel.service.getAllCategories(OffersCategoriesRequestModel());
|
|
|
|
GifLoaderDialogUtils.hideDialog(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
List<String> options = clinics.map((e) => e.toString()).toList();
|
|
|
|
|
|
|
|
showMaterialSelectionPicker(
|
|
|
|
context: context,
|
|
|
|
title: "Select Clinic",
|
|
|
|
items: options,
|
|
|
|
selectedItem: options.first,
|
|
|
|
onChanged: (value) async {
|
|
|
|
var selectedClinic = clinics.firstWhere((element) => element.toString() == value);
|
|
|
|
var clinicProducts = await viewModel.service.getAllProducts(request: OffersProductsRequestModel(categoryId: selectedClinic.id), context: context, showLoading: true);
|
|
|
|
if(clinicProducts.isNotEmpty)
|
|
|
|
Navigator.of(context).push(
|
|
|
|
MaterialPageRoute(
|
|
|
|
builder: (BuildContext context) => ClinicPackagesPage(products: clinicProducts)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
else
|
|
|
|
utils.Utils.showErrorToast("No offers available for this clinic");
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------
|
|
|
|
// Main Widgets of Page
|
|
|
|
//----------------------------------
|
|
|
|
|
|
|
|
CarouselSlider bannerCarousel(){
|
|
|
|
_bannerCarousel = CarouselSlider.builder(
|
|
|
|
carouselController: _carouselController,
|
|
|
|
itemCount: 10,
|
|
|
|
itemBuilder: (BuildContext context, int itemIndex) {
|
|
|
|
return Padding(
|
|
|
|
padding: const EdgeInsets.only(top: 10, bottom: 10, left: 15, right: 15),
|
|
|
|
child: FractionallySizedBox(
|
|
|
|
widthFactor: 1,
|
|
|
|
heightFactor: 1,
|
|
|
|
child: utils.applyShadow(
|
|
|
|
spreadRadius: 1,
|
|
|
|
blurRadius: 5,
|
|
|
|
child: InkWell(
|
|
|
|
child: ClipRRect(
|
|
|
|
borderRadius: BorderRadius.circular(10),
|
|
|
|
child: utils.Utils.loadNetworkImage(url: "https://wallpaperaccess.com/full/30103.jpg",)
|
|
|
|
),
|
|
|
|
onTap: (){
|
|
|
|
Navigator.of(context).push(
|
|
|
|
MaterialPageRoute(
|
|
|
|
builder: (BuildContext context) => OfferAndPackagesDetail(model: "",)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
},
|
|
|
|
)
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
options: CarouselOptions(
|
|
|
|
autoPlayInterval: Duration(milliseconds: 3500),
|
|
|
|
enlargeStrategy: CenterPageEnlargeStrategy.scale,
|
|
|
|
enlargeCenterPage: true,
|
|
|
|
autoPlay: false,
|
|
|
|
autoPlayCurve: Curves.fastOutSlowIn,
|
|
|
|
enableInfiniteScroll: true,
|
|
|
|
autoPlayAnimationDuration: Duration(milliseconds: 1500),
|
|
|
|
viewportFraction: 1,
|
|
|
|
onPageChanged: (page, reason){
|
|
|
|
setState(() {
|
|
|
|
carouselIndicatorIndex = page;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
),
|
|
|
|
);
|
|
|
|
return _bannerCarousel;
|
|
|
|
}
|
|
|
|
|
|
|
|
TextField searchTextField(){
|
|
|
|
return _textFieldSearch =
|
|
|
|
TextField(
|
|
|
|
controller: _searchTextController,
|
|
|
|
decoration: InputDecoration(
|
|
|
|
contentPadding: EdgeInsets.only(top: 0.0, bottom: 0.0, left: 10, right: 10),
|
|
|
|
enabledBorder: OutlineInputBorder(
|
|
|
|
borderSide: BorderSide( width: 0.5, color: Colors.grey),
|
|
|
|
borderRadius: const BorderRadius.all(
|
|
|
|
const Radius.circular(10.0),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
focusedBorder: OutlineInputBorder(
|
|
|
|
borderSide: BorderSide( width: 1, color: Colors.grey),
|
|
|
|
borderRadius: const BorderRadius.all(
|
|
|
|
const Radius.circular(10.0),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
filled: true,
|
|
|
|
fillColor: Colors.white,
|
|
|
|
hintText: "Search",
|
|
|
|
hintStyle: TextStyle(color: Colors.grey[350], fontWeight: FontWeight.bold),
|
|
|
|
suffixIcon: IconButton(
|
|
|
|
onPressed: (){
|
|
|
|
// viewModel.search(text: _searchTextController.text);
|
|
|
|
},
|
|
|
|
icon: Icon(Icons.search_rounded, size: 35,),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget filterOptionSelection(){
|
|
|
|
_textFieldFilterSelection =
|
|
|
|
TextField(
|
|
|
|
enabled: false,
|
|
|
|
controller: _searchTextController,
|
|
|
|
decoration: InputDecoration(
|
|
|
|
contentPadding: EdgeInsets.only(top: 0.0, bottom: 0.0, left: 10, right: 10),
|
|
|
|
border: OutlineInputBorder(
|
|
|
|
borderSide: BorderSide(color: Colors.grey, width: 1),
|
|
|
|
borderRadius: const BorderRadius.all(
|
|
|
|
const Radius.circular(10.0),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
disabledBorder: OutlineInputBorder(
|
|
|
|
borderSide: BorderSide( width: 0.5, color: Colors.grey),
|
|
|
|
borderRadius: const BorderRadius.all(
|
|
|
|
const Radius.circular(10.0),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
focusedBorder: OutlineInputBorder(
|
|
|
|
borderRadius: const BorderRadius.all(
|
|
|
|
const Radius.circular(10.0),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
filled: true,
|
|
|
|
fillColor: Colors.white,
|
|
|
|
hintText: "Browse offers by Clinic",
|
|
|
|
hintStyle: TextStyle(color: Colors.grey[350], fontWeight: FontWeight.bold),
|
|
|
|
suffixIcon: IconButton(
|
|
|
|
onPressed: (){
|
|
|
|
showClinicSelectionList();
|
|
|
|
},
|
|
|
|
icon: Icon(Icons.keyboard_arrow_down_rounded, size: 35, color: Colors.grey,),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
return InkWell(
|
|
|
|
child: _textFieldFilterSelection,
|
|
|
|
onTap: (){
|
|
|
|
showClinicSelectionList();
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget latestOfferListView({@required double itemWidth, @required double itemContentPadding}){
|
|
|
|
return _listViewLatestOffers =
|
|
|
|
ListView.separated(
|
|
|
|
scrollDirection: Axis.horizontal,
|
|
|
|
itemCount: viewModel.bestSellerList.length,
|
|
|
|
itemBuilder: (BuildContext context, int index) {
|
|
|
|
return PackagesItemCard(itemWidth: itemWidth, itemContentPadding: itemContentPadding, itemModel: viewModel.bestSellerList[index], onCartClick: onProductCartClick,);
|
|
|
|
},
|
|
|
|
separatorBuilder: separator,
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget bestSellerListView({@required double itemWidth, @required double itemContentPadding}){
|
|
|
|
return _listViewLatestOffers =
|
|
|
|
ListView.separated(
|
|
|
|
scrollDirection: Axis.horizontal,
|
|
|
|
itemCount: viewModel.bestSellerList.length,
|
|
|
|
itemBuilder: (BuildContext context, int index) {
|
|
|
|
return PackagesItemCard(itemWidth: itemWidth, itemContentPadding: itemContentPadding, itemModel: viewModel.bestSellerList[index], onCartClick: onProductCartClick,);
|
|
|
|
},
|
|
|
|
separatorBuilder: separator,
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Widget separator(BuildContext context, int index){
|
|
|
|
return Container(
|
|
|
|
width: 1,
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
gradient: LinearGradient(
|
|
|
|
begin: Alignment(-1.0, -2.0),
|
|
|
|
end: Alignment(1.0, 4.0),
|
|
|
|
colors: [
|
|
|
|
Colors.grey,
|
|
|
|
Colors.grey[100],
|
|
|
|
Colors.grey[200],
|
|
|
|
Colors.grey[300],
|
|
|
|
Colors.grey[400],
|
|
|
|
Colors.grey[500]
|
|
|
|
]
|
|
|
|
)),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|