Flutter 1.17.0 support, Sort by feature, Cash on delivery added, Login/register flow change for Apple user guidelines, Bug fixes, Pubspec.yaml update, AndroidManifest.xml bug fix
This commit is contained in:
parent
54e215507f
commit
8cd7118b0b
@ -1,5 +1,12 @@
|
||||
## [2.0.2] - 2020-05-04
|
||||
## [2.0.2] - 2020-05-08
|
||||
|
||||
* Flutter 1.17.0 support
|
||||
* Sort by feature
|
||||
* Cash on delivery added
|
||||
* RazorPay added
|
||||
* Login/register flow change for Apple user guidelines
|
||||
* Bug fixes
|
||||
* Pubspec.yaml update
|
||||
* AndroidManifest.xml bug fix
|
||||
|
||||
## [2.0.1] - 2020-04-30
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB |
BIN
LabelStoreMax/assets/images/cash_on_delivery.jpeg
Normal file
BIN
LabelStoreMax/assets/images/cash_on_delivery.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@ -264,9 +264,6 @@
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/Braintree/Braintree.framework",
|
||||
"${PODS_ROOT}/Braintree/Frameworks/CardinalMobile.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/BraintreeDropIn/BraintreeDropIn.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
|
||||
"${PODS_ROOT}/../Flutter/Flutter.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/Stripe/Stripe.framework",
|
||||
@ -275,6 +272,8 @@
|
||||
"${BUILT_PRODUCTS_DIR}/flutter_web_browser/flutter_web_browser.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/package_info/package_info.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
|
||||
"${PODS_ROOT}/razorpay-pod/Pod/Razorpay.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/razorpay_flutter/razorpay_flutter.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
|
||||
@ -282,9 +281,6 @@
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Braintree.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CardinalMobile.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BraintreeDropIn.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Stripe.framework",
|
||||
@ -293,6 +289,8 @@
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_web_browser.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Razorpay.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/razorpay_flutter.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import UIKit
|
||||
import Flutter
|
||||
import Braintree
|
||||
|
||||
@UIApplicationMain
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
|
||||
@ -129,5 +129,18 @@
|
||||
"Shipping Details": "Shipping Details",
|
||||
"State": "State",
|
||||
"Country": "Country",
|
||||
"UPDATE DETAILS": "UPDATE DETAILS"
|
||||
"UPDATE DETAILS": "UPDATE DETAILS",
|
||||
"No more products": "No more products",
|
||||
"release to load more": "release to load more",
|
||||
"Load Failed! Click retry!": "Load Failed! Click retry!",
|
||||
"pull up load": "pull up load",
|
||||
"Sort: Low to high": "Sort: Low to high",
|
||||
"Sort: High to low": "Sort: High to low",
|
||||
"Sort: Name A-Z": "Sort: Name A-Z",
|
||||
"Sort: Name Z-A": "Sort: Name Z-A",
|
||||
"Cancel": "Cancel",
|
||||
"Sort results": "Sort results",
|
||||
"you're now logged in": "You're now logged in",
|
||||
"Hello": "Hello",
|
||||
"Welcome back": "Welcome back"
|
||||
}
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
import 'package:label_storemax/helpers/tools.dart';
|
||||
import 'package:label_storemax/models/payment_type.dart';
|
||||
import 'package:label_storemax/providers/cash_on_delivery.dart';
|
||||
import 'package:label_storemax/providers/stripe_pay.dart';
|
||||
|
||||
// Payment methods available for uses in the app
|
||||
@ -25,11 +26,21 @@ List<PaymentType> arrPaymentMethods = [
|
||||
),
|
||||
),
|
||||
|
||||
addPayment(
|
||||
PaymentType(
|
||||
id: 2,
|
||||
name: "CashOnDelivery",
|
||||
desc: "Cash on delivery",
|
||||
assetImage: "cash_on_delivery.jpeg",
|
||||
pay: cashOnDeliveryPay,
|
||||
),
|
||||
),
|
||||
|
||||
// e.g. add more here
|
||||
|
||||
// addPayment(
|
||||
// PaymentType(
|
||||
// id: 2,
|
||||
// id: 3,
|
||||
// name: "MyNewPaymentMethod",
|
||||
// desc: "Debit or Credit Card",
|
||||
// assetImage: "add icon image to assets/images/myimage.png",
|
||||
|
||||
@ -50,8 +50,10 @@ class _AppLocalizationsDelegate
|
||||
const _AppLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) =>
|
||||
app_locales_supported.contains(locale.languageCode);
|
||||
bool isSupported(Locale locale) => app_locales_supported
|
||||
.map((e) => e.languageCode)
|
||||
.toList()
|
||||
.contains(locale.languageCode);
|
||||
|
||||
@override
|
||||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||||
|
||||
@ -82,9 +82,9 @@ TextTheme textThemePrimary() {
|
||||
fontWeight: FontWeight.w600),
|
||||
headline: new TextStyle(color: Colors.black, fontFamily: appFontFamily),
|
||||
title: new TextStyle(
|
||||
color: Colors.black,
|
||||
fontFamily: appFontFamily,
|
||||
),
|
||||
color: Colors.black87,
|
||||
fontFamily: appFontFamily,
|
||||
fontWeight: FontWeight.w600),
|
||||
subhead: new TextStyle(
|
||||
color: Colors.black,
|
||||
fontFamily: appFontFamily,
|
||||
|
||||
@ -19,7 +19,7 @@ import 'package:label_storemax/models/checkout_session.dart';
|
||||
import 'package:woosignal/models/payload/order_wc.dart';
|
||||
import 'package:woosignal/models/response/tax_rate.dart';
|
||||
|
||||
Future<OrderWC> buildOrderWC({TaxRate taxRate}) async {
|
||||
Future<OrderWC> buildOrderWC({TaxRate taxRate, bool markPaid = true}) async {
|
||||
OrderWC orderWC = OrderWC();
|
||||
|
||||
String paymentMethodName = CheckoutSession.getInstance.paymentType.name ?? "";
|
||||
@ -30,7 +30,7 @@ Future<OrderWC> buildOrderWC({TaxRate taxRate}) async {
|
||||
|
||||
orderWC.paymentMethodTitle = paymentMethodName.toLowerCase();
|
||||
|
||||
orderWC.setPaid = true;
|
||||
orderWC.setPaid = markPaid;
|
||||
orderWC.status = "pending";
|
||||
orderWC.currency = app_currency_iso.toUpperCase();
|
||||
orderWC.customerId =
|
||||
|
||||
16
LabelStoreMax/lib/helpers/enums/sort_enums.dart
Normal file
16
LabelStoreMax/lib/helpers/enums/sort_enums.dart
Normal file
@ -0,0 +1,16 @@
|
||||
// Label StoreMAX
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2020, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
enum SortByType {
|
||||
LowToHigh,
|
||||
HighToLow,
|
||||
NameAZ,
|
||||
NameZA,
|
||||
}
|
||||
@ -38,5 +38,5 @@ authLogout(BuildContext context) async {
|
||||
await sharedPref.save(keyAuthCheck, null);
|
||||
destroyUserId(context);
|
||||
Cart.getInstance.clear();
|
||||
navigatorPush(context, routeName: "/account-landing", forgetAll: true);
|
||||
navigatorPush(context, routeName: "/home", forgetAll: true);
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:label_storemax/app_payment_methods.dart';
|
||||
import 'package:label_storemax/helpers/app_localizations.dart';
|
||||
@ -22,9 +23,12 @@ import 'package:label_storemax/models/payment_type.dart';
|
||||
import 'package:html/parser.dart';
|
||||
import 'package:flutter_web_browser/flutter_web_browser.dart';
|
||||
import 'package:flutter_money_formatter/flutter_money_formatter.dart';
|
||||
import 'package:label_storemax/widgets/woosignal_ui.dart';
|
||||
import 'package:math_expressions/math_expressions.dart';
|
||||
import 'package:platform_alert_dialog/platform_alert_dialog.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:status_alert/status_alert.dart';
|
||||
import 'package:woosignal/models/response/products.dart';
|
||||
import 'package:woosignal/models/response/tax_rate.dart';
|
||||
import 'package:woosignal/woosignal.dart';
|
||||
|
||||
@ -65,11 +69,6 @@ showStatusAlert(context,
|
||||
);
|
||||
}
|
||||
|
||||
class PaymentMethodType {
|
||||
static final int STRIPE = 1;
|
||||
static final int APPLEPAY = 2;
|
||||
}
|
||||
|
||||
class EdgeAlertStyle {
|
||||
static final int SUCCESS = 1;
|
||||
static final int WARNING = 2;
|
||||
@ -142,7 +141,7 @@ String formatStringCurrency({@required String total}) {
|
||||
if (total == null || total == "") {
|
||||
tmpVal = 0;
|
||||
} else {
|
||||
tmpVal = double.parse(total);
|
||||
tmpVal = parseWcPrice(total);
|
||||
}
|
||||
FlutterMoneyFormatter fmf = FlutterMoneyFormatter(
|
||||
amount: tmpVal,
|
||||
@ -185,6 +184,9 @@ checkout(
|
||||
}
|
||||
|
||||
double strCal({@required String sum}) {
|
||||
if (sum == null || sum == "") {
|
||||
return 0;
|
||||
}
|
||||
Parser p = Parser();
|
||||
Expression exp = p.parse(sum);
|
||||
ContextModel cm = ContextModel();
|
||||
@ -192,6 +194,9 @@ double strCal({@required String sum}) {
|
||||
}
|
||||
|
||||
Future<double> workoutShippingCostWC({@required String sum}) async {
|
||||
if (sum == null || sum == "") {
|
||||
return 0;
|
||||
}
|
||||
List<CartLineItem> cartLineItem = await Cart.getInstance.getCart();
|
||||
sum = sum.replaceAllMapped(defaultRegex(r'\[qty\]', strict: true), (replace) {
|
||||
return cartLineItem
|
||||
@ -263,6 +268,9 @@ Future<double> workoutShippingCostWC({@required String sum}) async {
|
||||
|
||||
Future<double> workoutShippingClassCostWC(
|
||||
{@required String sum, List<CartLineItem> cartLineItem}) async {
|
||||
if (sum == null || sum == "") {
|
||||
return 0;
|
||||
}
|
||||
sum = sum.replaceAllMapped(defaultRegex(r'\[qty\]', strict: true), (replace) {
|
||||
return cartLineItem
|
||||
.map((f) => f.quantity)
|
||||
@ -357,14 +365,22 @@ bool validPassword(String pw) {
|
||||
}
|
||||
|
||||
navigatorPush(BuildContext context,
|
||||
{@required String routeName, Object arguments, bool forgetAll = false}) {
|
||||
{@required String routeName,
|
||||
Object arguments,
|
||||
bool forgetAll = false,
|
||||
int forgetLast}) {
|
||||
if (forgetAll) {
|
||||
Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
routeName, (Route<dynamic> route) => false,
|
||||
arguments: arguments ?? null);
|
||||
} else {
|
||||
Navigator.of(context).pushNamed(routeName, arguments: arguments ?? null);
|
||||
}
|
||||
if (forgetLast != null) {
|
||||
int count = 0;
|
||||
Navigator.of(context).popUntil((route) {
|
||||
return count++ == forgetLast;
|
||||
});
|
||||
}
|
||||
Navigator.of(context).pushNamed(routeName, arguments: arguments ?? null);
|
||||
}
|
||||
|
||||
PlatformDialogAction dialogAction(BuildContext context,
|
||||
@ -450,3 +466,58 @@ String formatForDateTime(FormatType formatType) {
|
||||
}
|
||||
|
||||
String capitalize(String s) => s[0].toUpperCase() + s.substring(1);
|
||||
|
||||
double parseWcPrice(String price) => (double.tryParse(price) ?? 0);
|
||||
|
||||
Widget refreshableScroll(context,
|
||||
{@required refreshController,
|
||||
@required VoidCallback onRefresh,
|
||||
@required VoidCallback onLoading,
|
||||
@required List<Product> products,
|
||||
@required onTap,
|
||||
key}) {
|
||||
return SmartRefresher(
|
||||
enablePullDown: false,
|
||||
enablePullUp: true,
|
||||
footer: CustomFooter(
|
||||
builder: (BuildContext context, LoadStatus mode) {
|
||||
Widget body;
|
||||
if (mode == LoadStatus.idle) {
|
||||
body = Text(trans(context, "pull up load"));
|
||||
} else if (mode == LoadStatus.loading) {
|
||||
body = CupertinoActivityIndicator();
|
||||
} else if (mode == LoadStatus.failed) {
|
||||
body = Text(trans(context, "Load Failed! Click retry!"));
|
||||
} else if (mode == LoadStatus.canLoading) {
|
||||
body = Text(trans(context, "release to load more"));
|
||||
} else {
|
||||
body = Text(trans(context, "No more products"));
|
||||
}
|
||||
return Container(
|
||||
height: 55.0,
|
||||
child: Center(child: body),
|
||||
);
|
||||
},
|
||||
),
|
||||
controller: refreshController,
|
||||
onRefresh: onRefresh,
|
||||
onLoading: onLoading,
|
||||
child: (products.length != null && products.length > 0
|
||||
? GridView.count(
|
||||
crossAxisCount: 2,
|
||||
children: List.generate(
|
||||
products.length,
|
||||
(index) {
|
||||
return wsCardProductItem(context,
|
||||
index: index, product: products[index], onTap: onTap);
|
||||
},
|
||||
))
|
||||
: wsNoResults(context)));
|
||||
}
|
||||
|
||||
class UserAuth {
|
||||
UserAuth._privateConstructor();
|
||||
static final UserAuth instance = UserAuth._privateConstructor();
|
||||
|
||||
String redirect = "/home";
|
||||
}
|
||||
|
||||
@ -10,11 +10,13 @@
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
/*
|
||||
Developer Notes
|
||||
|
||||
SUPPORT EMAIL - support@woosignal.com
|
||||
VERSION - 2.0.1
|
||||
VERSION - 2.0.2
|
||||
https://woosignal.com
|
||||
*/
|
||||
|
||||
@ -22,15 +24,51 @@
|
||||
|
||||
const app_name = "MyApp";
|
||||
|
||||
const app_key = "your app key";
|
||||
const app_key =
|
||||
"Your app key from WooSingal";
|
||||
// Your App key from WooSignal
|
||||
// link: https://woosignal.com/dashboard/apps
|
||||
|
||||
const app_logo_url = "https://is5-ssl.mzstatic.com/image/thumb/Purple115/v4/4b/e8/9a/4be89a5a-607e-1fb3-c45a-3261e84a061b/source/512x512bb.jpg";
|
||||
const app_logo_url = "https://woosignal.com/images/120x120_woosignal.png";
|
||||
|
||||
const app_terms_url = "https://yourdomain.com/terms";
|
||||
const app_privacy_url = "https://yourdomain.com/privacy";
|
||||
|
||||
|
||||
/*<! ------ APP SETTINGS ------!>*/
|
||||
|
||||
const app_currency_symbol = "\£";
|
||||
const app_currency_iso = "gbp";
|
||||
const app_locales_supported = [
|
||||
Locale('en'),
|
||||
];
|
||||
// If you want to localize the app, add the locale above
|
||||
// then create a new lang json file using keys from en.json
|
||||
// e.g. lang/es.json
|
||||
|
||||
|
||||
/*<! ------ PAYMENT GATEWAYS ------!>*/
|
||||
|
||||
// Available: "Stripe", "CashOnDelivery",
|
||||
// Add the method to the array below e.g. ["Stripe", "CashOnDelivery"]
|
||||
|
||||
const app_payment_methods = ["Stripe"];
|
||||
|
||||
|
||||
/*<! ------ STRIPE (OPTIONAL) ------!>*/
|
||||
|
||||
// Your StripeAccount key from WooSignal
|
||||
// link: https://woosignal.com/dashboard
|
||||
|
||||
const app_stripe_account = "Your StripeAccount from WooSignal";
|
||||
|
||||
const app_stripe_live_mode = false;
|
||||
// For Live Payments follow the below steps
|
||||
// #1 SET the above to true for live payments
|
||||
// #2 Next visit https://woosignal.com/dashboard
|
||||
// #3 Then change "Environment for Stripe" to Live mode
|
||||
|
||||
|
||||
/*<! ------ WP LOGIN (OPTIONAL) ------!>*/
|
||||
|
||||
// Allows customers to login/register, view account, purchase items as a user.
|
||||
@ -40,29 +78,10 @@ const app_privacy_url = "https://yourdomain.com/privacy";
|
||||
|
||||
const use_wp_login = false;
|
||||
const app_base_url = "https://mysite.com"; // change to your url
|
||||
const app_forgot_password_url = "https://mysite.com/my-account/lost-password"; // change to your forgot password url
|
||||
const app_forgot_password_url =
|
||||
"https://mysite.com/my-account/lost-password"; // change to your forgot password url
|
||||
const app_wp_api_path = "/wp-json"; // By default "/wp-json" should work
|
||||
|
||||
/*<! ------ STRIPE (OPTIONAL) ------!>*/
|
||||
|
||||
// Your StripeAccount key from WooSignal
|
||||
// link: https://woosignal.com/dashboard
|
||||
|
||||
const app_stripe_account = "Stripe Key from WooSignal";
|
||||
|
||||
const app_stripe_live_mode = false;
|
||||
// For Live Payments follow the below steps
|
||||
// #1 SET the above to true for live payments
|
||||
// #2 Next visit https://woosignal.com/dashboard
|
||||
// #3 Then change "Environment for Stripe" to Live mode
|
||||
|
||||
/*<! ------ APP CURRENCY ------!>*/
|
||||
|
||||
const app_currency_symbol = "\£";
|
||||
const app_currency_iso = "gbp";
|
||||
const app_locales_supported = ['en'];
|
||||
|
||||
const app_payment_methods = ["Stripe"];
|
||||
|
||||
/*<! ------ DEBUGGER ENABLED ------!>*/
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:label_storemax/helpers/shared_pref/sp_auth.dart';
|
||||
import 'package:label_storemax/pages/account_billing_details.dart';
|
||||
import 'package:label_storemax/pages/account_detail.dart';
|
||||
import 'package:label_storemax/pages/account_landing.dart';
|
||||
@ -51,13 +50,12 @@ void main() async {
|
||||
DeviceOrientation.portraitUp,
|
||||
]);
|
||||
|
||||
String initialRoute = (use_wp_login) ? "/account-landing" : "/home";
|
||||
WPJsonAPI.instance.initWith(
|
||||
baseUrl: app_base_url,
|
||||
shouldDebug: app_debug,
|
||||
wpJsonPath: app_wp_api_path);
|
||||
if (await authCheck() == true) {
|
||||
initialRoute = "/home";
|
||||
String initialRoute = "/home";
|
||||
if (use_wp_login == true) {
|
||||
WPJsonAPI.instance.initWith(
|
||||
baseUrl: app_base_url,
|
||||
shouldDebug: app_debug,
|
||||
wpJsonPath: app_wp_api_path);
|
||||
}
|
||||
|
||||
runApp(
|
||||
@ -71,7 +69,6 @@ void main() async {
|
||||
'/cart': (BuildContext context) => new CartPage(),
|
||||
'/error': (BuildContext context) => new ErrorPage(),
|
||||
'/checkout': (BuildContext context) => new CheckoutConfirmationPage(),
|
||||
'/account-landing': (BuildContext context) => new AccountLandingPage(),
|
||||
'/account-register': (BuildContext context) =>
|
||||
new AccountRegistrationPage(),
|
||||
'/account-detail': (BuildContext context) => new AccountDetailPage(),
|
||||
@ -84,6 +81,12 @@ void main() async {
|
||||
},
|
||||
onGenerateRoute: (settings) {
|
||||
switch (settings.name) {
|
||||
case '/account-landing':
|
||||
return PageTransition(
|
||||
child: AccountLandingPage(),
|
||||
type: PageTransitionType.downToUp,
|
||||
);
|
||||
|
||||
case '/browse-category':
|
||||
if (settings.arguments != null) {
|
||||
final ProductCategory category =
|
||||
@ -200,9 +203,7 @@ void main() async {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
supportedLocales: [
|
||||
Locale('en'),
|
||||
],
|
||||
supportedLocales: app_locales_supported,
|
||||
localizationsDelegates: [
|
||||
AppLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
|
||||
@ -142,7 +142,7 @@ class Cart {
|
||||
|
||||
if (taxableCartLines.length > 0) {
|
||||
cartSubtotal = taxableCartLines
|
||||
.map<double>((m) => double.parse(m.subtotal))
|
||||
.map<double>((m) => parseWcPrice(m.subtotal))
|
||||
.reduce((a, b) => a + b);
|
||||
}
|
||||
|
||||
@ -155,13 +155,19 @@ class Cart {
|
||||
case "flat_rate":
|
||||
FlatRate flatRate = (shippingType.object as FlatRate);
|
||||
if (flatRate.taxable != null && flatRate.taxable) {
|
||||
shippingTotal += double.parse(shippingType.cost);
|
||||
shippingTotal += parseWcPrice(
|
||||
shippingType.cost == null || shippingType.cost == ""
|
||||
? "0"
|
||||
: shippingType.cost);
|
||||
}
|
||||
break;
|
||||
case "local_pickup":
|
||||
LocalPickup localPickup = (shippingType.object as LocalPickup);
|
||||
if (localPickup.taxable != null && localPickup.taxable) {
|
||||
shippingTotal += double.parse(localPickup.cost);
|
||||
shippingTotal += parseWcPrice(
|
||||
(localPickup.cost == null || localPickup.cost == ""
|
||||
? "0"
|
||||
: localPickup.cost));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -171,10 +177,10 @@ class Cart {
|
||||
|
||||
double total = 0;
|
||||
if (subtotal != 0) {
|
||||
total += ((double.parse(taxRate.rate) * subtotal) / 100);
|
||||
total += ((parseWcPrice(taxRate.rate) * subtotal) / 100);
|
||||
}
|
||||
if (shippingTotal != 0) {
|
||||
total += ((double.parse(taxRate.rate) * shippingTotal) / 100);
|
||||
total += ((parseWcPrice(taxRate.rate) * shippingTotal) / 100);
|
||||
}
|
||||
return (total).toStringAsFixed(2);
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
import 'package:label_storemax/helpers/tools.dart';
|
||||
|
||||
class CartLineItem {
|
||||
String name;
|
||||
int productId;
|
||||
@ -45,7 +47,7 @@ class CartLineItem {
|
||||
this.metaData});
|
||||
|
||||
String getCartTotal() {
|
||||
return (quantity * double.parse(subtotal)).toString();
|
||||
return (quantity * parseWcPrice(subtotal)).toString();
|
||||
}
|
||||
|
||||
CartLineItem.fromJson(Map<String, dynamic> json)
|
||||
@ -56,7 +58,10 @@ class CartLineItem {
|
||||
shippingClassId = json['shipping_class_id'].toString(),
|
||||
taxStatus = json['tax_status'],
|
||||
stockQuantity = json['stock_quantity'],
|
||||
isManagedStock = json['is_managed_stock'],
|
||||
isManagedStock = (json['is_managed_stock'] != null &&
|
||||
json['is_managed_stock'] is bool)
|
||||
? json['is_managed_stock']
|
||||
: false,
|
||||
shippingIsTaxable = json['shipping_is_taxable'],
|
||||
subtotal = json['subtotal'],
|
||||
total = json['total'],
|
||||
|
||||
@ -61,18 +61,18 @@ class CheckoutSession {
|
||||
}
|
||||
|
||||
Future<String> total({bool withFormat, TaxRate taxRate}) async {
|
||||
double totalCart = double.parse(await Cart.getInstance.getTotal());
|
||||
double totalCart = parseWcPrice(await Cart.getInstance.getTotal());
|
||||
double totalShipping = 0;
|
||||
if (shippingType != null && shippingType.object != null) {
|
||||
switch (shippingType.methodId) {
|
||||
case "flat_rate":
|
||||
totalShipping = double.parse(shippingType.cost);
|
||||
totalShipping = parseWcPrice(shippingType.cost);
|
||||
break;
|
||||
case "free_shipping":
|
||||
totalShipping = double.parse(shippingType.cost);
|
||||
totalShipping = parseWcPrice(shippingType.cost);
|
||||
break;
|
||||
case "local_pickup":
|
||||
totalShipping = double.parse(shippingType.cost);
|
||||
totalShipping = parseWcPrice(shippingType.cost);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -83,12 +83,12 @@ class CheckoutSession {
|
||||
|
||||
if (taxRate != null) {
|
||||
String taxAmount = await Cart.getInstance.taxAmount(taxRate);
|
||||
total += double.parse(taxAmount);
|
||||
total += parseWcPrice(taxAmount);
|
||||
}
|
||||
|
||||
if (withFormat != null && withFormat == true) {
|
||||
return formatDoubleCurrency(total: total);
|
||||
}
|
||||
return total.toString();
|
||||
return total.toStringAsFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ class _AboutPageState extends State<AboutPage> {
|
||||
},
|
||||
),
|
||||
title: Text(trans(context, "About"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead),
|
||||
style: Theme.of(context).primaryTextTheme.headline6),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: SafeArea(
|
||||
@ -85,8 +85,9 @@ class _AboutPageState extends State<AboutPage> {
|
||||
trans(context, "Version") +
|
||||
": " +
|
||||
snapshot.data.version,
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.body2),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyText1),
|
||||
padding: EdgeInsets.only(top: 15, bottom: 15),
|
||||
);
|
||||
}
|
||||
|
||||
@ -89,7 +89,7 @@ class _AccountBillingDetailsPageState extends State<AccountBillingDetailsPage> {
|
||||
backgroundColor: Colors.transparent,
|
||||
title: Text(
|
||||
trans(context, "Billing Details"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1,
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
|
||||
@ -85,7 +85,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
),
|
||||
title: Text(
|
||||
trans(context, "Account"),
|
||||
style: Theme.of(context).primaryTextTheme.title,
|
||||
style: Theme.of(context).primaryTextTheme.headline6,
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
@ -212,7 +212,12 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
leading: Icon(Icons.account_circle),
|
||||
title: Text(trans(context, "Update details")),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, "/account-update");
|
||||
Navigator.pushNamed(context, "/account-update").then((onValue) {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
_fetchWpUserData();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
@ -238,9 +243,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.exit_to_app),
|
||||
title: Text(trans(context, "Logout")),
|
||||
onTap: () {
|
||||
authLogout(context);
|
||||
},
|
||||
onTap: () => authLogout(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -331,7 +334,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
formatStringCurrency(total: _orders[i].total),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.body1
|
||||
.bodyText2
|
||||
.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black),
|
||||
@ -343,7 +346,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
trans(context, "items"),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.body2
|
||||
.bodyText1
|
||||
.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black),
|
||||
@ -364,7 +367,7 @@ class _AccountDetailPageState extends State<AccountDetailPage>
|
||||
textAlign: TextAlign.right,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.body2
|
||||
.bodyText1
|
||||
.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black),
|
||||
|
||||
@ -68,7 +68,7 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
textAlign: TextAlign.left,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.display1
|
||||
.headline4
|
||||
.copyWith(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w700,
|
||||
@ -119,7 +119,7 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
Padding(
|
||||
child: Text(
|
||||
trans(context, "Create an account"),
|
||||
style: Theme.of(context).primaryTextTheme.body2,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1,
|
||||
),
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
)
|
||||
@ -133,6 +133,10 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
action: () {
|
||||
launch(app_forgot_password_url);
|
||||
}),
|
||||
Divider(),
|
||||
wsLinkButton(context, title: trans(context, "Back"), action: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -157,7 +161,13 @@ class _AccountLandingPageState extends State<AccountLandingPage> {
|
||||
authUser(token);
|
||||
storeUserId(wpUserLoginResponse.data.userId.toString());
|
||||
|
||||
navigatorPush(context, routeName: "/home", forgetAll: true);
|
||||
showEdgeAlertWith(context,
|
||||
title: trans(context, "Hello"),
|
||||
desc: trans(context, "Welcome back"),
|
||||
style: EdgeAlertStyle.SUCCESS,
|
||||
icon: Icons.account_circle);
|
||||
navigatorPush(context,
|
||||
routeName: UserAuth.instance.redirect, forgetLast: 1);
|
||||
} else {
|
||||
showEdgeAlertWith(context,
|
||||
title: trans(context, "Oops!"),
|
||||
|
||||
@ -55,7 +55,7 @@ class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
|
||||
),
|
||||
title: Text(
|
||||
"Order #" + _orderId.toString(),
|
||||
style: Theme.of(context).primaryTextTheme.title,
|
||||
style: Theme.of(context).primaryTextTheme.headline6,
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
@ -157,7 +157,7 @@ class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
|
||||
total: _order.lineItems[i].total),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.body1
|
||||
.bodyText2
|
||||
.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black),
|
||||
@ -169,7 +169,7 @@ class _AccountOrderDetailPageState extends State<AccountOrderDetailPage> {
|
||||
.toString(),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.body2
|
||||
.bodyText1
|
||||
.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black),
|
||||
|
||||
@ -16,7 +16,6 @@ import 'package:label_storemax/labelconfig.dart';
|
||||
import 'package:label_storemax/widgets/buttons.dart';
|
||||
import 'package:label_storemax/widgets/woosignal_ui.dart';
|
||||
import 'package:woosignal/helpers/shared_pref.dart';
|
||||
import 'package:wp_json_api/models/responses/WPUserInfoUpdatedResponse.dart';
|
||||
import 'package:wp_json_api/models/responses/WPUserRegisterResponse.dart';
|
||||
import 'package:wp_json_api/wp_json_api.dart';
|
||||
|
||||
@ -61,7 +60,7 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
|
||||
),
|
||||
title: Text(
|
||||
"Register",
|
||||
style: Theme.of(context).primaryTextTheme.title,
|
||||
style: Theme.of(context).primaryTextTheme.headline6,
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
@ -173,19 +172,25 @@ class _AccountRegistrationPageState extends State<AccountRegistrationPage> {
|
||||
|
||||
WPUserRegisterResponse wpUserRegisterResponse = await WPJsonAPI.instance
|
||||
.api((request) => request.wpRegister(
|
||||
email: email, password: password, username: username));
|
||||
email: email.toLowerCase(),
|
||||
password: password,
|
||||
username: username));
|
||||
|
||||
if (wpUserRegisterResponse != null) {
|
||||
String token = wpUserRegisterResponse.data.userToken;
|
||||
authUser(token);
|
||||
storeUserId(wpUserRegisterResponse.data.userId.toString());
|
||||
|
||||
WPUserInfoUpdatedResponse wpUserInfoUpdatedResponse = await WPJsonAPI
|
||||
.instance
|
||||
.api((request) => request.wpUpdateUserInfo(token,
|
||||
firstName: firstName, lastName: lastName));
|
||||
await WPJsonAPI.instance.api((request) => request
|
||||
.wpUpdateUserInfo(token, firstName: firstName, lastName: lastName));
|
||||
|
||||
navigatorPush(context, routeName: "/home", forgetAll: true);
|
||||
showEdgeAlertWith(context,
|
||||
title: trans(context, "Hello") + " $firstName",
|
||||
desc: trans(context, "you're now logged in"),
|
||||
style: EdgeAlertStyle.SUCCESS,
|
||||
icon: Icons.account_circle);
|
||||
navigatorPush(context,
|
||||
routeName: UserAuth.instance.redirect, forgetLast: 2);
|
||||
} else {
|
||||
setState(() {
|
||||
showEdgeAlertWith(context,
|
||||
|
||||
@ -90,7 +90,7 @@ class _AccountShippingDetailsPageState
|
||||
backgroundColor: Colors.transparent,
|
||||
title: Text(
|
||||
trans(context, "Shipping Details"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1,
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
|
||||
@ -8,9 +8,13 @@
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:label_storemax/helpers/enums/sort_enums.dart';
|
||||
import 'package:label_storemax/helpers/tools.dart';
|
||||
import 'package:label_storemax/widgets/app_loader.dart';
|
||||
import 'package:label_storemax/widgets/buttons.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:woosignal/models/response/product_category.dart';
|
||||
import 'package:woosignal/models/response/products.dart' as WS;
|
||||
import 'package:label_storemax/widgets/woosignal_ui.dart';
|
||||
@ -29,8 +33,9 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
|
||||
_BrowseCategoryPageState(this._selectedCategory);
|
||||
|
||||
List<WS.Product> _products = [];
|
||||
var _productsController = ScrollController();
|
||||
|
||||
RefreshController _refreshController =
|
||||
RefreshController(initialRefresh: false);
|
||||
ProductCategory _selectedCategory;
|
||||
bool _isLoading;
|
||||
int _page;
|
||||
@ -46,34 +51,17 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
|
||||
_page = 1;
|
||||
_shouldStopRequests = false;
|
||||
waitForNextRequest = false;
|
||||
|
||||
_fetchProductsForCategory();
|
||||
_addScrollListener();
|
||||
}
|
||||
|
||||
_addScrollListener() async {
|
||||
_productsController.addListener(() {
|
||||
double maxScroll = _productsController.position.maxScrollExtent;
|
||||
double currentScroll = _productsController.position.pixels;
|
||||
double delta = 50.0;
|
||||
if (maxScroll - currentScroll <= delta) {
|
||||
if (_shouldStopRequests) {
|
||||
return;
|
||||
}
|
||||
if (waitForNextRequest) {
|
||||
return;
|
||||
}
|
||||
|
||||
_fetchMoreProducts();
|
||||
}
|
||||
});
|
||||
_fetchMoreProducts();
|
||||
}
|
||||
|
||||
_fetchMoreProducts() async {
|
||||
waitForNextRequest = true;
|
||||
List<WS.Product> products = await appWooSignal((api) {
|
||||
return api.getProducts(perPage: 50, page: _page, status: "publish");
|
||||
});
|
||||
List<WS.Product> products = await appWooSignal((api) => api.getProducts(
|
||||
perPage: 50,
|
||||
category: _selectedCategory.id.toString(),
|
||||
page: _page,
|
||||
status: "publish",
|
||||
stockStatus: "instock"));
|
||||
_products.addAll(products);
|
||||
waitForNextRequest = false;
|
||||
_page = _page + 1;
|
||||
@ -82,13 +70,6 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
|
||||
if (products.length == 0) {
|
||||
_shouldStopRequests = true;
|
||||
}
|
||||
}
|
||||
|
||||
_fetchProductsForCategory() async {
|
||||
_products = await appWooSignal((api) {
|
||||
return api.getProducts(
|
||||
category: _selectedCategory.id.toString(), perPage: 50);
|
||||
});
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
@ -109,12 +90,18 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(trans(context, "Browse"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead),
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1),
|
||||
Text(_selectedCategory.name,
|
||||
style: Theme.of(context).primaryTextTheme.title)
|
||||
style: Theme.of(context).primaryTextTheme.headline6)
|
||||
],
|
||||
),
|
||||
centerTitle: true,
|
||||
actions: <Widget>[
|
||||
IconButton(
|
||||
icon: Icon(Icons.tune),
|
||||
onPressed: _modalSheetTune,
|
||||
)
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
minimum: safeAreaDefault(),
|
||||
@ -122,25 +109,105 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
|
||||
? Center(
|
||||
child: showAppLoader(),
|
||||
)
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: (_products.length != null && _products.length > 0
|
||||
? GridView.count(
|
||||
crossAxisCount: 2,
|
||||
controller: _productsController,
|
||||
children: List.generate(_products.length, (index) {
|
||||
return wsCardProductItem(context,
|
||||
index: index, product: _products[index]);
|
||||
}))
|
||||
: wsNoResults(context)),
|
||||
flex: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
: refreshableScroll(context,
|
||||
refreshController: _refreshController,
|
||||
onRefresh: _onRefresh,
|
||||
onLoading: _onLoading,
|
||||
products: _products,
|
||||
onTap: _showProduct),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onRefresh() async {
|
||||
await _fetchMoreProducts();
|
||||
setState(() {});
|
||||
if (_shouldStopRequests) {
|
||||
_refreshController.resetNoData();
|
||||
} else {
|
||||
_refreshController.refreshCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
void _onLoading() async {
|
||||
await _fetchMoreProducts();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
if (_shouldStopRequests) {
|
||||
_refreshController.loadNoData();
|
||||
} else {
|
||||
_refreshController.loadComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_sortProducts({@required SortByType by}) {
|
||||
switch (by) {
|
||||
case SortByType.LowToHigh:
|
||||
_products.sort((product1, product2) => (parseWcPrice(product1.price))
|
||||
.compareTo((double.tryParse(product2.price) ?? 0)));
|
||||
break;
|
||||
case SortByType.HighToLow:
|
||||
_products.sort((product1, product2) => (parseWcPrice(product2.price))
|
||||
.compareTo((double.tryParse(product1.price) ?? 0)));
|
||||
break;
|
||||
case SortByType.NameAZ:
|
||||
_products.sort(
|
||||
(product1, product2) => product1.name.compareTo(product2.name));
|
||||
break;
|
||||
case SortByType.NameZA:
|
||||
_products.sort(
|
||||
(product1, product2) => product2.name.compareTo(product1.name));
|
||||
break;
|
||||
}
|
||||
setState(() {
|
||||
Navigator.pop(context);
|
||||
});
|
||||
}
|
||||
|
||||
_modalSheetTune() {
|
||||
wsModalBottom(
|
||||
context,
|
||||
title: trans(context, "Sort results"),
|
||||
bodyWidget: ListView(
|
||||
children: <Widget>[
|
||||
wsLinkButton(context,
|
||||
title: trans(context, "Sort: Low to high"),
|
||||
action: () => _sortProducts(by: SortByType.LowToHigh)),
|
||||
Divider(
|
||||
height: 0,
|
||||
),
|
||||
wsLinkButton(context,
|
||||
title: trans(context, "Sort: High to low"),
|
||||
action: () => _sortProducts(by: SortByType.HighToLow)),
|
||||
Divider(
|
||||
height: 0,
|
||||
),
|
||||
wsLinkButton(context,
|
||||
title: trans(context, "Sort: Name A-Z"),
|
||||
action: () => _sortProducts(by: SortByType.NameAZ)),
|
||||
Divider(
|
||||
height: 0,
|
||||
),
|
||||
wsLinkButton(context,
|
||||
title: trans(context, "Sort: Name Z-A"),
|
||||
action: () => _sortProducts(by: SortByType.NameZA)),
|
||||
Divider(
|
||||
height: 0,
|
||||
),
|
||||
wsLinkButton(context,
|
||||
title: trans(context, "Cancel"), action: _dismissModal)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_dismissModal() {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
_showProduct(WS.Product product) {
|
||||
Navigator.pushNamed(context, "/product-detail", arguments: product);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,8 +11,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:label_storemax/helpers/tools.dart';
|
||||
import 'package:label_storemax/widgets/app_loader.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:woosignal/models/response/products.dart' as WS;
|
||||
import 'package:label_storemax/widgets/woosignal_ui.dart';
|
||||
|
||||
class BrowseSearchPage extends StatefulWidget {
|
||||
final String search;
|
||||
@ -25,7 +25,8 @@ class BrowseSearchPage extends StatefulWidget {
|
||||
class _BrowseSearchState extends State<BrowseSearchPage> {
|
||||
_BrowseSearchState(this._search);
|
||||
|
||||
var _productsController = ScrollController();
|
||||
RefreshController _refreshController =
|
||||
RefreshController(initialRefresh: false);
|
||||
List<WS.Product> _products = [];
|
||||
String _search;
|
||||
bool _isLoading;
|
||||
@ -42,39 +43,26 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
|
||||
_shouldStopRequests = false;
|
||||
waitForNextRequest = false;
|
||||
|
||||
_fetchProductsForSearch(_page);
|
||||
_addScrollListener();
|
||||
_fetchProductsForSearch();
|
||||
}
|
||||
|
||||
_addScrollListener() async {
|
||||
_productsController.addListener(() {
|
||||
double maxScroll = _productsController.position.maxScrollExtent;
|
||||
double currentScroll = _productsController.position.pixels;
|
||||
double delta = 50.0;
|
||||
if (maxScroll - currentScroll <= delta) {
|
||||
if (_shouldStopRequests) {
|
||||
return;
|
||||
}
|
||||
if (waitForNextRequest) {
|
||||
return;
|
||||
}
|
||||
_fetchProductsForSearch(_page);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_fetchProductsForSearch(int page) async {
|
||||
_fetchProductsForSearch() async {
|
||||
waitForNextRequest = true;
|
||||
List<WS.Product> products = await appWooSignal((api) {
|
||||
_page = _page + 1;
|
||||
return api.getProducts(
|
||||
search: _search, perPage: 100, page: page, status: "publish");
|
||||
});
|
||||
List<WS.Product> products = await appWooSignal((api) => api.getProducts(
|
||||
perPage: 100,
|
||||
search: _search,
|
||||
page: _page,
|
||||
status: "publish",
|
||||
stockStatus: "instock"));
|
||||
_products.addAll(products);
|
||||
waitForNextRequest = false;
|
||||
_page = _page + 1;
|
||||
|
||||
waitForNextRequest = false;
|
||||
if (products.length == 0) {
|
||||
_shouldStopRequests = true;
|
||||
}
|
||||
setState(() {
|
||||
_products.addAll(products.toList());
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
@ -94,9 +82,9 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(trans(context, "Search results for"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead),
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1),
|
||||
Text("\"" + _search + "\"",
|
||||
style: Theme.of(context).primaryTextTheme.title)
|
||||
style: Theme.of(context).primaryTextTheme.headline6)
|
||||
],
|
||||
),
|
||||
centerTitle: true,
|
||||
@ -107,29 +95,40 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
|
||||
? Center(
|
||||
child: showAppLoader(),
|
||||
)
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: (_products.length != null && _products.length > 0
|
||||
? GridView.count(
|
||||
crossAxisCount: 2,
|
||||
controller: _productsController,
|
||||
children: List.generate(
|
||||
_products.length,
|
||||
(index) {
|
||||
return wsCardProductItem(context,
|
||||
index: index, product: _products[index]);
|
||||
},
|
||||
),
|
||||
)
|
||||
: wsNoResults(context)),
|
||||
flex: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
: refreshableScroll(context,
|
||||
refreshController: _refreshController,
|
||||
onRefresh: _onRefresh,
|
||||
onLoading: _onLoading,
|
||||
products: _products,
|
||||
onTap: _showProduct),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onRefresh() async {
|
||||
await _fetchProductsForSearch();
|
||||
setState(() {});
|
||||
if (_shouldStopRequests) {
|
||||
_refreshController.resetNoData();
|
||||
} else {
|
||||
_refreshController.refreshCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
void _onLoading() async {
|
||||
await _fetchProductsForSearch();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
if (_shouldStopRequests) {
|
||||
_refreshController.loadNoData();
|
||||
} else {
|
||||
_refreshController.loadComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_showProduct(WS.Product product) {
|
||||
Navigator.pushNamed(context, "/product-detail", arguments: product);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,9 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:label_storemax/helpers/shared_pref/sp_auth.dart';
|
||||
import 'package:label_storemax/helpers/tools.dart';
|
||||
import 'package:label_storemax/labelconfig.dart';
|
||||
import 'package:label_storemax/models/cart.dart';
|
||||
import 'package:label_storemax/models/cart_line_item.dart';
|
||||
import 'package:label_storemax/models/checkout_session.dart';
|
||||
@ -67,6 +69,9 @@ class _CartPageState extends State<CartPage> {
|
||||
|
||||
void _actionProceedToCheckout() async {
|
||||
List<CartLineItem> cartLineItems = await Cart.getInstance.getCart();
|
||||
if (_isLoading == true) {
|
||||
return;
|
||||
}
|
||||
if (cartLineItems.length <= 0) {
|
||||
showEdgeAlertWith(context,
|
||||
title: trans(context, "Cart"),
|
||||
@ -94,6 +99,11 @@ class _CartPageState extends State<CartPage> {
|
||||
CheckoutSession.getInstance.billingDetails.shippingAddress =
|
||||
sfCustomerAddress;
|
||||
}
|
||||
if (use_wp_login == true && !(await authCheck())) {
|
||||
UserAuth.instance.redirect = "/checkout";
|
||||
Navigator.pushNamed(context, "/account-landing");
|
||||
return;
|
||||
}
|
||||
Navigator.pushNamed(context, "/checkout");
|
||||
}
|
||||
|
||||
@ -131,6 +141,9 @@ class _CartPageState extends State<CartPage> {
|
||||
desc: trans(context, "Item removed"),
|
||||
style: EdgeAlertStyle.WARNING,
|
||||
icon: Icons.remove_shopping_cart);
|
||||
if (_cartLines.length == 0) {
|
||||
_isCartEmpty = true;
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@ -142,6 +155,7 @@ class _CartPageState extends State<CartPage> {
|
||||
desc: trans(context, "Cart cleared"),
|
||||
style: EdgeAlertStyle.SUCCESS,
|
||||
icon: Icons.delete_outline);
|
||||
_isCartEmpty = true;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@ -151,7 +165,7 @@ class _CartPageState extends State<CartPage> {
|
||||
resizeToAvoidBottomPadding: false,
|
||||
appBar: AppBar(
|
||||
title: Text(trans(context, "Shopping Cart"),
|
||||
style: Theme.of(context).appBarTheme.textTheme.title),
|
||||
style: Theme.of(context).appBarTheme.textTheme.headline6),
|
||||
textTheme: Theme.of(context).textTheme,
|
||||
elevation: 1,
|
||||
actions: <Widget>[
|
||||
@ -161,7 +175,7 @@ class _CartPageState extends State<CartPage> {
|
||||
child: Align(
|
||||
child: Padding(
|
||||
child: Text(trans(context, "Clear Cart"),
|
||||
style: Theme.of(context).primaryTextTheme.body2),
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1),
|
||||
padding: EdgeInsets.only(right: 8),
|
||||
),
|
||||
alignment: Alignment.centerLeft,
|
||||
@ -191,7 +205,8 @@ class _CartPageState extends State<CartPage> {
|
||||
),
|
||||
Padding(
|
||||
child: Text(trans(context, "Empty Basket"),
|
||||
style: Theme.of(context).primaryTextTheme.body1),
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.bodyText2),
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
)
|
||||
],
|
||||
|
||||
@ -30,19 +30,18 @@ class CheckoutConfirmationPage extends StatefulWidget {
|
||||
class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
CheckoutConfirmationPageState();
|
||||
|
||||
GlobalKey<CheckoutConfirmationPageState> _key =
|
||||
GlobalKey<CheckoutConfirmationPageState>();
|
||||
|
||||
bool _showFullLoader;
|
||||
|
||||
List<TaxRate> _taxRates;
|
||||
TaxRate _taxRate;
|
||||
bool _isProcessingPayment;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_showFullLoader = true;
|
||||
_isProcessingPayment = false;
|
||||
if (CheckoutSession.getInstance.paymentType == null) {
|
||||
CheckoutSession.getInstance.paymentType = arrPaymentMethods.first;
|
||||
}
|
||||
@ -50,8 +49,6 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
_getTaxes();
|
||||
}
|
||||
|
||||
_fetchUserId() {}
|
||||
|
||||
void reloadState({bool showLoader}) {
|
||||
setState(() {
|
||||
_showFullLoader = showLoader ?? false;
|
||||
@ -135,7 +132,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
children: <Widget>[
|
||||
Center(
|
||||
child: Text(trans(context, "Checkout"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead),
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
@ -239,8 +236,10 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
],
|
||||
),
|
||||
wsPrimaryButton(context,
|
||||
title: trans(context, "CHECKOUT"),
|
||||
action: _handleCheckout),
|
||||
title: _isProcessingPayment
|
||||
? "PROCESSING..."
|
||||
: trans(context, "CHECKOUT"),
|
||||
action: _isProcessingPayment ? null : _handleCheckout),
|
||||
],
|
||||
)
|
||||
: Center(
|
||||
@ -252,7 +251,7 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
padding: const EdgeInsets.only(top: 15),
|
||||
child: Text(
|
||||
trans(context, "One moment") + "...",
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1,
|
||||
),
|
||||
)
|
||||
],
|
||||
@ -301,7 +300,21 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_isProcessingPayment == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isProcessingPayment = true;
|
||||
});
|
||||
|
||||
CheckoutSession.getInstance.paymentType
|
||||
.pay(context, state: this, taxRate: _taxRate);
|
||||
|
||||
Future.delayed(Duration(milliseconds: 5000), () {
|
||||
setState(() {
|
||||
_isProcessingPayment = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,35 +85,33 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
_showSelectCountryModal() {
|
||||
wsModalBottom(context,
|
||||
title: trans(context, "Select a country"),
|
||||
bodyWidget: Expanded(
|
||||
child: ListView.separated(
|
||||
itemCount: appCountryOptions.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
Map<String, String> strName = appCountryOptions[index];
|
||||
bodyWidget: ListView.separated(
|
||||
itemCount: appCountryOptions.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
Map<String, String> strName = appCountryOptions[index];
|
||||
|
||||
return InkWell(
|
||||
child: Container(
|
||||
child: Text(strName["name"],
|
||||
style: Theme.of(context).primaryTextTheme.body2),
|
||||
padding: EdgeInsets.only(top: 25, bottom: 25),
|
||||
),
|
||||
splashColor: Colors.grey,
|
||||
highlightColor: Colors.black12,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_strBillingCountry = strName["name"];
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
separatorBuilder: (cxt, i) {
|
||||
return Divider(
|
||||
height: 0,
|
||||
color: Colors.black12,
|
||||
);
|
||||
},
|
||||
),
|
||||
return InkWell(
|
||||
child: Container(
|
||||
child: Text(strName["name"],
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1),
|
||||
padding: EdgeInsets.only(top: 25, bottom: 25),
|
||||
),
|
||||
splashColor: Colors.grey,
|
||||
highlightColor: Colors.black12,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_strBillingCountry = strName["name"];
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
separatorBuilder: (cxt, i) {
|
||||
return Divider(
|
||||
height: 0,
|
||||
color: Colors.black12,
|
||||
);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
@ -125,7 +123,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
backgroundColor: Colors.transparent,
|
||||
title: Text(
|
||||
trans(context, "Billing & Shipping Details"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.headline6,
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
@ -241,7 +239,8 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
Text(trans(context, "Remember my details"),
|
||||
style: Theme.of(context).primaryTextTheme.body2),
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.bodyText2),
|
||||
Checkbox(
|
||||
value: valRememberDetails,
|
||||
onChanged: (bool value) {
|
||||
|
||||
@ -43,7 +43,7 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
title: Text(trans(context, "Payment Method"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead),
|
||||
style: Theme.of(context).primaryTextTheme.headline6),
|
||||
automaticallyImplyLeading: false,
|
||||
centerTitle: true,
|
||||
),
|
||||
@ -74,35 +74,41 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: getPaymentTypes().length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.only(
|
||||
top: 10, bottom: 10, left: 8, right: 8),
|
||||
leading: Image(
|
||||
image: AssetImage("assets/images/" +
|
||||
getPaymentTypes()[index].assetImage),
|
||||
width: 60,
|
||||
fit: BoxFit.fitHeight,
|
||||
alignment: Alignment.center),
|
||||
title: Text(getPaymentTypes()[index].desc,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.subhead),
|
||||
selected: true,
|
||||
trailing: (CheckoutSession
|
||||
.getInstance.paymentType ==
|
||||
getPaymentTypes()[index]
|
||||
? Icon(Icons.check)
|
||||
: null),
|
||||
onTap: () {
|
||||
CheckoutSession.getInstance.paymentType =
|
||||
getPaymentTypes()[index];
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
}),
|
||||
child: ListView.separated(
|
||||
itemCount: getPaymentTypes().length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.only(
|
||||
top: 10, bottom: 10, left: 8, right: 8),
|
||||
leading: Image(
|
||||
image: AssetImage("assets/images/" +
|
||||
getPaymentTypes()[index].assetImage),
|
||||
width: 60,
|
||||
fit: BoxFit.contain,
|
||||
alignment: Alignment.center),
|
||||
title: Text(getPaymentTypes()[index].desc,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.subtitle1),
|
||||
selected: true,
|
||||
trailing:
|
||||
(CheckoutSession.getInstance.paymentType ==
|
||||
getPaymentTypes()[index]
|
||||
? Icon(Icons.check)
|
||||
: null),
|
||||
onTap: () {
|
||||
CheckoutSession.getInstance.paymentType =
|
||||
getPaymentTypes()[index];
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
},
|
||||
separatorBuilder: (cxt, i) {
|
||||
return Divider(
|
||||
color: Colors.black12,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
wsLinkButton(context, title: trans(context, "CANCEL"),
|
||||
action: () {
|
||||
|
||||
@ -17,7 +17,6 @@ import 'package:label_storemax/models/customer_address.dart';
|
||||
import 'package:label_storemax/models/shipping_type.dart';
|
||||
import 'package:label_storemax/widgets/app_loader.dart';
|
||||
import 'package:label_storemax/widgets/buttons.dart';
|
||||
import 'package:math_expressions/math_expressions.dart';
|
||||
import 'package:woosignal/models/response/shipping_method.dart';
|
||||
import 'package:label_storemax/app_country_options.dart';
|
||||
|
||||
@ -49,9 +48,8 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
}
|
||||
|
||||
_getShippingMethods() async {
|
||||
List<WSShipping> wsShipping = await appWooSignal((api) {
|
||||
return api.getShippingMethods();
|
||||
});
|
||||
List<WSShipping> wsShipping =
|
||||
await appWooSignal((api) => api.getShippingMethods());
|
||||
CustomerAddress customerAddress =
|
||||
CheckoutSession.getInstance.billingDetails.shippingAddress;
|
||||
String postalCode = customerAddress.postalCode;
|
||||
@ -70,9 +68,12 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
}
|
||||
}
|
||||
|
||||
if (_shipping != null) {
|
||||
if (_shipping != null && _shipping.methods != null) {
|
||||
if (_shipping.methods.flatRate != null) {
|
||||
_shipping.methods.flatRate.forEach((flatRate) {
|
||||
_shipping.methods.flatRate
|
||||
.where((t) => t != null)
|
||||
.toList()
|
||||
.forEach((flatRate) {
|
||||
Map<String, dynamic> tmpShippingOption = {};
|
||||
tmpShippingOption = {
|
||||
"id": flatRate.id,
|
||||
@ -86,7 +87,10 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
}
|
||||
|
||||
if (_shipping.methods.localPickup != null) {
|
||||
_shipping.methods.localPickup.forEach((localPickup) {
|
||||
_shipping.methods.localPickup
|
||||
.where((t) => t != null)
|
||||
.toList()
|
||||
.forEach((localPickup) {
|
||||
Map<String, dynamic> tmpShippingOption = {};
|
||||
tmpShippingOption = {
|
||||
"id": localPickup.id,
|
||||
@ -100,7 +104,10 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
}
|
||||
|
||||
if (_shipping.methods.freeShipping != null) {
|
||||
_shipping.methods.freeShipping.forEach((freeShipping) {
|
||||
_shipping.methods.freeShipping
|
||||
.where((t) => t != null)
|
||||
.toList()
|
||||
.forEach((freeShipping) {
|
||||
if (isNumeric(freeShipping.cost)) {
|
||||
Map<String, dynamic> tmpShippingOption = {};
|
||||
tmpShippingOption = {
|
||||
@ -183,7 +190,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
context,
|
||||
"Shipping Methods",
|
||||
),
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.headline6,
|
||||
),
|
||||
automaticallyImplyLeading: false,
|
||||
centerTitle: true,
|
||||
@ -234,7 +241,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
['title'],
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.subhead),
|
||||
.subtitle1),
|
||||
selected: true,
|
||||
subtitle: FutureBuilder<String>(
|
||||
future: _getShippingPrice(index),
|
||||
@ -299,7 +306,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
|
||||
"Shipping is not supported for your country, sorry"),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.title,
|
||||
.headline6,
|
||||
textAlign: TextAlign.center))),
|
||||
wsLinkButton(context, title: trans(context, "CANCEL"),
|
||||
action: () {
|
||||
|
||||
@ -60,25 +60,25 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
|
||||
Padding(
|
||||
child: Text(
|
||||
trans(context, "Order Status"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1,
|
||||
),
|
||||
padding: EdgeInsets.only(bottom: 15),
|
||||
),
|
||||
Text(
|
||||
trans(context, "Thank You!"),
|
||||
style: Theme.of(context).primaryTextTheme.title,
|
||||
style: Theme.of(context).primaryTextTheme.headline6,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
Text(
|
||||
trans(context, "Your transaction details"),
|
||||
style: Theme.of(context).primaryTextTheme.body1,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText2,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
Text(
|
||||
trans(context, "Order Ref") +
|
||||
". #" +
|
||||
_order.id.toString(),
|
||||
style: Theme.of(context).primaryTextTheme.body2,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
],
|
||||
@ -96,7 +96,9 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
|
||||
child: Image(
|
||||
image: new AssetImage("assets/images/camion.gif"),
|
||||
height: 170),
|
||||
color: Colors.white,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
),
|
||||
width: double.infinity),
|
||||
],
|
||||
),
|
||||
@ -104,7 +106,7 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
|
||||
child: Padding(
|
||||
child: Text(
|
||||
trans(context, "Items"),
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
padding: EdgeInsets.all(8),
|
||||
@ -130,24 +132,28 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
|
||||
Text(lineItem.name,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.body2,
|
||||
.bodyText1,
|
||||
softWrap: false,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis),
|
||||
Text("x" + lineItem.quantity.toString(),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.body1),
|
||||
.bodyText2),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
formatStringCurrency(
|
||||
total: lineItem.total.toString()),
|
||||
style: Theme.of(context).primaryTextTheme.body2)
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyText1)
|
||||
],
|
||||
),
|
||||
decoration: BoxDecoration(color: Colors.white),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
),
|
||||
padding: EdgeInsets.all(16),
|
||||
margin: EdgeInsets.all(8),
|
||||
);
|
||||
|
||||
@ -46,7 +46,7 @@ class _ErrorPageState extends State<ErrorPage> {
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
trans(context, "Sorry, something went wrong"),
|
||||
style: Theme.of(context).primaryTextTheme.body1,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText2,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
||||
@ -12,6 +12,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:label_storemax/helpers/tools.dart';
|
||||
import 'package:label_storemax/widgets/app_loader.dart';
|
||||
import 'package:label_storemax/widgets/cart_icon.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:woosignal/models/response/product_category.dart' as WS;
|
||||
import 'package:woosignal/models/response/products.dart' as WS;
|
||||
import 'package:label_storemax/widgets/woosignal_ui.dart';
|
||||
@ -26,10 +27,11 @@ class HomePage extends StatefulWidget {
|
||||
class _HomePageState extends State<HomePage> {
|
||||
_HomePageState();
|
||||
|
||||
RefreshController _refreshController =
|
||||
RefreshController(initialRefresh: false);
|
||||
List<WS.Product> _products = [];
|
||||
List<WS.ProductCategory> _categories = [];
|
||||
|
||||
var _productsController = ScrollController();
|
||||
final GlobalKey _key = GlobalKey();
|
||||
|
||||
int _page;
|
||||
bool _shouldStopRequests;
|
||||
@ -41,115 +43,68 @@ class _HomePageState extends State<HomePage> {
|
||||
super.initState();
|
||||
|
||||
_isLoading = true;
|
||||
|
||||
_page = 1;
|
||||
_home();
|
||||
_addScrollListener();
|
||||
}
|
||||
|
||||
_home() async {
|
||||
await _fetchProducts();
|
||||
await _fetchCategories();
|
||||
_shouldStopRequests = false;
|
||||
waitForNextRequest = false;
|
||||
await _fetchMoreProducts();
|
||||
await _fetchCategories();
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
_fetchProducts() async {
|
||||
_products = await appWooSignal((api) {
|
||||
return api.getProducts(perPage: 50, page: _page, status: "publish");
|
||||
});
|
||||
}
|
||||
|
||||
_fetchCategories() async {
|
||||
_categories = await appWooSignal((api) {
|
||||
return api.getProductCategories();
|
||||
});
|
||||
}
|
||||
|
||||
_addScrollListener() async {
|
||||
_productsController.addListener(() {
|
||||
double maxScroll = _productsController.position.maxScrollExtent;
|
||||
double currentScroll = _productsController.position.pixels;
|
||||
double delta = 50.0;
|
||||
if (maxScroll - currentScroll <= delta) {
|
||||
if (_shouldStopRequests) {
|
||||
return;
|
||||
}
|
||||
if (waitForNextRequest) {
|
||||
return;
|
||||
}
|
||||
_fetchMoreProducts();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_fetchMoreProducts() async {
|
||||
if (_shouldStopRequests) {
|
||||
return;
|
||||
}
|
||||
if (waitForNextRequest) {
|
||||
return;
|
||||
}
|
||||
waitForNextRequest = true;
|
||||
List<WS.Product> products = await appWooSignal((api) {
|
||||
_page = _page + 1;
|
||||
return api.getProducts(perPage: 50, page: _page, status: "publish");
|
||||
});
|
||||
List<WS.Product> products = await appWooSignal((api) => api.getProducts(
|
||||
perPage: 50, page: _page, status: "publish", stockStatus: "instock"));
|
||||
_page = _page + 1;
|
||||
if (products.length == 0) {
|
||||
_shouldStopRequests = true;
|
||||
}
|
||||
waitForNextRequest = false;
|
||||
setState(() {
|
||||
_products.addAll(products.toList());
|
||||
});
|
||||
}
|
||||
|
||||
void _modalBottomSheetMenu() {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (builder) {
|
||||
return new Container(
|
||||
height: double.infinity,
|
||||
width: double.infinity - 10,
|
||||
color: Colors.transparent,
|
||||
child: new Container(
|
||||
padding: EdgeInsets.only(top: 25, left: 18, right: 18),
|
||||
decoration: new BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: new BorderRadius.only(
|
||||
topLeft: const Radius.circular(10.0),
|
||||
topRight: const Radius.circular(10.0),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Text(trans(context, "Categories"),
|
||||
style: Theme.of(context).primaryTextTheme.display1,
|
||||
textAlign: TextAlign.left),
|
||||
Expanded(
|
||||
child: new ListView.builder(
|
||||
itemCount: _categories.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return InkWell(
|
||||
child: Container(
|
||||
child: Text(_categories[index].name),
|
||||
padding: EdgeInsets.all(15),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: HexColor("#f2f2f2"), width: 2),
|
||||
),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, "/browse-category",
|
||||
arguments: _categories[index]);
|
||||
},
|
||||
);
|
||||
}),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
_key.currentState.setState(() {});
|
||||
wsModalBottom(
|
||||
context,
|
||||
title: trans(context, "Categories"),
|
||||
bodyWidget: ListView.separated(
|
||||
itemCount: _categories.length,
|
||||
separatorBuilder: (cxt, i) {
|
||||
return Divider();
|
||||
},
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ListTile(
|
||||
title: Text(parseHtmlString(_categories[index].name)),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.pushNamed(context, "/browse-category",
|
||||
arguments: _categories[index])
|
||||
.then((value) => setState(() {}));
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -161,9 +116,7 @@ class _HomePageState extends State<HomePage> {
|
||||
leading: Container(
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.menu),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, "/home-menu");
|
||||
},
|
||||
onPressed: () => Navigator.pushNamed(context, "/home-menu"),
|
||||
),
|
||||
margin: EdgeInsets.only(left: 0),
|
||||
),
|
||||
@ -177,11 +130,10 @@ class _HomePageState extends State<HomePage> {
|
||||
color: Colors.black,
|
||||
size: 35,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, "/home-search");
|
||||
},
|
||||
onPressed: () => Navigator.pushNamed(context, "/home-search")
|
||||
.then((value) => _key.currentState.setState(() {})),
|
||||
),
|
||||
wsCartIcon(context)
|
||||
wsCartIcon(context, key: _key)
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
@ -198,10 +150,10 @@ class _HomePageState extends State<HomePage> {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(trans(context, "Shop") + " / ",
|
||||
style: Theme.of(context).primaryTextTheme.subhead),
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1),
|
||||
Text(
|
||||
trans(context, "Newest"),
|
||||
style: Theme.of(context).primaryTextTheme.body1,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText2,
|
||||
)
|
||||
],
|
||||
),
|
||||
@ -210,25 +162,21 @@ class _HomePageState extends State<HomePage> {
|
||||
height: 60,
|
||||
child: Text(
|
||||
trans(context, "Browse categories"),
|
||||
style: Theme.of(context).primaryTextTheme.body2,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1,
|
||||
),
|
||||
onPressed: () {
|
||||
_modalBottomSheetMenu();
|
||||
},
|
||||
onPressed: _modalBottomSheetMenu,
|
||||
)
|
||||
],
|
||||
),
|
||||
(_isLoading
|
||||
? Expanded(child: showAppLoader())
|
||||
: Expanded(
|
||||
child: GridView.count(
|
||||
controller: _productsController,
|
||||
crossAxisCount: 2,
|
||||
children: List.generate(_products.length, (index) {
|
||||
return wsCardProductItem(context,
|
||||
index: index, product: _products[index]);
|
||||
}),
|
||||
),
|
||||
child: refreshableScroll(context,
|
||||
refreshController: _refreshController,
|
||||
onRefresh: _onRefresh,
|
||||
onLoading: _onLoading,
|
||||
products: _products,
|
||||
onTap: _showProduct),
|
||||
flex: 1,
|
||||
)),
|
||||
],
|
||||
@ -236,4 +184,32 @@ class _HomePageState extends State<HomePage> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _onRefresh() async {
|
||||
await _fetchMoreProducts();
|
||||
setState(() {});
|
||||
if (_shouldStopRequests) {
|
||||
_refreshController.resetNoData();
|
||||
} else {
|
||||
_refreshController.refreshCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
void _onLoading() async {
|
||||
await _fetchMoreProducts();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
if (_shouldStopRequests) {
|
||||
_refreshController.loadNoData();
|
||||
} else {
|
||||
_refreshController.loadComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_showProduct(WS.Product product) {
|
||||
Navigator.pushNamed(context, "/product-detail", arguments: product)
|
||||
.then((value) => _key.currentState.setState(() {}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:label_storemax/helpers/shared_pref/sp_auth.dart';
|
||||
import 'package:label_storemax/labelconfig.dart';
|
||||
import 'package:label_storemax/widgets/menu_item.dart';
|
||||
import 'package:label_storemax/helpers/tools.dart';
|
||||
@ -37,7 +38,7 @@ class _HomeMenuPageState extends State<HomeMenuPage> {
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0.0,
|
||||
title: Text(trans(context, "Menu"),
|
||||
style: Theme.of(context).primaryTextTheme.title),
|
||||
style: Theme.of(context).primaryTextTheme.headline6),
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.close),
|
||||
onPressed: () {
|
||||
@ -89,7 +90,12 @@ class _HomeMenuPageState extends State<HomeMenuPage> {
|
||||
Navigator.pushNamed(context, "/about");
|
||||
}
|
||||
|
||||
void _actionProfile() {
|
||||
void _actionProfile() async {
|
||||
if (use_wp_login == true && !(await authCheck())) {
|
||||
UserAuth.instance.redirect = "/account-detail";
|
||||
Navigator.pushNamed(context, "/account-landing");
|
||||
return;
|
||||
}
|
||||
Navigator.pushNamed(context, "/account-detail");
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ class _HomeSearchPageState extends State<HomeSearchPage> {
|
||||
),
|
||||
TextField(
|
||||
controller: _txtSearchController,
|
||||
style: Theme.of(context).primaryTextTheme.display2,
|
||||
style: Theme.of(context).primaryTextTheme.headline3,
|
||||
keyboardType: TextInputType.text,
|
||||
autocorrect: false,
|
||||
autofocus: true,
|
||||
|
||||
@ -50,9 +50,23 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
}
|
||||
|
||||
_fetchProductVariations() async {
|
||||
_productVariations = await appWooSignal((api) {
|
||||
return api.getProductVariations(_product.id);
|
||||
});
|
||||
List<WS.ProductVariation> tmpVariations = [];
|
||||
int currentPage = 1;
|
||||
|
||||
bool isFetching = true;
|
||||
while (isFetching) {
|
||||
List<WS.ProductVariation> tmp = await appWooSignal((api) {
|
||||
return api.getProductVariations(_product.id,
|
||||
perPage: 100, page: currentPage);
|
||||
});
|
||||
if (tmp != null && tmp.length > 0) {
|
||||
tmpVariations.addAll(tmp);
|
||||
currentPage += 1;
|
||||
} else {
|
||||
isFetching = false;
|
||||
}
|
||||
}
|
||||
_productVariations = tmpVariations;
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
@ -89,33 +103,30 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
title: trans(context, "Select a") +
|
||||
" " +
|
||||
_product.attributes[attributeIndex].name,
|
||||
bodyWidget: Expanded(
|
||||
child: ListView.separated(
|
||||
itemCount: _product.attributes[attributeIndex].options.length,
|
||||
separatorBuilder: (BuildContext context, int index) => Divider(),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ListTile(
|
||||
title: Text(_product.attributes[attributeIndex].options[index],
|
||||
style: Theme.of(context).primaryTextTheme.subhead),
|
||||
trailing: (_tmpAttributeObj.isNotEmpty &&
|
||||
_tmpAttributeObj.containsKey(attributeIndex) &&
|
||||
_tmpAttributeObj[attributeIndex]["value"] ==
|
||||
_product.attributes[attributeIndex].options[index])
|
||||
? Icon(Icons.check, color: Colors.blueAccent)
|
||||
: null,
|
||||
onTap: () {
|
||||
_tmpAttributeObj[attributeIndex] = {
|
||||
"name": _product.attributes[attributeIndex].name,
|
||||
"value": _product.attributes[attributeIndex].options[index]
|
||||
};
|
||||
Navigator.pop(context, () {});
|
||||
Navigator.pop(context);
|
||||
_modalBottomSheetAttributes();
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
flex: 1,
|
||||
bodyWidget: ListView.separated(
|
||||
itemCount: _product.attributes[attributeIndex].options.length,
|
||||
separatorBuilder: (BuildContext context, int index) => Divider(),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ListTile(
|
||||
title: Text(_product.attributes[attributeIndex].options[index],
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1),
|
||||
trailing: (_tmpAttributeObj.isNotEmpty &&
|
||||
_tmpAttributeObj.containsKey(attributeIndex) &&
|
||||
_tmpAttributeObj[attributeIndex]["value"] ==
|
||||
_product.attributes[attributeIndex].options[index])
|
||||
? Icon(Icons.check, color: Colors.blueAccent)
|
||||
: null,
|
||||
onTap: () {
|
||||
_tmpAttributeObj[attributeIndex] = {
|
||||
"name": _product.attributes[attributeIndex].name,
|
||||
"value": _product.attributes[attributeIndex].options[index]
|
||||
};
|
||||
Navigator.pop(context, () {});
|
||||
Navigator.pop(context);
|
||||
_modalBottomSheetAttributes();
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -134,8 +145,7 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
wsModalBottom(
|
||||
context,
|
||||
title: trans(context, "Options"),
|
||||
bodyWidget: Expanded(
|
||||
child: ListView.separated(
|
||||
bodyWidget: ListView.separated(
|
||||
itemCount: _product.attributes.length,
|
||||
separatorBuilder: (BuildContext context, int index) => Divider(
|
||||
color: Colors.black12,
|
||||
@ -144,11 +154,11 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ListTile(
|
||||
title: Text(_product.attributes[index].name,
|
||||
style: Theme.of(context).primaryTextTheme.subhead),
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1),
|
||||
subtitle: (_tmpAttributeObj.isNotEmpty &&
|
||||
_tmpAttributeObj.containsKey(index))
|
||||
? Text(_tmpAttributeObj[index]["value"],
|
||||
style: Theme.of(context).primaryTextTheme.body2)
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1)
|
||||
: Text(trans(context, "Select a") +
|
||||
" " +
|
||||
_product.attributes[index].name),
|
||||
@ -161,7 +171,7 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
},
|
||||
);
|
||||
},
|
||||
)),
|
||||
),
|
||||
extraWidget: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(top: BorderSide(color: Colors.black12, width: 1))),
|
||||
@ -179,14 +189,14 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
findProductVariation() == null)
|
||||
? trans(context, "This variation is unavailable")
|
||||
: trans(context, "Choose your options"))),
|
||||
style: Theme.of(context).primaryTextTheme.subhead),
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1),
|
||||
Text(
|
||||
(findProductVariation() != null
|
||||
? findProductVariation().stockStatus != "instock"
|
||||
? trans(context, "Out of stock")
|
||||
: ""
|
||||
: ""),
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1,
|
||||
),
|
||||
wsPrimaryButton(context, title: trans(context, "Add to cart"),
|
||||
action: () {
|
||||
@ -255,11 +265,10 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
wsModalBottom(
|
||||
context,
|
||||
title: trans(context, "Description"),
|
||||
bodyWidget: Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Text(parseHtmlString(_product.description)),
|
||||
bodyWidget: SingleChildScrollView(
|
||||
child: Text(
|
||||
parseHtmlString(_product.description),
|
||||
),
|
||||
flex: 1,
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -312,7 +321,9 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
Container(
|
||||
height: 100,
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 10, horizontal: 16),
|
||||
vertical: 10,
|
||||
horizontal: 16,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@ -320,8 +331,11 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
Flexible(
|
||||
child: Text(
|
||||
_product.name,
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.body2,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyText1
|
||||
.copyWith(
|
||||
color: Colors.black87, fontSize: 20),
|
||||
textAlign: TextAlign.left,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
@ -338,13 +352,24 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
total: _product.price),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.display1
|
||||
.headline4
|
||||
.copyWith(
|
||||
fontSize: 20,
|
||||
),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
],
|
||||
(_product.onSale == true
|
||||
? Text(
|
||||
formatStringCurrency(
|
||||
total: _product.regularPrice),
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
decoration:
|
||||
TextDecoration.lineThrough,
|
||||
),
|
||||
)
|
||||
: null)
|
||||
].where((t) => t != null).toList(),
|
||||
),
|
||||
flex: 2,
|
||||
)
|
||||
@ -352,7 +377,10 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
),
|
||||
),
|
||||
Container(
|
||||
color: Colors.white,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: wsBoxShadow(),
|
||||
borderRadius: BorderRadius.circular(4)),
|
||||
padding:
|
||||
EdgeInsets.symmetric(vertical: 4, horizontal: 16),
|
||||
height: 180,
|
||||
@ -378,15 +406,13 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
trans(context, "Full description"),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.body1
|
||||
.bodyText2
|
||||
.copyWith(fontSize: 14),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
height: 50,
|
||||
minWidth: 60,
|
||||
onPressed: () {
|
||||
_modalBottomSheetMenu();
|
||||
},
|
||||
onPressed: _modalBottomSheetMenu,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -432,7 +458,8 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Quantity",
|
||||
style: Theme.of(context).primaryTextTheme.body2,
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.bodyText1,
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
@ -451,8 +478,9 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
),
|
||||
Text(
|
||||
_quantityIndicator.toString(),
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.body2,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyText1,
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
@ -479,11 +507,12 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
child: Align(
|
||||
child: Text(
|
||||
formatStringCurrency(
|
||||
total: (double.parse(_product.price) *
|
||||
total: (parseWcPrice(_product.price) *
|
||||
_quantityIndicator)
|
||||
.toString()),
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.display1,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline4,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
alignment: Alignment.centerLeft,
|
||||
@ -492,9 +521,7 @@ class _ProductDetailState extends State<ProductDetailPage> {
|
||||
child: wsPrimaryButton(
|
||||
context,
|
||||
title: trans(context, "Add to cart"),
|
||||
action: () {
|
||||
_addItemToCart();
|
||||
},
|
||||
action: () => _addItemToCart(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@ -50,13 +50,15 @@ class _ProductImageViewerPageState extends State<ProductImageViewerPage> {
|
||||
index: _initialIndex,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return CachedNetworkImage(
|
||||
imageUrl: _arrImageSrc[index],
|
||||
placeholder: (context, url) =>
|
||||
new CircularProgressIndicator(
|
||||
strokeWidth: 2, backgroundColor: Colors.black12),
|
||||
errorWidget: (context, url, error) =>
|
||||
new Icon(Icons.error),
|
||||
fit: BoxFit.contain);
|
||||
imageUrl: _arrImageSrc[index],
|
||||
placeholder: (context, url) =>
|
||||
new CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
backgroundColor: Colors.black12,
|
||||
),
|
||||
errorWidget: (context, url, error) => new Icon(Icons.error),
|
||||
fit: BoxFit.contain,
|
||||
);
|
||||
},
|
||||
itemCount: _arrImageSrc.length,
|
||||
viewportFraction: 0.9,
|
||||
|
||||
51
LabelStoreMax/lib/providers/cash_on_delivery.dart
Normal file
51
LabelStoreMax/lib/providers/cash_on_delivery.dart
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// LabelCore
|
||||
// Label StoreMAX
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2020, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:label_storemax/helpers/data/order_wc.dart';
|
||||
import 'package:label_storemax/helpers/tools.dart';
|
||||
import 'package:label_storemax/models/cart.dart';
|
||||
import 'package:label_storemax/pages/checkout_confirmation.dart';
|
||||
import 'package:woosignal/models/payload/order_wc.dart';
|
||||
import 'package:woosignal/models/response/order.dart';
|
||||
import 'package:woosignal/models/response/tax_rate.dart';
|
||||
|
||||
cashOnDeliveryPay(context,
|
||||
{@required CheckoutConfirmationPageState state, TaxRate taxRate}) async {
|
||||
try {
|
||||
OrderWC orderWC = await buildOrderWC(taxRate: taxRate, markPaid: false);
|
||||
|
||||
Order order = await appWooSignal((api) => api.createOrder(orderWC));
|
||||
|
||||
if (order != null) {
|
||||
Cart.getInstance.clear();
|
||||
Navigator.pushNamed(context, "/checkout-status", arguments: order);
|
||||
} else {
|
||||
showEdgeAlertWith(
|
||||
context,
|
||||
title: trans(context, "Error"),
|
||||
desc: trans(context,
|
||||
trans(context, "Something went wrong, please contact our store")),
|
||||
);
|
||||
state.reloadState(showLoader: false);
|
||||
}
|
||||
} catch (ex) {
|
||||
showEdgeAlertWith(
|
||||
context,
|
||||
title: trans(context, "Error"),
|
||||
desc: trans(context,
|
||||
trans(context, "Something went wrong, please contact our store")),
|
||||
);
|
||||
state.reloadState(showLoader: false);
|
||||
}
|
||||
}
|
||||
62
LabelStoreMax/lib/providers/example_pay.dart
Normal file
62
LabelStoreMax/lib/providers/example_pay.dart
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// LabelCore
|
||||
// Label StoreMAX
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2020, WooSignal Ltd. All rights reserved.
|
||||
//
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:label_storemax/helpers/data/order_wc.dart';
|
||||
import 'package:label_storemax/helpers/tools.dart';
|
||||
import 'package:label_storemax/models/cart.dart';
|
||||
import 'package:label_storemax/pages/checkout_confirmation.dart';
|
||||
import 'package:woosignal/models/payload/order_wc.dart';
|
||||
import 'package:woosignal/models/response/order.dart';
|
||||
import 'package:woosignal/models/response/tax_rate.dart';
|
||||
|
||||
// CALL THE BELOW METHOD TO SHOW AND HIDE LOADER
|
||||
// state.reloadState(showLoader: false);
|
||||
|
||||
// CHECKOUT HELPER
|
||||
// IT WILL RETURN THE ORDER TOTAL, BILLING DETAILS AND CART
|
||||
// await checkout(taxRate, (total, billingDetails, cart) async {
|
||||
//
|
||||
// });
|
||||
|
||||
// REMEMBER TO ADD THIS METHOD E.G. "examplePay" TO THE APP_PAYMENT_METHODS
|
||||
// AS THE PAY METHOD
|
||||
|
||||
examplePay(context,
|
||||
{@required CheckoutConfirmationPageState state, TaxRate taxRate}) async {
|
||||
// HANDLE YOUR PAYMENT INTEGRATION HERE
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
// THEN ON SUCCESS OF A PAYMENT YOU CAN DO SOMETHING SIMILAR BELOW
|
||||
|
||||
// CREATES ORDER MODEL
|
||||
OrderWC orderWC = await buildOrderWC(taxRate: taxRate, markPaid: true);
|
||||
|
||||
// CREATES ORDER IN WOOCOMMERCE
|
||||
Order order = await appWooSignal((api) => api.createOrder(orderWC));
|
||||
|
||||
// CHECK IF ORDER IS NULL
|
||||
if (order != null) {
|
||||
Cart.getInstance.clear();
|
||||
Navigator.pushNamed(context, "/checkout-status", arguments: order);
|
||||
} else {
|
||||
showEdgeAlertWith(
|
||||
context,
|
||||
title: trans(context, "Error"),
|
||||
desc: trans(context,
|
||||
trans(context, "Something went wrong, please contact our store")),
|
||||
);
|
||||
state.reloadState(showLoader: false);
|
||||
}
|
||||
}
|
||||
@ -25,87 +25,94 @@ import 'package:woosignal_stripe/woosignal_stripe.dart';
|
||||
|
||||
stripePay(context,
|
||||
{@required CheckoutConfirmationPageState state, TaxRate taxRate}) async {
|
||||
// CONFIGURE STRIPE
|
||||
FlutterStripePayment.setStripeSettings(
|
||||
stripeAccount: app_stripe_account, liveMode: app_stripe_live_mode);
|
||||
try {
|
||||
// CONFIGURE STRIPE
|
||||
FlutterStripePayment.setStripeSettings(
|
||||
stripeAccount: app_stripe_account, liveMode: app_stripe_live_mode);
|
||||
|
||||
var paymentResponse = await FlutterStripePayment.addPaymentMethod();
|
||||
var paymentResponse = await FlutterStripePayment.addPaymentMethod();
|
||||
|
||||
// CHECK STATUS FROM STRIPE
|
||||
if (paymentResponse.status == PaymentResponseStatus.succeeded) {
|
||||
state.reloadState(showLoader: true);
|
||||
// CHECK STATUS FROM STRIPE
|
||||
if (paymentResponse.status == PaymentResponseStatus.succeeded) {
|
||||
state.reloadState(showLoader: true);
|
||||
|
||||
// CHECKOUT HELPER
|
||||
await checkout(taxRate, (total, billingDetails, cart) async {
|
||||
Map<String, dynamic> address = {
|
||||
"name": billingDetails.billingAddress.nameFull(),
|
||||
"line1": billingDetails.shippingAddress.addressLine,
|
||||
"city": billingDetails.shippingAddress.city,
|
||||
"postal_code": billingDetails.shippingAddress.postalCode,
|
||||
"country": billingDetails.shippingAddress.country
|
||||
};
|
||||
// CHECKOUT HELPER
|
||||
await checkout(taxRate, (total, billingDetails, cart) async {
|
||||
Map<String, dynamic> address = {
|
||||
"name": billingDetails.billingAddress.nameFull(),
|
||||
"line1": billingDetails.shippingAddress.addressLine,
|
||||
"city": billingDetails.shippingAddress.city,
|
||||
"postal_code": billingDetails.shippingAddress.postalCode,
|
||||
"country": billingDetails.shippingAddress.country
|
||||
};
|
||||
|
||||
String cartShortDesc = await cart.cartShortDesc();
|
||||
String cartShortDesc = await cart.cartShortDesc();
|
||||
|
||||
dynamic rsp = await appWooSignal((api) {
|
||||
return api.stripePaymentIntent(
|
||||
amount: total,
|
||||
email: billingDetails.billingAddress.emailAddress,
|
||||
desc: cartShortDesc,
|
||||
shipping: address,
|
||||
dynamic rsp = await appWooSignal((api) => api.stripePaymentIntent(
|
||||
amount: total,
|
||||
email: billingDetails.billingAddress.emailAddress,
|
||||
desc: cartShortDesc,
|
||||
shipping: address,
|
||||
));
|
||||
|
||||
if (rsp == null) {
|
||||
showEdgeAlertWith(context,
|
||||
title: trans(context, "Oops!"),
|
||||
desc: trans(context, "Something went wrong, please try again."),
|
||||
icon: Icons.payment,
|
||||
style: EdgeAlertStyle.WARNING);
|
||||
state.reloadState(showLoader: false);
|
||||
return;
|
||||
}
|
||||
|
||||
String clientSecret = rsp["client_secret"];
|
||||
var intentResponse = await FlutterStripePayment.confirmPaymentIntent(
|
||||
clientSecret,
|
||||
paymentResponse.paymentMethodId,
|
||||
(double.parse(total) * 100),
|
||||
);
|
||||
});
|
||||
|
||||
if (rsp == null) {
|
||||
showEdgeAlertWith(context,
|
||||
title: trans(context, "Oops!"),
|
||||
desc: trans(context, "Something went wrong, please try again."),
|
||||
icon: Icons.payment,
|
||||
style: EdgeAlertStyle.WARNING);
|
||||
state.reloadState(showLoader: false);
|
||||
return;
|
||||
}
|
||||
if (intentResponse.status == PaymentResponseStatus.succeeded) {
|
||||
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
|
||||
Order order = await appWooSignal((api) => api.createOrder(orderWC));
|
||||
|
||||
String clientSecret = rsp["client_secret"];
|
||||
var intentResponse = await FlutterStripePayment.confirmPaymentIntent(
|
||||
clientSecret,
|
||||
paymentResponse.paymentMethodId,
|
||||
(double.parse(total) * 100),
|
||||
);
|
||||
|
||||
if (intentResponse.status == PaymentResponseStatus.succeeded) {
|
||||
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
|
||||
Order order = await appWooSignal((api) {
|
||||
return api.createOrder(orderWC);
|
||||
});
|
||||
|
||||
if (order != null) {
|
||||
Cart.getInstance.clear();
|
||||
Navigator.pushNamed(context, "/checkout-status", arguments: order);
|
||||
} else {
|
||||
if (order != null) {
|
||||
Cart.getInstance.clear();
|
||||
Navigator.pushNamed(context, "/checkout-status", arguments: order);
|
||||
} else {
|
||||
showEdgeAlertWith(
|
||||
context,
|
||||
title: trans(context, "Error"),
|
||||
desc: trans(
|
||||
context,
|
||||
trans(context,
|
||||
"Something went wrong, please contact our store")),
|
||||
);
|
||||
state.reloadState(showLoader: false);
|
||||
}
|
||||
} else if (intentResponse.status == PaymentResponseStatus.failed) {
|
||||
if (app_debug) {
|
||||
print(intentResponse.errorMessage);
|
||||
}
|
||||
showEdgeAlertWith(
|
||||
context,
|
||||
title: trans(context, "Error"),
|
||||
desc: trans(
|
||||
context,
|
||||
trans(
|
||||
context, "Something went wrong, please contact our store")),
|
||||
desc: intentResponse.errorMessage,
|
||||
);
|
||||
state.reloadState(showLoader: false);
|
||||
} else {
|
||||
state.reloadState(showLoader: false);
|
||||
}
|
||||
} else if (intentResponse.status == PaymentResponseStatus.failed) {
|
||||
if (app_debug) {
|
||||
print(intentResponse.errorMessage);
|
||||
}
|
||||
showEdgeAlertWith(
|
||||
context,
|
||||
title: trans(context, "Error"),
|
||||
desc: intentResponse.errorMessage,
|
||||
);
|
||||
state.reloadState(showLoader: false);
|
||||
} else {
|
||||
state.reloadState(showLoader: false);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
state.reloadState(showLoader: false);
|
||||
}
|
||||
} catch (ex) {
|
||||
showEdgeAlertWith(context,
|
||||
title: trans(context, "Oops!"),
|
||||
desc: trans(context, "Something went wrong, please try again."),
|
||||
icon: Icons.payment,
|
||||
style: EdgeAlertStyle.WARNING);
|
||||
state.reloadState(showLoader: false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ Widget wsSecondaryButton(BuildContext context,
|
||||
child: RaisedButton(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Text(title,
|
||||
style: Theme.of(context).primaryTextTheme.body2,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1,
|
||||
textAlign: TextAlign.center),
|
||||
onPressed: action,
|
||||
color: HexColor("#f6f6f9"),
|
||||
@ -54,7 +54,7 @@ Widget wsLinkButton(BuildContext context,
|
||||
child: MaterialButton(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Text(title,
|
||||
style: Theme.of(context).primaryTextTheme.body2,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1,
|
||||
textAlign: TextAlign.left),
|
||||
onPressed: action,
|
||||
elevation: 0,
|
||||
|
||||
@ -12,44 +12,48 @@ import 'package:flutter/material.dart';
|
||||
import 'package:label_storemax/models/cart.dart';
|
||||
import 'package:label_storemax/models/cart_line_item.dart';
|
||||
|
||||
Widget wsCartIcon(BuildContext context) {
|
||||
return IconButton(
|
||||
icon: Stack(
|
||||
children: <Widget>[
|
||||
Positioned.fill(
|
||||
child: Align(
|
||||
child: Icon(Icons.shopping_cart, size: 20, color: Colors.black87),
|
||||
alignment: Alignment.bottomCenter,
|
||||
),
|
||||
bottom: 0),
|
||||
Positioned.fill(
|
||||
child: Align(
|
||||
child: FutureBuilder<List<CartLineItem>>(
|
||||
future: Cart.getInstance.getCart(),
|
||||
builder: (BuildContext context,
|
||||
AsyncSnapshot<List<CartLineItem>> snapshot) {
|
||||
switch (snapshot.connectionState) {
|
||||
case ConnectionState.waiting:
|
||||
return Text("");
|
||||
default:
|
||||
if (snapshot.hasError)
|
||||
return Text("");
|
||||
else
|
||||
return new Text(
|
||||
snapshot.data.length.toString(),
|
||||
style: Theme.of(context).primaryTextTheme.body2,
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
}
|
||||
},
|
||||
Widget wsCartIcon(BuildContext context, {Key key}) {
|
||||
return StatefulBuilder(
|
||||
key: key,
|
||||
builder: (BuildContext context, StateSetter setState) => IconButton(
|
||||
icon: Stack(
|
||||
children: <Widget>[
|
||||
Positioned.fill(
|
||||
child: Align(
|
||||
child:
|
||||
Icon(Icons.shopping_cart, size: 20, color: Colors.black87),
|
||||
alignment: Alignment.bottomCenter,
|
||||
),
|
||||
alignment: Alignment.topCenter,
|
||||
),
|
||||
top: 0)
|
||||
],
|
||||
bottom: 0),
|
||||
Positioned.fill(
|
||||
child: Align(
|
||||
child: FutureBuilder<List<CartLineItem>>(
|
||||
future: Cart.getInstance.getCart(),
|
||||
builder: (BuildContext context,
|
||||
AsyncSnapshot<List<CartLineItem>> snapshot) {
|
||||
switch (snapshot.connectionState) {
|
||||
case ConnectionState.waiting:
|
||||
return Text("");
|
||||
default:
|
||||
if (snapshot.hasError)
|
||||
return Text("");
|
||||
else
|
||||
return new Text(
|
||||
snapshot.data.length.toString(),
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1,
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
alignment: Alignment.topCenter,
|
||||
),
|
||||
top: 0)
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, "/cart");
|
||||
},
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(context, "/cart");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ Widget wsMenuItem(BuildContext context,
|
||||
children: <Widget>[
|
||||
leading,
|
||||
Text(" " + title,
|
||||
style: Theme.of(context).primaryTextTheme.body1),
|
||||
style: Theme.of(context).primaryTextTheme.bodyText2),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@ -28,7 +28,7 @@ Widget wsRow2Text(BuildContext context, {String text1, String text2}) {
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: Container(
|
||||
child: Text(text1, style: Theme.of(context).textTheme.title),
|
||||
child: Text(text1, style: Theme.of(context).textTheme.headline6),
|
||||
),
|
||||
flex: 3,
|
||||
),
|
||||
@ -37,7 +37,7 @@ Widget wsRow2Text(BuildContext context, {String text1, String text2}) {
|
||||
child: Text(text2,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.body2
|
||||
.bodyText1
|
||||
.copyWith(fontSize: 16, color: Colors.black87)),
|
||||
),
|
||||
flex: 3,
|
||||
@ -50,7 +50,7 @@ Widget wsNoResults(BuildContext context) {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Text(trans(context, "No results"),
|
||||
style: Theme.of(context).primaryTextTheme.body1),
|
||||
style: Theme.of(context).primaryTextTheme.bodyText2),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -70,7 +70,10 @@ Widget wsCheckoutRow(BuildContext context,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
child: Text(heading,
|
||||
style: Theme.of(context).primaryTextTheme.body1),
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyText2
|
||||
.copyWith(fontSize: 16)),
|
||||
padding: EdgeInsets.only(bottom: 8),
|
||||
),
|
||||
Flexible(
|
||||
@ -87,8 +90,9 @@ Widget wsCheckoutRow(BuildContext context,
|
||||
Flexible(
|
||||
child: Container(
|
||||
child: Text(leadTitle,
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.subtitle1,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: false),
|
||||
@ -131,15 +135,15 @@ Widget wsTextEditingRow(BuildContext context,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: Padding(
|
||||
child:
|
||||
Text(heading, style: Theme.of(context).primaryTextTheme.body2),
|
||||
child: Text(heading,
|
||||
style: Theme.of(context).primaryTextTheme.bodyText1),
|
||||
padding: EdgeInsets.only(bottom: 2),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TextField(
|
||||
controller: controller,
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1,
|
||||
keyboardType: keyboardType ?? TextInputType.text,
|
||||
autocorrect: false,
|
||||
autofocus: shouldAutoFocus ?? false,
|
||||
@ -160,13 +164,15 @@ Widget widgetCheckoutMeta(BuildContext context, {String title, String amount}) {
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: Container(
|
||||
child: Text(title, style: Theme.of(context).primaryTextTheme.body1),
|
||||
child:
|
||||
Text(title, style: Theme.of(context).primaryTextTheme.bodyText2),
|
||||
),
|
||||
flex: 3,
|
||||
),
|
||||
Flexible(
|
||||
child: Container(
|
||||
child: Text(amount, style: Theme.of(context).primaryTextTheme.body2),
|
||||
child:
|
||||
Text(amount, style: Theme.of(context).primaryTextTheme.bodyText1),
|
||||
),
|
||||
flex: 3,
|
||||
)
|
||||
@ -188,51 +194,68 @@ List<BoxShadow> wsBoxShadow({double blurRadius}) {
|
||||
];
|
||||
}
|
||||
|
||||
Widget wsCardProductItem(BuildContext context, {int index, Product product}) {
|
||||
Widget wsCardProductItem(BuildContext context,
|
||||
{int index, Product product, onTap}) {
|
||||
return InkWell(
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: (product.images.length > 0
|
||||
? product.images.first.src
|
||||
: ""),
|
||||
placeholder: (context, url) =>
|
||||
new CircularProgressIndicator(),
|
||||
errorWidget: (context, url, error) => new Icon(Icons.error),
|
||||
fit: BoxFit.fitWidth),
|
||||
flex: 4,
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
boxShadow: wsBoxShadow(blurRadius: 4),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
child: CachedNetworkImage(
|
||||
imageUrl:
|
||||
(product.images.length > 0 ? product.images.first.src : ""),
|
||||
placeholder: (context, url) => new CircularProgressIndicator(),
|
||||
errorWidget: (context, url, error) => new Icon(Icons.error),
|
||||
fit: BoxFit.contain),
|
||||
flex: 4,
|
||||
),
|
||||
Flexible(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
formatStringCurrency(total: product.price),
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
(product.onSale
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
child: Text(
|
||||
formatStringCurrency(total: product.regularPrice),
|
||||
style: Theme.of(context).textTheme.bodyText1.copyWith(
|
||||
decoration: TextDecoration.lineThrough,
|
||||
color: Colors.grey),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
)
|
||||
: null),
|
||||
].where((t) => t != null).toList(),
|
||||
),
|
||||
Flexible(
|
||||
child: Text(
|
||||
formatStringCurrency(total: product.price),
|
||||
style: Theme.of(context).textTheme.body2,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
flex: 1,
|
||||
flex: 1,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
product.name,
|
||||
style: Theme.of(context).textTheme.bodyText2,
|
||||
overflow: TextOverflow.clip,
|
||||
maxLines: 1,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
product.name,
|
||||
style: Theme.of(context).textTheme.body1,
|
||||
overflow: TextOverflow.clip,
|
||||
maxLines: 1,
|
||||
),
|
||||
flex: 1,
|
||||
)
|
||||
],
|
||||
)),
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, "/product-detail", arguments: product);
|
||||
},
|
||||
flex: 1,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () => onTap(product),
|
||||
);
|
||||
}
|
||||
|
||||
@ -245,27 +268,41 @@ void wsModalBottom(BuildContext context,
|
||||
return SafeArea(
|
||||
child: Container(
|
||||
height: double.infinity,
|
||||
width: double.infinity - 10,
|
||||
width: double.infinity,
|
||||
color: Colors.transparent,
|
||||
child: new Container(
|
||||
padding: EdgeInsets.only(top: 25, left: 18, right: 18),
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: new BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: new BorderRadius.only(
|
||||
topLeft: const Radius.circular(10.0),
|
||||
topRight: const Radius.circular(10.0)),
|
||||
topLeft: const Radius.circular(10.0),
|
||||
topRight: const Radius.circular(10.0),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Text(title,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.display1
|
||||
.copyWith(fontSize: 20),
|
||||
textAlign: TextAlign.left),
|
||||
bodyWidget,
|
||||
extraWidget ?? Container()
|
||||
],
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
child: Text(title,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline4
|
||||
.copyWith(fontSize: 20),
|
||||
textAlign: TextAlign.left),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: wsBoxShadow(),
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8)),
|
||||
child: bodyWidget),
|
||||
),
|
||||
extraWidget ?? null
|
||||
].where((t) => t != null).toList(),
|
||||
)),
|
||||
),
|
||||
);
|
||||
@ -431,13 +468,14 @@ Widget wsCardCartItem(BuildContext context,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
cartLineItem.name,
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style: Theme.of(context).primaryTextTheme.subtitle1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 3,
|
||||
),
|
||||
(cartLineItem.variationOptions != null
|
||||
? Text(cartLineItem.variationOptions,
|
||||
style: Theme.of(context).primaryTextTheme.body2)
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.bodyText1)
|
||||
: Container()),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
@ -449,11 +487,14 @@ Widget wsCardCartItem(BuildContext context,
|
||||
: trans(context, "In Stock")),
|
||||
style: (cartLineItem.stockStatus == "outofstock"
|
||||
? Theme.of(context).textTheme.caption
|
||||
: Theme.of(context).primaryTextTheme.body1)),
|
||||
: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyText2)),
|
||||
Text(
|
||||
formatDoubleCurrency(
|
||||
total: double.parse(cartLineItem.total)),
|
||||
style: Theme.of(context).primaryTextTheme.subhead,
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.subtitle1,
|
||||
textAlign: TextAlign.center)
|
||||
],
|
||||
),
|
||||
@ -479,7 +520,7 @@ Widget wsCardCartItem(BuildContext context,
|
||||
highlightColor: Colors.transparent,
|
||||
),
|
||||
Text(cartLineItem.quantity.toString(),
|
||||
style: Theme.of(context).primaryTextTheme.title),
|
||||
style: Theme.of(context).primaryTextTheme.headline6),
|
||||
IconButton(
|
||||
icon: Icon(Icons.remove_circle_outline),
|
||||
onPressed: actionDecrementQuantity,
|
||||
|
||||
@ -7,35 +7,28 @@ packages:
|
||||
name: archive
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.11"
|
||||
version: "2.0.13"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.2"
|
||||
version: "1.6.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
version: "2.4.1"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
braintree_payment:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: braintree_payment
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.4"
|
||||
version: "2.0.0"
|
||||
bubble_tab_indicator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -56,7 +49,7 @@ packages:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
version: "1.1.3"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -70,7 +63,7 @@ packages:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.14.11"
|
||||
version: "1.14.12"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -84,7 +77,7 @@ packages:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.1.4"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -237,7 +230,7 @@ packages:
|
||||
name: image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.1.12"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -350,13 +343,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
pull_to_refresh:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: pull_to_refresh
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.8"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
version: "2.1.3"
|
||||
rxdart:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -403,7 +403,7 @@ packages:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.5"
|
||||
version: "1.7.0"
|
||||
sqflite:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -466,7 +466,7 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.11"
|
||||
version: "0.2.15"
|
||||
transformer_page_view:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -529,7 +529,7 @@ packages:
|
||||
name: woosignal
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.6"
|
||||
version: "1.0.8"
|
||||
woosignal_stripe:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -550,7 +550,7 @@ packages:
|
||||
name: xml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.5.0"
|
||||
version: "3.6.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# Label StoreMax
|
||||
# Version 2.0.0
|
||||
# Version 2.0.2
|
||||
#authors: - "Anthony Gordon"
|
||||
#documentation: https://woosignal.com/docs/app/ios/label-storemax
|
||||
#homepage: https://woosignal.com/
|
||||
@ -23,7 +23,7 @@ environment:
|
||||
sdk: ">=2.1.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
woosignal: ^1.0.6
|
||||
woosignal: ^1.0.8
|
||||
woosignal_stripe: ^0.0.4
|
||||
wp_json_api: ^0.1.2
|
||||
shared_preferences: ^0.5.6+3
|
||||
@ -34,6 +34,7 @@ dependencies:
|
||||
flutter_money_formatter: ^0.8.3
|
||||
platform_alert_dialog: ^1.0.0+2
|
||||
flutter_web_browser: ^0.11.0
|
||||
pull_to_refresh: ^1.5.8
|
||||
dio: ^3.0.9
|
||||
intl: ^0.16.1
|
||||
flutter_swiper: ^1.1.6
|
||||
@ -44,7 +45,6 @@ dependencies:
|
||||
flutter_spinkit: ^4.1.2+1
|
||||
flutter_launcher_icons: ^0.7.4
|
||||
html: ^0.14.0+3
|
||||
braintree_payment: ^1.2.4
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
@ -75,7 +75,7 @@ flutter:
|
||||
- assets/images/credit_cards.png
|
||||
- assets/images/shipping_icon.png
|
||||
- assets/images/dark_powered_by_stripe.png
|
||||
- assets/images/cart_empty.png
|
||||
- assets/images/cash_on_delivery.jpeg
|
||||
- lang/en.json
|
||||
|
||||
fonts:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user