Flutter 1.17.0 support, Sort by feature, Cash on delivery added, Login/register flow change for Apple user guidelines, Bug fixes, Pubspec.yaml update, AndroidManifest.xml bug fix

This commit is contained in:
WooSignal 2020-05-08 15:35:30 +01:00
parent 54e215507f
commit 8cd7118b0b
48 changed files with 1131 additions and 676 deletions

View File

@ -1,5 +1,12 @@
## [2.0.2] - 2020-05-04
## [2.0.2] - 2020-05-08
* Flutter 1.17.0 support
* Sort by feature
* Cash on delivery added
* RazorPay added
* Login/register flow change for Apple user guidelines
* Bug fixes
* Pubspec.yaml update
* AndroidManifest.xml bug fix
## [2.0.1] - 2020-04-30

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -264,9 +264,6 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/Braintree/Braintree.framework",
"${PODS_ROOT}/Braintree/Frameworks/CardinalMobile.framework",
"${BUILT_PRODUCTS_DIR}/BraintreeDropIn/BraintreeDropIn.framework",
"${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
"${PODS_ROOT}/../Flutter/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/Stripe/Stripe.framework",
@ -275,6 +272,8 @@
"${BUILT_PRODUCTS_DIR}/flutter_web_browser/flutter_web_browser.framework",
"${BUILT_PRODUCTS_DIR}/package_info/package_info.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
"${PODS_ROOT}/razorpay-pod/Pod/Razorpay.framework",
"${BUILT_PRODUCTS_DIR}/razorpay_flutter/razorpay_flutter.framework",
"${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework",
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
@ -282,9 +281,6 @@
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Braintree.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CardinalMobile.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BraintreeDropIn.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Stripe.framework",
@ -293,6 +289,8 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_web_browser.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Razorpay.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/razorpay_flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",

View File

@ -1,6 +1,5 @@
import UIKit
import Flutter
import Braintree
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {

View File

@ -129,5 +129,18 @@
"Shipping Details": "Shipping Details",
"State": "State",
"Country": "Country",
"UPDATE DETAILS": "UPDATE DETAILS"
"UPDATE DETAILS": "UPDATE DETAILS",
"No more products": "No more products",
"release to load more": "release to load more",
"Load Failed! Click retry!": "Load Failed! Click retry!",
"pull up load": "pull up load",
"Sort: Low to high": "Sort: Low to high",
"Sort: High to low": "Sort: High to low",
"Sort: Name A-Z": "Sort: Name A-Z",
"Sort: Name Z-A": "Sort: Name Z-A",
"Cancel": "Cancel",
"Sort results": "Sort results",
"you're now logged in": "You're now logged in",
"Hello": "Hello",
"Welcome back": "Welcome back"
}

View File

@ -10,6 +10,7 @@
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/payment_type.dart';
import 'package:label_storemax/providers/cash_on_delivery.dart';
import 'package:label_storemax/providers/stripe_pay.dart';
// Payment methods available for uses in the app
@ -25,11 +26,21 @@ List<PaymentType> arrPaymentMethods = [
),
),
addPayment(
PaymentType(
id: 2,
name: "CashOnDelivery",
desc: "Cash on delivery",
assetImage: "cash_on_delivery.jpeg",
pay: cashOnDeliveryPay,
),
),
// e.g. add more here
// addPayment(
// PaymentType(
// id: 2,
// id: 3,
// name: "MyNewPaymentMethod",
// desc: "Debit or Credit Card",
// assetImage: "add icon image to assets/images/myimage.png",

View File

@ -50,8 +50,10 @@ class _AppLocalizationsDelegate
const _AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) =>
app_locales_supported.contains(locale.languageCode);
bool isSupported(Locale locale) => app_locales_supported
.map((e) => e.languageCode)
.toList()
.contains(locale.languageCode);
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;

View File

@ -82,9 +82,9 @@ TextTheme textThemePrimary() {
fontWeight: FontWeight.w600),
headline: new TextStyle(color: Colors.black, fontFamily: appFontFamily),
title: new TextStyle(
color: Colors.black,
fontFamily: appFontFamily,
),
color: Colors.black87,
fontFamily: appFontFamily,
fontWeight: FontWeight.w600),
subhead: new TextStyle(
color: Colors.black,
fontFamily: appFontFamily,

View File

@ -19,7 +19,7 @@ import 'package:label_storemax/models/checkout_session.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/tax_rate.dart';
Future<OrderWC> buildOrderWC({TaxRate taxRate}) async {
Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
OrderWC orderWC = OrderWC();
String paymentMethodName = CheckoutSession.getInstance.paymentType.name ?? "";
@ -30,7 +30,7 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate}) async {
orderWC.paymentMethodTitle = paymentMethodName.toLowerCase();
orderWC.setPaid = true;
orderWC.setPaid = markPaid;
orderWC.status = "pending";
orderWC.currency = app_currency_iso.toUpperCase();
orderWC.customerId =

View File

@ -0,0 +1,16 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// 2020, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
enum SortByType {
LowToHigh,
HighToLow,
NameAZ,
NameZA,
}

View File

@ -38,5 +38,5 @@ authLogout(BuildContext context) async {
await sharedPref.save(keyAuthCheck, null);
destroyUserId(context);
Cart.getInstance.clear();
navigatorPush(context, routeName: "/account-landing", forgetAll: true);
navigatorPush(context, routeName: "/home", forgetAll: true);
}

View File

@ -8,6 +8,7 @@
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart';
import 'package:label_storemax/app_payment_methods.dart';
import 'package:label_storemax/helpers/app_localizations.dart';
@ -22,9 +23,12 @@ import 'package:label_storemax/models/payment_type.dart';
import 'package:html/parser.dart';
import 'package:flutter_web_browser/flutter_web_browser.dart';
import 'package:flutter_money_formatter/flutter_money_formatter.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:math_expressions/math_expressions.dart';
import 'package:platform_alert_dialog/platform_alert_dialog.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:status_alert/status_alert.dart';
import 'package:woosignal/models/response/products.dart';
import 'package:woosignal/models/response/tax_rate.dart';
import 'package:woosignal/woosignal.dart';
@ -65,11 +69,6 @@ showStatusAlert(context,
);
}
class PaymentMethodType {
static final int STRIPE = 1;
static final int APPLEPAY = 2;
}
class EdgeAlertStyle {
static final int SUCCESS = 1;
static final int WARNING = 2;
@ -142,7 +141,7 @@ String formatStringCurrency({@required String total}) {
if (total == null || total == "") {
tmpVal = 0;
} else {
tmpVal = double.parse(total);
tmpVal = parseWcPrice(total);
}
FlutterMoneyFormatter fmf = FlutterMoneyFormatter(
amount: tmpVal,
@ -185,6 +184,9 @@ checkout(
}
double strCal({@required String sum}) {
if (sum == null || sum == "") {
return 0;
}
Parser p = Parser();
Expression exp = p.parse(sum);
ContextModel cm = ContextModel();
@ -192,6 +194,9 @@ double strCal({@required String sum}) {
}
Future<double> workoutShippingCostWC({@required String sum}) async {
if (sum == null || sum == "") {
return 0;
}
List<CartLineItem> cartLineItem = await Cart.getInstance.getCart();
sum = sum.replaceAllMapped(defaultRegex(r'\[qty\]', strict: true), (replace) {
return cartLineItem
@ -263,6 +268,9 @@ Future<double> workoutShippingCostWC({@required String sum}) async {
Future<double> workoutShippingClassCostWC(
{@required String sum, List<CartLineItem> cartLineItem}) async {
if (sum == null || sum == "") {
return 0;
}
sum = sum.replaceAllMapped(defaultRegex(r'\[qty\]', strict: true), (replace) {
return cartLineItem
.map((f) => f.quantity)
@ -357,14 +365,22 @@ bool validPassword(String pw) {
}
navigatorPush(BuildContext context,
{@required String routeName, Object arguments, bool forgetAll = false}) {
{@required String routeName,
Object arguments,
bool forgetAll = false,
int forgetLast}) {
if (forgetAll) {
Navigator.of(context).pushNamedAndRemoveUntil(
routeName, (Route<dynamic> route) => false,
arguments: arguments ?? null);
} else {
Navigator.of(context).pushNamed(routeName, arguments: arguments ?? null);
}
if (forgetLast != null) {
int count = 0;
Navigator.of(context).popUntil((route) {
return count++ == forgetLast;
});
}
Navigator.of(context).pushNamed(routeName, arguments: arguments ?? null);
}
PlatformDialogAction dialogAction(BuildContext context,
@ -450,3 +466,58 @@ String formatForDateTime(FormatType formatType) {
}
String capitalize(String s) => s[0].toUpperCase() + s.substring(1);
double parseWcPrice(String price) => (double.tryParse(price) ?? 0);
Widget refreshableScroll(context,
{@required refreshController,
@required VoidCallback onRefresh,
@required VoidCallback onLoading,
@required List<Product> products,
@required onTap,
key}) {
return SmartRefresher(
enablePullDown: false,
enablePullUp: true,
footer: CustomFooter(
builder: (BuildContext context, LoadStatus mode) {
Widget body;
if (mode == LoadStatus.idle) {
body = Text(trans(context, "pull up load"));
} else if (mode == LoadStatus.loading) {
body = CupertinoActivityIndicator();
} else if (mode == LoadStatus.failed) {
body = Text(trans(context, "Load Failed! Click retry!"));
} else if (mode == LoadStatus.canLoading) {
body = Text(trans(context, "release to load more"));
} else {
body = Text(trans(context, "No more products"));
}
return Container(
height: 55.0,
child: Center(child: body),
);
},
),
controller: refreshController,
onRefresh: onRefresh,
onLoading: onLoading,
child: (products.length != null && products.length > 0
? GridView.count(
crossAxisCount: 2,
children: List.generate(
products.length,
(index) {
return wsCardProductItem(context,
index: index, product: products[index], onTap: onTap);
},
))
: wsNoResults(context)));
}
class UserAuth {
UserAuth._privateConstructor();
static final UserAuth instance = UserAuth._privateConstructor();
String redirect = "/home";
}

View File

@ -10,11 +10,13 @@
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'dart:ui';
/*
Developer Notes
SUPPORT EMAIL - support@woosignal.com
VERSION - 2.0.1
VERSION - 2.0.2
https://woosignal.com
*/
@ -22,15 +24,51 @@
const app_name = "MyApp";
const app_key = "your app key";
const app_key =
"Your app key from WooSingal";
// Your App key from WooSignal
// link: https://woosignal.com/dashboard/apps
const app_logo_url = "https://is5-ssl.mzstatic.com/image/thumb/Purple115/v4/4b/e8/9a/4be89a5a-607e-1fb3-c45a-3261e84a061b/source/512x512bb.jpg";
const app_logo_url = "https://woosignal.com/images/120x120_woosignal.png";
const app_terms_url = "https://yourdomain.com/terms";
const app_privacy_url = "https://yourdomain.com/privacy";
/*<! ------ APP SETTINGS ------!>*/
const app_currency_symbol = "\£";
const app_currency_iso = "gbp";
const app_locales_supported = [
Locale('en'),
];
// If you want to localize the app, add the locale above
// then create a new lang json file using keys from en.json
// e.g. lang/es.json
/*<! ------ PAYMENT GATEWAYS ------!>*/
// Available: "Stripe", "CashOnDelivery",
// Add the method to the array below e.g. ["Stripe", "CashOnDelivery"]
const app_payment_methods = ["Stripe"];
/*<! ------ STRIPE (OPTIONAL) ------!>*/
// Your StripeAccount key from WooSignal
// link: https://woosignal.com/dashboard
const app_stripe_account = "Your StripeAccount from WooSignal";
const app_stripe_live_mode = false;
// For Live Payments follow the below steps
// #1 SET the above to true for live payments
// #2 Next visit https://woosignal.com/dashboard
// #3 Then change "Environment for Stripe" to Live mode
/*<! ------ WP LOGIN (OPTIONAL) ------!>*/
// Allows customers to login/register, view account, purchase items as a user.
@ -40,29 +78,10 @@ const app_privacy_url = "https://yourdomain.com/privacy";
const use_wp_login = false;
const app_base_url = "https://mysite.com"; // change to your url
const app_forgot_password_url = "https://mysite.com/my-account/lost-password"; // change to your forgot password url
const app_forgot_password_url =
"https://mysite.com/my-account/lost-password"; // change to your forgot password url
const app_wp_api_path = "/wp-json"; // By default "/wp-json" should work
/*<! ------ STRIPE (OPTIONAL) ------!>*/
// Your StripeAccount key from WooSignal
// link: https://woosignal.com/dashboard
const app_stripe_account = "Stripe Key from WooSignal";
const app_stripe_live_mode = false;
// For Live Payments follow the below steps
// #1 SET the above to true for live payments
// #2 Next visit https://woosignal.com/dashboard
// #3 Then change "Environment for Stripe" to Live mode
/*<! ------ APP CURRENCY ------!>*/
const app_currency_symbol = "\£";
const app_currency_iso = "gbp";
const app_locales_supported = ['en'];
const app_payment_methods = ["Stripe"];
/*<! ------ DEBUGGER ENABLED ------!>*/

View File

@ -10,7 +10,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:label_storemax/helpers/shared_pref/sp_auth.dart';
import 'package:label_storemax/pages/account_billing_details.dart';
import 'package:label_storemax/pages/account_detail.dart';
import 'package:label_storemax/pages/account_landing.dart';
@ -51,13 +50,12 @@ void main() async {
DeviceOrientation.portraitUp,
]);
String initialRoute = (use_wp_login) ? "/account-landing" : "/home";
WPJsonAPI.instance.initWith(
baseUrl: app_base_url,
shouldDebug: app_debug,
wpJsonPath: app_wp_api_path);
if (await authCheck() == true) {
initialRoute = "/home";
String initialRoute = "/home";
if (use_wp_login == true) {
WPJsonAPI.instance.initWith(
baseUrl: app_base_url,
shouldDebug: app_debug,
wpJsonPath: app_wp_api_path);
}
runApp(
@ -71,7 +69,6 @@ void main() async {
'/cart': (BuildContext context) => new CartPage(),
'/error': (BuildContext context) => new ErrorPage(),
'/checkout': (BuildContext context) => new CheckoutConfirmationPage(),
'/account-landing': (BuildContext context) => new AccountLandingPage(),
'/account-register': (BuildContext context) =>
new AccountRegistrationPage(),
'/account-detail': (BuildContext context) => new AccountDetailPage(),
@ -84,6 +81,12 @@ void main() async {
},
onGenerateRoute: (settings) {
switch (settings.name) {
case '/account-landing':
return PageTransition(
child: AccountLandingPage(),
type: PageTransitionType.downToUp,
);
case '/browse-category':
if (settings.arguments != null) {
final ProductCategory category =
@ -200,9 +203,7 @@ void main() async {
return null;
}
},
supportedLocales: [
Locale('en'),
],
supportedLocales: app_locales_supported,
localizationsDelegates: [
AppLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,

View File

@ -142,7 +142,7 @@ class Cart {
if (taxableCartLines.length > 0) {
cartSubtotal = taxableCartLines
.map<double>((m) => double.parse(m.subtotal))
.map<double>((m) => parseWcPrice(m.subtotal))
.reduce((a, b) => a + b);
}
@ -155,13 +155,19 @@ class Cart {
case "flat_rate":
FlatRate flatRate = (shippingType.object as FlatRate);
if (flatRate.taxable != null && flatRate.taxable) {
shippingTotal += double.parse(shippingType.cost);
shippingTotal += parseWcPrice(
shippingType.cost == null || shippingType.cost == ""
? "0"
: shippingType.cost);
}
break;
case "local_pickup":
LocalPickup localPickup = (shippingType.object as LocalPickup);
if (localPickup.taxable != null && localPickup.taxable) {
shippingTotal += double.parse(localPickup.cost);
shippingTotal += parseWcPrice(
(localPickup.cost == null || localPickup.cost == ""
? "0"
: localPickup.cost));
}
break;
default:
@ -171,10 +177,10 @@ class Cart {
double total = 0;
if (subtotal != 0) {
total += ((double.parse(taxRate.rate) * subtotal) / 100);
total += ((parseWcPrice(taxRate.rate) * subtotal) / 100);
}
if (shippingTotal != 0) {
total += ((double.parse(taxRate.rate) * shippingTotal) / 100);
total += ((parseWcPrice(taxRate.rate) * shippingTotal) / 100);
}
return (total).toStringAsFixed(2);
}

View File

@ -8,6 +8,8 @@
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:label_storemax/helpers/tools.dart';
class CartLineItem {
String name;
int productId;
@ -45,7 +47,7 @@ class CartLineItem {
this.metaData});
String getCartTotal() {
return (quantity * double.parse(subtotal)).toString();
return (quantity * parseWcPrice(subtotal)).toString();
}
CartLineItem.fromJson(Map<String, dynamic> json)
@ -56,7 +58,10 @@ class CartLineItem {
shippingClassId = json['shipping_class_id'].toString(),
taxStatus = json['tax_status'],
stockQuantity = json['stock_quantity'],
isManagedStock = json['is_managed_stock'],
isManagedStock = (json['is_managed_stock'] != null &&
json['is_managed_stock'] is bool)
? json['is_managed_stock']
: false,
shippingIsTaxable = json['shipping_is_taxable'],
subtotal = json['subtotal'],
total = json['total'],

View File

@ -61,18 +61,18 @@ class CheckoutSession {
}
Future<String> total({bool withFormat, TaxRate taxRate}) async {
double totalCart = double.parse(await Cart.getInstance.getTotal());
double totalCart = parseWcPrice(await Cart.getInstance.getTotal());
double totalShipping = 0;
if (shippingType != null && shippingType.object != null) {
switch (shippingType.methodId) {
case "flat_rate":
totalShipping = double.parse(shippingType.cost);
totalShipping = parseWcPrice(shippingType.cost);
break;
case "free_shipping":
totalShipping = double.parse(shippingType.cost);
totalShipping = parseWcPrice(shippingType.cost);
break;
case "local_pickup":
totalShipping = double.parse(shippingType.cost);
totalShipping = parseWcPrice(shippingType.cost);
break;
default:
break;
@ -83,12 +83,12 @@ class CheckoutSession {
if (taxRate != null) {
String taxAmount = await Cart.getInstance.taxAmount(taxRate);
total += double.parse(taxAmount);
total += parseWcPrice(taxAmount);
}
if (withFormat != null && withFormat == true) {
return formatDoubleCurrency(total: total);
}
return total.toString();
return total.toStringAsFixed(2);
}
}

View File

@ -42,7 +42,7 @@ class _AboutPageState extends State<AboutPage> {
},
),
title: Text(trans(context, "About"),
style: Theme.of(context).primaryTextTheme.subhead),
style: Theme.of(context).primaryTextTheme.headline6),
centerTitle: true,
),
body: SafeArea(
@ -85,8 +85,9 @@ class _AboutPageState extends State<AboutPage> {
trans(context, "Version") +
": " +
snapshot.data.version,
style:
Theme.of(context).primaryTextTheme.body2),
style: Theme.of(context)
.primaryTextTheme
.bodyText1),
padding: EdgeInsets.only(top: 15, bottom: 15),
);
}

View File

@ -89,7 +89,7 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
backgroundColor: Colors.transparent,
title: Text(
trans(context, "Billing Details"),
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.subtitle1,
),
centerTitle: true,
),

View File

@ -85,7 +85,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
),
title: Text(
trans(context, "Account"),
style: Theme.of(context).primaryTextTheme.title,
style: Theme.of(context).primaryTextTheme.headline6,
),
centerTitle: true,
),
@ -212,7 +212,12 @@ class _AccountDetailPageState extends State<AccountDetailPage>
leading: Icon(Icons.account_circle),
title: Text(trans(context, "Update details")),
onTap: () {
Navigator.pushNamed(context, "/account-update");
Navigator.pushNamed(context, "/account-update").then((onValue) {
setState(() {
_isLoading = true;
});
_fetchWpUserData();
});
},
),
),
@ -238,9 +243,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
child: ListTile(
leading: Icon(Icons.exit_to_app),
title: Text(trans(context, "Logout")),
onTap: () {
authLogout(context);
},
onTap: () => authLogout(context),
),
),
],
@ -331,7 +334,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
formatStringCurrency(total: _orders[i].total),
style: Theme.of(context)
.primaryTextTheme
.body1
.bodyText2
.copyWith(
fontWeight: FontWeight.w600,
color: Colors.black),
@ -343,7 +346,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
trans(context, "items"),
style: Theme.of(context)
.primaryTextTheme
.body2
.bodyText1
.copyWith(
fontWeight: FontWeight.w600,
color: Colors.black),
@ -364,7 +367,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
textAlign: TextAlign.right,
style: Theme.of(context)
.primaryTextTheme
.body2
.bodyText1
.copyWith(
fontWeight: FontWeight.w400,
color: Colors.black),

View File

@ -68,7 +68,7 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
textAlign: TextAlign.left,
style: Theme.of(context)
.primaryTextTheme
.display1
.headline4
.copyWith(
fontSize: 24,
fontWeight: FontWeight.w700,
@ -119,7 +119,7 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
Padding(
child: Text(
trans(context, "Create an account"),
style: Theme.of(context).primaryTextTheme.body2,
style: Theme.of(context).primaryTextTheme.bodyText1,
),
padding: EdgeInsets.only(left: 8),
)
@ -133,6 +133,10 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
action: () {
launch(app_forgot_password_url);
}),
Divider(),
wsLinkButton(context, title: trans(context, "Back"), action: () {
Navigator.pop(context);
}),
],
),
),
@ -157,7 +161,13 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
authUser(token);
storeUserId(wpUserLoginResponse.data.userId.toString());
navigatorPush(context, routeName: "/home", forgetAll: true);
showEdgeAlertWith(context,
title: trans(context, "Hello"),
desc: trans(context, "Welcome back"),
style: EdgeAlertStyle.SUCCESS,
icon: Icons.account_circle);
navigatorPush(context,
routeName: UserAuth.instance.redirect, forgetLast: 1);
} else {
showEdgeAlertWith(context,
title: trans(context, "Oops!"),

View File

@ -55,7 +55,7 @@ class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
),
title: Text(
"Order #" + _orderId.toString(),
style: Theme.of(context).primaryTextTheme.title,
style: Theme.of(context).primaryTextTheme.headline6,
),
centerTitle: true,
),
@ -157,7 +157,7 @@ class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
total: _order.lineItems[i].total),
style: Theme.of(context)
.primaryTextTheme
.body1
.bodyText2
.copyWith(
fontWeight: FontWeight.w600,
color: Colors.black),
@ -169,7 +169,7 @@ class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
.toString(),
style: Theme.of(context)
.primaryTextTheme
.body2
.bodyText1
.copyWith(
fontWeight: FontWeight.w600,
color: Colors.black),

View File

@ -16,7 +16,6 @@ import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/widgets/buttons.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:woosignal/helpers/shared_pref.dart';
import 'package:wp_json_api/models/responses/WPUserInfoUpdatedResponse.dart';
import 'package:wp_json_api/models/responses/WPUserRegisterResponse.dart';
import 'package:wp_json_api/wp_json_api.dart';
@ -61,7 +60,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
),
title: Text(
"Register",
style: Theme.of(context).primaryTextTheme.title,
style: Theme.of(context).primaryTextTheme.headline6,
),
centerTitle: true,
),
@ -173,19 +172,25 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
WPUserRegisterResponse wpUserRegisterResponse = await WPJsonAPI.instance
.api((request) => request.wpRegister(
email: email, password: password, username: username));
email: email.toLowerCase(),
password: password,
username: username));
if (wpUserRegisterResponse != null) {
String token = wpUserRegisterResponse.data.userToken;
authUser(token);
storeUserId(wpUserRegisterResponse.data.userId.toString());
WPUserInfoUpdatedResponse wpUserInfoUpdatedResponse = await WPJsonAPI
.instance
.api((request) => request.wpUpdateUserInfo(token,
firstName: firstName, lastName: lastName));
await WPJsonAPI.instance.api((request) => request
.wpUpdateUserInfo(token, firstName: firstName, lastName: lastName));
navigatorPush(context, routeName: "/home", forgetAll: true);
showEdgeAlertWith(context,
title: trans(context, "Hello") + " $firstName",
desc: trans(context, "you're now logged in"),
style: EdgeAlertStyle.SUCCESS,
icon: Icons.account_circle);
navigatorPush(context,
routeName: UserAuth.instance.redirect, forgetLast: 2);
} else {
setState(() {
showEdgeAlertWith(context,

View File

@ -90,7 +90,7 @@ class _AccountShippingDetailsPageState
backgroundColor: Colors.transparent,
title: Text(
trans(context, "Shipping Details"),
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.subtitle1,
),
centerTitle: true,
),

View File

@ -8,9 +8,13 @@
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/enums/sort_enums.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:label_storemax/widgets/buttons.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:woosignal/models/response/product_category.dart';
import 'package:woosignal/models/response/products.dart' as WS;
import 'package:label_storemax/widgets/woosignal_ui.dart';
@ -29,8 +33,9 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
_BrowseCategoryPageState(this._selectedCategory);
List<WS.Product> _products = [];
var _productsController = ScrollController();
RefreshController _refreshController =
RefreshController(initialRefresh: false);
ProductCategory _selectedCategory;
bool _isLoading;
int _page;
@ -46,34 +51,17 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
_page = 1;
_shouldStopRequests = false;
waitForNextRequest = false;
_fetchProductsForCategory();
_addScrollListener();
}
_addScrollListener() async {
_productsController.addListener(() {
double maxScroll = _productsController.position.maxScrollExtent;
double currentScroll = _productsController.position.pixels;
double delta = 50.0;
if (maxScroll - currentScroll <= delta) {
if (_shouldStopRequests) {
return;
}
if (waitForNextRequest) {
return;
}
_fetchMoreProducts();
}
});
_fetchMoreProducts();
}
_fetchMoreProducts() async {
waitForNextRequest = true;
List<WS.Product> products = await appWooSignal((api) {
return api.getProducts(perPage: 50, page: _page, status: "publish");
});
List<WS.Product> products = await appWooSignal((api) => api.getProducts(
perPage: 50,
category: _selectedCategory.id.toString(),
page: _page,
status: "publish",
stockStatus: "instock"));
_products.addAll(products);
waitForNextRequest = false;
_page = _page + 1;
@ -82,13 +70,6 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
if (products.length == 0) {
_shouldStopRequests = true;
}
}
_fetchProductsForCategory() async {
_products = await appWooSignal((api) {
return api.getProducts(
category: _selectedCategory.id.toString(), perPage: 50);
});
setState(() {
_isLoading = false;
});
@ -109,12 +90,18 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(trans(context, "Browse"),
style: Theme.of(context).primaryTextTheme.subhead),
style: Theme.of(context).primaryTextTheme.subtitle1),
Text(_selectedCategory.name,
style: Theme.of(context).primaryTextTheme.title)
style: Theme.of(context).primaryTextTheme.headline6)
],
),
centerTitle: true,
actions: <Widget>[
IconButton(
icon: Icon(Icons.tune),
onPressed: _modalSheetTune,
)
],
),
body: SafeArea(
minimum: safeAreaDefault(),
@ -122,25 +109,105 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
? Center(
child: showAppLoader(),
)
: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: (_products.length != null && _products.length > 0
? GridView.count(
crossAxisCount: 2,
controller: _productsController,
children: List.generate(_products.length, (index) {
return wsCardProductItem(context,
index: index, product: _products[index]);
}))
: wsNoResults(context)),
flex: 1,
),
],
),
: refreshableScroll(context,
refreshController: _refreshController,
onRefresh: _onRefresh,
onLoading: _onLoading,
products: _products,
onTap: _showProduct),
),
);
}
void _onRefresh() async {
await _fetchMoreProducts();
setState(() {});
if (_shouldStopRequests) {
_refreshController.resetNoData();
} else {
_refreshController.refreshCompleted();
}
}
void _onLoading() async {
await _fetchMoreProducts();
if (mounted) {
setState(() {});
if (_shouldStopRequests) {
_refreshController.loadNoData();
} else {
_refreshController.loadComplete();
}
}
}
_sortProducts({@required SortByType by}) {
switch (by) {
case SortByType.LowToHigh:
_products.sort((product1, product2) => (parseWcPrice(product1.price))
.compareTo((double.tryParse(product2.price) ?? 0)));
break;
case SortByType.HighToLow:
_products.sort((product1, product2) => (parseWcPrice(product2.price))
.compareTo((double.tryParse(product1.price) ?? 0)));
break;
case SortByType.NameAZ:
_products.sort(
(product1, product2) => product1.name.compareTo(product2.name));
break;
case SortByType.NameZA:
_products.sort(
(product1, product2) => product2.name.compareTo(product1.name));
break;
}
setState(() {
Navigator.pop(context);
});
}
_modalSheetTune() {
wsModalBottom(
context,
title: trans(context, "Sort results"),
bodyWidget: ListView(
children: <Widget>[
wsLinkButton(context,
title: trans(context, "Sort: Low to high"),
action: () => _sortProducts(by: SortByType.LowToHigh)),
Divider(
height: 0,
),
wsLinkButton(context,
title: trans(context, "Sort: High to low"),
action: () => _sortProducts(by: SortByType.HighToLow)),
Divider(
height: 0,
),
wsLinkButton(context,
title: trans(context, "Sort: Name A-Z"),
action: () => _sortProducts(by: SortByType.NameAZ)),
Divider(
height: 0,
),
wsLinkButton(context,
title: trans(context, "Sort: Name Z-A"),
action: () => _sortProducts(by: SortByType.NameZA)),
Divider(
height: 0,
),
wsLinkButton(context,
title: trans(context, "Cancel"), action: _dismissModal)
],
),
);
}
_dismissModal() {
Navigator.pop(context);
}
_showProduct(WS.Product product) {
Navigator.pushNamed(context, "/product-detail", arguments: product);
}
}

View File

@ -11,8 +11,8 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:woosignal/models/response/products.dart' as WS;
import 'package:label_storemax/widgets/woosignal_ui.dart';
class BrowseSearchPage extends StatefulWidget {
final String search;
@ -25,7 +25,8 @@ class BrowseSearchPage extends StatefulWidget {
class _BrowseSearchState extends State<BrowseSearchPage> {
_BrowseSearchState(this._search);
var _productsController = ScrollController();
RefreshController _refreshController =
RefreshController(initialRefresh: false);
List<WS.Product> _products = [];
String _search;
bool _isLoading;
@ -42,39 +43,26 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
_shouldStopRequests = false;
waitForNextRequest = false;
_fetchProductsForSearch(_page);
_addScrollListener();
_fetchProductsForSearch();
}
_addScrollListener() async {
_productsController.addListener(() {
double maxScroll = _productsController.position.maxScrollExtent;
double currentScroll = _productsController.position.pixels;
double delta = 50.0;
if (maxScroll - currentScroll <= delta) {
if (_shouldStopRequests) {
return;
}
if (waitForNextRequest) {
return;
}
_fetchProductsForSearch(_page);
}
});
}
_fetchProductsForSearch(int page) async {
_fetchProductsForSearch() async {
waitForNextRequest = true;
List<WS.Product> products = await appWooSignal((api) {
_page = _page + 1;
return api.getProducts(
search: _search, perPage: 100, page: page, status: "publish");
});
List<WS.Product> products = await appWooSignal((api) => api.getProducts(
perPage: 100,
search: _search,
page: _page,
status: "publish",
stockStatus: "instock"));
_products.addAll(products);
waitForNextRequest = false;
_page = _page + 1;
waitForNextRequest = false;
if (products.length == 0) {
_shouldStopRequests = true;
}
setState(() {
_products.addAll(products.toList());
_isLoading = false;
});
}
@ -94,9 +82,9 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(trans(context, "Search results for"),
style: Theme.of(context).primaryTextTheme.subhead),
style: Theme.of(context).primaryTextTheme.subtitle1),
Text("\"" + _search + "\"",
style: Theme.of(context).primaryTextTheme.title)
style: Theme.of(context).primaryTextTheme.headline6)
],
),
centerTitle: true,
@ -107,29 +95,40 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
? Center(
child: showAppLoader(),
)
: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: (_products.length != null && _products.length > 0
? GridView.count(
crossAxisCount: 2,
controller: _productsController,
children: List.generate(
_products.length,
(index) {
return wsCardProductItem(context,
index: index, product: _products[index]);
},
),
)
: wsNoResults(context)),
flex: 1,
),
],
),
: refreshableScroll(context,
refreshController: _refreshController,
onRefresh: _onRefresh,
onLoading: _onLoading,
products: _products,
onTap: _showProduct),
),
);
}
void _onRefresh() async {
await _fetchProductsForSearch();
setState(() {});
if (_shouldStopRequests) {
_refreshController.resetNoData();
} else {
_refreshController.refreshCompleted();
}
}
void _onLoading() async {
await _fetchProductsForSearch();
if (mounted) {
setState(() {});
if (_shouldStopRequests) {
_refreshController.loadNoData();
} else {
_refreshController.loadComplete();
}
}
}
_showProduct(WS.Product product) {
Navigator.pushNamed(context, "/product-detail", arguments: product);
}
}

View File

@ -10,7 +10,9 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/shared_pref/sp_auth.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart';
@ -67,6 +69,9 @@ class _CartPageState extends State<CartPage> {
void _actionProceedToCheckout() async {
List<CartLineItem> cartLineItems = await Cart.getInstance.getCart();
if (_isLoading == true) {
return;
}
if (cartLineItems.length <= 0) {
showEdgeAlertWith(context,
title: trans(context, "Cart"),
@ -94,6 +99,11 @@ class _CartPageState extends State<CartPage> {
CheckoutSession.getInstance.billingDetails.shippingAddress =
sfCustomerAddress;
}
if (use_wp_login == true && !(await authCheck())) {
UserAuth.instance.redirect = "/checkout";
Navigator.pushNamed(context, "/account-landing");
return;
}
Navigator.pushNamed(context, "/checkout");
}
@ -131,6 +141,9 @@ class _CartPageState extends State<CartPage> {
desc: trans(context, "Item removed"),
style: EdgeAlertStyle.WARNING,
icon: Icons.remove_shopping_cart);
if (_cartLines.length == 0) {
_isCartEmpty = true;
}
setState(() {});
}
@ -142,6 +155,7 @@ class _CartPageState extends State<CartPage> {
desc: trans(context, "Cart cleared"),
style: EdgeAlertStyle.SUCCESS,
icon: Icons.delete_outline);
_isCartEmpty = true;
setState(() {});
}
@ -151,7 +165,7 @@ class _CartPageState extends State<CartPage> {
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text(trans(context, "Shopping Cart"),
style: Theme.of(context).appBarTheme.textTheme.title),
style: Theme.of(context).appBarTheme.textTheme.headline6),
textTheme: Theme.of(context).textTheme,
elevation: 1,
actions: <Widget>[
@ -161,7 +175,7 @@ class _CartPageState extends State<CartPage> {
child: Align(
child: Padding(
child: Text(trans(context, "Clear Cart"),
style: Theme.of(context).primaryTextTheme.body2),
style: Theme.of(context).primaryTextTheme.bodyText1),
padding: EdgeInsets.only(right: 8),
),
alignment: Alignment.centerLeft,
@ -191,7 +205,8 @@ class _CartPageState extends State<CartPage> {
),
Padding(
child: Text(trans(context, "Empty Basket"),
style: Theme.of(context).primaryTextTheme.body1),
style:
Theme.of(context).primaryTextTheme.bodyText2),
padding: EdgeInsets.only(top: 10),
)
],

View File

@ -30,19 +30,18 @@ class CheckoutConfirmationPage extends StatefulWidget {
class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
CheckoutConfirmationPageState();
GlobalKey<CheckoutConfirmationPageState> _key =
GlobalKey<CheckoutConfirmationPageState>();
bool _showFullLoader;
List<TaxRate> _taxRates;
TaxRate _taxRate;
bool _isProcessingPayment;
@override
void initState() {
super.initState();
_showFullLoader = true;
_isProcessingPayment = false;
if (CheckoutSession.getInstance.paymentType == null) {
CheckoutSession.getInstance.paymentType = arrPaymentMethods.first;
}
@ -50,8 +49,6 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
_getTaxes();
}
_fetchUserId() {}
void reloadState({bool showLoader}) {
setState(() {
_showFullLoader = showLoader ?? false;
@ -135,7 +132,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
children: <Widget>[
Center(
child: Text(trans(context, "Checkout"),
style: Theme.of(context).primaryTextTheme.subhead),
style: Theme.of(context).primaryTextTheme.subtitle1),
),
Expanded(
child: Container(
@ -239,8 +236,10 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
],
),
wsPrimaryButton(context,
title: trans(context, "CHECKOUT"),
action: _handleCheckout),
title: _isProcessingPayment
? "PROCESSING..."
: trans(context, "CHECKOUT"),
action: _isProcessingPayment ? null : _handleCheckout),
],
)
: Center(
@ -252,7 +251,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
padding: const EdgeInsets.only(top: 15),
child: Text(
trans(context, "One moment") + "...",
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.subtitle1,
),
)
],
@ -301,7 +300,21 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
return;
}
if (_isProcessingPayment == true) {
return;
}
setState(() {
_isProcessingPayment = true;
});
CheckoutSession.getInstance.paymentType
.pay(context, state: this, taxRate: _taxRate);
Future.delayed(Duration(milliseconds: 5000), () {
setState(() {
_isProcessingPayment = false;
});
});
}
}

View File

@ -85,35 +85,33 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
_showSelectCountryModal() {
wsModalBottom(context,
title: trans(context, "Select a country"),
bodyWidget: Expanded(
child: ListView.separated(
itemCount: appCountryOptions.length,
itemBuilder: (BuildContext context, int index) {
Map<String, String> strName = appCountryOptions[index];
bodyWidget: ListView.separated(
itemCount: appCountryOptions.length,
itemBuilder: (BuildContext context, int index) {
Map<String, String> strName = appCountryOptions[index];
return InkWell(
child: Container(
child: Text(strName["name"],
style: Theme.of(context).primaryTextTheme.body2),
padding: EdgeInsets.only(top: 25, bottom: 25),
),
splashColor: Colors.grey,
highlightColor: Colors.black12,
onTap: () {
setState(() {
_strBillingCountry = strName["name"];
Navigator.of(context).pop();
});
},
);
},
separatorBuilder: (cxt, i) {
return Divider(
height: 0,
color: Colors.black12,
);
},
),
return InkWell(
child: Container(
child: Text(strName["name"],
style: Theme.of(context).primaryTextTheme.bodyText1),
padding: EdgeInsets.only(top: 25, bottom: 25),
),
splashColor: Colors.grey,
highlightColor: Colors.black12,
onTap: () {
setState(() {
_strBillingCountry = strName["name"];
Navigator.of(context).pop();
});
},
);
},
separatorBuilder: (cxt, i) {
return Divider(
height: 0,
color: Colors.black12,
);
},
));
}
@ -125,7 +123,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
backgroundColor: Colors.transparent,
title: Text(
trans(context, "Billing & Shipping Details"),
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.headline6,
),
centerTitle: true,
),
@ -241,7 +239,8 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(trans(context, "Remember my details"),
style: Theme.of(context).primaryTextTheme.body2),
style:
Theme.of(context).primaryTextTheme.bodyText2),
Checkbox(
value: valRememberDetails,
onChanged: (bool value) {

View File

@ -43,7 +43,7 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
appBar: AppBar(
backgroundColor: Colors.transparent,
title: Text(trans(context, "Payment Method"),
style: Theme.of(context).primaryTextTheme.subhead),
style: Theme.of(context).primaryTextTheme.headline6),
automaticallyImplyLeading: false,
centerTitle: true,
),
@ -74,35 +74,41 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: getPaymentTypes().length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: EdgeInsets.only(
top: 10, bottom: 10, left: 8, right: 8),
leading: Image(
image: AssetImage("assets/images/" +
getPaymentTypes()[index].assetImage),
width: 60,
fit: BoxFit.fitHeight,
alignment: Alignment.center),
title: Text(getPaymentTypes()[index].desc,
style: Theme.of(context)
.primaryTextTheme
.subhead),
selected: true,
trailing: (CheckoutSession
.getInstance.paymentType ==
getPaymentTypes()[index]
? Icon(Icons.check)
: null),
onTap: () {
CheckoutSession.getInstance.paymentType =
getPaymentTypes()[index];
Navigator.pop(context);
},
);
}),
child: ListView.separated(
itemCount: getPaymentTypes().length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
contentPadding: EdgeInsets.only(
top: 10, bottom: 10, left: 8, right: 8),
leading: Image(
image: AssetImage("assets/images/" +
getPaymentTypes()[index].assetImage),
width: 60,
fit: BoxFit.contain,
alignment: Alignment.center),
title: Text(getPaymentTypes()[index].desc,
style: Theme.of(context)
.primaryTextTheme
.subtitle1),
selected: true,
trailing:
(CheckoutSession.getInstance.paymentType ==
getPaymentTypes()[index]
? Icon(Icons.check)
: null),
onTap: () {
CheckoutSession.getInstance.paymentType =
getPaymentTypes()[index];
Navigator.pop(context);
},
);
},
separatorBuilder: (cxt, i) {
return Divider(
color: Colors.black12,
);
},
),
),
wsLinkButton(context, title: trans(context, "CANCEL"),
action: () {

View File

@ -17,7 +17,6 @@ import 'package:label_storemax/models/customer_address.dart';
import 'package:label_storemax/models/shipping_type.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:label_storemax/widgets/buttons.dart';
import 'package:math_expressions/math_expressions.dart';
import 'package:woosignal/models/response/shipping_method.dart';
import 'package:label_storemax/app_country_options.dart';
@ -49,9 +48,8 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
}
_getShippingMethods() async {
List<WSShipping> wsShipping = await appWooSignal((api) {
return api.getShippingMethods();
});
List<WSShipping> wsShipping =
await appWooSignal((api) => api.getShippingMethods());
CustomerAddress customerAddress =
CheckoutSession.getInstance.billingDetails.shippingAddress;
String postalCode = customerAddress.postalCode;
@ -70,9 +68,12 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
}
}
if (_shipping != null) {
if (_shipping != null && _shipping.methods != null) {
if (_shipping.methods.flatRate != null) {
_shipping.methods.flatRate.forEach((flatRate) {
_shipping.methods.flatRate
.where((t) => t != null)
.toList()
.forEach((flatRate) {
Map<String, dynamic> tmpShippingOption = {};
tmpShippingOption = {
"id": flatRate.id,
@ -86,7 +87,10 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
}
if (_shipping.methods.localPickup != null) {
_shipping.methods.localPickup.forEach((localPickup) {
_shipping.methods.localPickup
.where((t) => t != null)
.toList()
.forEach((localPickup) {
Map<String, dynamic> tmpShippingOption = {};
tmpShippingOption = {
"id": localPickup.id,
@ -100,7 +104,10 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
}
if (_shipping.methods.freeShipping != null) {
_shipping.methods.freeShipping.forEach((freeShipping) {
_shipping.methods.freeShipping
.where((t) => t != null)
.toList()
.forEach((freeShipping) {
if (isNumeric(freeShipping.cost)) {
Map<String, dynamic> tmpShippingOption = {};
tmpShippingOption = {
@ -183,7 +190,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
context,
"Shipping Methods",
),
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.headline6,
),
automaticallyImplyLeading: false,
centerTitle: true,
@ -234,7 +241,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
['title'],
style: Theme.of(context)
.primaryTextTheme
.subhead),
.subtitle1),
selected: true,
subtitle: FutureBuilder<String>(
future: _getShippingPrice(index),
@ -299,7 +306,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
"Shipping is not supported for your country, sorry"),
style: Theme.of(context)
.primaryTextTheme
.title,
.headline6,
textAlign: TextAlign.center))),
wsLinkButton(context, title: trans(context, "CANCEL"),
action: () {

View File

@ -60,25 +60,25 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
Padding(
child: Text(
trans(context, "Order Status"),
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.subtitle1,
),
padding: EdgeInsets.only(bottom: 15),
),
Text(
trans(context, "Thank You!"),
style: Theme.of(context).primaryTextTheme.title,
style: Theme.of(context).primaryTextTheme.headline6,
textAlign: TextAlign.left,
),
Text(
trans(context, "Your transaction details"),
style: Theme.of(context).primaryTextTheme.body1,
style: Theme.of(context).primaryTextTheme.bodyText2,
textAlign: TextAlign.left,
),
Text(
trans(context, "Order Ref") +
". #" +
_order.id.toString(),
style: Theme.of(context).primaryTextTheme.body2,
style: Theme.of(context).primaryTextTheme.bodyText1,
textAlign: TextAlign.left,
),
],
@ -96,7 +96,9 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
child: Image(
image: new AssetImage("assets/images/camion.gif"),
height: 170),
color: Colors.white,
decoration: BoxDecoration(
color: Colors.white,
),
width: double.infinity),
],
),
@ -104,7 +106,7 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
child: Padding(
child: Text(
trans(context, "Items"),
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.subtitle1,
textAlign: TextAlign.left,
),
padding: EdgeInsets.all(8),
@ -130,24 +132,28 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
Text(lineItem.name,
style: Theme.of(context)
.primaryTextTheme
.body2,
.bodyText1,
softWrap: false,
maxLines: 2,
overflow: TextOverflow.ellipsis),
Text("x" + lineItem.quantity.toString(),
style: Theme.of(context)
.primaryTextTheme
.body1),
.bodyText2),
],
),
),
Text(
formatStringCurrency(
total: lineItem.total.toString()),
style: Theme.of(context).primaryTextTheme.body2)
style: Theme.of(context)
.primaryTextTheme
.bodyText1)
],
),
decoration: BoxDecoration(color: Colors.white),
decoration: BoxDecoration(
color: Colors.white,
),
padding: EdgeInsets.all(16),
margin: EdgeInsets.all(8),
);

View File

@ -46,7 +46,7 @@ class _ErrorPageState extends State<ErrorPage> {
padding: const EdgeInsets.all(16.0),
child: Text(
trans(context, "Sorry, something went wrong"),
style: Theme.of(context).primaryTextTheme.body1,
style: Theme.of(context).primaryTextTheme.bodyText2,
textAlign: TextAlign.center,
),
),

View File

@ -12,6 +12,7 @@ import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:label_storemax/widgets/cart_icon.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:woosignal/models/response/product_category.dart' as WS;
import 'package:woosignal/models/response/products.dart' as WS;
import 'package:label_storemax/widgets/woosignal_ui.dart';
@ -26,10 +27,11 @@ class HomePage extends StatefulWidget {
class _HomePageState extends State<HomePage> {
_HomePageState();
RefreshController _refreshController =
RefreshController(initialRefresh: false);
List<WS.Product> _products = [];
List<WS.ProductCategory> _categories = [];
var _productsController = ScrollController();
final GlobalKey _key = GlobalKey();
int _page;
bool _shouldStopRequests;
@ -41,115 +43,68 @@ class _HomePageState extends State<HomePage> {
super.initState();
_isLoading = true;
_page = 1;
_home();
_addScrollListener();
}
_home() async {
await _fetchProducts();
await _fetchCategories();
_shouldStopRequests = false;
waitForNextRequest = false;
await _fetchMoreProducts();
await _fetchCategories();
setState(() {
_isLoading = false;
});
}
_fetchProducts() async {
_products = await appWooSignal((api) {
return api.getProducts(perPage: 50, page: _page, status: "publish");
});
}
_fetchCategories() async {
_categories = await appWooSignal((api) {
return api.getProductCategories();
});
}
_addScrollListener() async {
_productsController.addListener(() {
double maxScroll = _productsController.position.maxScrollExtent;
double currentScroll = _productsController.position.pixels;
double delta = 50.0;
if (maxScroll - currentScroll <= delta) {
if (_shouldStopRequests) {
return;
}
if (waitForNextRequest) {
return;
}
_fetchMoreProducts();
}
});
}
_fetchMoreProducts() async {
if (_shouldStopRequests) {
return;
}
if (waitForNextRequest) {
return;
}
waitForNextRequest = true;
List<WS.Product> products = await appWooSignal((api) {
_page = _page + 1;
return api.getProducts(perPage: 50, page: _page, status: "publish");
});
List<WS.Product> products = await appWooSignal((api) => api.getProducts(
perPage: 50, page: _page, status: "publish", stockStatus: "instock"));
_page = _page + 1;
if (products.length == 0) {
_shouldStopRequests = true;
}
waitForNextRequest = false;
setState(() {
_products.addAll(products.toList());
});
}
void _modalBottomSheetMenu() {
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
builder: (builder) {
return new Container(
height: double.infinity,
width: double.infinity - 10,
color: Colors.transparent,
child: new Container(
padding: EdgeInsets.only(top: 25, left: 18, right: 18),
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0),
),
),
child: Column(
children: <Widget>[
Text(trans(context, "Categories"),
style: Theme.of(context).primaryTextTheme.display1,
textAlign: TextAlign.left),
Expanded(
child: new ListView.builder(
itemCount: _categories.length,
itemBuilder: (BuildContext context, int index) {
return InkWell(
child: Container(
child: Text(_categories[index].name),
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: HexColor("#f2f2f2"), width: 2),
),
),
),
onTap: () {
Navigator.pushNamed(context, "/browse-category",
arguments: _categories[index]);
},
);
}),
)
],
),
),
);
},
_key.currentState.setState(() {});
wsModalBottom(
context,
title: trans(context, "Categories"),
bodyWidget: ListView.separated(
itemCount: _categories.length,
separatorBuilder: (cxt, i) {
return Divider();
},
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(parseHtmlString(_categories[index].name)),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, "/browse-category",
arguments: _categories[index])
.then((value) => setState(() {}));
},
);
},
),
);
}
@ -161,9 +116,7 @@ class _HomePageState extends State<HomePage> {
leading: Container(
child: IconButton(
icon: Icon(Icons.menu),
onPressed: () {
Navigator.pushNamed(context, "/home-menu");
},
onPressed: () => Navigator.pushNamed(context, "/home-menu"),
),
margin: EdgeInsets.only(left: 0),
),
@ -177,11 +130,10 @@ class _HomePageState extends State<HomePage> {
color: Colors.black,
size: 35,
),
onPressed: () {
Navigator.pushNamed(context, "/home-search");
},
onPressed: () => Navigator.pushNamed(context, "/home-search")
.then((value) => _key.currentState.setState(() {})),
),
wsCartIcon(context)
wsCartIcon(context, key: _key)
],
),
body: SafeArea(
@ -198,10 +150,10 @@ class _HomePageState extends State<HomePage> {
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(trans(context, "Shop") + " / ",
style: Theme.of(context).primaryTextTheme.subhead),
style: Theme.of(context).primaryTextTheme.subtitle1),
Text(
trans(context, "Newest"),
style: Theme.of(context).primaryTextTheme.body1,
style: Theme.of(context).primaryTextTheme.bodyText2,
)
],
),
@ -210,25 +162,21 @@ class _HomePageState extends State<HomePage> {
height: 60,
child: Text(
trans(context, "Browse categories"),
style: Theme.of(context).primaryTextTheme.body2,
style: Theme.of(context).primaryTextTheme.bodyText1,
),
onPressed: () {
_modalBottomSheetMenu();
},
onPressed: _modalBottomSheetMenu,
)
],
),
(_isLoading
? Expanded(child: showAppLoader())
: Expanded(
child: GridView.count(
controller: _productsController,
crossAxisCount: 2,
children: List.generate(_products.length, (index) {
return wsCardProductItem(context,
index: index, product: _products[index]);
}),
),
child: refreshableScroll(context,
refreshController: _refreshController,
onRefresh: _onRefresh,
onLoading: _onLoading,
products: _products,
onTap: _showProduct),
flex: 1,
)),
],
@ -236,4 +184,32 @@ class _HomePageState extends State<HomePage> {
),
);
}
void _onRefresh() async {
await _fetchMoreProducts();
setState(() {});
if (_shouldStopRequests) {
_refreshController.resetNoData();
} else {
_refreshController.refreshCompleted();
}
}
void _onLoading() async {
await _fetchMoreProducts();
if (mounted) {
setState(() {});
if (_shouldStopRequests) {
_refreshController.loadNoData();
} else {
_refreshController.loadComplete();
}
}
}
_showProduct(WS.Product product) {
Navigator.pushNamed(context, "/product-detail", arguments: product)
.then((value) => _key.currentState.setState(() {}));
}
}

View File

@ -9,6 +9,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/shared_pref/sp_auth.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/widgets/menu_item.dart';
import 'package:label_storemax/helpers/tools.dart';
@ -37,7 +38,7 @@ class _HomeMenuPageState extends State<HomeMenuPage> {
backgroundColor: Colors.transparent,
elevation: 0.0,
title: Text(trans(context, "Menu"),
style: Theme.of(context).primaryTextTheme.title),
style: Theme.of(context).primaryTextTheme.headline6),
leading: IconButton(
icon: Icon(Icons.close),
onPressed: () {
@ -89,7 +90,12 @@ class _HomeMenuPageState extends State<HomeMenuPage> {
Navigator.pushNamed(context, "/about");
}
void _actionProfile() {
void _actionProfile() async {
if (use_wp_login == true && !(await authCheck())) {
UserAuth.instance.redirect = "/account-detail";
Navigator.pushNamed(context, "/account-landing");
return;
}
Navigator.pushNamed(context, "/account-detail");
}
}

View File

@ -61,7 +61,7 @@ class _HomeSearchPageState extends State<HomeSearchPage> {
),
TextField(
controller: _txtSearchController,
style: Theme.of(context).primaryTextTheme.display2,
style: Theme.of(context).primaryTextTheme.headline3,
keyboardType: TextInputType.text,
autocorrect: false,
autofocus: true,

View File

@ -50,9 +50,23 @@ class _ProductDetailState extends State<ProductDetailPage> {
}
_fetchProductVariations() async {
_productVariations = await appWooSignal((api) {
return api.getProductVariations(_product.id);
});
List<WS.ProductVariation> tmpVariations = [];
int currentPage = 1;
bool isFetching = true;
while (isFetching) {
List<WS.ProductVariation> tmp = await appWooSignal((api) {
return api.getProductVariations(_product.id,
perPage: 100, page: currentPage);
});
if (tmp != null && tmp.length > 0) {
tmpVariations.addAll(tmp);
currentPage += 1;
} else {
isFetching = false;
}
}
_productVariations = tmpVariations;
setState(() {
_isLoading = false;
});
@ -89,33 +103,30 @@ class _ProductDetailState extends State<ProductDetailPage> {
title: trans(context, "Select a") +
" " +
_product.attributes[attributeIndex].name,
bodyWidget: Expanded(
child: ListView.separated(
itemCount: _product.attributes[attributeIndex].options.length,
separatorBuilder: (BuildContext context, int index) => Divider(),
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(_product.attributes[attributeIndex].options[index],
style: Theme.of(context).primaryTextTheme.subhead),
trailing: (_tmpAttributeObj.isNotEmpty &&
_tmpAttributeObj.containsKey(attributeIndex) &&
_tmpAttributeObj[attributeIndex]["value"] ==
_product.attributes[attributeIndex].options[index])
? Icon(Icons.check, color: Colors.blueAccent)
: null,
onTap: () {
_tmpAttributeObj[attributeIndex] = {
"name": _product.attributes[attributeIndex].name,
"value": _product.attributes[attributeIndex].options[index]
};
Navigator.pop(context, () {});
Navigator.pop(context);
_modalBottomSheetAttributes();
},
);
},
),
flex: 1,
bodyWidget: ListView.separated(
itemCount: _product.attributes[attributeIndex].options.length,
separatorBuilder: (BuildContext context, int index) => Divider(),
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(_product.attributes[attributeIndex].options[index],
style: Theme.of(context).primaryTextTheme.subtitle1),
trailing: (_tmpAttributeObj.isNotEmpty &&
_tmpAttributeObj.containsKey(attributeIndex) &&
_tmpAttributeObj[attributeIndex]["value"] ==
_product.attributes[attributeIndex].options[index])
? Icon(Icons.check, color: Colors.blueAccent)
: null,
onTap: () {
_tmpAttributeObj[attributeIndex] = {
"name": _product.attributes[attributeIndex].name,
"value": _product.attributes[attributeIndex].options[index]
};
Navigator.pop(context, () {});
Navigator.pop(context);
_modalBottomSheetAttributes();
},
);
},
),
);
}
@ -134,8 +145,7 @@ class _ProductDetailState extends State<ProductDetailPage> {
wsModalBottom(
context,
title: trans(context, "Options"),
bodyWidget: Expanded(
child: ListView.separated(
bodyWidget: ListView.separated(
itemCount: _product.attributes.length,
separatorBuilder: (BuildContext context, int index) => Divider(
color: Colors.black12,
@ -144,11 +154,11 @@ class _ProductDetailState extends State<ProductDetailPage> {
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(_product.attributes[index].name,
style: Theme.of(context).primaryTextTheme.subhead),
style: Theme.of(context).primaryTextTheme.subtitle1),
subtitle: (_tmpAttributeObj.isNotEmpty &&
_tmpAttributeObj.containsKey(index))
? Text(_tmpAttributeObj[index]["value"],
style: Theme.of(context).primaryTextTheme.body2)
style: Theme.of(context).primaryTextTheme.bodyText1)
: Text(trans(context, "Select a") +
" " +
_product.attributes[index].name),
@ -161,7 +171,7 @@ class _ProductDetailState extends State<ProductDetailPage> {
},
);
},
)),
),
extraWidget: Container(
decoration: BoxDecoration(
border: Border(top: BorderSide(color: Colors.black12, width: 1))),
@ -179,14 +189,14 @@ class _ProductDetailState extends State<ProductDetailPage> {
findProductVariation() == null)
? trans(context, "This variation is unavailable")
: trans(context, "Choose your options"))),
style: Theme.of(context).primaryTextTheme.subhead),
style: Theme.of(context).primaryTextTheme.subtitle1),
Text(
(findProductVariation() != null
? findProductVariation().stockStatus != "instock"
? trans(context, "Out of stock")
: ""
: ""),
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.subtitle1,
),
wsPrimaryButton(context, title: trans(context, "Add to cart"),
action: () {
@ -255,11 +265,10 @@ class _ProductDetailState extends State<ProductDetailPage> {
wsModalBottom(
context,
title: trans(context, "Description"),
bodyWidget: Expanded(
child: SingleChildScrollView(
child: Text(parseHtmlString(_product.description)),
bodyWidget: SingleChildScrollView(
child: Text(
parseHtmlString(_product.description),
),
flex: 1,
),
);
}
@ -312,7 +321,9 @@ class _ProductDetailState extends State<ProductDetailPage> {
Container(
height: 100,
padding: EdgeInsets.symmetric(
vertical: 10, horizontal: 16),
vertical: 10,
horizontal: 16,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -320,8 +331,11 @@ class _ProductDetailState extends State<ProductDetailPage> {
Flexible(
child: Text(
_product.name,
style:
Theme.of(context).primaryTextTheme.body2,
style: Theme.of(context)
.primaryTextTheme
.bodyText1
.copyWith(
color: Colors.black87, fontSize: 20),
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
maxLines: 2,
@ -338,13 +352,24 @@ class _ProductDetailState extends State<ProductDetailPage> {
total: _product.price),
style: Theme.of(context)
.primaryTextTheme
.display1
.headline4
.copyWith(
fontSize: 20,
),
textAlign: TextAlign.right,
),
],
(_product.onSale == true
? Text(
formatStringCurrency(
total: _product.regularPrice),
style: TextStyle(
color: Colors.grey,
decoration:
TextDecoration.lineThrough,
),
)
: null)
].where((t) => t != null).toList(),
),
flex: 2,
)
@ -352,7 +377,10 @@ class _ProductDetailState extends State<ProductDetailPage> {
),
),
Container(
color: Colors.white,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: wsBoxShadow(),
borderRadius: BorderRadius.circular(4)),
padding:
EdgeInsets.symmetric(vertical: 4, horizontal: 16),
height: 180,
@ -378,15 +406,13 @@ class _ProductDetailState extends State<ProductDetailPage> {
trans(context, "Full description"),
style: Theme.of(context)
.primaryTextTheme
.body1
.bodyText2
.copyWith(fontSize: 14),
textAlign: TextAlign.right,
),
height: 50,
minWidth: 60,
onPressed: () {
_modalBottomSheetMenu();
},
onPressed: _modalBottomSheetMenu,
),
],
),
@ -432,7 +458,8 @@ class _ProductDetailState extends State<ProductDetailPage> {
children: <Widget>[
Text(
"Quantity",
style: Theme.of(context).primaryTextTheme.body2,
style:
Theme.of(context).primaryTextTheme.bodyText1,
),
Row(
children: <Widget>[
@ -451,8 +478,9 @@ class _ProductDetailState extends State<ProductDetailPage> {
),
Text(
_quantityIndicator.toString(),
style:
Theme.of(context).primaryTextTheme.body2,
style: Theme.of(context)
.primaryTextTheme
.bodyText1,
),
IconButton(
icon: Icon(
@ -479,11 +507,12 @@ class _ProductDetailState extends State<ProductDetailPage> {
child: Align(
child: Text(
formatStringCurrency(
total: (double.parse(_product.price) *
total: (parseWcPrice(_product.price) *
_quantityIndicator)
.toString()),
style:
Theme.of(context).primaryTextTheme.display1,
style: Theme.of(context)
.primaryTextTheme
.headline4,
textAlign: TextAlign.center,
),
alignment: Alignment.centerLeft,
@ -492,9 +521,7 @@ class _ProductDetailState extends State<ProductDetailPage> {
child: wsPrimaryButton(
context,
title: trans(context, "Add to cart"),
action: () {
_addItemToCart();
},
action: () => _addItemToCart(),
),
),
],

View File

@ -50,13 +50,15 @@ class _ProductImageViewerPageState extends State<ProductImageViewerPage> {
index: _initialIndex,
itemBuilder: (BuildContext context, int index) {
return CachedNetworkImage(
imageUrl: _arrImageSrc[index],
placeholder: (context, url) =>
new CircularProgressIndicator(
strokeWidth: 2, backgroundColor: Colors.black12),
errorWidget: (context, url, error) =>
new Icon(Icons.error),
fit: BoxFit.contain);
imageUrl: _arrImageSrc[index],
placeholder: (context, url) =>
new CircularProgressIndicator(
strokeWidth: 2,
backgroundColor: Colors.black12,
),
errorWidget: (context, url, error) => new Icon(Icons.error),
fit: BoxFit.contain,
);
},
itemCount: _arrImageSrc.length,
viewportFraction: 0.9,

View File

@ -0,0 +1,51 @@
//
// LabelCore
// Label StoreMAX
//
// Created by Anthony Gordon.
// 2020, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
import 'package:flutter/widgets.dart';
import 'package:label_storemax/helpers/data/order_wc.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/pages/checkout_confirmation.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart';
import 'package:woosignal/models/response/tax_rate.dart';
cashOnDeliveryPay(context,
{@required CheckoutConfirmationPageState state, TaxRate taxRate}) async {
try {
OrderWC orderWC = await buildOrderWC(taxRate: taxRate, markPaid: false);
Order order = await appWooSignal((api) => api.createOrder(orderWC));
if (order != null) {
Cart.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
showEdgeAlertWith(
context,
title: trans(context, "Error"),
desc: trans(context,
trans(context, "Something went wrong, please contact our store")),
);
state.reloadState(showLoader: false);
}
} catch (ex) {
showEdgeAlertWith(
context,
title: trans(context, "Error"),
desc: trans(context,
trans(context, "Something went wrong, please contact our store")),
);
state.reloadState(showLoader: false);
}
}

View File

@ -0,0 +1,62 @@
//
// LabelCore
// Label StoreMAX
//
// Created by Anthony Gordon.
// 2020, WooSignal Ltd. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
import 'package:flutter/widgets.dart';
import 'package:label_storemax/helpers/data/order_wc.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/pages/checkout_confirmation.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart';
import 'package:woosignal/models/response/tax_rate.dart';
// CALL THE BELOW METHOD TO SHOW AND HIDE LOADER
// state.reloadState(showLoader: false);
// CHECKOUT HELPER
// IT WILL RETURN THE ORDER TOTAL, BILLING DETAILS AND CART
// await checkout(taxRate, (total, billingDetails, cart) async {
//
// });
// REMEMBER TO ADD THIS METHOD E.G. "examplePay" TO THE APP_PAYMENT_METHODS
// AS THE PAY METHOD
examplePay(context,
{@required CheckoutConfirmationPageState state, TaxRate taxRate}) async {
// HANDLE YOUR PAYMENT INTEGRATION HERE
// ...
// ...
// ...
// THEN ON SUCCESS OF A PAYMENT YOU CAN DO SOMETHING SIMILAR BELOW
// CREATES ORDER MODEL
OrderWC orderWC = await buildOrderWC(taxRate: taxRate, markPaid: true);
// CREATES ORDER IN WOOCOMMERCE
Order order = await appWooSignal((api) => api.createOrder(orderWC));
// CHECK IF ORDER IS NULL
if (order != null) {
Cart.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
showEdgeAlertWith(
context,
title: trans(context, "Error"),
desc: trans(context,
trans(context, "Something went wrong, please contact our store")),
);
state.reloadState(showLoader: false);
}
}

View File

@ -25,87 +25,94 @@ import 'package:woosignal_stripe/woosignal_stripe.dart';
stripePay(context,
{@required CheckoutConfirmationPageState state, TaxRate taxRate}) async {
// CONFIGURE STRIPE
FlutterStripePayment.setStripeSettings(
stripeAccount: app_stripe_account, liveMode: app_stripe_live_mode);
try {
// CONFIGURE STRIPE
FlutterStripePayment.setStripeSettings(
stripeAccount: app_stripe_account, liveMode: app_stripe_live_mode);
var paymentResponse = await FlutterStripePayment.addPaymentMethod();
var paymentResponse = await FlutterStripePayment.addPaymentMethod();
// CHECK STATUS FROM STRIPE
if (paymentResponse.status == PaymentResponseStatus.succeeded) {
state.reloadState(showLoader: true);
// CHECK STATUS FROM STRIPE
if (paymentResponse.status == PaymentResponseStatus.succeeded) {
state.reloadState(showLoader: true);
// CHECKOUT HELPER
await checkout(taxRate, (total, billingDetails, cart) async {
Map<String, dynamic> address = {
"name": billingDetails.billingAddress.nameFull(),
"line1": billingDetails.shippingAddress.addressLine,
"city": billingDetails.shippingAddress.city,
"postal_code": billingDetails.shippingAddress.postalCode,
"country": billingDetails.shippingAddress.country
};
// CHECKOUT HELPER
await checkout(taxRate, (total, billingDetails, cart) async {
Map<String, dynamic> address = {
"name": billingDetails.billingAddress.nameFull(),
"line1": billingDetails.shippingAddress.addressLine,
"city": billingDetails.shippingAddress.city,
"postal_code": billingDetails.shippingAddress.postalCode,
"country": billingDetails.shippingAddress.country
};
String cartShortDesc = await cart.cartShortDesc();
String cartShortDesc = await cart.cartShortDesc();
dynamic rsp = await appWooSignal((api) {
return api.stripePaymentIntent(
amount: total,
email: billingDetails.billingAddress.emailAddress,
desc: cartShortDesc,
shipping: address,
dynamic rsp = await appWooSignal((api) => api.stripePaymentIntent(
amount: total,
email: billingDetails.billingAddress.emailAddress,
desc: cartShortDesc,
shipping: address,
));
if (rsp == null) {
showEdgeAlertWith(context,
title: trans(context, "Oops!"),
desc: trans(context, "Something went wrong, please try again."),
icon: Icons.payment,
style: EdgeAlertStyle.WARNING);
state.reloadState(showLoader: false);
return;
}
String clientSecret = rsp["client_secret"];
var intentResponse = await FlutterStripePayment.confirmPaymentIntent(
clientSecret,
paymentResponse.paymentMethodId,
(double.parse(total) * 100),
);
});
if (rsp == null) {
showEdgeAlertWith(context,
title: trans(context, "Oops!"),
desc: trans(context, "Something went wrong, please try again."),
icon: Icons.payment,
style: EdgeAlertStyle.WARNING);
state.reloadState(showLoader: false);
return;
}
if (intentResponse.status == PaymentResponseStatus.succeeded) {
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
Order order = await appWooSignal((api) => api.createOrder(orderWC));
String clientSecret = rsp["client_secret"];
var intentResponse = await FlutterStripePayment.confirmPaymentIntent(
clientSecret,
paymentResponse.paymentMethodId,
(double.parse(total) * 100),
);
if (intentResponse.status == PaymentResponseStatus.succeeded) {
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
Order order = await appWooSignal((api) {
return api.createOrder(orderWC);
});
if (order != null) {
Cart.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
if (order != null) {
Cart.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
showEdgeAlertWith(
context,
title: trans(context, "Error"),
desc: trans(
context,
trans(context,
"Something went wrong, please contact our store")),
);
state.reloadState(showLoader: false);
}
} else if (intentResponse.status == PaymentResponseStatus.failed) {
if (app_debug) {
print(intentResponse.errorMessage);
}
showEdgeAlertWith(
context,
title: trans(context, "Error"),
desc: trans(
context,
trans(
context, "Something went wrong, please contact our store")),
desc: intentResponse.errorMessage,
);
state.reloadState(showLoader: false);
} else {
state.reloadState(showLoader: false);
}
} else if (intentResponse.status == PaymentResponseStatus.failed) {
if (app_debug) {
print(intentResponse.errorMessage);
}
showEdgeAlertWith(
context,
title: trans(context, "Error"),
desc: intentResponse.errorMessage,
);
state.reloadState(showLoader: false);
} else {
state.reloadState(showLoader: false);
}
});
});
} else {
state.reloadState(showLoader: false);
}
} catch (ex) {
showEdgeAlertWith(context,
title: trans(context, "Oops!"),
desc: trans(context, "Something went wrong, please try again."),
icon: Icons.payment,
style: EdgeAlertStyle.WARNING);
state.reloadState(showLoader: false);
}
}

View File

@ -38,7 +38,7 @@ Widget wsSecondaryButton(BuildContext context,
child: RaisedButton(
padding: EdgeInsets.all(10),
child: Text(title,
style: Theme.of(context).primaryTextTheme.body2,
style: Theme.of(context).primaryTextTheme.bodyText1,
textAlign: TextAlign.center),
onPressed: action,
color: HexColor("#f6f6f9"),
@ -54,7 +54,7 @@ Widget wsLinkButton(BuildContext context,
child: MaterialButton(
padding: EdgeInsets.all(10),
child: Text(title,
style: Theme.of(context).primaryTextTheme.body2,
style: Theme.of(context).primaryTextTheme.bodyText1,
textAlign: TextAlign.left),
onPressed: action,
elevation: 0,

View File

@ -12,44 +12,48 @@ import 'package:flutter/material.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart';
Widget wsCartIcon(BuildContext context) {
return IconButton(
icon: Stack(
children: <Widget>[
Positioned.fill(
child: Align(
child: Icon(Icons.shopping_cart, size: 20, color: Colors.black87),
alignment: Alignment.bottomCenter,
),
bottom: 0),
Positioned.fill(
child: Align(
child: FutureBuilder<List<CartLineItem>>(
future: Cart.getInstance.getCart(),
builder: (BuildContext context,
AsyncSnapshot<List<CartLineItem>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text("");
default:
if (snapshot.hasError)
return Text("");
else
return new Text(
snapshot.data.length.toString(),
style: Theme.of(context).primaryTextTheme.body2,
textAlign: TextAlign.center,
);
}
},
Widget wsCartIcon(BuildContext context, {Key key}) {
return StatefulBuilder(
key: key,
builder: (BuildContext context, StateSetter setState) => IconButton(
icon: Stack(
children: <Widget>[
Positioned.fill(
child: Align(
child:
Icon(Icons.shopping_cart, size: 20, color: Colors.black87),
alignment: Alignment.bottomCenter,
),
alignment: Alignment.topCenter,
),
top: 0)
],
bottom: 0),
Positioned.fill(
child: Align(
child: FutureBuilder<List<CartLineItem>>(
future: Cart.getInstance.getCart(),
builder: (BuildContext context,
AsyncSnapshot<List<CartLineItem>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text("");
default:
if (snapshot.hasError)
return Text("");
else
return new Text(
snapshot.data.length.toString(),
style: Theme.of(context).primaryTextTheme.bodyText1,
textAlign: TextAlign.center,
);
}
},
),
alignment: Alignment.topCenter,
),
top: 0)
],
),
onPressed: () {
Navigator.pushNamed(context, "/cart");
},
),
onPressed: () {
Navigator.pushNamed(context, "/cart");
},
);
}

View File

@ -24,7 +24,7 @@ Widget wsMenuItem(BuildContext context,
children: <Widget>[
leading,
Text(" " + title,
style: Theme.of(context).primaryTextTheme.body1),
style: Theme.of(context).primaryTextTheme.bodyText2),
],
),
),

View File

@ -28,7 +28,7 @@ Widget wsRow2Text(BuildContext context, {String text1, String text2}) {
children: <Widget>[
Flexible(
child: Container(
child: Text(text1, style: Theme.of(context).textTheme.title),
child: Text(text1, style: Theme.of(context).textTheme.headline6),
),
flex: 3,
),
@ -37,7 +37,7 @@ Widget wsRow2Text(BuildContext context, {String text1, String text2}) {
child: Text(text2,
style: Theme.of(context)
.primaryTextTheme
.body2
.bodyText1
.copyWith(fontSize: 16, color: Colors.black87)),
),
flex: 3,
@ -50,7 +50,7 @@ Widget wsNoResults(BuildContext context) {
return Column(
children: <Widget>[
Text(trans(context, "No results"),
style: Theme.of(context).primaryTextTheme.body1),
style: Theme.of(context).primaryTextTheme.bodyText2),
],
);
}
@ -70,7 +70,10 @@ Widget wsCheckoutRow(BuildContext context,
children: <Widget>[
Padding(
child: Text(heading,
style: Theme.of(context).primaryTextTheme.body1),
style: Theme.of(context)
.primaryTextTheme
.bodyText2
.copyWith(fontSize: 16)),
padding: EdgeInsets.only(bottom: 8),
),
Flexible(
@ -87,8 +90,9 @@ Widget wsCheckoutRow(BuildContext context,
Flexible(
child: Container(
child: Text(leadTitle,
style:
Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context)
.primaryTextTheme
.subtitle1,
maxLines: 2,
overflow: TextOverflow.ellipsis,
softWrap: false),
@ -131,15 +135,15 @@ Widget wsTextEditingRow(BuildContext context,
children: <Widget>[
Flexible(
child: Padding(
child:
Text(heading, style: Theme.of(context).primaryTextTheme.body2),
child: Text(heading,
style: Theme.of(context).primaryTextTheme.bodyText1),
padding: EdgeInsets.only(bottom: 2),
),
),
Flexible(
child: TextField(
controller: controller,
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.subtitle1,
keyboardType: keyboardType ?? TextInputType.text,
autocorrect: false,
autofocus: shouldAutoFocus ?? false,
@ -160,13 +164,15 @@ Widget widgetCheckoutMeta(BuildContext context, {String title, String amount}) {
children: <Widget>[
Flexible(
child: Container(
child: Text(title, style: Theme.of(context).primaryTextTheme.body1),
child:
Text(title, style: Theme.of(context).primaryTextTheme.bodyText2),
),
flex: 3,
),
Flexible(
child: Container(
child: Text(amount, style: Theme.of(context).primaryTextTheme.body2),
child:
Text(amount, style: Theme.of(context).primaryTextTheme.bodyText1),
),
flex: 3,
)
@ -188,51 +194,68 @@ List<BoxShadow> wsBoxShadow({double blurRadius}) {
];
}
Widget wsCardProductItem(BuildContext context, {int index, Product product}) {
Widget wsCardProductItem(BuildContext context,
{int index, Product product, onTap}) {
return InkWell(
child: Container(
padding: EdgeInsets.all(10),
margin: EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Flexible(
child: CachedNetworkImage(
imageUrl: (product.images.length > 0
? product.images.first.src
: ""),
placeholder: (context, url) =>
new CircularProgressIndicator(),
errorWidget: (context, url, error) => new Icon(Icons.error),
fit: BoxFit.fitWidth),
flex: 4,
padding: EdgeInsets.all(10),
margin: EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(5),
boxShadow: wsBoxShadow(blurRadius: 4),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Flexible(
child: CachedNetworkImage(
imageUrl:
(product.images.length > 0 ? product.images.first.src : ""),
placeholder: (context, url) => new CircularProgressIndicator(),
errorWidget: (context, url, error) => new Icon(Icons.error),
fit: BoxFit.contain),
flex: 4,
),
Flexible(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
formatStringCurrency(total: product.price),
style: Theme.of(context).textTheme.bodyText1,
textAlign: TextAlign.center,
),
(product.onSale
? Padding(
padding: const EdgeInsets.only(left: 8),
child: Text(
formatStringCurrency(total: product.regularPrice),
style: Theme.of(context).textTheme.bodyText1.copyWith(
decoration: TextDecoration.lineThrough,
color: Colors.grey),
textAlign: TextAlign.left,
),
)
: null),
].where((t) => t != null).toList(),
),
Flexible(
child: Text(
formatStringCurrency(total: product.price),
style: Theme.of(context).textTheme.body2,
textAlign: TextAlign.left,
),
flex: 1,
flex: 1,
),
Expanded(
child: Text(
product.name,
style: Theme.of(context).textTheme.bodyText2,
overflow: TextOverflow.clip,
maxLines: 1,
),
Expanded(
child: Text(
product.name,
style: Theme.of(context).textTheme.body1,
overflow: TextOverflow.clip,
maxLines: 1,
),
flex: 1,
)
],
)),
onTap: () {
Navigator.pushNamed(context, "/product-detail", arguments: product);
},
flex: 1,
)
],
),
),
onTap: () => onTap(product),
);
}
@ -245,27 +268,41 @@ void wsModalBottom(BuildContext context,
return SafeArea(
child: Container(
height: double.infinity,
width: double.infinity - 10,
width: double.infinity,
color: Colors.transparent,
child: new Container(
padding: EdgeInsets.only(top: 25, left: 18, right: 18),
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0)),
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0),
),
),
child: Column(
children: <Widget>[
Text(title,
style: Theme.of(context)
.primaryTextTheme
.display1
.copyWith(fontSize: 20),
textAlign: TextAlign.left),
bodyWidget,
extraWidget ?? Container()
],
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Text(title,
style: Theme.of(context)
.primaryTextTheme
.headline4
.copyWith(fontSize: 20),
textAlign: TextAlign.left),
),
Expanded(
child: Container(
padding:
EdgeInsets.symmetric(horizontal: 16, vertical: 8),
width: double.infinity,
decoration: BoxDecoration(
boxShadow: wsBoxShadow(),
color: Colors.white,
borderRadius: BorderRadius.circular(8)),
child: bodyWidget),
),
extraWidget ?? null
].where((t) => t != null).toList(),
)),
),
);
@ -431,13 +468,14 @@ Widget wsCardCartItem(BuildContext context,
children: <Widget>[
Text(
cartLineItem.name,
style: Theme.of(context).primaryTextTheme.subhead,
style: Theme.of(context).primaryTextTheme.subtitle1,
overflow: TextOverflow.ellipsis,
maxLines: 3,
),
(cartLineItem.variationOptions != null
? Text(cartLineItem.variationOptions,
style: Theme.of(context).primaryTextTheme.body2)
style:
Theme.of(context).primaryTextTheme.bodyText1)
: Container()),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
@ -449,11 +487,14 @@ Widget wsCardCartItem(BuildContext context,
: trans(context, "In Stock")),
style: (cartLineItem.stockStatus == "outofstock"
? Theme.of(context).textTheme.caption
: Theme.of(context).primaryTextTheme.body1)),
: Theme.of(context)
.primaryTextTheme
.bodyText2)),
Text(
formatDoubleCurrency(
total: double.parse(cartLineItem.total)),
style: Theme.of(context).primaryTextTheme.subhead,
style:
Theme.of(context).primaryTextTheme.subtitle1,
textAlign: TextAlign.center)
],
),
@ -479,7 +520,7 @@ Widget wsCardCartItem(BuildContext context,
highlightColor: Colors.transparent,
),
Text(cartLineItem.quantity.toString(),
style: Theme.of(context).primaryTextTheme.title),
style: Theme.of(context).primaryTextTheme.headline6),
IconButton(
icon: Icon(Icons.remove_circle_outline),
onPressed: actionDecrementQuantity,

View File

@ -7,35 +7,28 @@ packages:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.11"
version: "2.0.13"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.2"
version: "1.6.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.0"
version: "2.4.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.5"
braintree_payment:
dependency: "direct main"
description:
name: braintree_payment
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.4"
version: "2.0.0"
bubble_tab_indicator:
dependency: "direct main"
description:
@ -56,7 +49,7 @@ packages:
name: charcode
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
version: "1.1.3"
clock:
dependency: transitive
description:
@ -70,7 +63,7 @@ packages:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.11"
version: "1.14.12"
convert:
dependency: transitive
description:
@ -84,7 +77,7 @@ packages:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
version: "2.1.4"
csslib:
dependency: transitive
description:
@ -237,7 +230,7 @@ packages:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
version: "2.1.12"
intl:
dependency: "direct main"
description:
@ -350,13 +343,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
pull_to_refresh:
dependency: "direct main"
description:
name: pull_to_refresh
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.8"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "2.1.3"
rxdart:
dependency: transitive
description:
@ -403,7 +403,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.5"
version: "1.7.0"
sqflite:
dependency: transitive
description:
@ -466,7 +466,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.11"
version: "0.2.15"
transformer_page_view:
dependency: transitive
description:
@ -529,7 +529,7 @@ packages:
name: woosignal
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.6"
version: "1.0.8"
woosignal_stripe:
dependency: "direct main"
description:
@ -550,7 +550,7 @@ packages:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "3.5.0"
version: "3.6.1"
yaml:
dependency: transitive
description:

View File

@ -1,5 +1,5 @@
# Label StoreMax
# Version 2.0.0
# Version 2.0.2
#authors: - "Anthony Gordon"
#documentation: https://woosignal.com/docs/app/ios/label-storemax
#homepage: https://woosignal.com/
@ -23,7 +23,7 @@ environment:
sdk: ">=2.1.0 <3.0.0"
dependencies:
woosignal: ^1.0.6
woosignal: ^1.0.8
woosignal_stripe: ^0.0.4
wp_json_api: ^0.1.2
shared_preferences: ^0.5.6+3
@ -34,6 +34,7 @@ dependencies:
flutter_money_formatter: ^0.8.3
platform_alert_dialog: ^1.0.0+2
flutter_web_browser: ^0.11.0
pull_to_refresh: ^1.5.8
dio: ^3.0.9
intl: ^0.16.1
flutter_swiper: ^1.1.6
@ -44,7 +45,6 @@ dependencies:
flutter_spinkit: ^4.1.2+1
flutter_launcher_icons: ^0.7.4
html: ^0.14.0+3
braintree_payment: ^1.2.4
flutter:
sdk: flutter
@ -75,7 +75,7 @@ flutter:
- assets/images/credit_cards.png
- assets/images/shipping_icon.png
- assets/images/dark_powered_by_stripe.png
- assets/images/cart_empty.png
- assets/images/cash_on_delivery.jpeg
- lang/en.json
fonts: