Offers & discounts UI updating

merge-requests/493/head
haroon amjad 4 years ago
parent d5c68c5032
commit 502c7fd3de

@ -1630,4 +1630,6 @@ const Map localizedValues = {
"RRTTitle": {"en": "RRT", "ar": "خدمة فريق"},
"RRTSubTitle": {"en": "Service", "ar": "الاستجابة السريع"},
"transportation": {"en": "Transportation", "ar": "النقل"},
"myCart": {"en": "Cart", "ar": "عربة التسوق"},
"browseOffers": {"en": "Browse offers by clinic", "ar": "تصفح العروض حسب العيادة"},
};

@ -192,6 +192,8 @@ class PackagesResponseModel with JsonConvert<PackagesResponseModel> {
List<dynamic> discountIds;
@JSONField(name: "store_ids")
List<dynamic> storeIds;
@JSONField(name: "store_names")
List<dynamic> storeNames;
@JSONField(name: "manufacturer_ids")
List<int> manufacturerIds;
List<dynamic> reviews;

@ -110,6 +110,7 @@ class OffersAndPackagesServices extends BaseService {
var url = EXA_CART_API_BASE_URL + PACKAGES_PRODUCTS;
await baseAppClient.simpleGet(url, headers: packagesAuthHeader,
onSuccess: (dynamic stringResponse, int statusCode) {
latestOffersList.clear();
if (statusCode == 200) {
var jsonResponse = json.decode(stringResponse);
jsonResponse['products'].forEach((json) {

@ -313,6 +313,12 @@ offerProductsResponseModelFromJson(PackagesResponseModel data, Map<String, dynam
data.storeIds = new List<dynamic>();
data.storeIds.addAll(json['store_ids']);
}
if (json['store_names'] != null) {
data.storeNames = new List<dynamic>();
data.storeNames.addAll(json['store_names']);
}
if (json['manufacturer_ids'] != null) {
data.manufacturerIds = json['manufacturer_ids']?.map((v) => v?.toInt())?.toList()?.cast<int>();
}

@ -5,6 +5,7 @@ import 'package:diplomaticquarterapp/core/viewModels/dashboard_view_model.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart';
import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart';
import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart';
import 'package:diplomaticquarterapp/models/gradient_color.dart';
import 'package:diplomaticquarterapp/models/hmg_services.dart';
import 'package:diplomaticquarterapp/models/slider_data.dart';
@ -282,7 +283,7 @@ class _HomePageFragment2State extends State<HomePageFragment2> {
flex: 1,
child: InkWell(
onTap: () {
final user = projectViewModel.user;
AuthenticatedUser user = projectViewModel.user;
Navigator.of(context).push(MaterialPageRoute(builder: (context) => PackagesHomePage(user)));
},
child: Container(

@ -1,214 +1,254 @@
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesResponseModel.dart';
import 'package:diplomaticquarterapp/core/viewModels/packages_offers/PackagesOffersViewModel.dart';
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
import 'package:diplomaticquarterapp/pages/pharmacies/ProductCheckTypeWidget.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart' as utils;
import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
import 'package:diplomaticquarterapp/widgets/others/StarRating.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:expandable/expandable.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:html/parser.dart';
import 'package:rating_bar/rating_bar.dart';
class OfferAndPackagesDetail extends StatefulWidget{
class OfferAndPackagesDetail extends StatefulWidget {
final PackagesResponseModel itemModel;
final Function(PackagesResponseModel product) onCartClick;
const OfferAndPackagesDetail({@required this.itemModel, Key key}) : super(key: key);
const OfferAndPackagesDetail({@required this.itemModel, @required this.onCartClick, Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => OfferAndPackagesDetailState();
}
class OfferAndPackagesDetailState extends State<OfferAndPackagesDetail>{
class OfferAndPackagesDetailState extends State<OfferAndPackagesDetail> {
PackagesViewModel viewModel;
bool expandFlag = false;
var controller = new ExpandableController();
@override
Widget build(BuildContext context) {
return BaseView<PackagesViewModel>(
onModelReady: (model){
onModelReady: (model) {
viewModel = model;
},
builder: (_, model, wi) => AppScaffold(
appBarTitle: TranslationBase.of(context).offerAndPackages,
isShowAppBar: true,
isPharmacy: false,
showPharmacyCart: false,
showHomeAppBarIcon: false,
isOfferPackages: true,
showOfferPackagesCart: true,
isShowDecPage: false,
body: Stack(
appBarTitle: TranslationBase.of(context).offerAndPackages,
isShowAppBar: true,
isPharmacy: false,
showPharmacyCart: false,
showHomeAppBarIcon: false,
isOfferPackages: true,
showOfferPackagesCart: true,
isShowDecPage: false,
showNewAppBar: true,
showNewAppBarTitle: true,
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 60),
child: ListView(
children: [
Padding(
padding: const EdgeInsets.all(5),
child: Stack(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: AspectRatio(
aspectRatio: 1/1,
child: utils.applyShadow(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: utils.Utils.loadNetworkImage(url: "https://wallpaperaccess.com/full/30103.jpg",)
),
)
),
),
Align(
alignment: Alignment.topLeft,
child: Image.asset(
'assets/images/discount_${'en'}.png',
height: 70,
width: 70,
),
),
],
),
Container(
color: Colors.white,
padding: const EdgeInsets.all(21.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: Image.network("https://mdlaboratories.com/offersdiscounts/images/thumbs/0000162_dermatology-testing.jpeg", fit: BoxFit.fill),
),
),
Container(
padding: const EdgeInsets.only(left: 21.0, right: 21.0, top: 21.0),
child: Text(widget.itemModel.name, maxLines: 1, style: TextStyle(fontSize: 19.0, fontWeight: FontWeight.bold, letterSpacing: -1.14))),
Container(
padding: const EdgeInsets.only(left: 21.0, right: 21.0),
child: Text(widget.itemModel.shortDescription,
maxLines: 2, style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w600, letterSpacing: -0.56, color: CustomColors.textColor), overflow: TextOverflow.clip)),
Row(
children: [
Container(
padding: const EdgeInsets.only(left: 21.0, right: 21.0, top: 12.0),
child: RatingBar.readOnly(
initialRating: 4.5,
size: 18.0,
filledColor: Color(0XFFD02127),
emptyColor: Color(0XFFD02127),
isHalfAllowed: true,
halfFilledIcon: Icons.star_half,
filledIcon: Icons.star,
emptyIcon: Icons.star_border,
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Texts(
"Child Dental Offer",
fontSize: 25,
fontWeight: FontWeight.normal,
color: Colors.black,
),
Stack(
children: [
Texts(
"200 SAR",
fontWeight: FontWeight.normal,
decoration: TextDecoration.lineThrough,
color: Colors.grey,
fontSize: 12
),
Padding(
padding: const EdgeInsets.only(top: 15),
child: Texts(
"894.99 SAR",
fontWeight: FontWeight.bold,
color: Colors.green,
fontSize: 18
),
],
),
Container(
padding: const EdgeInsets.only(left: 21.0, right: 21.0, top: 18.0),
width: double.infinity,
height: 50.0,
child: ListView.separated(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: widget.itemModel.storeNames.length,
separatorBuilder: (context, index) {
return mWidth(5.0);
},
itemBuilder: (BuildContext context, int index) {
return contactButton(widget.itemModel.storeNames[index].toString());
},
),
),
Container(
padding: const EdgeInsets.only(top: 18.0),
child: ExpandableNotifier(
initialExpanded: true,
child: Container(
color: Colors.white,
child: Column(
children: <Widget>[
ScrollOnExpand(
scrollOnExpand: true,
scrollOnCollapse: false,
child: ExpandablePanel(
hasIcon: false,
theme: const ExpandableThemeData(
headerAlignment: ExpandablePanelHeaderAlignment.center,
tapBodyToCollapse: true,
),
header: Padding(
padding: const EdgeInsets.only(top: 20, bottom: 20, left: 21, right: 21),
child: InkWell(
onTap: () {
setState(() {
expandFlag = !expandFlag;
controller.expanded = expandFlag;
});
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
TranslationBase.of(context).description,
maxLines: 1,
style: TextStyle(fontSize: 19.0, fontWeight: FontWeight.bold, letterSpacing: -1.14),
),
],
),
),
Icon(
expandFlag ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
color: Color(0xff2E303A),
),
],
),
),
],
),
StarRating(
size: 20,
totalCount: null,
totalAverage: 5,
forceStars: true),
SizedBox(height: 20,),
Texts(
"Details",
fontWeight: FontWeight.bold,
color: Colors.grey,
fontSize: 20
),
AspectRatio(
aspectRatio: 2/1,
child: Container(
color: Colors.grey[300],
child: Padding(
padding: const EdgeInsets.all(10),
child: Texts("Detail of offers written here"),
)
),
builder: (_, collapsed, expanded) {
return Expandable(
controller: controller,
collapsed: collapsed,
expanded: Container(
padding: const EdgeInsets.only(left: 21.0, right: 21.0, bottom: 21.0),
child: Text(parseHtmlString(widget.itemModel.fullDescription),
style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w600, letterSpacing: -0.56, color: CustomColors.textColor), overflow: TextOverflow.clip)),
theme: const ExpandableThemeData(crossFadePoint: 0),
);
},
),
SizedBox(height: 10,),
],
),
),
],
),
),
),
),
],
),
),
bottomSheet: Container(
padding: const EdgeInsets.only(top: 16, bottom: 16, left: 21, right: 21),
color: Colors.white,
child: Row(
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if(widget.itemModel.hasDiscountsApplied) Container(
margin: const EdgeInsets.only(top: 0.0),
child: Text(widget.itemModel.oldPrice.toString() + " " + TranslationBase.of(context).sar,
style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.w600, letterSpacing: -0.6, decoration: TextDecoration.lineThrough, color: CustomColors.grey2))),
Container(
margin: const EdgeInsets.only(top: 0.0),
child: Text(widget.itemModel.price.toString().trim() + " " + TranslationBase.of(context).sar,
style: TextStyle(fontSize: 19.0, fontWeight: FontWeight.bold, letterSpacing: -0.56))),
],
),
),
Padding(
padding: const EdgeInsets.all(10),
child: Align(
alignment: Alignment.bottomRight,
child: Row(
children: [
Expanded(
child: RaisedButton.icon(
padding: EdgeInsets.only(top: 5, bottom: 5, left: 0, right: 0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
side: BorderSide(color: Colors.red, width: 0.5)
),
color: Colors.red,
icon: Icon(
Icons.add_shopping_cart_outlined,
size: 25,
color: Colors.white,
),
label: Texts(
"Add to Cart",
fontSize: 17, color: Colors.white, fontWeight: FontWeight.normal,
),
onPressed: (){},),
),
SizedBox(width: 15,),
Expanded(
child: OutlineButton.icon(
padding: EdgeInsets.only(top: 5, bottom: 5, left: 0, right: 0),
borderSide: BorderSide(width: 1.0, color: Colors.red),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
SizedBox(width: 8),
Expanded(
child: SizedBox(
height: 43,
width: double.infinity,
child: FlatButton(
onPressed: () {
// onCartClick();
widget.onCartClick(widget.itemModel);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: SvgPicture.asset("assets/images/new/add-to-cart.svg", color: Colors.white),
),
Container(
child: Text(
TranslationBase.of(context).addToCart,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.48),
),
color: Colors.white,
icon: Icon(
Icons.favorite_rounded,
size: 25,
color: Colors.red,
),
label: Texts(
"Add to Favorites",
fontSize: 17, color: Colors.red, fontWeight: FontWeight.normal
),
onPressed: (){
},),
),
],
),
],
),
color: const Color(0xffD02127),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
),
),
)
),
],
),
),
),
);
}
String parseHtmlString(String htmlString) {
var document = parse(htmlString);
String parsedString = parse(document.body.text).documentElement.text;
return parsedString;
}
],
)
Widget contactButton(String title) {
return SizedBox(
height: 32,
width: 80.0,
child: FlatButton(
onPressed: () {},
color: Colors.white,
shape: StadiumBorder(side: BorderSide(color: CustomColors.devider, width: 1)),
child: Text(
title,
style: TextStyle(fontSize: 10, letterSpacing: -0.4, color: CustomColors.textColor),
maxLines: 1,
),
),
);
}
}

@ -32,20 +32,18 @@ class PackagesCartPage extends StatefulWidget {
_PackagesCartPageState createState() => _PackagesCartPageState();
}
class _PackagesCartPageState extends State<PackagesCartPage>
with AfterLayoutMixin<PackagesCartPage>, SingleTickerProviderStateMixin {
class _PackagesCartPageState extends State<PackagesCartPage> with AfterLayoutMixin<PackagesCartPage>, SingleTickerProviderStateMixin {
getLanguageID() async {
languageID = await sharedPref.getString(APP_LANGUAGE);
}
double subtotal,tax, total;
double subtotal, tax, total;
@override
void initState() {
_agreeTerms = false;
_selectedPaymentMethod = null;
_animationController =
AnimationController(vsync: this, duration: Duration(seconds: 500));
_animationController = AnimationController(vsync: this, duration: Duration(seconds: 500));
super.initState();
}
@ -69,22 +67,13 @@ class _PackagesCartPageState extends State<PackagesCartPage>
}
onPayNowClick() async {
await viewModel.service
.placeOrder(
context: context,
paymentParams: _selectedPaymentParams)
.then((orderId) {
await viewModel.service.placeOrder(context: context, paymentParams: _selectedPaymentParams).then((orderId) {
if (orderId.runtimeType == int) {
// result == order_id
var browser = MyInAppBrowser(
context: context,
onExitCallback: (data, isDone) => paymentClosed(
orderId: orderId, withStatus: isDone, data: data));
browser.openPackagesPaymentBrowser(
customer_id: viewModel.service.customer.id, order_id: orderId);
var browser = MyInAppBrowser(context: context, onExitCallback: (data, isDone) => paymentClosed(orderId: orderId, withStatus: isDone, data: data));
browser.openPackagesPaymentBrowser(customer_id: viewModel.service.customer.id, order_id: orderId);
} else {
utils.Utils.showErrorToast(
'Failed to place order, please try again later');
utils.Utils.showErrorToast('Failed to place order, please try again later');
}
}).catchError((error) {
utils.Utils.showErrorToast(error.toString());
@ -111,56 +100,48 @@ class _PackagesCartPageState extends State<PackagesCartPage>
isOfferPackages: true,
showOfferPackagesCart: false,
isShowDecPage: false,
showNewAppBar: true,
showNewAppBarTitle: true,
body: Column(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(5),
child: StaggeredGridView.countBuilder(
crossAxisCount: (_columnCount * _columnCount),
itemCount: viewModel.cartItemList.length,
itemBuilder: (BuildContext context, int index) {
var item = viewModel.cartItemList[index];
return Dismissible(
key: Key(index.toString()),
direction: DismissDirection.startToEnd,
background: _cartItemDeleteContainer(),
secondaryBackground: _cartItemDeleteContainer(),
confirmDismiss: (direction) async {
bool status = await viewModel.service
.deleteProductFromCart(item.id,
context: context, showLoading: false);
return status;
},
onDismissed: (direction) {
debugPrint('Index: $index');
viewModel.cartItemList.removeAt(index);
},
child: PackagesCartItemCard(
itemModel: item,
shouldStepperChangeApply: (apply, total) async {
var request = AddProductToCartRequestModel(
product_id: item.productId,
quantity: apply);
ResponseModel response = await viewModel
.service
.addProductToCart(request,
context: context, showLoading: false)
.catchError((error) {
utils.Utils.showErrorToast(error);
});
if(response.status){
fetchData();
}
return response.status ?? false;
},
));
},
staggeredTileBuilder: (int index) =>
StaggeredTile.fit(_columnCount),
mainAxisSpacing: 0,
crossAxisSpacing: 10,
)),
child: StaggeredGridView.countBuilder(
crossAxisCount: (_columnCount * _columnCount),
itemCount: viewModel.cartItemList.length,
itemBuilder: (BuildContext context, int index) {
var item = viewModel.cartItemList[index];
return Dismissible(
key: Key(index.toString()),
direction: DismissDirection.startToEnd,
background: _cartItemDeleteContainer(),
secondaryBackground: _cartItemDeleteContainer(),
confirmDismiss: (direction) async {
bool status = await viewModel.service.deleteProductFromCart(item.id, context: context, showLoading: false);
return status;
},
onDismissed: (direction) {
viewModel.cartItemList.removeAt(index);
},
child: PackagesCartItemCard(
itemModel: item,
viewModel: viewModel,
getCartItems: fetchData,
shouldStepperChangeApply: (apply, total) async {
var request = AddProductToCartRequestModel(product_id: item.productId, quantity: apply);
ResponseModel response = await viewModel.service.addProductToCart(request, context: context, showLoading: false).catchError((error) {
utils.Utils.showErrorToast(error);
});
if (response.status) {
fetchData();
}
return response.status ?? false;
},
));
},
staggeredTileBuilder: (int index) => StaggeredTile.fit(_columnCount),
mainAxisSpacing: 0,
crossAxisSpacing: 10,
),
),
Container(
height: 0.25,
@ -170,8 +151,7 @@ class _PackagesCartPageState extends State<PackagesCartPage>
color: Colors.white,
child: Column(
children: [
Texts(TranslationBase.of(context).selectPaymentOption,
fontSize: 10, fontWeight: FontWeight.bold),
Texts(TranslationBase.of(context).selectPaymentOption, fontSize: 10, fontWeight: FontWeight.bold),
Container(
height: 0.25,
width: 100,
@ -184,11 +164,7 @@ class _PackagesCartPageState extends State<PackagesCartPage>
height: 0.25,
color: Colors.grey[300],
),
Container(
height: 40,
child: _termsAndCondition(context,
onSelected: onTermsClick,
onInfoClick: onTermsInfoClick)),
Container(height: 40, child: _termsAndCondition(context, onSelected: onTermsClick, onInfoClick: onTermsInfoClick)),
Container(
height: 0.25,
color: Colors.grey[300],
@ -204,7 +180,7 @@ class _PackagesCartPageState extends State<PackagesCartPage>
}
fetchData() async {
await viewModel.service.cartItems(context: context).then((value){
await viewModel.service.cartItems(context: context).then((value) {
subtotal = value['subtotal'] ?? 0.0;
tax = value['tax'] ?? 0.0;
total = value['total'] ?? 0.0;
@ -213,15 +189,12 @@ class _PackagesCartPageState extends State<PackagesCartPage>
setState(() {});
}
paymentClosed(
{@required int orderId, @required bool withStatus, dynamic data}) async {
paymentClosed({@required int orderId, @required bool withStatus, dynamic data}) async {
viewModel.service.getOrderById(orderId, context: context).then((value) {
var heading = withStatus ? "Success" : "Failed";
var title = withStatus ? "Your order has been placed successfully" : "Failed to place your order";
var title = withStatus ? "Your order has been placed successfully" : "Failed to place your order";
var subTitle = "Order# ${value.data.customOrderNumber}";
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => PackageOrderCompletedPage(
heading: heading, title: title, subTitle: subTitle)));
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => PackageOrderCompletedPage(heading: heading, title: title, subTitle: subTitle)));
}).catchError((error) {
debugPrint(error);
});
@ -231,7 +204,8 @@ class _PackagesCartPageState extends State<PackagesCartPage>
// /* Payment Footer Widgets */
// ---------------------------
String _selectedPaymentMethod;
Map<dynamic,dynamic> _selectedPaymentParams;
Map<dynamic, dynamic> _selectedPaymentParams;
Widget _paymentOptions(BuildContext context, Function(String) onSelected, {PackagesViewModel viewModel}) {
double height = 30;
@ -247,18 +221,17 @@ Widget _paymentOptions(BuildContext context, Function(String) onSelected, {Packa
),
],
borderRadius: BorderRadius.all(Radius.circular(5)),
border: Border.all(
color: isSelected ? Colors.green : Colors.grey,
width: isSelected ? 1 : 0.5)),
border: Border.all(color: isSelected ? Colors.green : Colors.grey, width: isSelected ? 1 : 0.5)),
child: Padding(
padding: const EdgeInsets.all(4),
child: Image.asset('assets/images/new-design/$imageName'),
));
}
Future<String> selectTamaraPaymentOption() async{
Future<String> selectTamaraPaymentOption() async {
final tamara_options = await viewModel.service.getTamaraOptions(context: context, showLoading: true);
final selected = await SingleSelectionDialog<TamaraPaymentOption>(tamara_options, icon: Image.asset('assets/images/new-design/tamara.png'), title: TranslationBase.of(context).tamaraInstPlan).show(context);
final selected =
await SingleSelectionDialog<TamaraPaymentOption>(tamara_options, icon: Image.asset('assets/images/new-design/tamara.png'), title: TranslationBase.of(context).tamaraInstPlan).show(context);
return selected.name;
}
@ -272,9 +245,9 @@ Widget _paymentOptions(BuildContext context, Function(String) onSelected, {Packa
children: [
InkWell(
child: buttonContent(_selectedPaymentMethod == "tamara", 'tamara.png'),
onTap: () async{
onTap: () async {
final tamara_option = await selectTamaraPaymentOption();
_selectedPaymentParams = {"channel" : "Web", "payment_method_system_name" : "Payments.Tamara", "payment_option" : tamara_option};
_selectedPaymentParams = {"channel": "Web", "payment_method_system_name": "Payments.Tamara", "payment_option": tamara_option};
onSelected("tamara");
},
),
@ -284,7 +257,7 @@ Widget _paymentOptions(BuildContext context, Function(String) onSelected, {Packa
InkWell(
child: buttonContent(_selectedPaymentMethod == "mada", 'mada.png'),
onTap: () {
_selectedPaymentParams = {"payment_method_system_name" : "Payments.PayFort", "payment_option" : "MADA"};
_selectedPaymentParams = {"payment_method_system_name": "Payments.PayFort", "payment_option": "MADA"};
onSelected("mada");
},
),
@ -294,7 +267,7 @@ Widget _paymentOptions(BuildContext context, Function(String) onSelected, {Packa
InkWell(
child: buttonContent(_selectedPaymentMethod == "visa", 'visa.png'),
onTap: () {
_selectedPaymentParams = {"payment_method_system_name" : "Payments.PayFort", "payment_option" : "VISA"};
_selectedPaymentParams = {"payment_method_system_name": "Payments.PayFort", "payment_option": "VISA"};
onSelected("visa");
},
),
@ -304,7 +277,7 @@ Widget _paymentOptions(BuildContext context, Function(String) onSelected, {Packa
InkWell(
child: buttonContent(_selectedPaymentMethod == "mastercard", 'mastercard.png'),
onTap: () {
_selectedPaymentParams = {"payment_method_system_name" : "Payments.PayFort", "payment_option" : "MASTERCARD"};
_selectedPaymentParams = {"payment_method_system_name": "Payments.PayFort", "payment_option": "MASTERCARD"};
onSelected("mastercard");
},
),
@ -326,17 +299,15 @@ Widget _paymentOptions(BuildContext context, Function(String) onSelected, {Packa
}
bool _agreeTerms = false;
Widget _termsAndCondition(BuildContext context,
{@required Function(bool) onSelected, @required VoidCallback onInfoClick}) {
Widget _termsAndCondition(BuildContext context, {@required Function(bool) onSelected, @required VoidCallback onInfoClick}) {
return Padding(
padding: const EdgeInsets.all(5),
child: Row(
children: [
InkWell(
child: Icon(
_agreeTerms
? Icons.check_circle
: Icons.radio_button_unchecked_sharp,
_agreeTerms ? Icons.check_circle : Icons.radio_button_unchecked_sharp,
size: 20,
color: _agreeTerms ? Colors.green[600] : Colors.grey[400],
),
@ -386,18 +357,8 @@ Widget _payNow(BuildContext context, {double subtotal, double tax, double total,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Texts(
'${TranslationBase.of(context).subtotal}: $_subtotal ${TranslationBase.of(context).sar}',
heightFactor: 1.5,
fontWeight: FontWeight.bold,
color: Colors.grey,
fontSize: 8),
Texts(
'${TranslationBase.of(context).vat}: $_tax ${TranslationBase.of(context).sar}',
heightFactor: 1.5,
fontWeight: FontWeight.bold,
color: Colors.grey,
fontSize: 8),
Texts('${TranslationBase.of(context).subtotal}: $_subtotal ${TranslationBase.of(context).sar}', heightFactor: 1.5, fontWeight: FontWeight.bold, color: Colors.grey, fontSize: 8),
Texts('${TranslationBase.of(context).vat}: $_tax ${TranslationBase.of(context).sar}', heightFactor: 1.5, fontWeight: FontWeight.bold, color: Colors.grey, fontSize: 8),
Padding(
padding: const EdgeInsets.all(3),
child: Container(
@ -406,12 +367,7 @@ Widget _payNow(BuildContext context, {double subtotal, double tax, double total,
color: Colors.grey[300],
),
),
Texts(
'${TranslationBase.of(context).total}: $_total ${TranslationBase.of(context).sar}',
heightFactor: 1.5,
fontWeight: FontWeight.bold,
color: Colors.black54,
fontSize: 15)
Texts('${TranslationBase.of(context).total}: $_total ${TranslationBase.of(context).sar}', heightFactor: 1.5, fontWeight: FontWeight.bold, color: Colors.black54, fontSize: 15)
],
),
),
@ -425,10 +381,7 @@ Widget _payNow(BuildContext context, {double subtotal, double tax, double total,
fontWeight: FontWeight.bold,
),
padding: EdgeInsets.only(top: 5, bottom: 5, left: 0, right: 0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
side: BorderSide(
color: Theme.of(context).primaryColor, width: 0.5)),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5), side: BorderSide(color: Theme.of(context).primaryColor, width: 0.5)),
color: Theme.of(context).primaryColor,
onPressed: isPayNowAQctive ? onPayNowClick : null,
),

@ -12,24 +12,20 @@ import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.da
import 'package:diplomaticquarterapp/models/Authentication/select_device_imei_res.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/routes.dart';
import 'package:diplomaticquarterapp/services/authentication/auth_provider.dart' as auth;
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart' as utils;
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/radio_selection_dialog.dart';
import 'package:diplomaticquarterapp/widgets/offers_packages/PackagesOfferCard.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
class PackagesHomePage extends StatefulWidget {
@ -48,6 +44,7 @@ class _PackagesHomePageState extends State<PackagesHomePage> {
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
viewModel.service.patientUser = widget.user;
viewModel.service.loadOffersPackagesDataForMainPage(
context: context,
completion: () {
@ -111,11 +108,8 @@ class _PackagesHomePageState extends State<PackagesHomePage> {
body: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 10,
),
Padding(
padding: const EdgeInsets.all(21),
padding: projectViewModel.isArabic ? const EdgeInsets.only(top: 21, right: 21, bottom: 21) : const EdgeInsets.only(top: 21, left: 21, bottom: 21),
child: Column(
children: [
inputWidget(TranslationBase.of(context).search, "", _searchTextController, isInputTypeNum: false),
@ -126,6 +120,7 @@ class _PackagesHomePageState extends State<PackagesHomePage> {
onTap: () => showClinicSelectionList(),
child: Container(
padding: EdgeInsets.all(12),
margin: projectViewModel.isArabic ? const EdgeInsets.only(left: 21) : const EdgeInsets.only(right: 21),
width: double.infinity,
height: 65,
decoration: BoxDecoration(
@ -139,7 +134,7 @@ class _PackagesHomePageState extends State<PackagesHomePage> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
selectedClinic != null ? selectedClinic.name : "Browse offers by clinic",
selectedClinic != null ? selectedClinic.name : TranslationBase.of(context).browseOffers,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
@ -218,15 +213,16 @@ class _PackagesHomePageState extends State<PackagesHomePage> {
children: [
Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: Icon(
Icons.add_shopping_cart_rounded,
size: 30.0,
color: Colors.white,
),
child: SvgPicture.asset("assets/images/new/cart.svg"),
// child: Icon(
// Icons.add_shopping_cart_rounded,
// size: 30.0,
// color: Colors.white,
// ),
),
Container(
child: Text(
TranslationBase.of(context).shoppingCart,
TranslationBase.of(context).myCart,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.48),
),
@ -315,7 +311,9 @@ class _PackagesHomePageState extends State<PackagesHomePage> {
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]])),
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]])),
);
}
@ -346,9 +344,11 @@ class _PackagesHomePageState extends State<PackagesHomePage> {
}
}
Widget inputWidget(String _labelText, String _hintText, TextEditingController _controller, {VoidCallback suffixTap, bool isEnable = true, bool hasSelection = false, int lines, bool isInputTypeNum = false}) {
Widget inputWidget(String _labelText, String _hintText, TextEditingController _controller,
{VoidCallback suffixTap, bool isEnable = true, bool hasSelection = false, int lines, bool isInputTypeNum = false}) {
return Container(
padding: EdgeInsets.only(left: 16, right: 16, bottom: 15, top: 15),
margin: projectViewModel.isArabic ? const EdgeInsets.only(left: 21) : const EdgeInsets.only(right: 21),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),

@ -509,7 +509,7 @@ class TranslationBase {
String get switchUser => localizedValues['switch-login'][locale.languageCode];
String get removeMember => localizedValues['remove-membe'][locale.languageCode];
String get removeMember => localizedValues['remove-member'][locale.languageCode];
String get allowView => localizedValues['allow-view'][locale.languageCode];
@ -2618,6 +2618,10 @@ class TranslationBase {
String get RRTSubTitle => localizedValues["RRTSubTitle"][locale.languageCode];
String get transportation => localizedValues["transportation"][locale.languageCode];
String get browseOffers => localizedValues["browseOffers"][locale.languageCode];
String get myCart => localizedValues["myCart"][locale.languageCode];
}
class TranslationBaseDelegate extends LocalizationsDelegate<TranslationBase> {

@ -1,217 +1,136 @@
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesCartItemsResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesResponseModel.dart';
import 'package:diplomaticquarterapp/core/viewModels/packages_offers/PackagesOffersViewModel.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/CounterView.dart';
import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
bool wide = true;
class PackagesCartItemCard extends StatefulWidget {
final PackagesCartItemsResponseModel itemModel;
final StepperCallbackFuture shouldStepperChangeApply ;
final StepperCallbackFuture shouldStepperChangeApply;
final PackagesViewModel viewModel;
final Function getCartItems;
const PackagesCartItemCard(
{
@required this.itemModel,
@required this.shouldStepperChangeApply,
Key key})
: super(key: key);
const PackagesCartItemCard({@required this.itemModel, @required this.shouldStepperChangeApply, @required this.viewModel, this.getCartItems, Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => PackagesCartItemCardState();
}
class PackagesCartItemCardState extends State<PackagesCartItemCard> {
@override
Widget build(BuildContext context) {
wide = !wide;
return Container(
color: Colors.transparent,
child: Card(
elevation: 3,
shadowColor: Colors.grey[100],
color: Colors.white,
child: Stack(
children: [
Container(
height: 100,
child: Row(
children: [
_image(widget.itemModel.product),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
decoration: cardRadius(15.0),
margin: EdgeInsets.only(left: 21.0, right: 21.0, top: 12.0),
height: 90,
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
_image(widget.itemModel.product),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_itemName(widget.itemModel.product.getName()),
_itemDescription(widget.itemModel.product.shortDescription),
Container(
padding: const EdgeInsets.only(top: 12.0),
width: MediaQuery.of(context).size.width * 0.65,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_itemPrice(widget.itemModel.product.price, context: context),
InkWell(
onTap: () async {
await widget.viewModel.service.deleteProductFromCart(widget.itemModel.id, context: context, showLoading: false);
widget.getCartItems();
},
child: Row(
children: [
_itemName(widget.itemModel.product.getName()),
Row(
children: [
_itemPrice(widget.itemModel.product.price, context: context),
_priceSeperator(),
_itemOldPrice(widget.itemModel.product.oldPrice, context: context),
],
),
Row(
children: [
_itemCounter(
widget.itemModel.quantity,
minQuantity: widget.itemModel.product.orderMinimumQuantity,
maxQuantity: widget.itemModel.product.orderMaximumQuantity,
shouldStepperChangeApply: (apply,total) async{
bool success = await widget.shouldStepperChangeApply(apply,total);
if(success == true)
setState(() => widget.itemModel.quantity = total);
return success;
}
Padding(
padding: const EdgeInsets.only(left: 5.0, right: 5.0),
child: Text(
TranslationBase.of(context).removeMember,
style: TextStyle(
fontSize: 10,
color: CustomColors.accentColor,
fontWeight: FontWeight.w600,
letterSpacing: -0.36,
),
],
),
),
SvgPicture.asset("assets/images/new-design/delete.svg", color: CustomColors.accentColor),
],
)
],
),
),
),
],
),
// Positioned(
// bottom: 8,
// left: 10,
// child: Row(
// children: [
// _totalLabel(context: context),
// _totalPrice((widget.itemModel.product.price * widget.itemModel.quantity), context: context),
// ],
// ),
// )
],
)
)
),
],
)
],
),
);
}
}
// --------------------
// Product Image
// --------------------
Widget _image(PackagesResponseModel model) => AspectRatio(
aspectRatio: 1/1,
child: Padding(
padding: const EdgeInsets.all(10),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300], width: 0.25),
boxShadow: [
BoxShadow(color: Colors.grey[200], blurRadius: 2.0, spreadRadius: 1, offset: Offset(1,1.5))
],
borderRadius: BorderRadius.circular(8),
color: Colors.white,
shape: BoxShape.rectangle,
),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: (model.images.isNotEmpty)
? Utils.loadNetworkImage(url: model.images.first.src, fitting:BoxFit.fill)
: Container(color: Colors.grey[200])
aspectRatio: 1 / 1,
child: Padding(
padding: const EdgeInsets.all(9),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300], width: 0.25),
boxShadow: [BoxShadow(color: Colors.grey[200], blurRadius: 2.0, spreadRadius: 1, offset: Offset(1, 1.5))],
borderRadius: BorderRadius.circular(15),
color: Colors.white,
shape: BoxShape.rectangle,
),
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: (model.images.isNotEmpty) ? Utils.loadNetworkImage(url: model.images.first.src, fitting: BoxFit.fill) : Container(color: Colors.grey[200])),
),
),
),
),
);
);
// --------------------
// Product Name
// --------------------
Widget _itemName(String name) => Padding(
padding: const EdgeInsets.all(0),
child: Texts(
name,
fontWeight: FontWeight.normal,
color: Colors.black,
fontSize: 15
)
);
padding: const EdgeInsets.only(top: 9.0),
child: Text(name,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
letterSpacing: -0.56,
)));
Widget _itemDescription(String desc) => Padding(
padding: const EdgeInsets.only(top: 0.0),
child: Text(desc,
style: TextStyle(
fontSize: 10,
// fontWeight: FontWeight.bold,
letterSpacing: -0.4,
)));
Widget _itemPrice(double price, {@required BuildContext context}) {
final prc = (price ?? 0.0).toStringAsFixed(2);
return Padding(
padding: const EdgeInsets.all(0),
child: Texts(
'${prc} ${TranslationBase.of(context).sar}',
fontWeight: FontWeight.bold,
color: Colors.green,
fontSize: 15
)
);
}
// --------------------
// Price Seperator
// --------------------
Widget _priceSeperator() => Padding(
padding: const EdgeInsets.only(left: 3, right: 3),
child: Container(height: 0.5, width: 5, color: Colors.grey[100],),
);
// --------------------
// Product Price
// --------------------
Widget _itemOldPrice(double oldPrice, {@required BuildContext context}) {
final prc = (oldPrice ?? 0.0).toStringAsFixed(2);
return Padding(
padding: const EdgeInsets.all(0),
child: Texts(
'${prc} ${TranslationBase.of(context).sar}',
fontWeight: FontWeight.normal,
decoration: TextDecoration.lineThrough,
color: Colors.grey,
fontSize: 10
)
);
child: Text(
'${prc} ${TranslationBase.of(context).sar}',
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
letterSpacing: -0.4,
),
),
);
}
// --------------------
// Product Price
// --------------------
Widget _itemCounter(int quantity, {int minQuantity, int maxQuantity, StepperCallbackFuture shouldStepperChangeApply}) => Padding(
padding: const EdgeInsets.all(0),
child: StepperView(
height: 25,
backgroundColor: Colors.grey[300],
foregroundColor: Colors.grey[200],
initialNumber: quantity,
minNumber: minQuantity,
maxNumber: maxQuantity,
counterCallback: shouldStepperChangeApply,
decreaseCallback: (){},
increaseCallback: (){},
)
);
Widget _totalLabel({@required BuildContext context}) => Padding(
padding: const EdgeInsets.all(0),
child: Texts(
'${TranslationBase.of(context).totalWithColonRight}',
fontWeight: FontWeight.bold,
color: Colors.grey[600],
fontSize: 13
)
);
Widget _totalPrice(double totalPrice, {@required BuildContext context}) => Padding(
padding: const EdgeInsets.all(0),
child: Texts(
'${totalPrice.toStringAsFixed(2)} ${TranslationBase.of(context).sar}',
fontWeight: FontWeight.normal,
color: Colors.green,
)
);

@ -8,6 +8,7 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
import 'package:diplomaticquarterapp/widgets/others/StarRating.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:rating_bar/rating_bar.dart';
bool wide = true;
@ -33,7 +34,7 @@ class PackagesItemCardState extends State<PackagesItemCard> {
wide = !wide;
return InkWell(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => OfferAndPackagesDetail(itemModel: widget.itemModel)));
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => OfferAndPackagesDetail(itemModel: widget.itemModel, onCartClick: widget.onCartClick)));
},
child: Container(
// width: widget.itemWidth,
@ -73,11 +74,7 @@ class PackagesItemCardState extends State<PackagesItemCard> {
],
),
InkWell(
child: Icon(
Icons.add_shopping_cart_rounded,
size: 30.0,
color: Colors.black,
),
child: SvgPicture.asset("assets/images/new/add-to-cart.svg"),
onTap: () {
widget.onCartClick(widget.itemModel);
},
@ -89,80 +86,5 @@ class PackagesItemCardState extends State<PackagesItemCard> {
),
),
);
// Stack(
// children: [
// Column(
// mainAxisSize: MainAxisSize.max,
// children: [
// AspectRatio(
// aspectRatio:1 / 1,
// child: applyShadow(
// child: ClipRRect(
// borderRadius: BorderRadius.circular(10),
// child: Utils.loadNetworkImage(
// url: imageUrl(),
// )),
// )),
// Texts(
// widget.itemModel.getName(),
// fontWeight: FontWeight.normal,
// color: Colors.black,
// fontSize: 15
// ),
// Padding(
// padding: const EdgeInsets.only(left: 10, right: 10),
// child: Row(
// crossAxisAlignment: CrossAxisAlignment.end,
// mainAxisSize: MainAxisSize.max,
// children: [
// Stack(
// children: [
// Texts(
// '${widget.itemModel.oldPrice} ${'SAR'}',
// fontWeight: FontWeight.normal,
// decoration: TextDecoration.lineThrough,
// color: Colors.grey,
// fontSize: 12
// ),
// Padding(
// padding: const EdgeInsets.only(top: 8),
// child: Texts(
// '${widget.itemModel.price} ${'SAR'}',
// fontWeight: FontWeight.bold,
// color: Colors.green,
// fontSize: 18
// ),
// ),
// Padding(
// padding: const EdgeInsets.only(top: 35),
// child: StarRating(
// size: 15,
// totalCount: null,
// totalAverage: widget.itemModel.approvedRatingSum.toDouble(),
// forceStars: true),
// )
// ],
// ),
// Spacer(
// flex: 1,
// ),
// InkWell(
// child: Icon(
// Icons.add_shopping_cart_rounded,
// size: 30.0,
// color: Colors.grey,
// ),
// onTap: () {
// widget.onCartClick(widget.itemModel);
// },
// ),
// ],
// ),
// ),
// ],
// ),
// ],
// ),
// );
}
}

Loading…
Cancel
Save