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 { Future getProductLocationData() async {
hasError = false; hasError = false;
setState(ViewState.Busy); setState(ViewState.BusyLocal);
await _productDetailService.getProductAvailabiltyDetail(); await _productDetailService.getProductAvailabiltyDetail();
if (_productDetailService.hasError) { if (_productDetailService.hasError) {
error = _productDetailService.error; error = _productDetailService.error;

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

@ -1,8 +1,5 @@
import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart';
import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.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/pages/pharmacies/screens/product-details/footor/quantity_box.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/buttons/secondary_button.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 '../cart-order-page.dart';
import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart'; import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'ProductAppBar.dart'; import 'shared/product_details_app_bar.dart';
import 'availability_info.dart'; import 'availability_info.dart';
import 'details_info.dart'; import 'details_info.dart';
import 'discount_description.dart'; import 'discount_description.dart';
@ -102,304 +102,228 @@ class __ProductDetailPageState extends State<ProductDetailPage>
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
ProjectViewModel projectViewModel = Provider.of(context); return BaseView<ProductDetailViewModel>(
final screenSize = MediaQuery.of(context).size; allowAny: true,
builder: (_, model, wi) => AppScaffold(
return AppScaffold( appBarTitle: TranslationBase.of(context).productDetails,
appBarTitle: TranslationBase.of(context).productDetails, isShowAppBar: true,
isShowAppBar: true, isPharmacy: true,
isPharmacy: true, isShowDecPage: false,
isShowDecPage: false, customAppBar: ProductAppBar(
customAppBar: ProductAppBar(product: widget.product,), product: widget.product,
body: SingleChildScrollView( ),
child: Column( body: SingleChildScrollView(
children: [ child: Column(
Container( children: [
width: double.infinity, Container(
color: Colors.white, width: double.infinity,
child: Column( color: Colors.white,
children: [ child: Column(
if (widget.product.images.isNotEmpty) children: [
Container( if (widget.product.images.isNotEmpty)
height: MediaQuery.of(context).size.height * .40, Container(
child: Image.network( height: MediaQuery.of(context).size.height * .40,
widget.product.images[0].src.trim(), child: Image.network(
fit: BoxFit.contain, widget.product.images[0].src.trim(),
fit: BoxFit.contain,
),
), ),
), if (widget.product.discountDescription != null)
if (widget.product.discountDescription != null) DiscountDescription(product: widget.product)
DiscountDescription(product: widget.product) ],
], ),
), ),
), SizedBox(
SizedBox( height: 4,
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,
), ),
), Container(
SizedBox( color: Colors.white,
height: 6, child: ProductNameAndPrice(
), context,
Container( widget.product,
color: Colors.white, customerId: customerId,
child: Column( addToWishlistFunction: (item) {
mainAxisAlignment: MainAxisAlignment.start, addToWishlistFunction(item);
crossAxisAlignment: CrossAxisAlignment.start, setState(() {});
children: [ },
Container( deleteFromWishlistFunction: (item) {
padding: EdgeInsets.symmetric( deleteFromWishlistFunction(item);
vertical: 15, horizontal: 10), setState(() {});
child: Texts( },
TranslationBase.of(context).specification, notifyMeWhenAvailable: (context, itemId) {
fontSize: 15, notifyMeWhenAvailable(context, itemId);
fontWeight: FontWeight.bold, },
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(
SizedBox( height: 6,
height: 6, ),
), Container(
// Container( // width: 500,
// height: 500, margin: EdgeInsets.only(bottom: 6),
// color: Colors.white, color: Colors.white,
// child: Scaffold( child: Column(
// backgroundColor: Colors.white, crossAxisAlignment: CrossAxisAlignment.start,
// extendBodyBehindAppBar: false, children: [
// appBar: PreferredSize( Row(
// preferredSize: Size.fromHeight( mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// MediaQuery.of(context).size.height * 0.070), children: [
// child: Container( Column(
// height: MediaQuery.of(context).size.height * 0.070, children: [
// decoration: BoxDecoration( FlatButton(
// border: Border( onPressed: () {
// bottom: BorderSide( setState(() {
// color: Theme.of(context).dividerColor, isDetails = true;
// width: 0.5), //width: 0.7 isReviews = false;
// ), isAvailability = false;
// color: Colors.white), });
// child: Center( },
// child: TabBar( child: Text(
// isScrollable: false, TranslationBase.of(context).details,
// controller: _tabController, style: TextStyle(
// // indicatorColor: Colors.transparent, fontSize: 16,
// indicatorWeight: 1.0, fontWeight: FontWeight.bold),
// indicatorSize: TabBarIndicatorSize.tab, ),
// indicatorColor:Colors.green, color: Colors.white,
// 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),
), ),
color: Colors.white, CustomDivider(
), color: isDetails
CustomDivider( ? Colors.green
color: isDetails : Colors.transparent,
? Colors.green )
: Colors.transparent, ],
) ),
], SizedBox(
), width: 20,
SizedBox( ),
width: 20, Column(
), children: [
Column( FlatButton(
children: [ onPressed: () async {
FlatButton( if(widget.product.approvedTotalReviews>0) {
onPressed: () { GifLoaderDialogUtils.showMyDialog(
setState(() { context);
isDetails = false; await model.getProductReviewsData(
isReviews = true; widget.product.id);
isAvailability = false; GifLoaderDialogUtils.hideDialog(context);
}); }
}, setState(() {
child: Text( isDetails = false;
TranslationBase.of(context).reviews, isReviews = true;
style: TextStyle( isAvailability = false;
fontSize: 16, });
fontWeight: FontWeight.bold), },
child: Text(
TranslationBase.of(context).reviews,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold),
),
color: Colors.white,
), ),
color: Colors.white, CustomDivider(
), color: isReviews
CustomDivider( ? Colors.green
color: isReviews : Colors.transparent,
? 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),
), ),
color: Colors.white, ],
), ),
CustomDivider( SizedBox(
color: isAvailability width: 20,
? Colors.green ),
: Colors.transparent, Column(
), children: [
], FlatButton(
), onPressed: () async {
], GifLoaderDialogUtils.showMyDialog(
), context);
SizedBox( await model.getProductLocationData();
height: 10, GifLoaderDialogUtils.hideDialog(context);
),
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( setState(() {
height: 80, 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(
bottomSheet: FooterWidget( widget.product.stockAvailability != 'Out of stock',
widget.product.stockAvailability != 'Out of stock', widget.product.orderMaximumQuantity,
widget.product.orderMaximumQuantity, widget.product.orderMinimumQuantity,
widget.product.orderMinimumQuantity, widget.product.stockQuantity,
widget.product.stockQuantity, widget.product,
widget.product, price: price,
price: price, isOverQuantity: isOverQuantity,
isOverQuantity: isOverQuantity, addToCartFunction: addToCartFunction,
addToCartFunction: addToCartFunction, ),
), ));
);
} }
} }

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

@ -1,97 +1,89 @@
import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart'; import 'package:diplomaticquarterapp/core/model/pharmacies/PharmacyProduct.dart';
import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/product_detail_view_model.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/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rating_bar/rating_bar.dart'; import 'package:rating_bar/rating_bar.dart';
class ReviewsInfo extends StatelessWidget { class ReviewsInfo extends StatelessWidget {
final PharmacyProduct product; 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BaseView<ProductDetailViewModel>( return previousModel.productDetailService.length != 0 &&
onModelReady: (model) => model.getProductReviewsData(product.id), previousModel.productDetailService[0].reviews.length != 0
allowAny: true, ? ListView.builder(
builder: (_, model, wi) => NetworkBaseView( physics: ScrollPhysics(),
baseViewModel:model , itemCount: previousModel.productDetailService[0].reviews.length,
child: model.productDetailService.length != 0 && scrollDirection: Axis.vertical,
model.productDetailService[0].reviews.length != 0 shrinkWrap: true,
? ListView.builder( itemBuilder: (BuildContext context, int index) {
physics: ScrollPhysics(), return Padding(
itemCount: model.productDetailService[0].reviews.length, padding: EdgeInsets.all(8.0),
scrollDirection: Axis.vertical, child: Column(
shrinkWrap: true, mainAxisAlignment: MainAxisAlignment.start,
itemBuilder: (BuildContext context, int index) { crossAxisAlignment: CrossAxisAlignment.start,
return Padding( children: [
padding: EdgeInsets.all(8.0), Container(
child: Column( child: Row(
mainAxisAlignment: MainAxisAlignment.start, children: [
crossAxisAlignment: CrossAxisAlignment.start, Container(
children: [ child: Text(
Container( previousModel.productDetailService[0].reviews[index]
child: Row( .customerId
children: [ .toString(),
Container( style: TextStyle(
child: Text( fontSize: 17,
model.productDetailService[0].reviews[index] color: Colors.grey,
.customerId fontWeight: FontWeight.w600),
.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),
],
), ),
); Container(
}, margin: EdgeInsets.only(left: 210),
) child: RatingBar.readOnly(
: Container( initialRating: previousModel.productDetailService[0]
padding: EdgeInsets.all(15), .reviews[index].rating
alignment: Alignment.center, .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( 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
// margin: EdgeInsets.only(left: 25),
width: 40, width: 40,
height: 40, height: 40,
decoration: BoxDecoration( decoration: BoxDecoration(

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