v3.0.0 - Major release, Flutter 2.0.0+ support + more

This commit is contained in:
Anthony 2021-03-08 01:38:45 +00:00
parent b935c2a29d
commit ed6460836f
58 changed files with 1390 additions and 1087 deletions

View File

@ -1,3 +1,11 @@
## [3.0.0] - 2020-03-08
* Major release
* Flutter 2.0.0+ support
* Manage app from WooSignal
* Code tidy up
* Bug fixes
## [2.6.0] - 2020-02-24 ## [2.6.0] - 2020-02-24
* Ability to manage affiliate products * Ability to manage affiliate products

View File

@ -1 +1 @@
bc983e13b3efb48b50e7a3cb8fc4ede2 5b271ab1c6a17b054237577340baf791

View File

@ -1,18 +1,18 @@
# #
# NOTE: This podspec is NOT to be published. It is only used as a local source! # NOTE: This podspec is NOT to be published. It is only used as a local source!
# This is a generated file; do not edit or check into version control.
# #
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'Flutter' s.name = 'Flutter'
s.version = '1.0.0' s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.' s.summary = 'High-performance, high-fidelity mobile apps.'
s.description = <<-DESC
Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
DESC
s.homepage = 'https://flutter.io' s.homepage = 'https://flutter.io'
s.license = { :type => 'MIT' } s.license = { :type => 'MIT' }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
s.ios.deployment_target = '8.0' s.ios.deployment_target = '8.0'
s.vendored_frameworks = 'Flutter.framework' # Framework linking is handled by Flutter tooling, not CocoaPods.
# Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs.
s.vendored_frameworks = 'path/to/nothing'
end end

View File

@ -265,7 +265,6 @@
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
"${PODS_ROOT}/../Flutter/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/Stripe/Stripe.framework", "${BUILT_PRODUCTS_DIR}/Stripe/Stripe.framework",
"${BUILT_PRODUCTS_DIR}/device_info/device_info.framework", "${BUILT_PRODUCTS_DIR}/device_info/device_info.framework",
"${BUILT_PRODUCTS_DIR}/flutter_money_formatter/flutter_money_formatter.framework", "${BUILT_PRODUCTS_DIR}/flutter_money_formatter/flutter_money_formatter.framework",
@ -283,7 +282,6 @@
name = "[CP] Embed Pods Frameworks"; name = "[CP] Embed Pods Frameworks";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.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", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Stripe.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_money_formatter.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_money_formatter.framework",

View File

@ -2,6 +2,6 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "self:">
</FileRef> </FileRef>
</Workspace> </Workspace>

View File

@ -172,5 +172,7 @@
"Account updated": "Konto aktualisiert", "Account updated": "Konto aktualisiert",
"Spend a minimum of": "Geben Sie mindestens ein", "Spend a minimum of": "Geben Sie mindestens ein",
"for": "zum", "for": "zum",
"Buy Product": "Produkt kaufen" "Buy Product": "Produkt kaufen",
"Retry": "Wiederholen",
"Retry later": "Versuchen Sie es später erneut"
} }

View File

@ -172,5 +172,7 @@
"Account updated": "Account updated", "Account updated": "Account updated",
"Spend a minimum of": "Spend a minimum of", "Spend a minimum of": "Spend a minimum of",
"for": "for", "for": "for",
"Buy Product": "Buy Product" "Buy Product": "Buy Product",
"Retry": "Retry",
"Retry later": "Retry later"
} }

View File

@ -172,5 +172,7 @@
"Account updated": "Cuenta actualizada", "Account updated": "Cuenta actualizada",
"Spend a minimum of": "Gasta un mínimo de", "Spend a minimum of": "Gasta un mínimo de",
"for": "para", "for": "para",
"Buy Product": "Comprar producto" "Buy Product": "Comprar producto",
"Retry": "Rever",
"Retry later": "Reintentar más tarde"
} }

View File

@ -172,5 +172,7 @@
"Account updated": "Compte mis à jour", "Account updated": "Compte mis à jour",
"Spend a minimum of": "Dépensez un minimum de", "Spend a minimum of": "Dépensez un minimum de",
"for": "pour", "for": "pour",
"Buy Product": "Acheter un produit" "Buy Product": "Acheter un produit",
"Retry": "Recommencez",
"Retry later": "Réessayer plus tard"
} }

View File

@ -172,5 +172,7 @@
"Account updated": "khaata apadet kiya gaya", "Account updated": "khaata apadet kiya gaya",
"Spend a minimum of": "kam se kam kharch karen", "Spend a minimum of": "kam se kam kharch karen",
"for": "ke liye", "for": "ke liye",
"Buy Product": "utpaad khareeden" "Buy Product": "utpaad khareeden",
"Retry": "pun: prayaas karen",
"Retry later": "baad mein pun: prayaas karen"
} }

View File

@ -172,5 +172,7 @@
"Account updated": "Account aggiornato", "Account updated": "Account aggiornato",
"Spend a minimum of": "Spendi un minimo di", "Spend a minimum of": "Spendi un minimo di",
"for": "per", "for": "per",
"Buy Product": "Acquista prodotto" "Buy Product": "Acquista prodotto",
"Retry": "Riprova",
"Retry later": "Riprova più tardi"
} }

View File

@ -172,5 +172,7 @@
"Account updated": "Conta atualizada", "Account updated": "Conta atualizada",
"Spend a minimum of": "Gaste um mínimo de", "Spend a minimum of": "Gaste um mínimo de",
"for": "para", "for": "para",
"Buy Product": "Comprar Produto" "Buy Product": "Comprar Produto",
"Retry": "Tentar novamente",
"Retry later": "Tentar mais tarde"
} }

View File

@ -0,0 +1,17 @@
//
// Generated file. Do not edit.
//
// ignore_for_file: lines_longer_than_80_chars
import 'package:shared_preferences_web/shared_preferences_web.dart';
import 'package:url_launcher_web/url_launcher_web.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
// ignore: public_member_api_docs
void registerPlugins(Registrar registrar) {
SharedPreferencesPlugin.registerWith(registrar);
UrlLauncherPlugin.registerWith(registrar);
registrar.registerMessageHandler();
}

View File

@ -0,0 +1,9 @@
import 'package:woosignal/models/response/woosignal_app.dart';
class AppHelper {
AppHelper._privateConstructor();
static final AppHelper instance = AppHelper._privateConstructor();
WooSignalApp appConfig;
}

View File

@ -40,9 +40,7 @@ class AppLocalizations {
}); });
} }
String trans(String key) { String trans(String key) => _localizedStrings[key];
return _localizedStrings[key];
}
} }
class _AppLocalizationsDelegate class _AppLocalizationsDelegate

View File

@ -10,18 +10,20 @@
import 'dart:io'; import 'dart:io';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart'; import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart';
import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/billing_details.dart'; import 'package:label_storemax/models/billing_details.dart';
import 'package:label_storemax/models/cart.dart'; import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart'; import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart'; import 'package:label_storemax/models/checkout_session.dart';
import 'package:woosignal/models/payload/order_wc.dart'; import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/tax_rate.dart'; import 'package:woosignal/models/response/tax_rate.dart';
import 'package:woosignal/models/response/woosignal_app.dart';
Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async { Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
OrderWC orderWC = OrderWC(); OrderWC orderWC = OrderWC();
WooSignalApp wooSignalApp = AppHelper.instance.appConfig;
String paymentMethodName = CheckoutSession.getInstance.paymentType.name ?? ""; String paymentMethodName = CheckoutSession.getInstance.paymentType.name ?? "";
@ -33,9 +35,9 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
orderWC.setPaid = markPaid; orderWC.setPaid = markPaid;
orderWC.status = "pending"; orderWC.status = "pending";
orderWC.currency = app_currency_iso.toUpperCase(); orderWC.currency = wooSignalApp.currencyMeta.code.toUpperCase();
orderWC.customerId = orderWC.customerId =
(use_wp_login == true) ? int.parse(await readUserId()) : 0; (wooSignalApp.wpLoginEnabled == 1) ? int.parse(await readUserId()) : 0;
List<LineItems> lineItems = []; List<LineItems> lineItems = [];
List<CartLineItem> cartItems = await Cart.getInstance.getCart(); List<CartLineItem> cartItems = await Cart.getInstance.getCart();
@ -89,7 +91,7 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
orderWC.shipping = shipping; orderWC.shipping = shipping;
orderWC.shippingLines = []; orderWC.shippingLines = [];
if (app_disable_shipping == false) { if (wooSignalApp.disableShipping != 1) {
Map<String, dynamic> shippingLineFeeObj = Map<String, dynamic> shippingLineFeeObj =
CheckoutSession.getInstance.shippingType.toShippingLineFee(); CheckoutSession.getInstance.shippingType.toShippingLineFee();
if (shippingLineFeeObj != null) { if (shippingLineFeeObj != null) {

View File

@ -20,8 +20,7 @@ storeUserId(String v) async {
Future<String> readUserId() async { Future<String> readUserId() async {
SharedPref sharedPref = SharedPref(); SharedPref sharedPref = SharedPref();
String val = await sharedPref.read(keyUserId); return await sharedPref.read(keyUserId);
return val;
} }
destroyUserId(BuildContext context) async { destroyUserId(BuildContext context) async {

View File

@ -15,6 +15,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:label_storemax/app_payment_methods.dart'; import 'package:label_storemax/app_payment_methods.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/app_localizations.dart'; import 'package:label_storemax/helpers/app_localizations.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:label_storemax/labelconfig.dart'; import 'package:label_storemax/labelconfig.dart';
@ -127,7 +128,7 @@ String formatDoubleCurrency({double total}) {
FlutterMoneyFormatter fmf = FlutterMoneyFormatter( FlutterMoneyFormatter fmf = FlutterMoneyFormatter(
amount: total, amount: total,
settings: MoneyFormatterSettings( settings: MoneyFormatterSettings(
symbol: app_currency_symbol, symbol: AppHelper.instance.appConfig.currencyMeta.symbolNative,
), ),
); );
return fmf.output.symbolOnLeft; return fmf.output.symbolOnLeft;
@ -143,7 +144,7 @@ String formatStringCurrency({@required String total}) {
FlutterMoneyFormatter fmf = FlutterMoneyFormatter( FlutterMoneyFormatter fmf = FlutterMoneyFormatter(
amount: tmpVal, amount: tmpVal,
settings: MoneyFormatterSettings( settings: MoneyFormatterSettings(
symbol: app_currency_symbol, symbol: AppHelper.instance.appConfig.currencyMeta.symbolNative,
), ),
); );
return fmf.output.symbolOnLeft; return fmf.output.symbolOnLeft;
@ -159,7 +160,8 @@ String workoutSaleDiscount(
openBrowserTab({@required String url}) async { openBrowserTab({@required String url}) async {
await FlutterWebBrowser.openWebPage( await FlutterWebBrowser.openWebPage(
url: url, customTabsOptions: CustomTabsOptions(toolbarColor: Colors.white70)); url: url,
customTabsOptions: CustomTabsOptions(toolbarColor: Colors.white70));
} }
EdgeInsets safeAreaDefault() { EdgeInsets safeAreaDefault() {
@ -438,9 +440,7 @@ String dateFormatted({@required String date, @required String formatType}) =>
enum FormatType { enum FormatType {
DateTime, DateTime,
Date, Date,
Time, Time,
} }
@ -511,8 +511,7 @@ Widget refreshableScroll(context,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Container( return Container(
height: 200, height: 200,
child: wsCardProductItem( child: ProductItemContainer(
context,
index: (index), index: (index),
product: products[index], product: products[index],
onTap: onTap, onTap: onTap,
@ -523,7 +522,7 @@ Widget refreshableScroll(context,
mainAxisSpacing: 4.0, mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0, crossAxisSpacing: 4.0,
) )
: wsNoResults(context)), : NoProductResults()),
); );
} }
@ -554,11 +553,8 @@ Future<List<DefaultShipping>> getDefaultShipping(BuildContext context) async {
List<DefaultShipping> shipping = []; List<DefaultShipping> shipping = [];
dataJson.forEach((key, value) { dataJson.forEach((key, value) {
DefaultShipping defaultShipping = DefaultShipping(); DefaultShipping defaultShipping =
defaultShipping.code = key; DefaultShipping(code: key, country: value['country'], states: []);
defaultShipping.country = value['country'];
defaultShipping.states = [];
if (value['states'] != null) { if (value['states'] != null) {
value['states'].forEach((key1, value2) { value['states'].forEach((key1, value2) {
defaultShipping.states defaultShipping.states

View File

@ -16,7 +16,7 @@ import 'dart:ui';
Developer Notes Developer Notes
SUPPORT EMAIL - support@woosignal.com SUPPORT EMAIL - support@woosignal.com
VERSION - 2.6.0 VERSION - 3.0.0
https://woosignal.com https://woosignal.com
*/ */
@ -29,20 +29,8 @@ const app_key = "Your app key from WooSignal";
// Your App key from WooSignal // Your App key from WooSignal
// link: https://woosignal.com/dashboard/apps // link: https://woosignal.com/dashboard/apps
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 ------!>*/ /*<! ------ APP SETTINGS ------!>*/
const app_currency_symbol = "\£";
const app_currency_iso = "gbp";
const app_products_prices_include_tax = true;
const app_disable_shipping = false;
const Locale app_locale = Locale('en'); const Locale app_locale = Locale('en');
const List<Locale> app_locales_supported = [ const List<Locale> app_locales_supported = [
@ -57,7 +45,8 @@ const List<Locale> app_locales_supported = [
// then create a new lang json file using keys from en.json // then create a new lang json file using keys from en.json
// e.g. lang/es.json // e.g. lang/es.json
const app_product_placeholder_image = "https://woosignal.com/images/woocommerce-placeholder.png"; const app_product_placeholder_image =
"https://woosignal.com/images/woocommerce-placeholder.png";
/*<! ------ PAYMENT GATEWAYS ------!>*/ /*<! ------ PAYMENT GATEWAYS ------!>*/
@ -73,25 +62,12 @@ const app_payment_methods = ["Stripe"];
const app_stripe_account = "Your Stripe Key from WooSignal"; const app_stripe_account = "Your Stripe Key from WooSignal";
const app_stripe_live_mode = false; const app_stripe_live_mode = false; // set to true for live Stripe payments
// For Live Payments follow the below steps // For Live Payments follow the below steps
// #1 SET the above to true for live payments // #1 SET the above to true for live payments
// #2 Next visit https://woosignal.com/dashboard // #2 Next visit https://woosignal.com/dashboard
// #3 Then change "Environment for Stripe" to Live mode // #3 Then change "Environment for Stripe" to Live mode
/*<! ------ WP LOGIN (OPTIONAL) ------!>*/
// Allows customers to login/register, view account, purchase items as a user.
// #1 Install the "WP JSON API" plugin on WordPress via https://woosignal.com/plugins/wordpress/wp-json-api
// #2 Next activate the plugin on your WordPress and enable "use_wp_login = true"
// link: https://woosignal.com/dashboard/plugins
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_wp_api_path = "/wp-json"; // By default "/wp-json" should work
/*<! ------ Razor Pay (OPTIONAL) ------!>*/ /*<! ------ Razor Pay (OPTIONAL) ------!>*/
// https://razorpay.com/ // https://razorpay.com/

View File

@ -11,7 +11,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:hexcolor/hexcolor.dart'; import 'package:hexcolor/hexcolor.dart';
import 'package:label_storemax/helpers/shared_pref.dart'; import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/pages/account_billing_details.dart'; import 'package:label_storemax/pages/account_billing_details.dart';
import 'package:label_storemax/pages/account_detail.dart'; import 'package:label_storemax/pages/account_detail.dart';
import 'package:label_storemax/pages/account_landing.dart'; import 'package:label_storemax/pages/account_landing.dart';
@ -21,11 +22,12 @@ import 'package:label_storemax/pages/account_register.dart';
import 'package:label_storemax/pages/account_shipping_details.dart'; import 'package:label_storemax/pages/account_shipping_details.dart';
import 'package:label_storemax/pages/customer_countries.dart'; import 'package:label_storemax/pages/customer_countries.dart';
import 'package:label_storemax/pages/error_page.dart'; import 'package:label_storemax/pages/error_page.dart';
import 'package:label_storemax/pages/no_connection_page.dart';
import 'package:label_storemax/pages/product_image_viewer_page.dart'; import 'package:label_storemax/pages/product_image_viewer_page.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:woosignal/models/response/order.dart'; import 'package:woosignal/models/response/order.dart';
import 'package:woosignal/models/response/product_category.dart'; import 'package:woosignal/models/response/product_category.dart';
import 'package:woosignal/models/response/products.dart'; import 'package:woosignal/models/response/products.dart';
import 'package:woosignal/models/response/woosignal_app.dart';
import 'package:wp_json_api/wp_json_api.dart'; import 'package:wp_json_api/wp_json_api.dart';
import 'labelconfig.dart'; import 'labelconfig.dart';
import 'package:label_storemax/pages/checkout_details.dart'; import 'package:label_storemax/pages/checkout_details.dart';
@ -52,18 +54,25 @@ void main() async {
await SystemChrome.setPreferredOrientations([ await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp, DeviceOrientation.portraitUp,
]); ]);
String initialRoute = '/no-connection';
WooSignalApp wooSignalApp = await appWooSignal((api) => api.getApp());
String initialRoute = "/home"; if (wooSignalApp != null) {
if (use_wp_login == true) { initialRoute = "/home";
AppHelper.instance.appConfig = wooSignalApp;
if (wooSignalApp.wpLoginEnabled == 1) {
WPJsonAPI.instance.initWith( WPJsonAPI.instance.initWith(
baseUrl: app_base_url, baseUrl: wooSignalApp.wpLoginBaseUrl,
shouldDebug: app_debug, shouldDebug: wooSignalApp.appDebug == 1 ? true : false,
wpJsonPath: app_wp_api_path); wpJsonPath: wooSignalApp.wpLoginWpApiPath,
);
}
} }
runApp( runApp(
new MaterialApp( new MaterialApp(
title: app_name, title: wooSignalApp?.appName ?? "Label StoreMax",
color: Colors.white, color: Colors.white,
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
initialRoute: initialRoute, initialRoute: initialRoute,
@ -81,6 +90,7 @@ void main() async {
new AccountBillingDetailsPage(), new AccountBillingDetailsPage(),
'/account-shipping-details': (BuildContext context) => '/account-shipping-details': (BuildContext context) =>
new AccountShippingDetailsPage(), new AccountShippingDetailsPage(),
'/no-connection': (BuildContext context) => new NoConnectionPage(),
}, },
onGenerateRoute: (settings) { onGenerateRoute: (settings) {
switch (settings.name) { switch (settings.name) {

View File

@ -10,8 +10,9 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/shared_pref.dart'; import 'package:label_storemax/helpers/shared_pref.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart_line_item.dart'; import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart'; import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/models/shipping_type.dart'; import 'package:label_storemax/models/shipping_type.dart';
@ -31,7 +32,7 @@ class Cart {
SharedPref sharedPref = SharedPref(); SharedPref sharedPref = SharedPref();
String currentCartArrJSON = (await sharedPref.read(_keyCart) as String); String currentCartArrJSON = (await sharedPref.read(_keyCart) as String);
if (currentCartArrJSON == null) { if (currentCartArrJSON == null) {
cartLineItems = List<CartLineItem>(); cartLineItems = [];
} else { } else {
cartLineItems = (jsonDecode(currentCartArrJSON) as List<dynamic>) cartLineItems = (jsonDecode(currentCartArrJSON) as List<dynamic>)
.map((i) => CartLineItem.fromJson(i)) .map((i) => CartLineItem.fromJson(i))
@ -40,7 +41,7 @@ class Cart {
return cartLineItems; return cartLineItems;
} }
void addToCart({CartLineItem cartLineItem}) async { void addToCart({@required CartLineItem cartLineItem}) async {
List<CartLineItem> cartLineItems = await getCart(); List<CartLineItem> cartLineItems = await getCart();
if (cartLineItem.variationId != null) { if (cartLineItem.variationId != null) {
@ -52,7 +53,7 @@ class Cart {
return; return;
} }
} else { } else {
var firstCartItem = cartLineItems.firstWhere( CartLineItem firstCartItem = cartLineItems.firstWhere(
(i) => i.productId == cartLineItem.productId, (i) => i.productId == cartLineItem.productId,
orElse: () => null); orElse: () => null);
if (firstCartItem != null) { if (firstCartItem != null) {
@ -64,7 +65,7 @@ class Cart {
saveCartToPref(cartLineItems: cartLineItems); saveCartToPref(cartLineItems: cartLineItems);
} }
Future<String> getTotal({bool withFormat}) async { Future<String> getTotal({bool withFormat = false}) async {
List<CartLineItem> cartLineItems = await getCart(); List<CartLineItem> cartLineItems = await getCart();
double total = 0; double total = 0;
cartLineItems.forEach((cartItem) { cartLineItems.forEach((cartItem) {
@ -77,7 +78,7 @@ class Cart {
return total.toStringAsFixed(2); return total.toStringAsFixed(2);
} }
Future<String> getSubtotal({bool withFormat}) async { Future<String> getSubtotal({bool withFormat = false}) async {
List<CartLineItem> cartLineItems = await getCart(); List<CartLineItem> cartLineItems = await getCart();
double subtotal = 0; double subtotal = 0;
cartLineItems.forEach((cartItem) { cartLineItems.forEach((cartItem) {
@ -90,9 +91,10 @@ class Cart {
} }
void updateQuantity( void updateQuantity(
{CartLineItem cartLineItem, int incrementQuantity}) async { {@required CartLineItem cartLineItem,
@required int incrementQuantity}) async {
List<CartLineItem> cartLineItems = await getCart(); List<CartLineItem> cartLineItems = await getCart();
List<CartLineItem> tmpCartItem = new List<CartLineItem>(); List<CartLineItem> tmpCartItem = [];
cartLineItems.forEach((cartItem) { cartLineItems.forEach((cartItem) {
if (cartItem.variationId == cartLineItem.variationId && if (cartItem.variationId == cartLineItem.variationId &&
cartItem.productId == cartLineItem.productId) { cartItem.productId == cartLineItem.productId) {
@ -107,15 +109,14 @@ class Cart {
Future<String> cartShortDesc() async { Future<String> cartShortDesc() async {
List<CartLineItem> cartLineItems = await getCart(); List<CartLineItem> cartLineItems = await getCart();
var tmpShortItemDesc = []; return cartLineItems
cartLineItems.forEach((cartItem) { .map((cartItem) =>
tmpShortItemDesc "${cartItem.quantity.toString()} x | ${cartItem.name}")
.add(cartItem.quantity.toString() + " x | " + cartItem.name); .toList()
}); .join(",");
return tmpShortItemDesc.join(",");
} }
void removeCartItemForIndex({int index}) async { void removeCartItemForIndex({@required int index}) async {
List<CartLineItem> cartLineItems = await getCart(); List<CartLineItem> cartLineItems = await getCart();
cartLineItems.removeAt(index); cartLineItems.removeAt(index);
saveCartToPref(cartLineItems: cartLineItems); saveCartToPref(cartLineItems: cartLineItems);
@ -123,13 +124,13 @@ class Cart {
void clear() { void clear() {
SharedPref sharedPref = SharedPref(); SharedPref sharedPref = SharedPref();
List<CartLineItem> cartLineItems = new List<CartLineItem>(); List<CartLineItem> cartLineItems = [];
String jsonArrCartItems = String jsonArrCartItems =
jsonEncode(cartLineItems.map((i) => i.toJson()).toList()); jsonEncode(cartLineItems.map((i) => i.toJson()).toList());
sharedPref.save(_keyCart, jsonArrCartItems); sharedPref.save(_keyCart, jsonArrCartItems);
} }
void saveCartToPref({List<CartLineItem> cartLineItems}) { void saveCartToPref({@required List<CartLineItem> cartLineItems}) {
SharedPref sharedPref = SharedPref(); SharedPref sharedPref = SharedPref();
String jsonArrCartItems = String jsonArrCartItems =
jsonEncode(cartLineItems.map((i) => i.toJson()).toList()); jsonEncode(cartLineItems.map((i) => i.toJson()).toList());
@ -149,7 +150,7 @@ class Cart {
cartItems.where((c) => c.taxStatus == 'taxable').toList(); cartItems.where((c) => c.taxStatus == 'taxable').toList();
double cartSubtotal = 0; double cartSubtotal = 0;
if (app_products_prices_include_tax == false && if (AppHelper.instance.appConfig.productPricesIncludeTax == 1 &&
taxableCartLines.length > 0) { taxableCartLines.length > 0) {
cartSubtotal = taxableCartLines cartSubtotal = taxableCartLines
.map<double>((m) => parseWcPrice(m.subtotal) * m.quantity) .map<double>((m) => parseWcPrice(m.subtotal) * m.quantity)

View File

@ -100,7 +100,7 @@ class CheckoutSession {
sharedPref.remove(sfKeyShippingCheckout); sharedPref.remove(sfKeyShippingCheckout);
} }
Future<String> total({bool withFormat, TaxRate taxRate}) async { Future<String> total({bool withFormat = false, TaxRate taxRate}) async {
double totalCart = parseWcPrice(await Cart.getInstance.getTotal()); double totalCart = parseWcPrice(await Cart.getInstance.getTotal());
double totalShipping = 0; double totalShipping = 0;
if (shippingType != null && shippingType.object != null) { if (shippingType != null && shippingType.object != null) {
@ -126,7 +126,7 @@ class CheckoutSession {
total += parseWcPrice(taxAmount); total += parseWcPrice(taxAmount);
} }
if (withFormat != null && withFormat == true) { if (withFormat == true) {
return formatDoubleCurrency(total: total); return formatDoubleCurrency(total: total);
} }
return total.toStringAsFixed(2); return total.toStringAsFixed(2);

View File

@ -49,7 +49,7 @@ class CustomerAddress {
: false); : false);
String addressFull() { String addressFull() {
List<String> tmpArrAddress = new List<String>(); List<String> tmpArrAddress = [];
if (addressLine != null && addressLine != "") { if (addressLine != null && addressLine != "") {
tmpArrAddress.add(addressLine); tmpArrAddress.add(addressLine);
} }
@ -70,7 +70,7 @@ class CustomerAddress {
} }
String nameFull() { String nameFull() {
List<String> tmpArrName = new List<String>(); List<String> tmpArrName = [];
if (firstName != "") { if (firstName != "") {
tmpArrName.add(firstName); tmpArrName.add(firstName);
} }

View File

@ -40,9 +40,8 @@ class CustomerCountry {
} }
} }
bool hasState() { bool hasState() =>
return this.state != null && this.state.name != null ? true : false; (this.state != null && this.state.name != null ? true : false);
}
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>(); final Map<String, dynamic> data = new Map<String, dynamic>();

View File

@ -8,18 +8,21 @@
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/cupertino.dart';
class DefaultShipping { class DefaultShipping {
String code; String code;
String country; String country;
List<DefaultShippingState> states; List<DefaultShippingState> states;
DefaultShipping({this.code, this.country, this.states}); DefaultShipping(
{@required this.code, @required this.country, @required this.states});
} }
class DefaultShippingState { class DefaultShippingState {
String code; String code;
String name; String name;
DefaultShippingState({this.code, this.name}); DefaultShippingState({@required this.code, @required this.name});
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>(); final Map<String, dynamic> data = new Map<String, dynamic>();
@ -29,9 +32,6 @@ class DefaultShippingState {
} }
DefaultShippingState.fromJson(Map<String, dynamic> json) { DefaultShippingState.fromJson(Map<String, dynamic> json) {
if (json == null) {
return;
}
this.code = json['code']; this.code = json['code'];
this.name = json['name']; this.name = json['name'];
} }

View File

@ -8,6 +8,8 @@
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/cupertino.dart';
class PaymentType { class PaymentType {
int id; int id;
String name; String name;
@ -15,5 +17,10 @@ class PaymentType {
String assetImage; String assetImage;
Function pay; Function pay;
PaymentType({this.id, this.name, this.desc, this.assetImage, this.pay}); PaymentType(
{@required this.id,
@required this.name,
@required this.desc,
@required this.assetImage,
@required this.pay});
} }

View File

@ -8,6 +8,7 @@
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/cupertino.dart';
import 'package:woosignal/models/response/shipping_method.dart'; import 'package:woosignal/models/response/shipping_method.dart';
import '../helpers/tools.dart'; import '../helpers/tools.dart';
@ -18,7 +19,11 @@ class ShippingType {
String minimumValue; String minimumValue;
dynamic object; dynamic object;
ShippingType({this.methodId, this.object, this.cost, this.minimumValue}); ShippingType(
{@required this.methodId,
this.object,
@required this.cost,
@required this.minimumValue});
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
'methodId': methodId, 'methodId': methodId,
@ -27,8 +32,8 @@ class ShippingType {
'minimumValue': minimumValue 'minimumValue': minimumValue
}; };
String getTotal({bool withFormatting}) { String getTotal({bool withFormatting = false}) {
if (this.methodId != null && this.object != null) { if (this.object != null) {
switch (this.methodId) { switch (this.methodId) {
case "flat_rate": case "flat_rate":
FlatRate flatRate = (this.object as FlatRate); FlatRate flatRate = (this.object as FlatRate);
@ -47,14 +52,13 @@ class ShippingType {
: localPickup.cost); : localPickup.cost);
default: default:
return "0"; return "0";
break;
} }
} }
return "0"; return "0";
} }
String getTitle() { String getTitle() {
if (this.methodId != null && this.object != null) { if (this.object != null) {
switch (this.methodId) { switch (this.methodId) {
case "flat_rate": case "flat_rate":
FlatRate flatRate = (this.object as FlatRate); FlatRate flatRate = (this.object as FlatRate);
@ -67,14 +71,13 @@ class ShippingType {
return localPickup.title; return localPickup.title;
default: default:
return ""; return "";
break;
} }
} }
return ""; return "";
} }
Map<String, dynamic> toShippingLineFee() { Map<String, dynamic> toShippingLineFee() {
if (this.methodId != null && this.object != null) { if (this.object != null) {
Map<String, dynamic> tmpShippingLinesObj = {}; Map<String, dynamic> tmpShippingLinesObj = {};
switch (this.methodId) { switch (this.methodId) {
@ -98,7 +101,6 @@ class ShippingType {
break; break;
default: default:
return null; return null;
break;
} }
return tmpShippingLinesObj; return tmpShippingLinesObj;
} }

View File

@ -9,11 +9,12 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/widgets/menu_item.dart'; import 'package:label_storemax/widgets/menu_item.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart'; import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:package_info/package_info.dart'; import 'package:package_info/package_info.dart';
import 'package:woosignal/models/response/woosignal_app.dart';
class AboutPage extends StatefulWidget { class AboutPage extends StatefulWidget {
AboutPage(); AboutPage();
@ -25,9 +26,12 @@ class AboutPage extends StatefulWidget {
class _AboutPageState extends State<AboutPage> { class _AboutPageState extends State<AboutPage> {
_AboutPageState(); _AboutPageState();
WooSignalApp _wooSignalApp;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_wooSignalApp = AppHelper.instance.appConfig;
} }
@override @override
@ -48,11 +52,11 @@ class _AboutPageState extends State<AboutPage> {
body: SafeArea( body: SafeArea(
minimum: safeAreaDefault(), minimum: safeAreaDefault(),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Flexible( Expanded(
child: storeLogo(), child: Center(child: StoreLogo()),
flex: 2, flex: 2,
), ),
Flexible( Flexible(
@ -60,14 +64,12 @@ class _AboutPageState extends State<AboutPage> {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[ children: <Widget>[
wsMenuItem( MenuItem(
context,
title: trans(context, "Privacy policy"), title: trans(context, "Privacy policy"),
leading: Icon(Icons.people), leading: Icon(Icons.people),
action: _actionPrivacy, action: _actionPrivacy,
), ),
wsMenuItem( MenuItem(
context,
title: trans(context, "Terms and conditions"), title: trans(context, "Terms and conditions"),
leading: Icon(Icons.description), leading: Icon(Icons.description),
action: _actionTerms, action: _actionTerms,
@ -106,11 +108,7 @@ class _AboutPageState extends State<AboutPage> {
); );
} }
void _actionTerms() { void _actionTerms() => openBrowserTab(url: _wooSignalApp.appTermslink);
openBrowserTab(url: app_terms_url);
}
void _actionPrivacy() { void _actionPrivacy() => openBrowserTab(url: _wooSignalApp.appPrivacylink);
openBrowserTab(url: app_privacy_url);
}
} }

View File

@ -32,31 +32,19 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
_AccountBillingDetailsPageState(); _AccountBillingDetailsPageState();
// BILLING TEXT CONTROLLERS // BILLING TEXT CONTROLLERS
TextEditingController _txtShippingFirstName; TextEditingController _txtShippingFirstName = TextEditingController();
TextEditingController _txtShippingLastName; TextEditingController _txtShippingLastName = TextEditingController();
TextEditingController _txtShippingAddressLine; TextEditingController _txtShippingAddressLine = TextEditingController();
TextEditingController _txtShippingCity; TextEditingController _txtShippingCity = TextEditingController();
TextEditingController _txtShippingState; TextEditingController _txtShippingState = TextEditingController();
TextEditingController _txtShippingPostalCode; TextEditingController _txtShippingPostalCode = TextEditingController();
TextEditingController _txtShippingCountry; TextEditingController _txtShippingCountry = TextEditingController();
bool _isLoading, _isUpdating; bool _isLoading = true, _isUpdating = false;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_txtShippingFirstName = TextEditingController();
_txtShippingLastName = TextEditingController();
_txtShippingAddressLine = TextEditingController();
_txtShippingCity = TextEditingController();
_txtShippingState = TextEditingController();
_txtShippingPostalCode = TextEditingController();
_txtShippingCountry = TextEditingController();
_isLoading = true;
_isUpdating = false;
_fetchUserDetails(); _fetchUserDetails();
} }
@ -84,7 +72,7 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
title: Text( title: Text(
@ -113,16 +101,14 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
Row( Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "First Name"), heading: trans(context, "First Name"),
controller: _txtShippingFirstName, controller: _txtShippingFirstName,
shouldAutoFocus: true, shouldAutoFocus: true,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Last Name"), heading: trans(context, "Last Name"),
controller: _txtShippingLastName, controller: _txtShippingLastName,
), ),
@ -132,21 +118,19 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.spaceEvenly, MainAxisAlignment.spaceEvenly,
), ),
wsTextEditingRow( TextEditingRow(
context,
heading: trans(context, "Address Line"), heading: trans(context, "Address Line"),
controller: _txtShippingAddressLine, controller: _txtShippingAddressLine,
), ),
Row(children: <Widget>[ Row(children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "City"), heading: trans(context, "City"),
controller: _txtShippingCity, controller: _txtShippingCity,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow(context, child: TextEditingRow(
heading: trans(context, "State"), heading: trans(context, "State"),
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
controller: _txtShippingState), controller: _txtShippingState),
@ -155,14 +139,13 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
Row( Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Postal code"), heading: trans(context, "Postal code"),
controller: _txtShippingPostalCode, controller: _txtShippingPostalCode,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow(context, child: TextEditingRow(
heading: trans(context, "Country"), heading: trans(context, "Country"),
keyboardType: keyboardType:
TextInputType.emailAddress, TextInputType.emailAddress,
@ -198,10 +181,10 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
), ),
Column( Column(
children: <Widget>[ children: <Widget>[
wsPrimaryButton(context, PrimaryButton(
title: trans(context, "UPDATE DETAILS"), title: trans(context, "UPDATE DETAILS"),
action: action:
_isUpdating ? null : _updateBillingDetails), _isUpdating ? () {} : _updateBillingDetails),
], ],
), ),
], ],

View File

@ -32,12 +32,14 @@ class _AccountDetailPageState extends State<AccountDetailPage>
RefreshController _refreshController = RefreshController _refreshController =
RefreshController(initialRefresh: false); RefreshController(initialRefresh: false);
bool _shouldStopRequests, waitForNextRequest, _isLoading, _isLoadingOrders; bool _shouldStopRequests = false,
waitForNextRequest = false,
_isLoading = true,
_isLoadingOrders = true;
int _page; int _page = 1, _currentTabIndex = 0;
List<Order> _orders; List<Order> _orders = [];
WCCustomerInfoResponse _wcCustomerInfoResponse; WCCustomerInfoResponse _wcCustomerInfoResponse;
int _currentTabIndex = 0;
Widget _activeBody; Widget _activeBody;
TabController _tabController; TabController _tabController;
@ -46,11 +48,6 @@ class _AccountDetailPageState extends State<AccountDetailPage>
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_shouldStopRequests = false;
waitForNextRequest = false;
_isLoading = true;
_isLoadingOrders = true;
_page = 1; _page = 1;
_orders = []; _orders = [];
_tabs = [ _tabs = [
@ -117,7 +114,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
), ),
centerTitle: true, centerTitle: true,
), ),
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
body: SafeArea( body: SafeArea(
minimum: safeAreaDefault(), minimum: safeAreaDefault(),
child: _isLoading child: _isLoading
@ -337,7 +334,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
controller: _refreshController, controller: _refreshController,
onRefresh: _onRefresh, onRefresh: _onRefresh,
onLoading: _onLoading, onLoading: _onLoading,
child: (_orders.length != null && _orders.length > 0 child: (_orders.length > 0
? ListView.builder( ? ListView.builder(
itemBuilder: (cxt, i) { itemBuilder: (cxt, i) {
return Card( return Card(
@ -482,12 +479,9 @@ class _AccountDetailPageState extends State<AccountDetailPage>
} }
} }
_viewProfileDetail(int i) { _viewProfileDetail(int i) => Navigator.pushNamed(
int orderId = _orders[i].id;
Navigator.pushNamed(
context, context,
"/account-order-detail", "/account-order-detail",
arguments: orderId, arguments: _orders[i].id,
); );
}
} }

View File

@ -10,10 +10,10 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/shared_pref/sp_auth.dart'; import 'package:label_storemax/helpers/shared_pref/sp_auth.dart';
import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart'; import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart';
import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/widgets/buttons.dart'; import 'package:label_storemax/widgets/buttons.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart'; import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -32,23 +32,20 @@ class AccountLandingPage extends StatefulWidget {
} }
class _AccountLandingPageState extends State<AccountLandingPage> { class _AccountLandingPageState extends State<AccountLandingPage> {
bool _hasTappedLogin; bool _hasTappedLogin = false;
TextEditingController _tfEmailController, _tfPasswordController; TextEditingController _tfEmailController = TextEditingController(),
_tfPasswordController = TextEditingController();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_hasTappedLogin = false;
_tfEmailController = TextEditingController();
_tfPasswordController = TextEditingController();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
body: SafeArea( body: SafeArea(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
@ -59,7 +56,7 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[ children: <Widget>[
storeLogo(height: 100), StoreLogo(height: 100),
Flexible( Flexible(
child: Container( child: Container(
height: 70, height: 70,
@ -91,19 +88,18 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[ children: <Widget>[
wsTextEditingRow(context, TextEditingRow(
heading: trans(context, "Email"), heading: trans(context, "Email"),
controller: _tfEmailController, controller: _tfEmailController,
keyboardType: TextInputType.emailAddress), keyboardType: TextInputType.emailAddress),
wsTextEditingRow(context, TextEditingRow(
heading: trans(context, "Password"), heading: trans(context, "Password"),
controller: _tfPasswordController, controller: _tfPasswordController,
keyboardType: TextInputType.visiblePassword, keyboardType: TextInputType.visiblePassword,
obscureText: true), obscureText: true),
wsPrimaryButton( PrimaryButton(
context,
title: trans(context, "Login"), title: trans(context, "Login"),
action: _hasTappedLogin == true ? null : _loginUser, action: _hasTappedLogin == true ? () {} : _loginUser,
), ),
], ],
), ),
@ -111,7 +107,7 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
], ],
), ),
), ),
FlatButton( TextButton(
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -133,12 +129,15 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
Navigator.pushNamed(context, "/account-register"); Navigator.pushNamed(context, "/account-register");
}, },
), ),
wsLinkButton(context, title: trans(context, "Forgot Password"), LinkButton(
title: trans(context, "Forgot Password"),
action: () { action: () {
launch(app_forgot_password_url); String forgotPasswordUrl =
AppHelper.instance.appConfig.wpLoginForgotPasswordUrl;
launch(forgotPasswordUrl);
}), }),
Divider(), Divider(),
wsLinkButton(context, LinkButton(
title: trans(context, "Back"), title: trans(context, "Back"),
action: () => Navigator.pop(context)), action: () => Navigator.pop(context)),
], ],
@ -151,7 +150,7 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
String email = _tfEmailController.text; String email = _tfEmailController.text;
String password = _tfPasswordController.text; String password = _tfPasswordController.text;
if (email != null) { if (email.isNotEmpty) {
email = email.trim(); email = email.trim();
} }

View File

@ -19,24 +19,21 @@ import 'package:woosignal/models/response/order.dart';
class AccountOrderDetailPage extends StatefulWidget { class AccountOrderDetailPage extends StatefulWidget {
final int orderId; final int orderId;
AccountOrderDetailPage({Key key, this.orderId}) : super(key: key); AccountOrderDetailPage({Key key, @required this.orderId}) : super(key: key);
@override @override
_AccountOrderDetailPageState createState() => _AccountOrderDetailPageState createState() => _AccountOrderDetailPageState();
_AccountOrderDetailPageState(this.orderId);
} }
class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> { class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
_AccountOrderDetailPageState(this._orderId); _AccountOrderDetailPageState();
int _orderId;
Order _order; Order _order;
bool _isLoading; bool _isLoading = true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_isLoading = true;
_fetchOrder(); _fetchOrder();
} }
@ -53,12 +50,12 @@ class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
margin: EdgeInsets.only(left: 0), margin: EdgeInsets.only(left: 0),
), ),
title: Text( title: Text(
"${capitalize(trans(context, "Order"))} #${_orderId.toString()}", "${capitalize(trans(context, "Order"))} #${widget.orderId.toString()}",
style: Theme.of(context).primaryTextTheme.headline6, style: Theme.of(context).primaryTextTheme.headline6,
), ),
centerTitle: true, centerTitle: true,
), ),
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
body: SafeArea( body: SafeArea(
minimum: safeAreaDefault(), minimum: safeAreaDefault(),
child: _isLoading child: _isLoading
@ -173,9 +170,7 @@ class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
textAlign: TextAlign.left, textAlign: TextAlign.left,
), ),
Text( Text(
"x" + "x${_order.lineItems[i].quantity.toString()}",
_order.lineItems[i].quantity
.toString(),
style: Theme.of(context) style: Theme.of(context)
.primaryTextTheme .primaryTextTheme
.bodyText1 .bodyText1
@ -209,7 +204,7 @@ class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
_fetchOrder() async { _fetchOrder() async {
_order = await appWooSignal((api) { _order = await appWooSignal((api) {
return api.retrieveOrder(_orderId); return api.retrieveOrder(widget.orderId);
}); });
if (_order != null) { if (_order != null) {
setState(() { setState(() {

View File

@ -30,8 +30,9 @@ class AccountProfileUpdatePage extends StatefulWidget {
class _AccountProfileUpdatePageState extends State<AccountProfileUpdatePage> { class _AccountProfileUpdatePageState extends State<AccountProfileUpdatePage> {
_AccountProfileUpdatePageState(); _AccountProfileUpdatePageState();
bool isLoading; bool isLoading = true;
TextEditingController _tfFirstName, _tfLastName; TextEditingController _tfFirstName = TextEditingController(),
_tfLastName = TextEditingController();
@override @override
void dispose() { void dispose() {
@ -41,11 +42,6 @@ class _AccountProfileUpdatePageState extends State<AccountProfileUpdatePage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
isLoading = true;
_tfFirstName = TextEditingController();
_tfLastName = TextEditingController();
_fetchUserDetails(); _fetchUserDetails();
} }
@ -91,16 +87,14 @@ class _AccountProfileUpdatePageState extends State<AccountProfileUpdatePage> {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "First Name"), heading: trans(context, "First Name"),
controller: _tfFirstName, controller: _tfFirstName,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Last Name"), heading: trans(context, "Last Name"),
controller: _tfLastName, controller: _tfLastName,
keyboardType: TextInputType.text, keyboardType: TextInputType.text,
@ -115,7 +109,7 @@ class _AccountProfileUpdatePageState extends State<AccountProfileUpdatePage> {
Padding( Padding(
padding: EdgeInsets.only(top: 10), padding: EdgeInsets.only(top: 10),
), ),
wsPrimaryButton(context, PrimaryButton(
title: trans(context, "Update details"), title: trans(context, "Update details"),
action: _updateDetails) action: _updateDetails)
], ],

View File

@ -9,13 +9,14 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/shared_pref/sp_auth.dart'; import 'package:label_storemax/helpers/shared_pref/sp_auth.dart';
import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart'; import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart';
import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/widgets/buttons.dart'; import 'package:label_storemax/widgets/buttons.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart'; import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:woosignal/helpers/shared_pref.dart'; import 'package:woosignal/helpers/shared_pref.dart';
import 'package:woosignal/models/response/woosignal_app.dart';
import 'package:wp_json_api/exceptions/empty_username_exception.dart'; import 'package:wp_json_api/exceptions/empty_username_exception.dart';
import 'package:wp_json_api/exceptions/existing_user_email_exception.dart'; import 'package:wp_json_api/exceptions/existing_user_email_exception.dart';
import 'package:wp_json_api/exceptions/existing_user_login_exception.dart'; import 'package:wp_json_api/exceptions/existing_user_login_exception.dart';
@ -36,21 +37,16 @@ class AccountRegistrationPage extends StatefulWidget {
class _AccountRegistrationPageState extends State<AccountRegistrationPage> { class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
_AccountRegistrationPageState(); _AccountRegistrationPageState();
bool _hasTappedRegister; bool _hasTappedRegister = false;
TextEditingController _tfEmailAddressController; TextEditingController _tfEmailAddressController = TextEditingController();
TextEditingController _tfPasswordController; TextEditingController _tfPasswordController = TextEditingController();
TextEditingController _tfFirstNameController; TextEditingController _tfFirstNameController = TextEditingController();
TextEditingController _tfLastNameController; TextEditingController _tfLastNameController = TextEditingController();
WooSignalApp _wooSignalApp = AppHelper.instance.appConfig;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_hasTappedRegister = false;
_tfEmailAddressController = TextEditingController();
_tfPasswordController = TextEditingController();
_tfFirstNameController = TextEditingController();
_tfLastNameController = TextEditingController();
} }
@override @override
@ -68,7 +64,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
), ),
centerTitle: true, centerTitle: true,
), ),
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
body: SafeArea( body: SafeArea(
minimum: safeAreaDefault(), minimum: safeAreaDefault(),
child: Column( child: Column(
@ -78,8 +74,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "First Name"), heading: trans(context, "First Name"),
controller: _tfFirstNameController, controller: _tfFirstNameController,
shouldAutoFocus: true, shouldAutoFocus: true,
@ -87,8 +82,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Last Name"), heading: trans(context, "Last Name"),
controller: _tfLastNameController, controller: _tfLastNameController,
shouldAutoFocus: false, shouldAutoFocus: false,
@ -97,24 +91,22 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
), ),
], ],
)), )),
wsTextEditingRow( TextEditingRow(
context,
heading: trans(context, "Email address"), heading: trans(context, "Email address"),
controller: _tfEmailAddressController, controller: _tfEmailAddressController,
shouldAutoFocus: false, shouldAutoFocus: false,
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
), ),
wsTextEditingRow( TextEditingRow(
context,
heading: trans(context, "Password"), heading: trans(context, "Password"),
controller: _tfPasswordController, controller: _tfPasswordController,
shouldAutoFocus: true, shouldAutoFocus: true,
obscureText: true, obscureText: true,
), ),
Padding( Padding(
child: wsPrimaryButton(context, child: PrimaryButton(
title: trans(context, "Sign up"), title: trans(context, "Sign up"),
action: _hasTappedRegister ? null : _signUpTapped), action: _hasTappedRegister ? () {} : _signUpTapped),
padding: EdgeInsets.only(top: 10), padding: EdgeInsets.only(top: 10),
), ),
Padding( Padding(
@ -123,7 +115,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
text: TextSpan( text: TextSpan(
text: trans( text: trans(
context, "By tapping \"Register\" you agree to ") + context, "By tapping \"Register\" you agree to ") +
app_name + AppHelper.instance.appConfig.appName +
'\'s ', '\'s ',
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
@ -154,7 +146,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
String firstName = _tfFirstNameController.text; String firstName = _tfFirstNameController.text;
String lastName = _tfLastNameController.text; String lastName = _tfLastNameController.text;
if (email != null) { if (email.isNotEmpty) {
email = email.trim(); email = email.trim();
} }
@ -180,7 +172,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
}); });
String username = String username =
(email.replaceAll(new RegExp(r'(@|\.)'), "")) + randomStr(4); (email.replaceAll(new RegExp(r'([@.])'), "")) + randomStr(4);
WPUserRegisterResponse wpUserRegisterResponse; WPUserRegisterResponse wpUserRegisterResponse;
try { try {
@ -243,7 +235,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
.wpUpdateUserInfo(token, firstName: firstName, lastName: lastName)); .wpUpdateUserInfo(token, firstName: firstName, lastName: lastName));
showEdgeAlertWith(context, showEdgeAlertWith(context,
title: trans(context, "Hello") + " $firstName", title: "${trans(context, "Hello")} $firstName",
desc: trans(context, "you're now logged in"), desc: trans(context, "you're now logged in"),
style: EdgeAlertStyle.SUCCESS, style: EdgeAlertStyle.SUCCESS,
icon: Icons.account_circle); icon: Icons.account_circle);
@ -254,7 +246,8 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
} }
_viewTOSModal() { _viewTOSModal() {
showPlatformAlertDialog(context, showPlatformAlertDialog(
context,
title: trans(context, "Actions"), title: trans(context, "Actions"),
subtitle: trans(context, "View Terms and Conditions or Privacy policy"), subtitle: trans(context, "View Terms and Conditions or Privacy policy"),
actions: [ actions: [
@ -264,16 +257,17 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
dialogAction(context, dialogAction(context,
title: trans(context, "Privacy Policy"), title: trans(context, "Privacy Policy"),
action: _viewPrivacyPolicy), action: _viewPrivacyPolicy),
]); ],
);
} }
void _viewTermsConditions() { void _viewTermsConditions() {
Navigator.pop(context); Navigator.pop(context);
openBrowserTab(url: app_terms_url); openBrowserTab(url: _wooSignalApp.appTermslink);
} }
void _viewPrivacyPolicy() { void _viewPrivacyPolicy() {
Navigator.pop(context); Navigator.pop(context);
openBrowserTab(url: app_privacy_url); openBrowserTab(url: _wooSignalApp.appPrivacylink);
} }
} }

View File

@ -33,31 +33,19 @@ class _AccountShippingDetailsPageState
_AccountShippingDetailsPageState(); _AccountShippingDetailsPageState();
// BILLING TEXT CONTROLLERS // BILLING TEXT CONTROLLERS
TextEditingController _txtShippingFirstName; TextEditingController _txtShippingFirstName = TextEditingController();
TextEditingController _txtShippingLastName; TextEditingController _txtShippingLastName = TextEditingController();
TextEditingController _txtShippingAddressLine; TextEditingController _txtShippingAddressLine = TextEditingController();
TextEditingController _txtShippingCity; TextEditingController _txtShippingCity = TextEditingController();
TextEditingController _txtShippingPostalCode; TextEditingController _txtShippingPostalCode = TextEditingController();
TextEditingController _txtShippingState; TextEditingController _txtShippingState = TextEditingController();
TextEditingController _txtShippingCountry; TextEditingController _txtShippingCountry = TextEditingController();
bool _isLoading, _isUpdating; bool _isLoading = true, _isUpdating = false;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_txtShippingFirstName = TextEditingController();
_txtShippingLastName = TextEditingController();
_txtShippingAddressLine = TextEditingController();
_txtShippingCity = TextEditingController();
_txtShippingPostalCode = TextEditingController();
_txtShippingState = TextEditingController();
_txtShippingCountry = TextEditingController();
_isLoading = true;
_isUpdating = false;
_fetchUserDetails(); _fetchUserDetails();
} }
@ -100,7 +88,7 @@ class _AccountShippingDetailsPageState
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
title: Text( title: Text(
@ -131,16 +119,14 @@ class _AccountShippingDetailsPageState
Row( Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "First Name"), heading: trans(context, "First Name"),
controller: _txtShippingFirstName, controller: _txtShippingFirstName,
shouldAutoFocus: true, shouldAutoFocus: true,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Last Name"), heading: trans(context, "Last Name"),
controller: _txtShippingLastName, controller: _txtShippingLastName,
), ),
@ -150,22 +136,19 @@ class _AccountShippingDetailsPageState
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.spaceEvenly, MainAxisAlignment.spaceEvenly,
), ),
wsTextEditingRow( TextEditingRow(
context,
heading: trans(context, "Address Line"), heading: trans(context, "Address Line"),
controller: _txtShippingAddressLine, controller: _txtShippingAddressLine,
), ),
Row(children: <Widget>[ Row(children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "City"), heading: trans(context, "City"),
controller: _txtShippingCity, controller: _txtShippingCity,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "State"), heading: trans(context, "State"),
controller: _txtShippingState, controller: _txtShippingState,
), ),
@ -174,15 +157,13 @@ class _AccountShippingDetailsPageState
Row( Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Postal code"), heading: trans(context, "Postal code"),
controller: _txtShippingPostalCode, controller: _txtShippingPostalCode,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Country"), heading: trans(context, "Country"),
controller: _txtShippingCountry, controller: _txtShippingCountry,
), ),
@ -218,10 +199,10 @@ class _AccountShippingDetailsPageState
), ),
Column( Column(
children: <Widget>[ children: <Widget>[
wsPrimaryButton(context, PrimaryButton(
title: trans(context, "UPDATE DETAILS"), title: trans(context, "UPDATE DETAILS"),
action: action:
_isUpdating ? null : _updateShippingDetails), _isUpdating ? () {} : _updateShippingDetails),
], ],
), ),
], ],

View File

@ -25,42 +25,38 @@ class BrowseCategoryPage extends StatefulWidget {
: super(key: key); : super(key: key);
@override @override
_BrowseCategoryPageState createState() => _BrowseCategoryPageState createState() => _BrowseCategoryPageState();
_BrowseCategoryPageState(productCategory);
} }
class _BrowseCategoryPageState extends State<BrowseCategoryPage> { class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
_BrowseCategoryPageState(this._selectedCategory); _BrowseCategoryPageState();
List<WS.Product> _products = []; List<WS.Product> _products = [];
RefreshController _refreshController = RefreshController _refreshController =
RefreshController(initialRefresh: false); RefreshController(initialRefresh: false);
ProductCategory _selectedCategory;
int _page; int _page = 1;
bool _shouldStopRequests, waitForNextRequest, _isLoading; bool _shouldStopRequests = false,
waitForNextRequest = false,
_isLoading = true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_isLoading = true;
_page = 1;
_shouldStopRequests = false;
waitForNextRequest = false;
_fetchMoreProducts(); _fetchMoreProducts();
} }
_fetchMoreProducts() async { _fetchMoreProducts() async {
waitForNextRequest = true; waitForNextRequest = true;
List<WS.Product> products = await appWooSignal((api) => api.getProducts( List<WS.Product> products = await appWooSignal(
(api) => api.getProducts(
perPage: 50, perPage: 50,
category: _selectedCategory.id.toString(), category: widget.productCategory.id.toString(),
page: _page, page: _page,
status: "publish", status: "publish",
stockStatus: "instock")); stockStatus: "instock"),
);
_products.addAll(products); _products.addAll(products);
waitForNextRequest = false; waitForNextRequest = false;
_page = _page + 1; _page = _page + 1;
@ -90,7 +86,7 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
children: <Widget>[ children: <Widget>[
Text(trans(context, "Browse"), Text(trans(context, "Browse"),
style: Theme.of(context).primaryTextTheme.subtitle1), style: Theme.of(context).primaryTextTheme.subtitle1),
Text(parseHtmlString(_selectedCategory.name), Text(parseHtmlString(widget.productCategory.name),
style: Theme.of(context).primaryTextTheme.headline6) style: Theme.of(context).primaryTextTheme.headline6)
], ],
), ),
@ -176,32 +172,31 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
title: trans(context, "Sort results"), title: trans(context, "Sort results"),
bodyWidget: ListView( bodyWidget: ListView(
children: <Widget>[ children: <Widget>[
wsLinkButton(context, LinkButton(
title: trans(context, "Sort: Low to high"), title: trans(context, "Sort: Low to high"),
action: () => _sortProducts(by: SortByType.LowToHigh)), action: () => _sortProducts(by: SortByType.LowToHigh)),
Divider( Divider(
height: 0, height: 0,
), ),
wsLinkButton(context, LinkButton(
title: trans(context, "Sort: High to low"), title: trans(context, "Sort: High to low"),
action: () => _sortProducts(by: SortByType.HighToLow)), action: () => _sortProducts(by: SortByType.HighToLow)),
Divider( Divider(
height: 0, height: 0,
), ),
wsLinkButton(context, LinkButton(
title: trans(context, "Sort: Name A-Z"), title: trans(context, "Sort: Name A-Z"),
action: () => _sortProducts(by: SortByType.NameAZ)), action: () => _sortProducts(by: SortByType.NameAZ)),
Divider( Divider(
height: 0, height: 0,
), ),
wsLinkButton(context, LinkButton(
title: trans(context, "Sort: Name Z-A"), title: trans(context, "Sort: Name Z-A"),
action: () => _sortProducts(by: SortByType.NameZA)), action: () => _sortProducts(by: SortByType.NameZA)),
Divider( Divider(
height: 0, height: 0,
), ),
wsLinkButton(context, LinkButton(title: trans(context, "Cancel"), action: _dismissModal)
title: trans(context, "Cancel"), action: _dismissModal)
], ],
), ),
); );

View File

@ -30,18 +30,14 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
List<WS.Product> _products = []; List<WS.Product> _products = [];
String _search; String _search;
int _page; int _page = 1;
bool _shouldStopRequests, waitForNextRequest, _isLoading; bool _shouldStopRequests = false,
waitForNextRequest = false,
_isLoading = true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_isLoading = true;
_page = 1;
_shouldStopRequests = false;
waitForNextRequest = false;
_fetchProductsForSearch(); _fetchProductsForSearch();
} }
@ -53,7 +49,8 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
search: _search, search: _search,
page: _page, page: _page,
status: "publish", status: "publish",
stockStatus: "instock"), stockStatus: "instock",
),
); );
_products.addAll(products); _products.addAll(products);
waitForNextRequest = false; waitForNextRequest = false;

View File

@ -10,9 +10,9 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/shared_pref/sp_auth.dart'; import 'package:label_storemax/helpers/shared_pref/sp_auth.dart';
import 'package:label_storemax/helpers/tools.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.dart';
import 'package:label_storemax/models/cart_line_item.dart'; import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart'; import 'package:label_storemax/models/checkout_session.dart';
@ -31,15 +31,12 @@ class CartPage extends StatefulWidget {
class _CartPageState extends State<CartPage> { class _CartPageState extends State<CartPage> {
_CartPageState(); _CartPageState();
bool _isLoading = false; bool _isLoading = true, _isCartEmpty = false;
bool _isCartEmpty = false; List<CartLineItem> _cartLines = [];
List<CartLineItem> _cartLines;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_cartLines = [];
_isLoading = true;
_cartCheck(); _cartCheck();
} }
@ -115,7 +112,8 @@ class _CartPageState extends State<CartPage> {
sfCustomerAddress; sfCustomerAddress;
} }
if (use_wp_login == true && !(await authCheck())) { if (AppHelper.instance.appConfig.wpLoginEnabled == 1 &&
!(await authCheck())) {
UserAuth.instance.redirect = "/checkout"; UserAuth.instance.redirect = "/checkout";
Navigator.pushNamed(context, "/account-landing"); Navigator.pushNamed(context, "/account-landing");
return; return;
@ -183,7 +181,7 @@ class _CartPageState extends State<CartPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
title: Text( title: Text(
trans(context, "Shopping Cart"), trans(context, "Shopping Cart"),
@ -252,8 +250,7 @@ class _CartPageState extends State<CartPage> {
itemCount: _cartLines.length, itemCount: _cartLines.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
CartLineItem cartLineItem = _cartLines[index]; CartLineItem cartLineItem = _cartLines[index];
return wsCardCartItem( return CartItemContainer(
context,
cartLineItem: cartLineItem, cartLineItem: cartLineItem,
actionIncrementQuantity: () => actionIncrementQuantity: () =>
actionIncrementQuantity( actionIncrementQuantity(
@ -291,8 +288,7 @@ class _CartPageState extends State<CartPage> {
} }
}, },
), ),
wsPrimaryButton( PrimaryButton(
context,
title: trans(context, "PROCEED TO CHECKOUT"), title: trans(context, "PROCEED TO CHECKOUT"),
action: _actionProceedToCheckout, action: _actionProceedToCheckout,
), ),

View File

@ -10,8 +10,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:label_storemax/app_payment_methods.dart'; import 'package:label_storemax/app_payment_methods.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/tools.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.dart';
import 'package:label_storemax/models/checkout_session.dart'; import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/models/customer_address.dart'; import 'package:label_storemax/models/customer_address.dart';
@ -20,6 +20,7 @@ import 'package:label_storemax/widgets/app_loader.dart';
import 'package:label_storemax/widgets/buttons.dart'; import 'package:label_storemax/widgets/buttons.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart'; import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:woosignal/models/response/tax_rate.dart'; import 'package:woosignal/models/response/tax_rate.dart';
import 'package:woosignal/models/response/woosignal_app.dart';
class CheckoutConfirmationPage extends StatefulWidget { class CheckoutConfirmationPage extends StatefulWidget {
CheckoutConfirmationPage({Key key}) : super(key: key); CheckoutConfirmationPage({Key key}) : super(key: key);
@ -32,17 +33,18 @@ class CheckoutConfirmationPage extends StatefulWidget {
class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> { class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
CheckoutConfirmationPageState(); CheckoutConfirmationPageState();
bool _showFullLoader, _isProcessingPayment; bool _showFullLoader = true, _isProcessingPayment = false;
List<TaxRate> _taxRates; List<TaxRate> _taxRates;
TaxRate _taxRate; TaxRate _taxRate;
WooSignalApp _wooSignalApp;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_wooSignalApp = AppHelper.instance.appConfig;
_taxRates = []; _taxRates = [];
_showFullLoader = true;
_isProcessingPayment = false;
if (CheckoutSession.getInstance.paymentType == null) { if (CheckoutSession.getInstance.paymentType == null) {
CheckoutSession.getInstance.paymentType = arrPaymentMethods.first; CheckoutSession.getInstance.paymentType = arrPaymentMethods.first;
} }
@ -100,8 +102,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
TaxRate taxRate; TaxRate taxRate;
if (shippingCountry.hasState()) { if (shippingCountry.hasState()) {
taxRate = _taxRates.firstWhere( taxRate = _taxRates.firstWhere((t) {
(t) {
if (shippingCountry == null || if (shippingCountry == null ||
(shippingCountry?.state?.code ?? "") == "") { (shippingCountry?.state?.code ?? "") == "") {
return false; return false;
@ -120,9 +121,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
return true; return true;
} }
return false; return false;
}, }, orElse: () => null);
orElse: () => null,
);
} }
if (taxRate == null) { if (taxRate == null) {
@ -183,10 +182,10 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
title: storeLogo(height: 50), title: StoreLogo(height: 50),
centerTitle: true, centerTitle: true,
), ),
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
body: SafeArea( body: SafeArea(
minimum: safeAreaDefault(), minimum: safeAreaDefault(),
child: !_showFullLoader child: !_showFullLoader
@ -260,7 +259,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
context, "Select a payment method"), context, "Select a payment method"),
action: _actionPayWith, action: _actionPayWith,
showBorderBottom: true)), showBorderBottom: true)),
app_disable_shipping == true _wooSignalApp.disableShipping == 1
? null ? null
: (CheckoutSession.getInstance.shippingType != : (CheckoutSession.getInstance.shippingType !=
null null
@ -295,7 +294,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
wsCheckoutSubtotalWidgetFB( wsCheckoutSubtotalWidgetFB(
title: trans(context, "Subtotal"), title: trans(context, "Subtotal"),
), ),
app_disable_shipping == true _wooSignalApp.disableShipping == 1
? null ? null
: widgetCheckoutMeta(context, : widgetCheckoutMeta(context,
title: trans(context, "Shipping fee"), title: trans(context, "Shipping fee"),
@ -316,8 +315,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
), ),
].where((e) => e != null).toList(), ].where((e) => e != null).toList(),
), ),
wsPrimaryButton( PrimaryButton(
context,
title: _isProcessingPayment title: _isProcessingPayment
? "PROCESSING..." ? "PROCESSING..."
: trans(context, "CHECKOUT"), : trans(context, "CHECKOUT"),
@ -369,7 +367,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
return; return;
} }
if (app_disable_shipping == false && if (_wooSignalApp.disableShipping == 1 &&
CheckoutSession.getInstance.shippingType == null) { CheckoutSession.getInstance.shippingType == null) {
showEdgeAlertWith( showEdgeAlertWith(
context, context,
@ -392,7 +390,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
return; return;
} }
if (app_disable_shipping == false && if (_wooSignalApp.disableShipping != 1 &&
CheckoutSession.getInstance.shippingType.minimumValue != null) { CheckoutSession.getInstance.shippingType.minimumValue != null) {
String total = await Cart.getInstance.getTotal(); String total = await Cart.getInstance.getTotal();
if (total == null) { if (total == null) {
@ -413,6 +411,17 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
} }
} }
bool appStatus = await appWooSignal((api) => api.checkAppStatus());
if (!appStatus) {
showEdgeAlertWith(context,
title: trans(context, "Sorry"),
desc: "${trans(context, "Retry later")}",
style: EdgeAlertStyle.INFO,
duration: 3);
return;
}
if (_isProcessingPayment == true) { if (_isProcessingPayment == true) {
return; return;
} }

View File

@ -29,29 +29,28 @@ class CheckoutDetailsPage extends StatefulWidget {
class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> { class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
_CheckoutDetailsPageState(); _CheckoutDetailsPageState();
bool _hasDifferentShippingAddress = false; bool _hasDifferentShippingAddress = false, valRememberDetails = true;
int activeTabIndex = 0; int activeTabIndex = 0;
// TEXT CONTROLLERS // TEXT CONTROLLERS
TextEditingController TextEditingController
// billing // billing
_txtBillingFirstName, _txtBillingFirstName = TextEditingController(),
_txtBillingLastName, _txtBillingLastName = TextEditingController(),
_txtBillingAddressLine, _txtBillingAddressLine = TextEditingController(),
_txtBillingCity, _txtBillingCity = TextEditingController(),
_txtBillingPostalCode, _txtBillingPostalCode = TextEditingController(),
_txtBillingEmailAddress, _txtBillingEmailAddress = TextEditingController(),
// shipping // shipping
_txtShippingFirstName, _txtShippingFirstName = TextEditingController(),
_txtShippingLastName, _txtShippingLastName = TextEditingController(),
_txtShippingAddressLine, _txtShippingAddressLine = TextEditingController(),
_txtShippingCity, _txtShippingCity = TextEditingController(),
_txtShippingPostalCode, _txtShippingPostalCode = TextEditingController(),
_txtShippingEmailAddress; _txtShippingEmailAddress = TextEditingController();
CustomerCountry _billingCountry, _shippingCountry; CustomerCountry _billingCountry, _shippingCountry;
var valRememberDetails = true;
Widget activeTab; Widget activeTab;
Widget tabShippingDetails() => CustomerAddressInput( Widget tabShippingDetails() => CustomerAddressInput(
@ -80,22 +79,6 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
void initState() { void initState() {
super.initState(); super.initState();
// SHIPPING
_txtShippingFirstName = TextEditingController();
_txtShippingLastName = TextEditingController();
_txtShippingAddressLine = TextEditingController();
_txtShippingCity = TextEditingController();
_txtShippingPostalCode = TextEditingController();
_txtShippingEmailAddress = TextEditingController();
// BILLING
_txtBillingFirstName = TextEditingController();
_txtBillingLastName = TextEditingController();
_txtBillingAddressLine = TextEditingController();
_txtBillingCity = TextEditingController();
_txtBillingPostalCode = TextEditingController();
_txtBillingEmailAddress = TextEditingController();
if (CheckoutSession.getInstance.billingDetails.billingAddress == null) { if (CheckoutSession.getInstance.billingDetails.billingAddress == null) {
CheckoutSession.getInstance.billingDetails.initSession(); CheckoutSession.getInstance.billingDetails.initSession();
CheckoutSession.getInstance.billingDetails.shippingAddress.initAddress(); CheckoutSession.getInstance.billingDetails.shippingAddress.initAddress();
@ -137,7 +120,8 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
postalCode: customerAddress.postalCode, postalCode: customerAddress.postalCode,
emailAddress: customerAddress.emailAddress, emailAddress: customerAddress.emailAddress,
customerCountry: customerAddress.customerCountry, customerCountry: customerAddress.customerCountry,
type: type); type: type,
);
} }
_setFields( _setFields(
@ -171,7 +155,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
title: Text( title: Text(
@ -286,7 +270,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
) )
], ],
), ),
wsPrimaryButton(context, PrimaryButton(
title: trans(context, "USE DETAILS"), title: trans(context, "USE DETAILS"),
action: () => _useDetailsTapped()), action: () => _useDetailsTapped()),
], ],
@ -398,9 +382,9 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
return customerShippingAddress; return customerShippingAddress;
} }
_navigateToSelectCountry({String type}) { _navigateToSelectCountry({@required String type}) {
Navigator.pushNamed(context, "/customer-countries").then((value) { Navigator.pushNamed(context, "/customer-countries").then((value) {
if (value == null || type == null) { if (value == null) {
return; return;
} }
if (type == "billing") { if (type == "billing") {

View File

@ -39,7 +39,7 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
title: Text(trans(context, "Payment Method"), title: Text(trans(context, "Payment Method"),
@ -106,8 +106,7 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
), ),
), ),
), ),
wsLinkButton( LinkButton(
context,
title: trans(context, "CANCEL"), title: trans(context, "CANCEL"),
action: () => Navigator.pop(context), action: () => Navigator.pop(context),
), ),

View File

@ -238,7 +238,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
title: Text( title: Text(
@ -383,9 +383,9 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
style: Theme.of(context) style: Theme.of(context)
.primaryTextTheme .primaryTextTheme
.headline6, .headline6,
textAlign: TextAlign.center))), textAlign: TextAlign.center,
wsLinkButton( ))),
context, LinkButton(
title: trans(context, "CANCEL"), title: trans(context, "CANCEL"),
action: () => Navigator.pop(context), action: () => Navigator.pop(context),
), ),
@ -409,13 +409,16 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
} }
_handleCheckoutTapped(int index) async { _handleCheckoutTapped(int index) async {
ShippingType shippingType = ShippingType(); Map<String, dynamic> shippingOptions = _wsShippingOptions[index];
shippingType.object = _wsShippingOptions[index]['object']; ShippingType shippingType = ShippingType(
shippingType.methodId = _wsShippingOptions[index]['method_id']; methodId: shippingOptions['method_id'],
object: shippingOptions['object'],
cost: (await _getShippingPrice(index)),
minimumValue: null);
if (_wsShippingOptions[index]['min_amount'] != null) { if (_wsShippingOptions[index]['min_amount'] != null) {
shippingType.minimumValue = _wsShippingOptions[index]['min_amount']; shippingType.minimumValue = _wsShippingOptions[index]['min_amount'];
} }
shippingType.cost = await _getShippingPrice(index);
CheckoutSession.getInstance.shippingType = shippingType; CheckoutSession.getInstance.shippingType = shippingType;

View File

@ -44,7 +44,7 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.white, backgroundColor: Colors.white,
elevation: 0.0, elevation: 0.0,
title: storeLogo(height: 60), title: StoreLogo(height: 60),
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
centerTitle: true, centerTitle: true,
), ),

View File

@ -42,7 +42,7 @@ class _CustomerCountriesPageState extends State<CustomerCountriesPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
resizeToAvoidBottomPadding: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
title: Text( title: Text(

View File

@ -50,7 +50,7 @@ class _ErrorPageState extends State<ErrorPage> {
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
), ),
wsLinkButton(context, LinkButton(
title: trans(context, "Back"), title: trans(context, "Back"),
action: () => Navigator.pop(context)), action: () => Navigator.pop(context)),
], ],

View File

@ -8,8 +8,8 @@
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/widgets/app_loader.dart'; import 'package:label_storemax/widgets/app_loader.dart';
import 'package:label_storemax/widgets/cart_icon.dart'; import 'package:label_storemax/widgets/cart_icon.dart';
@ -34,15 +34,12 @@ class _HomePageState extends State<HomePage> {
List<WS.ProductCategory> _categories = []; List<WS.ProductCategory> _categories = [];
final GlobalKey _key = GlobalKey(); final GlobalKey _key = GlobalKey();
int _page; int _page = 1;
bool _shouldStopRequests, waitForNextRequest, _isLoading; bool _shouldStopRequests, waitForNextRequest, _isLoading = true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_isLoading = true;
_page = 1;
_home(); _home();
} }
@ -86,7 +83,7 @@ class _HomePageState extends State<HomePage> {
}); });
} }
void _modalBottomSheetMenu() { _modalBottomSheetMenu() {
_key.currentState.setState(() {}); _key.currentState.setState(() {});
wsModalBottom( wsModalBottom(
context, context,
@ -94,8 +91,7 @@ class _HomePageState extends State<HomePage> {
bodyWidget: ListView.separated( bodyWidget: ListView.separated(
itemCount: _categories.length, itemCount: _categories.length,
separatorBuilder: (cxt, i) => Divider(), separatorBuilder: (cxt, i) => Divider(),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) => ListTile(
return ListTile(
title: Text(parseHtmlString(_categories[index].name)), title: Text(parseHtmlString(_categories[index].name)),
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
@ -103,14 +99,14 @@ class _HomePageState extends State<HomePage> {
arguments: _categories[index]) arguments: _categories[index])
.then((value) => setState(() {})); .then((value) => setState(() {}));
}, },
); ),
},
), ),
); );
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<String> bannerImages = AppHelper.instance.appConfig.bannerImages;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
@ -121,7 +117,7 @@ class _HomePageState extends State<HomePage> {
), ),
margin: EdgeInsets.only(left: 0), margin: EdgeInsets.only(left: 0),
), ),
title: storeLogo(height: 50), title: StoreLogo(height: 55),
centerTitle: true, centerTitle: true,
actions: <Widget>[ actions: <Widget>[
IconButton( IconButton(
@ -144,50 +140,18 @@ class _HomePageState extends State<HomePage> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
capitalize(trans(context, "Shop")) + " / ",
style: Theme.of(context).primaryTextTheme.subtitle1,
maxLines: 1,
),
AutoSizeText(
trans(context, "Newest"),
style: Theme.of(context).primaryTextTheme.bodyText2,
maxLines: 1,
),
],
),
Flexible(
child: MaterialButton(
minWidth: 100,
height: 60,
child: AutoSizeText(
trans(context, "Browse categories"),
style: Theme.of(context).primaryTextTheme.bodyText1,
maxLines: 1,
textAlign: TextAlign.right,
),
onPressed: _modalBottomSheetMenu,
),
)
],
),
(_isLoading (_isLoading
? Expanded(child: showAppLoader()) ? Expanded(child: showAppLoader())
: Expanded( : Expanded(
child: refreshableScroll( child: RefreshableScrollContainer(
context, controller: _refreshController,
refreshController: _refreshController,
onRefresh: _onRefresh, onRefresh: _onRefresh,
onLoading: _onLoading, onLoading: _onLoading,
products: _products, products: _products,
onTap: _showProduct, onTap: _showProduct,
bannerHeight: MediaQuery.of(context).size.height / 3.5,
bannerImages: bannerImages,
modalBottomSheetMenu: _modalBottomSheetMenu,
), ),
flex: 1, flex: 1,
)), )),
@ -206,7 +170,7 @@ class _HomePageState extends State<HomePage> {
_refreshController.refreshCompleted(); _refreshController.refreshCompleted();
} }
void _onLoading() async { _onLoading() async {
await _fetchMoreProducts(); await _fetchMoreProducts();
if (mounted) { if (mounted) {
@ -219,8 +183,7 @@ class _HomePageState extends State<HomePage> {
} }
} }
_showProduct(WSProduct.Product product) { _showProduct(WSProduct.Product product) =>
Navigator.pushNamed(context, "/product-detail", arguments: product) Navigator.pushNamed(context, "/product-detail", arguments: product)
.then((value) => _key.currentState.setState(() {})); .then((value) => _key.currentState.setState(() {}));
}
} }

View File

@ -9,8 +9,8 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/shared_pref/sp_auth.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/widgets/menu_item.dart';
import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/helpers/tools.dart';
@ -53,28 +53,25 @@ class _HomeMenuPageState extends State<HomeMenuPage> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
storeLogo(height: 100), StoreLogo(height: 100),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround, mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[ children: <Widget>[
(use_wp_login (AppHelper.instance.appConfig.wpLoginEnabled == 1
? wsMenuItem( ? MenuItem(
context,
title: trans(context, "Profile"), title: trans(context, "Profile"),
leading: Icon(Icons.account_circle), leading: Icon(Icons.account_circle),
action: _actionProfile, action: _actionProfile,
) )
: Container()), : Container()),
wsMenuItem( MenuItem(
context,
title: trans(context, "Cart"), title: trans(context, "Cart"),
leading: Icon(Icons.shopping_cart), leading: Icon(Icons.shopping_cart),
action: _actionCart, action: _actionCart,
), ),
wsMenuItem( MenuItem(
context,
title: trans(context, "About Us"), title: trans(context, "About Us"),
leading: Icon(Icons.account_balance), leading: Icon(Icons.account_balance),
action: _actionAboutUs, action: _actionAboutUs,
@ -97,7 +94,8 @@ class _HomeMenuPageState extends State<HomeMenuPage> {
} }
void _actionProfile() async { void _actionProfile() async {
if (use_wp_login == true && !(await authCheck())) { if (AppHelper.instance.appConfig.wpLoginEnabled == 1 &&
!(await authCheck())) {
UserAuth.instance.redirect = "/account-detail"; UserAuth.instance.redirect = "/account-detail";
Navigator.pushNamed(context, "/account-landing"); Navigator.pushNamed(context, "/account-landing");
return; return;

View File

@ -46,7 +46,7 @@ class _HomeSearchPageState extends State<HomeSearchPage> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
title: storeLogo(height: 60), title: StoreLogo(height: 55),
centerTitle: true, centerTitle: true,
), ),
body: SafeArea( body: SafeArea(
@ -69,8 +69,7 @@ class _HomeSearchPageState extends State<HomeSearchPage> {
), ),
Padding( Padding(
padding: const EdgeInsets.only(top: 10), padding: const EdgeInsets.only(top: 10),
child: wsPrimaryButton( child: PrimaryButton(
context,
title: trans(context, "Search"), title: trans(context, "Search"),
action: _actionSearch, action: _actionSearch,
), ),

View File

@ -0,0 +1,73 @@
// StoreMob
//
// Created by Anthony Gordon.
// 2021, 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/material.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/widgets/buttons.dart';
class NoConnectionPage extends StatefulWidget {
NoConnectionPage();
@override
_NoConnectionPageState createState() => _NoConnectionPageState();
}
class _NoConnectionPageState extends State<NoConnectionPage> {
_NoConnectionPageState();
@override
void initState() {
super.initState();
print('WooCommerce site is not connected');
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
minimum: safeAreaDefault(),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(
Icons.error_outline,
size: 100,
color: Colors.black54,
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
trans(context, "Oops, something went wrong"),
style: Theme.of(context).primaryTextTheme.bodyText2,
textAlign: TextAlign.center,
),
),
LinkButton(title: trans(context, "Retry"), action: _retry),
],
),
),
),
);
}
_retry() async {
AppHelper.instance.appConfig = await appWooSignal((api) => api.getApp());
if (AppHelper.instance.appConfig != null) {
Navigator.pushNamed(context, "/home");
return;
}
showEdgeAlertWith(context,
title: trans(context, "Oops"), desc: trans(context, "Retry later"));
}
}

View File

@ -17,7 +17,6 @@ import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/widgets/app_loader.dart'; import 'package:label_storemax/widgets/app_loader.dart';
import 'package:label_storemax/widgets/buttons.dart'; import 'package:label_storemax/widgets/buttons.dart';
import 'package:label_storemax/widgets/cart_icon.dart'; import 'package:label_storemax/widgets/cart_icon.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:woosignal/models/response/product_variation.dart' as WS; import 'package:woosignal/models/response/product_variation.dart' as WS;
import 'package:woosignal/models/response/products.dart' as WSProduct; import 'package:woosignal/models/response/products.dart' as WSProduct;
import 'package:flutter_swiper/flutter_swiper.dart'; import 'package:flutter_swiper/flutter_swiper.dart';
@ -201,13 +200,15 @@ class _ProductDetailState extends State<ProductDetailPage> {
: ""), : ""),
style: Theme.of(context).primaryTextTheme.subtitle1, style: Theme.of(context).primaryTextTheme.subtitle1,
), ),
wsPrimaryButton(context, title: trans(context, "Add to cart"), PrimaryButton(
title: trans(context, "Add to cart"),
action: () { action: () {
if (_product.attributes.length != if (_product.attributes.length !=
_tmpAttributeObj.values.length) { _tmpAttributeObj.values.length) {
showEdgeAlertWith(context, showEdgeAlertWith(context,
title: trans(context, "Oops"), title: trans(context, "Oops"),
desc: trans(context, "Please select valid options first"), desc:
trans(context, "Please select valid options first"),
style: EdgeAlertStyle.WARNING); style: EdgeAlertStyle.WARNING);
return; return;
} }
@ -216,7 +217,8 @@ class _ProductDetailState extends State<ProductDetailPage> {
if (productVariation == null) { if (productVariation == null) {
showEdgeAlertWith(context, showEdgeAlertWith(context,
title: trans(context, "Oops"), title: trans(context, "Oops"),
desc: trans(context, "Product variation does not exist"), desc:
trans(context, "Product variation does not exist"),
style: EdgeAlertStyle.WARNING); style: EdgeAlertStyle.WARNING);
return; return;
} }
@ -240,7 +242,8 @@ class _ProductDetailState extends State<ProductDetailPage> {
variationId: productVariation.id, variationId: productVariation.id,
quantity: 1, quantity: 1,
taxStatus: productVariation.taxStatus, taxStatus: productVariation.taxStatus,
shippingClassId: productVariation.shippingClassId.toString(), shippingClassId:
productVariation.shippingClassId.toString(),
subtotal: productVariation.price, subtotal: productVariation.price,
stockQuantity: productVariation.stockQuantity, stockQuantity: productVariation.stockQuantity,
isManagedStock: productVariation.manageStock, isManagedStock: productVariation.manageStock,
@ -285,7 +288,7 @@ class _ProductDetailState extends State<ProductDetailPage> {
actions: <Widget>[ actions: <Widget>[
wsCartIcon(context), wsCartIcon(context),
], ],
title: storeLogo(height: 55), title: StoreLogo(height: 55),
centerTitle: true, centerTitle: true,
), ),
body: SafeArea( body: SafeArea(
@ -522,15 +525,13 @@ class _ProductDetailState extends State<ProductDetailPage> {
)), )),
_product.type == "external" _product.type == "external"
? Flexible( ? Flexible(
child: wsPrimaryButton( child: PrimaryButton(
context,
title: trans(context, "Buy Product"), title: trans(context, "Buy Product"),
action: () => _viewExternalProduct(), action: () => _viewExternalProduct(),
), ),
) )
: Flexible( : Flexible(
child: wsPrimaryButton( child: PrimaryButton(
context,
title: trans(context, "Add to cart"), title: trans(context, "Add to cart"),
action: () => _addItemToCart(), action: () => _addItemToCart(),
), ),

View File

@ -12,11 +12,10 @@
// //
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/helpers/data/order_wc.dart'; import 'package:label_storemax/helpers/data/order_wc.dart';
import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart'; import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/pages/checkout_confirmation.dart'; import 'package:label_storemax/pages/checkout_confirmation.dart';
import 'package:razorpay_flutter/razorpay_flutter.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart';
import 'package:woosignal/models/response/tax_rate.dart'; import 'package:woosignal/models/response/tax_rate.dart';
@ -25,16 +24,16 @@ import 'package:woosignal/models/response/order.dart';
razorPay(context, razorPay(context,
{@required CheckoutConfirmationPageState state, TaxRate taxRate}) async { {@required CheckoutConfirmationPageState state, TaxRate taxRate}) async {
Razorpay _razorpay = Razorpay(); Razorpay razorPay = Razorpay();
_razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, razorPay.on(Razorpay.EVENT_PAYMENT_SUCCESS,
(PaymentSuccessResponse response) async { (PaymentSuccessResponse response) async {
OrderWC orderWC = await buildOrderWC(taxRate: taxRate); OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
Order order = await appWooSignal((api) => api.createOrder(orderWC)); Order order = await appWooSignal((api) => api.createOrder(orderWC));
if (order != null) { if (order != null) {
_razorpay.clear(); razorPay.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order); Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else { } else {
showEdgeAlertWith(context, showEdgeAlertWith(context,
@ -44,27 +43,27 @@ razorPay(context,
trans(context, "Something went wrong, please contact our store"), trans(context, "Something went wrong, please contact our store"),
), ),
style: EdgeAlertStyle.WARNING); style: EdgeAlertStyle.WARNING);
_razorpay.clear(); razorPay.clear();
state.reloadState(showLoader: false); state.reloadState(showLoader: false);
} }
}); });
_razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, (PaymentFailureResponse response) { razorPay.on(Razorpay.EVENT_PAYMENT_ERROR, (PaymentFailureResponse response) {
showEdgeAlertWith(context, showEdgeAlertWith(context,
title: trans(context, "Error"), title: trans(context, "Error"),
desc: response.message, desc: response.message,
style: EdgeAlertStyle.WARNING); style: EdgeAlertStyle.WARNING);
_razorpay.clear(); razorPay.clear();
state.reloadState(showLoader: false); state.reloadState(showLoader: false);
}); });
_razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, razorPay.on(Razorpay.EVENT_EXTERNAL_WALLET,
(ExternalWalletResponse response) { (ExternalWalletResponse response) {
showEdgeAlertWith(context, showEdgeAlertWith(context,
title: trans(context, "Error"), title: trans(context, "Error"),
desc: trans(context, "Not supported, try a card payment"), desc: trans(context, "Not supported, try a card payment"),
style: EdgeAlertStyle.WARNING); style: EdgeAlertStyle.WARNING);
_razorpay.clear(); razorPay.clear();
state.reloadState(showLoader: false); state.reloadState(showLoader: false);
}); });
@ -73,7 +72,7 @@ razorPay(context,
var options = { var options = {
'key': app_razor_id, 'key': app_razor_id,
'amount': (parseWcPrice(total) * 100).toInt(), 'amount': (parseWcPrice(total) * 100).toInt(),
'name': app_name, 'name': AppHelper.instance.appConfig.appName,
'description': await cart.cartShortDesc(), 'description': await cart.cartShortDesc(),
'prefill': { 'prefill': {
"name": [ "name": [
@ -87,6 +86,6 @@ razorPay(context,
state.reloadState(showLoader: true); state.reloadState(showLoader: true);
_razorpay.open(options); razorPay.open(options);
}); });
} }

View File

@ -11,64 +11,110 @@
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart'; import 'package:hexcolor/hexcolor.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
Widget wsPrimaryButton(BuildContext context, class PrimaryButton extends StatelessWidget {
{@required String title, void Function() action}) { const PrimaryButton({
Key key,
this.title,
this.action,
}) : super(key: key);
final String title;
final void Function() action;
@override
Widget build(BuildContext context) => WooSignalButton(
key: key,
title: title,
action: action,
textStyle:
Theme.of(context).primaryTextTheme.button.copyWith(fontSize: 16),
bgColor: HexColor("#529cda"),
);
}
class SecondaryButton extends StatelessWidget {
const SecondaryButton({
Key key,
this.title,
this.action,
}) : super(key: key);
final String title;
final void Function() action;
@override
Widget build(BuildContext context) => WooSignalButton(
key: key,
title: title,
action: action,
textStyle: Theme.of(context).primaryTextTheme.bodyText1.copyWith(
color: Colors.black87,
),
bgColor: HexColor("#f6f6f9"),
);
}
class LinkButton extends StatelessWidget {
const LinkButton({
Key key,
this.title,
this.action,
}) : super(key: key);
final String title;
final void Function() action;
@override
Widget build(BuildContext context) => WooSignalButton(
key: key,
title: title,
action: action,
textStyle: Theme.of(context).primaryTextTheme.bodyText1,
bgColor: Colors.transparent,
);
}
class WooSignalButton extends StatelessWidget {
const WooSignalButton({
Key key,
this.title,
this.action,
this.textStyle,
this.bgColor,
}) : super(key: key);
final String title;
final void Function() action;
final TextStyle textStyle;
final Color bgColor;
@override
Widget build(BuildContext context) {
return Container( return Container(
height: 55, height: 55,
child: RaisedButton( width: double.infinity,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)), decoration: BoxDecoration(
color: Colors.transparent,
),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0)),
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
elevation: 0,
primary: bgColor,
shadowColor: Colors.transparent),
child: Text( child: Text(
title, title,
style: Theme.of(context).primaryTextTheme.button.copyWith(fontSize: 16), style: textStyle,
maxLines: 2, maxLines: 2,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
onPressed: action ?? null, onPressed: action ?? null,
elevation: 0,
),
);
}
Widget wsSecondaryButton(BuildContext context,
{String title, void Function() action}) {
return Container(
height: 60,
margin: EdgeInsets.only(top: 10),
child: RaisedButton(
child: Text(
title,
style: Theme.of(context).primaryTextTheme.bodyText1.copyWith(
color: Colors.black87,
),
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
onPressed: action,
color: HexColor("#f6f6f9"),
elevation: 1,
),
);
}
Widget wsLinkButton(BuildContext context,
{String title, void Function() action}) {
return Container(
height: 60,
margin: EdgeInsets.only(top: 10),
child: MaterialButton(
padding: EdgeInsets.all(10),
child: Text(
title,
style: Theme.of(context).primaryTextTheme.bodyText1,
textAlign: TextAlign.left,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
onPressed: action,
elevation: 0,
), ),
); );
}
} }

View File

@ -37,16 +37,14 @@ class CustomerAddressInput extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "First Name"), heading: trans(context, "First Name"),
controller: txtControllerFirstName, controller: txtControllerFirstName,
shouldAutoFocus: true, shouldAutoFocus: true,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Last Name"), heading: trans(context, "Last Name"),
controller: txtControllerLastName, controller: txtControllerLastName,
), ),
@ -60,15 +58,13 @@ class CustomerAddressInput extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Address Line"), heading: trans(context, "Address Line"),
controller: txtControllerAddressLine, controller: txtControllerAddressLine,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "City"), heading: trans(context, "City"),
controller: txtControllerCity, controller: txtControllerCity,
), ),
@ -80,14 +76,13 @@ class CustomerAddressInput extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: wsTextEditingRow( child: TextEditingRow(
context,
heading: trans(context, "Postal code"), heading: trans(context, "Postal code"),
controller: txtControllerPostalCode, controller: txtControllerPostalCode,
), ),
), ),
Flexible( Flexible(
child: wsTextEditingRow(context, child: TextEditingRow(
heading: trans(context, "Email address"), heading: trans(context, "Email address"),
keyboardType: TextInputType.emailAddress, keyboardType: TextInputType.emailAddress,
controller: txtControllerEmailAddress), controller: txtControllerEmailAddress),
@ -96,13 +91,24 @@ class CustomerAddressInput extends StatelessWidget {
), ),
), ),
Flexible( Flexible(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
(customerCountry.hasState() if (customerCountry.hasState())
? Flexible( Flexible(
child: Padding( child: Column(
child: wsSecondaryButton( children: [
context, Container(
child: Text(
trans(context, "State"),
style: Theme.of(context).primaryTextTheme.bodyText1,
textAlign: TextAlign.left,
),
width: double.infinity,
),
Padding(
child: SecondaryButton(
title: (customerCountry.state != null title: (customerCountry.state != null
? "${trans(context, "Selected")}\n${customerCountry?.state?.name ?? ""}" ? "${trans(context, "Selected")}\n${customerCountry?.state?.name ?? ""}"
: trans(context, "Select state")), : trans(context, "Select state")),
@ -110,12 +116,22 @@ class CustomerAddressInput extends StatelessWidget {
), ),
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
), ),
) ],
: null), ),
),
Flexible( Flexible(
child: Padding( child: Column(
child: wsSecondaryButton( children: [
context, Container(
child: Text(
trans(context, "Country"),
style: Theme.of(context).primaryTextTheme.bodyText1,
textAlign: TextAlign.left,
),
width: double.infinity,
),
Padding(
child: SecondaryButton(
title: (customerCountry != null && title: (customerCountry != null &&
(customerCountry?.name ?? "").isNotEmpty (customerCountry?.name ?? "").isNotEmpty
? "${trans(context, "Selected")}\n${customerCountry.name}" ? "${trans(context, "Selected")}\n${customerCountry.name}"
@ -124,12 +140,15 @@ class CustomerAddressInput extends StatelessWidget {
), ),
padding: EdgeInsets.all(8), padding: EdgeInsets.all(8),
), ),
],
),
), ),
].where((element) => element != null).toList(), ].where((element) => element != null).toList(),
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
), ),
), ),
),
].where((e) => e != null).toList(), ].where((e) => e != null).toList(),
); );
} }

View File

@ -10,9 +10,20 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
Widget wsMenuItem(BuildContext context, class MenuItem extends StatelessWidget {
{String title, Widget leading, void Function() action}) { const MenuItem({
return Flexible( Key key,
this.title,
this.leading,
this.action,
}) : super(key: key);
final String title;
final Widget leading;
final void Function() action;
@override
Widget build(BuildContext context) => Flexible(
child: InkWell( child: InkWell(
child: Card( child: Card(
child: Container( child: Container(

View File

@ -9,13 +9,18 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import 'package:hexcolor/hexcolor.dart'; import 'package:hexcolor/hexcolor.dart';
import 'package:label_storemax/helpers/app_helper.dart';
import 'package:label_storemax/labelconfig.dart'; import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart.dart'; import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart'; import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart'; import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/widgets/app_loader.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'; import 'package:woosignal/models/response/products.dart';
import 'package:label_storemax/helpers/tools.dart'; import 'package:label_storemax/helpers/tools.dart';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
@ -50,8 +55,13 @@ Widget wsRow2Text(BuildContext context, {String text1, String text2}) {
); );
} }
Widget wsNoResults(BuildContext context) { class NoProductResults extends StatelessWidget {
return Column( const NoProductResults({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) => Column(
children: <Widget>[ children: <Widget>[
Text(trans(context, "No results"), Text(trans(context, "No results"),
style: Theme.of(context).primaryTextTheme.bodyText2), style: Theme.of(context).primaryTextTheme.bodyText2),
@ -59,6 +69,156 @@ Widget wsNoResults(BuildContext context) {
); );
} }
class TopNav extends StatelessWidget {
const TopNav({Key key, this.onPressBrowseCategories}) : super(key: key);
final Function() onPressBrowseCategories;
@override
Widget build(BuildContext context) => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
"${capitalize(trans(context, "Shop"))} / ",
style: Theme.of(context).primaryTextTheme.subtitle1,
maxLines: 1,
),
AutoSizeText(
trans(context, "Newest"),
style: Theme.of(context).primaryTextTheme.bodyText2,
maxLines: 1,
),
],
),
Flexible(
child: MaterialButton(
minWidth: 100,
height: 60,
child: AutoSizeText(
trans(context, "Browse categories"),
style: Theme.of(context).primaryTextTheme.bodyText1,
maxLines: 1,
textAlign: TextAlign.right,
),
onPressed: onPressBrowseCategories,
),
)
],
);
}
class RefreshableScrollContainer extends StatelessWidget {
const RefreshableScrollContainer(
{Key key,
this.controller,
this.onRefresh,
this.onLoading,
this.products,
this.onTap,
this.bannerHeight,
this.bannerImages,
this.modalBottomSheetMenu})
: super(key: key);
final RefreshController controller;
final Function onRefresh;
final Function onLoading;
final List<Product> products;
final Function onTap;
final double bannerHeight;
final List<String> bannerImages;
final Function modalBottomSheetMenu;
@override
Widget build(BuildContext context) => SmartRefresher(
enablePullDown: true,
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: controller,
onRefresh: onRefresh,
onLoading: onLoading,
child: (products.length != null && products.length > 0
? StaggeredGridView.countBuilder(
crossAxisCount: 2,
itemCount:
(products.length + (bannerImages.length > 0 ? 2 : 0)),
itemBuilder: (BuildContext context, int index) {
if (bannerImages.length > 0 && index == 0) {
return Container(
child: Swiper(
itemBuilder: (BuildContext context, int index) {
return CachedImage(
image: bannerImages[index],
fit: BoxFit.contain,
);
},
itemCount: bannerImages.length,
viewportFraction: 0.8,
scale: 0.9,
),
height: bannerHeight,
);
}
if (bannerImages.length > 0 && index == 1 ||
bannerImages.length == 0 && index == 0) {
return TopNav(
onPressBrowseCategories: modalBottomSheetMenu,
);
}
int productIndex =
(index - (bannerImages.length > 0 ? 2 : 0));
return Container(
height: 200,
child: ProductItemContainer(
index: productIndex,
product: products[productIndex],
onTap: onTap,
),
);
},
staggeredTileBuilder: (int index) {
if (index == 0) {
return new StaggeredTile.fit(2);
}
if (bannerImages.length == 0) {
return new StaggeredTile.fit(1);
}
if (bannerImages.length > 0 && index == 0 || index == 1) {
return new StaggeredTile.fit(2);
}
return new StaggeredTile.fit(1);
},
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
)
: NoProductResults()),
);
}
Widget wsCheckoutRow(BuildContext context, Widget wsCheckoutRow(BuildContext context,
{heading: String, {heading: String,
Widget leadImage, Widget leadImage,
@ -130,13 +290,24 @@ Widget wsCheckoutRow(BuildContext context,
); );
} }
Widget wsTextEditingRow(BuildContext context, class TextEditingRow extends StatelessWidget {
{heading: String, const TextEditingRow({
TextEditingController controller, Key key,
bool shouldAutoFocus, this.heading,
TextInputType keyboardType, this.controller,
bool obscureText}) { this.shouldAutoFocus,
return Container( this.keyboardType,
this.obscureText,
}) : super(key: key);
final String heading;
final TextEditingController controller;
final bool shouldAutoFocus;
final TextInputType keyboardType;
final bool obscureText;
@override
Widget build(BuildContext context) => Container(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -191,8 +362,7 @@ Widget widgetCheckoutMeta(BuildContext context, {String title, String amount}) {
); );
} }
List<BoxShadow> wsBoxShadow({double blurRadius}) { List<BoxShadow> wsBoxShadow({double blurRadius}) => [
return [
BoxShadow( BoxShadow(
color: HexColor("#e8e8e8"), color: HexColor("#e8e8e8"),
blurRadius: blurRadius ?? 15.0, blurRadius: blurRadius ?? 15.0,
@ -203,11 +373,21 @@ List<BoxShadow> wsBoxShadow({double blurRadius}) {
), ),
) )
]; ];
}
Widget wsCardProductItem(BuildContext context, class ProductItemContainer extends StatelessWidget {
{int index, Product product, onTap}) { const ProductItemContainer({
return LayoutBuilder( Key key,
this.index,
this.product,
this.onTap,
}) : super(key: key);
final int index;
final Product product;
final Function onTap;
@override
Widget build(BuildContext context) => LayoutBuilder(
builder: (cxt, constraints) => InkWell( builder: (cxt, constraints) => InkWell(
child: Container( child: Container(
margin: EdgeInsets.all(4), margin: EdgeInsets.all(4),
@ -236,7 +416,8 @@ Widget wsCardProductItem(BuildContext context,
), ),
height: constraints.maxHeight / 2, height: constraints.maxHeight / 2,
), ),
errorWidget: (context, url, error) => new Icon(Icons.error), errorWidget: (context, url, error) =>
new Icon(Icons.error),
fit: BoxFit.contain, fit: BoxFit.contain,
height: constraints.maxHeight / 2, height: constraints.maxHeight / 2,
width: double.infinity, width: double.infinity,
@ -256,7 +437,8 @@ Widget wsCardProductItem(BuildContext context,
textAlign: TextAlign.center, textAlign: TextAlign.center,
text: TextSpan( text: TextSpan(
text: '', text: '',
style: Theme.of(context).textTheme.bodyText1, style:
Theme.of(context).textTheme.bodyText1,
children: <TextSpan>[ children: <TextSpan>[
TextSpan( TextSpan(
text: text:
@ -311,7 +493,8 @@ Widget wsCardProductItem(BuildContext context,
.textTheme .textTheme
.bodyText1 .bodyText1
.copyWith( .copyWith(
color: Colors.black54, fontSize: 11), color: Colors.black54,
fontSize: 11),
), ),
TextSpan( TextSpan(
text: formatStringCurrency( text: formatStringCurrency(
@ -321,7 +504,8 @@ Widget wsCardProductItem(BuildContext context,
.textTheme .textTheme
.bodyText1 .bodyText1
.copyWith( .copyWith(
decoration: TextDecoration.lineThrough, decoration:
TextDecoration.lineThrough,
color: Colors.grey, color: Colors.grey,
fontSize: 11), fontSize: 11),
), ),
@ -391,11 +575,11 @@ void wsModalBottom(BuildContext context,
)), )),
), ),
); );
}); },
);
} }
FutureBuilder getTotalWidget() { FutureBuilder getTotalWidget() => FutureBuilder<String>(
return FutureBuilder<String>(
future: Cart.getInstance.getTotal(withFormat: true), future: Cart.getInstance.getTotal(withFormat: true),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) { builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) { switch (snapshot.connectionState) {
@ -413,7 +597,6 @@ FutureBuilder getTotalWidget() {
} }
}, },
); );
}
FutureBuilder wsCheckoutTotalWidgetFB({String title, TaxRate taxRate}) { FutureBuilder wsCheckoutTotalWidgetFB({String title, TaxRate taxRate}) {
return FutureBuilder<String>( return FutureBuilder<String>(
@ -507,7 +690,7 @@ FutureBuilder wsWidgetCartItemsFB(
itemCount: snapshot.data.length, itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
CartLineItem cartLineItem = snapshot.data[index]; CartLineItem cartLineItem = snapshot.data[index];
return wsCardCartItem(context, return CartItemContainer(
cartLineItem: cartLineItem, cartLineItem: cartLineItem,
actionIncrementQuantity: actionIncrementQuantity, actionIncrementQuantity: actionIncrementQuantity,
actionDecrementQuantity: actionDecrementQuantity, actionDecrementQuantity: actionDecrementQuantity,
@ -518,12 +701,22 @@ FutureBuilder wsWidgetCartItemsFB(
); );
} }
Widget wsCardCartItem(BuildContext context, class CartItemContainer extends StatelessWidget {
{CartLineItem cartLineItem, const CartItemContainer({
void Function() actionIncrementQuantity, Key key,
void Function() actionDecrementQuantity, @required this.cartLineItem,
void Function() actionRemoveItem}) { @required this.actionIncrementQuantity,
return Container( @required this.actionDecrementQuantity,
@required this.actionRemoveItem,
}) : super(key: key);
final CartLineItem cartLineItem;
final void Function() actionIncrementQuantity;
final void Function() actionDecrementQuantity;
final void Function() actionRemoveItem;
@override
Widget build(BuildContext context) => Container(
margin: EdgeInsets.only(bottom: 7), margin: EdgeInsets.only(bottom: 7),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
@ -564,7 +757,9 @@ Widget wsCardCartItem(BuildContext context,
), ),
(cartLineItem.variationOptions != null (cartLineItem.variationOptions != null
? Text(cartLineItem.variationOptions, ? Text(cartLineItem.variationOptions,
style: Theme.of(context).primaryTextTheme.bodyText1) style: Theme.of(context)
.primaryTextTheme
.bodyText1)
: Container()), : Container()),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
@ -576,13 +771,16 @@ Widget wsCardCartItem(BuildContext context,
: trans(context, "In Stock")), : trans(context, "In Stock")),
style: (cartLineItem.stockStatus == "outofstock" style: (cartLineItem.stockStatus == "outofstock"
? Theme.of(context).textTheme.caption ? Theme.of(context).textTheme.caption
: Theme.of(context).primaryTextTheme.bodyText2), : Theme.of(context)
.primaryTextTheme
.bodyText2),
), ),
Text( Text(
formatDoubleCurrency( formatDoubleCurrency(
total: parseWcPrice(cartLineItem.total), total: parseWcPrice(cartLineItem.total),
), ),
style: Theme.of(context).primaryTextTheme.subtitle1, style:
Theme.of(context).primaryTextTheme.subtitle1,
textAlign: TextAlign.center, textAlign: TextAlign.center,
) )
], ],
@ -631,20 +829,50 @@ Widget wsCardCartItem(BuildContext context,
); );
} }
Widget storeLogo({double height, double width}) { class StoreLogo extends StatelessWidget {
return cachedImage(app_logo_url, const StoreLogo({
Key key,
this.height = 100,
this.width = 100,
this.placeholder = const CircularProgressIndicator(),
this.fit = BoxFit.contain,
}) : super(key: key);
final double height;
final double width;
final Widget placeholder;
final BoxFit fit;
@override
Widget build(BuildContext context) => CachedImage(
image: AppHelper.instance.appConfig.appLogo,
height: height, height: height,
placeholder: Container(height: height ?? 100, width: width ?? 100)); placeholder: Container(height: height, width: width));
} }
Widget cachedImage(image, {double height, Widget placeholder, BoxFit fit}) { class CachedImage extends StatelessWidget {
return CachedNetworkImage( const CachedImage({
Key key,
this.image,
this.height = 70,
this.width = 70,
this.placeholder = const CircularProgressIndicator(),
this.fit = BoxFit.contain,
}) : super(key: key);
final String image;
final double height;
final double width;
final Widget placeholder;
final BoxFit fit;
@override
Widget build(BuildContext context) => CachedNetworkImage(
imageUrl: image, imageUrl: image,
placeholder: (context, url) => placeholder: (context, url) => placeholder,
placeholder ?? new CircularProgressIndicator(),
errorWidget: (context, url, error) => new Icon(Icons.error), errorWidget: (context, url, error) => new Icon(Icons.error),
height: height ?? null, height: height,
width: null, width: width,
alignment: Alignment.center, alignment: Alignment.center,
fit: fit, fit: fit,
); );

View File

@ -21,7 +21,7 @@ packages:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.5.0-nullsafety.1" version: "2.5.0"
auto_size_text: auto_size_text:
dependency: "direct main" dependency: "direct main"
description: description:
@ -35,7 +35,7 @@ packages:
name: boolean_selector name: boolean_selector
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0-nullsafety.1" version: "2.1.0"
bubble_tab_indicator: bubble_tab_indicator:
dependency: "direct main" dependency: "direct main"
description: description:
@ -56,28 +56,28 @@ packages:
name: characters name: characters
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0-nullsafety.3" version: "1.1.0"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
name: charcode name: charcode
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0-nullsafety.1" version: "1.2.0"
clock: clock:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0-nullsafety.1" version: "1.1.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.15.0-nullsafety.3" version: "1.15.0"
convert: convert:
dependency: transitive dependency: transitive
description: description:
@ -154,7 +154,7 @@ packages:
name: fake_async name: fake_async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0-nullsafety.1" version: "1.2.0"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
@ -314,14 +314,21 @@ packages:
name: intl name: intl
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.16.1" version: "0.17.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.10-nullsafety.1" version: "0.12.10"
math_expressions: math_expressions:
dependency: "direct main" dependency: "direct main"
description: description:
@ -335,7 +342,7 @@ packages:
name: meta name: meta
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0-nullsafety.3" version: "1.3.0"
octo_image: octo_image:
dependency: transitive dependency: transitive
description: description:
@ -363,7 +370,7 @@ packages:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0-nullsafety.1" version: "1.8.0"
path_provider: path_provider:
dependency: transitive dependency: transitive
description: description:
@ -447,7 +454,7 @@ packages:
name: pull_to_refresh name: pull_to_refresh
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.6.3" version: "1.6.4"
razorpay_flutter: razorpay_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
@ -515,7 +522,7 @@ packages:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0-nullsafety.2" version: "1.8.0"
sqflite: sqflite:
dependency: transitive dependency: transitive
description: description:
@ -536,7 +543,7 @@ packages:
name: stack_trace name: stack_trace
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.10.0-nullsafety.1" version: "1.10.0"
status_alert: status_alert:
dependency: "direct main" dependency: "direct main"
description: description:
@ -550,14 +557,14 @@ packages:
name: stream_channel name: stream_channel
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0-nullsafety.1" version: "2.1.0"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0-nullsafety.1" version: "1.1.0"
synchronized: synchronized:
dependency: transitive dependency: transitive
description: description:
@ -571,14 +578,14 @@ packages:
name: term_glyph name: term_glyph
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0-nullsafety.1" version: "1.2.0"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.19-nullsafety.2" version: "0.2.19"
transformer_page_view: transformer_page_view:
dependency: transitive dependency: transitive
description: description:
@ -592,7 +599,7 @@ packages:
name: typed_data name: typed_data
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0-nullsafety.3" version: "1.3.0"
url_launcher: url_launcher:
dependency: "direct main" dependency: "direct main"
description: description:
@ -648,7 +655,7 @@ packages:
name: vector_math name: vector_math
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0-nullsafety.3" version: "2.1.0"
win32: win32:
dependency: transitive dependency: transitive
description: description:
@ -662,7 +669,7 @@ packages:
name: woosignal name: woosignal
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.1" version: "1.4.0"
woosignal_stripe: woosignal_stripe:
dependency: "direct main" dependency: "direct main"
description: description:
@ -699,5 +706,5 @@ packages:
source: hosted source: hosted
version: "2.2.1" version: "2.2.1"
sdks: sdks:
dart: ">=2.10.0 <2.11.0" dart: ">=2.12.0-0.0 <3.0.0"
flutter: ">=1.22.0 <2.0.0" flutter: ">=1.22.0"

View File

@ -1,14 +1,14 @@
# Official WooSignal App Template for WooCommerce # Official WooSignal App Template for WooCommerce
# Label StoreMax # Label StoreMax
# Version 2.6.0 # Version 3.0.0
# Homepage: https://woosignal.com # Homepage: https://woosignal.com
# Author: Anthony Gordon <agordon@woosignal.com> # Author: Anthony Gordon <agordon@woosignal.com>
# Documentation: https://woosignal.com/docs/app/ios/label-storemax # Documentation: https://woosignal.com/docs/app/ios/label-storemax
### Change App Icon ### Change App Icon
# 1 Replace: assets/icon/appicon.png (1024px1024px icon size) # 1 Replace: assets/icon/appicon.png (1024px1024px icon size)
# 2 Run this command from terminal: "flutter pub run flutter_launcher_icons:main" # 2 Run this command from the terminal: "flutter pub run flutter_launcher_icons:main"
### Uploading the IOS/Android app ### Uploading the IOS/Android app
# IOS https://flutter.dev/docs/deployment/ios # IOS https://flutter.dev/docs/deployment/ios
@ -19,11 +19,13 @@ description: LabelStoreMAX
version: 1.0.0+1 version: 1.0.0+1
publish_to: none
environment: environment:
sdk: ">=2.1.0 <3.0.0" sdk: ">=2.7.0 <3.0.0"
dependencies: dependencies:
woosignal: ^1.3.1 woosignal: ^1.4.0
woosignal_stripe: ^0.1.0 woosignal_stripe: ^0.1.0
razorpay_flutter: 1.2.3 razorpay_flutter: 1.2.3
wp_json_api: ^2.0.0 wp_json_api: ^2.0.0
@ -35,8 +37,8 @@ dependencies:
flutter_money_formatter: ^0.8.3 flutter_money_formatter: ^0.8.3
platform_alert_dialog: ^1.0.0+2 platform_alert_dialog: ^1.0.0+2
flutter_web_browser: ^0.13.1 flutter_web_browser: ^0.13.1
pull_to_refresh: 1.6.3 pull_to_refresh: 1.6.4
intl: ^0.16.1 intl: ^0.17.0
flutter_swiper: ^1.1.6 flutter_swiper: ^1.1.6
edge_alert: ^0.0.1 edge_alert: ^0.0.1
bubble_tab_indicator: ^0.1.4 bubble_tab_indicator: ^0.1.4
@ -67,7 +69,7 @@ flutter_icons:
image_path: "assets/icon/appicon.png" image_path: "assets/icon/appicon.png"
dependency_overrides: dependency_overrides:
intl: intl: ^0.17.0-nullsafety.2
flutter: flutter:

View File

@ -4,7 +4,7 @@
# WooCommerce App: Label StoreMax # WooCommerce App: Label StoreMax
### Label StoreMax - v2.6.0 ### Label StoreMax - v3.0.0
[Official WooSignal WooCommerce App](https://woosignal.com) [Official WooSignal WooCommerce App](https://woosignal.com)
@ -19,7 +19,7 @@
Label StoreMax is a WooCommerce Flutter App template, built exclusively for online shopping and it offers a great variety of options to customise the look and feel of the App. Label StoreMax supports product views, multi-variation products, category searches + more. Label StoreMax is a WooCommerce Flutter App template, built exclusively for online shopping and it offers a great variety of options to customise the look and feel of the App. Label StoreMax supports product views, multi-variation products, category searches + more.
1. Supports the latest WooCommerce (3.0+) 1. Supports the latest WooCommerce (3.5+)
2. [Documentation available](https://woosignal.com/docs/app/ios/label-storemax) 2. [Documentation available](https://woosignal.com/docs/app/ios/label-storemax)
## Some features integrated ## Some features integrated