add loader and cache on images

merge-update-with-lab-changes
Elham Rababh 4 years ago
parent 1e1e230908
commit 47e19c4ab5

@ -36,7 +36,7 @@ class ProductDetailViewModel extends BaseViewModel{
Future getProductLocationData() async {
hasError = false;
setState(ViewState.Busy);
setState(ViewState.BusyLocal);
await _productDetailService.getProductAvailabiltyDetail();
if (_productDetailService.hasError) {
error = _productDetailService.error;

@ -6,80 +6,76 @@ import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart';
import 'package:flutter/material.dart';
class AvailabilityInfo extends StatelessWidget {
final ProductDetailViewModel previousModel;
const AvailabilityInfo({Key key, this.previousModel}) : super(key: key);
@override
Widget build(BuildContext context) {
return BaseView<ProductDetailViewModel>(
onModelReady: (model) => model.getProductLocationData(),
allowAny: true,
builder: (_, model, wi) => NetworkBaseView(
baseViewModel: model,
child: model.productLocationService.length == 0
? Container(
padding: EdgeInsets.all(15),
alignment: Alignment.center,
child: Text(
TranslationBase.of(context).noLocationAvailable,
),
)
: ListView.builder(
physics: ScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: model.productLocationService.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: EdgeInsets.all(8.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: Image.network(model
.productLocationService[index].projectImageUrl),
),
SizedBox(
width: 10,
),
Expanded(
flex: 4,
child: Text(
model.productLocationService[index]
.locationDescription +
"\n" +
convertCityName(
model.productLocationService[0].cityName
.toString(),
),
style: TextStyle(fontSize: 12),
),
),
Expanded(
flex: 1,
child: IconButton(
icon: Icon(Icons.location_on),
color: Colors.red,
onPressed: () {},
),
),
Expanded(
flex: 1,
child: IconButton(
icon: Icon(Icons.phone),
color: Colors.red,
onPressed: () {},
),
),
],
),
Divider(height: 1.2, color: Colors.grey)
],
return previousModel.productLocationService.length == 0
? Container(
padding: EdgeInsets.all(15),
alignment: Alignment.center,
child: Text(
TranslationBase.of(context).noLocationAvailable,
),
)
: ListView.builder(
physics: ScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: previousModel.productLocationService.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: EdgeInsets.all(8.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: Image.network(previousModel
.productLocationService[index].projectImageUrl),
),
SizedBox(
width: 10,
),
Expanded(
flex: 4,
child: Text(
previousModel.productLocationService[index]
.locationDescription +
"\n" +
convertCityName(
previousModel.productLocationService[0].cityName
.toString(),
),
style: TextStyle(fontSize: 12),
),
),
Expanded(
flex: 1,
child: IconButton(
icon: Icon(Icons.location_on),
color: Colors.red,
onPressed: () {},
),
);
},
),
Expanded(
flex: 1,
child: IconButton(
icon: Icon(Icons.phone),
color: Colors.red,
onPressed: () {},
),
),
],
),
),
Divider(height: 1.2, color: Colors.grey)
],
),
);
},
);
}
}

@ -1,5 +1,4 @@
import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:flutter/material.dart';
class DiscountDescription extends StatelessWidget {

@ -1,8 +1,5 @@
import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart';
import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart';
import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
import 'package:diplomaticquarterapp/pages/login/login.dart';
import 'package:diplomaticquarterapp/pages/login/welcome.dart';
import 'package:diplomaticquarterapp/pages/pharmacies/screens/product-details/footor/quantity_box.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.dart';

@ -25,7 +25,7 @@ import 'package:diplomaticquarterapp/core/model/pharmacies/recommendedProduct_mo
import '../cart-order-page.dart';
import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'ProductAppBar.dart';
import 'shared/product_details_app_bar.dart';
import 'availability_info.dart';
import 'details_info.dart';
import 'discount_description.dart';
@ -102,304 +102,228 @@ class __ProductDetailPageState extends State<ProductDetailPage>
}
Widget build(BuildContext context) {
ProjectViewModel projectViewModel = Provider.of(context);
final screenSize = MediaQuery.of(context).size;
return AppScaffold(
appBarTitle: TranslationBase.of(context).productDetails,
isShowAppBar: true,
isPharmacy: true,
isShowDecPage: false,
customAppBar: ProductAppBar(product: widget.product,),
body: SingleChildScrollView(
child: Column(
children: [
Container(
width: double.infinity,
color: Colors.white,
child: Column(
children: [
if (widget.product.images.isNotEmpty)
Container(
height: MediaQuery.of(context).size.height * .40,
child: Image.network(
widget.product.images[0].src.trim(),
fit: BoxFit.contain,
return BaseView<ProductDetailViewModel>(
allowAny: true,
builder: (_, model, wi) => AppScaffold(
appBarTitle: TranslationBase.of(context).productDetails,
isShowAppBar: true,
isPharmacy: true,
isShowDecPage: false,
customAppBar: ProductAppBar(
product: widget.product,
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
width: double.infinity,
color: Colors.white,
child: Column(
children: [
if (widget.product.images.isNotEmpty)
Container(
height: MediaQuery.of(context).size.height * .40,
child: Image.network(
widget.product.images[0].src.trim(),
fit: BoxFit.contain,
),
),
),
if (widget.product.discountDescription != null)
DiscountDescription(product: widget.product)
],
if (widget.product.discountDescription != null)
DiscountDescription(product: widget.product)
],
),
),
),
SizedBox(
height: 4,
),
Container(
color: Colors.white,
child: ProductNameAndPrice(
context,
widget.product,
customerId: customerId,
addToWishlistFunction: (item) {
addToWishlistFunction(item);
setState(() {});
},
deleteFromWishlistFunction: (item) {
deleteFromWishlistFunction(item);
setState(() {});
},
notifyMeWhenAvailable: (context, itemId) {
notifyMeWhenAvailable(context, itemId);
},
isInWishList: isInWishList,
SizedBox(
height: 4,
),
),
SizedBox(
height: 6,
),
Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(
vertical: 15, horizontal: 10),
child: Texts(
TranslationBase.of(context).specification,
fontSize: 15,
fontWeight: FontWeight.bold,
Container(
color: Colors.white,
child: ProductNameAndPrice(
context,
widget.product,
customerId: customerId,
addToWishlistFunction: (item) {
addToWishlistFunction(item);
setState(() {});
},
deleteFromWishlistFunction: (item) {
deleteFromWishlistFunction(item);
setState(() {});
},
notifyMeWhenAvailable: (context, itemId) {
notifyMeWhenAvailable(context, itemId);
},
isInWishList: isInWishList,
),
),
SizedBox(
height: 6,
),
Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(
vertical: 15, horizontal: 10),
child: Texts(
TranslationBase.of(context).specification,
fontSize: 15,
fontWeight: FontWeight.bold,
),
width: double.infinity,
),
width: double.infinity,
),
// Divider(color: Colors.grey),
],
// Divider(color: Colors.grey),
],
),
),
),
SizedBox(
height: 6,
),
// Container(
// height: 500,
// color: Colors.white,
// child: Scaffold(
// backgroundColor: Colors.white,
// extendBodyBehindAppBar: false,
// appBar: PreferredSize(
// preferredSize: Size.fromHeight(
// MediaQuery.of(context).size.height * 0.070),
// child: Container(
// height: MediaQuery.of(context).size.height * 0.070,
// decoration: BoxDecoration(
// border: Border(
// bottom: BorderSide(
// color: Theme.of(context).dividerColor,
// width: 0.5), //width: 0.7
// ),
// color: Colors.white),
// child: Center(
// child: TabBar(
// isScrollable: false,
// controller: _tabController,
// // indicatorColor: Colors.transparent,
// indicatorWeight: 1.0,
// indicatorSize: TabBarIndicatorSize.tab,
// indicatorColor:Colors.green,
// labelColor: Theme.of(context).primaryColor,
// labelPadding: EdgeInsets.only(
// top: 0, left: 0, right: 0, bottom: 0),
// unselectedLabelColor: Colors.grey[800],
// tabs: [
// tabWidget(screenSize, _activeTab == 0,
// TranslationBase.of(context).details,
// ),
// tabWidget(screenSize, _activeTab == 1,
// TranslationBase.of(context).review,
// ),
// tabWidget(screenSize, _activeTab == 2,
// TranslationBase.of(context).availability),
// ],
// ),
// ),
// ),
// ),
// body: Column(
// children: [
// Expanded(
// child: TabBarView(
// physics: BouncingScrollPhysics(),
// controller: _tabController,
// children: [
// DetailsInfo(
// product: widget.product,
// ),
// ReviewsInfo(
// product: widget.product,
// ),
// AvailabilityInfo()
// ],
// ),
// ),
//
// ],
// ),
// ),
// ),
SizedBox(
height: 6,
),
//TODO Elham* Remove this
Container(
// width: 500,
margin: EdgeInsets.only(bottom: 6),
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
FlatButton(
onPressed: () {
setState(() {
isDetails = true;
isReviews = false;
isAvailability = false;
});
},
child: Text(
TranslationBase.of(context).details,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
SizedBox(
height: 6,
),
Container(
// width: 500,
margin: EdgeInsets.only(bottom: 6),
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
FlatButton(
onPressed: () {
setState(() {
isDetails = true;
isReviews = false;
isAvailability = false;
});
},
child: Text(
TranslationBase.of(context).details,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
),
color: Colors.white,
),
color: Colors.white,
),
CustomDivider(
color: isDetails
? Colors.green
: Colors.transparent,
)
],
),
SizedBox(
width: 20,
),
Column(
children: [
FlatButton(
onPressed: () {
setState(() {
isDetails = false;
isReviews = true;
isAvailability = false;
});
},
child: Text(
TranslationBase.of(context).reviews,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
CustomDivider(
color: isDetails
? Colors.green
: Colors.transparent,
)
],
),
SizedBox(
width: 20,
),
Column(
children: [
FlatButton(
onPressed: () async {
if(widget.product.approvedTotalReviews>0) {
GifLoaderDialogUtils.showMyDialog(
context);
await model.getProductReviewsData(
widget.product.id);
GifLoaderDialogUtils.hideDialog(context);
}
setState(() {
isDetails = false;
isReviews = true;
isAvailability = false;
});
},
child: Text(
TranslationBase.of(context).reviews,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
),
color: Colors.white,
),
color: Colors.white,
),
CustomDivider(
color: isReviews
? Colors.green
: Colors.transparent,
),
],
),
SizedBox(
width: 20,
),
Column(
children: [
FlatButton(
onPressed: () {
setState(() {
isDetails = false;
isReviews = false;
isAvailability = true;
});
},
child: Text(
TranslationBase.of(context).availability,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
CustomDivider(
color: isReviews
? Colors.green
: Colors.transparent,
),
color: Colors.white,
),
CustomDivider(
color: isAvailability
? Colors.green
: Colors.transparent,
),
],
),
],
),
SizedBox(
height: 10,
),
isDetails
? DetailsInfo(
product: widget.product,
)
: isReviews
? ReviewsInfo(
product: widget.product,
)
: isAvailability
? AvailabilityInfo()
: Container(),
],
),
),
///TODO Elham* check if we need recommanded
// Row(
// children: [
// customerId != null
// ? Container(
// width: 410,
// height: 50,
// color: Colors.white,
// child: Texts(
// TranslationBase.of(context).recommended,
// bold: true,
// ),
// )
// : Container(),
// ],
// ),
// RecommendedProducts(product: widget.product)
],
),
SizedBox(
width: 20,
),
Column(
children: [
FlatButton(
onPressed: () async {
GifLoaderDialogUtils.showMyDialog(
context);
await model.getProductLocationData();
GifLoaderDialogUtils.hideDialog(context);
SizedBox(
height: 80,
)
],
setState(() {
isDetails = false;
isReviews = false;
isAvailability = true;
});
},
child: Text(
TranslationBase.of(context).availability,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
),
color: Colors.white,
),
CustomDivider(
color: isAvailability
? Colors.green
: Colors.transparent,
),
],
),
],
),
SizedBox(
height: 10,
),
isDetails
? DetailsInfo(
product: widget.product,
)
: isReviews
? ReviewsInfo(
product: widget.product,
previousModel: model,
)
: isAvailability
? AvailabilityInfo(
previousModel: model,
)
: Container(),
],
),
),
SizedBox(
height: 80,
)
],
),
),
),
bottomSheet: FooterWidget(
widget.product.stockAvailability != 'Out of stock',
widget.product.orderMaximumQuantity,
widget.product.orderMinimumQuantity,
widget.product.stockQuantity,
widget.product,
price: price,
isOverQuantity: isOverQuantity,
addToCartFunction: addToCartFunction,
),
);
bottomSheet: FooterWidget(
widget.product.stockAvailability != 'Out of stock',
widget.product.orderMaximumQuantity,
widget.product.orderMinimumQuantity,
widget.product.stockQuantity,
widget.product,
price: price,
isOverQuantity: isOverQuantity,
addToCartFunction: addToCartFunction,
),
));
}
}

@ -10,7 +10,7 @@ import 'package:provider/provider.dart';
import 'package:rating_bar/rating_bar.dart';
import '../../../../locator.dart';
import 'CustomIcon.dart';
import 'shared/icon_with_bg.dart';
class ProductNameAndPrice extends StatefulWidget {
BuildContext context;

@ -1,97 +1,89 @@
import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart';
import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/product_detail_view_model.dart';
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart';
import 'package:flutter/material.dart';
import 'package:rating_bar/rating_bar.dart';
class ReviewsInfo extends StatelessWidget {
final PharmacyProduct product;
final ProductDetailViewModel previousModel;
const ReviewsInfo({Key key, this.product}) : super(key: key);
const ReviewsInfo({Key key, this.product, this.previousModel}) : super(key: key);
@override
Widget build(BuildContext context) {
return BaseView<ProductDetailViewModel>(
onModelReady: (model) => model.getProductReviewsData(product.id),
allowAny: true,
builder: (_, model, wi) => NetworkBaseView(
baseViewModel:model ,
child: model.productDetailService.length != 0 &&
model.productDetailService[0].reviews.length != 0
? ListView.builder(
physics: ScrollPhysics(),
itemCount: model.productDetailService[0].reviews.length,
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: Row(
children: [
Container(
child: Text(
model.productDetailService[0].reviews[index]
.customerId
.toString(),
style: TextStyle(
fontSize: 17,
color: Colors.grey,
fontWeight: FontWeight.w600),
),
),
Container(
margin: EdgeInsets.only(left: 210),
child: RatingBar.readOnly(
initialRating: model.productDetailService[0]
.reviews[index].rating
.toDouble(),
size: 15.0,
filledColor: Colors.yellow[700],
emptyColor: Colors.grey[500],
isHalfAllowed: true,
halfFilledIcon: Icons.star_half,
filledIcon: Icons.star,
emptyIcon: Icons.star,
),
),
],
),
),
SizedBox(
height: 10,
),
Container(
child: Text(
model.productDetailService[0].reviews[index]
.reviewText,
style: TextStyle(fontSize: 20),
),
),
SizedBox(
height: 50,
),
Divider(height: 1, color: Colors.grey),
],
return previousModel.productDetailService.length != 0 &&
previousModel.productDetailService[0].reviews.length != 0
? ListView.builder(
physics: ScrollPhysics(),
itemCount: previousModel.productDetailService[0].reviews.length,
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: Row(
children: [
Container(
child: Text(
previousModel.productDetailService[0].reviews[index]
.customerId
.toString(),
style: TextStyle(
fontSize: 17,
color: Colors.grey,
fontWeight: FontWeight.w600),
),
),
);
},
)
: Container(
padding: EdgeInsets.all(15),
alignment: Alignment.center,
Container(
margin: EdgeInsets.only(left: 210),
child: RatingBar.readOnly(
initialRating: previousModel.productDetailService[0]
.reviews[index].rating
.toDouble(),
size: 15.0,
filledColor: Colors.yellow[700],
emptyColor: Colors.grey[500],
isHalfAllowed: true,
halfFilledIcon: Icons.star_half,
filledIcon: Icons.star,
emptyIcon: Icons.star,
),
),
],
),
),
SizedBox(
height: 10,
),
Container(
child: Text(
TranslationBase.of(context).noReviewsAvailable,
previousModel.productDetailService[0].reviews[index]
.reviewText,
style: TextStyle(fontSize: 20),
),
// Text('No Reviews Available'),
),
SizedBox(
height: 50,
),
Divider(height: 1, color: Colors.grey),
],
),
);
},
)
: Container(
padding: EdgeInsets.all(15),
alignment: Alignment.center,
child: Text(
TranslationBase.of(context).noReviewsAvailable,
),
// Text('No Reviews Available'),
);
}
}

@ -11,7 +11,6 @@ class IconWithBg extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
// margin: EdgeInsets.only(left: 25),
width: 40,
height: 40,
decoration: BoxDecoration(

@ -7,10 +7,10 @@ import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
import '../../../../locator.dart';
import '../../compare-list.dart';
import '../cart-order-page.dart';
import 'CustomIcon.dart';
import '../../../../../locator.dart';
import '../../../compare-list.dart';
import '../../cart-order-page.dart';
import 'icon_with_bg.dart';
class ProductAppBar extends StatelessWidget with PreferredSizeWidget {
Loading…
Cancel
Save