diff --git a/LabelStoreMax/.flutter-plugins-dependencies b/LabelStoreMax/.flutter-plugins-dependencies index 53b0b37..739145f 100644 --- a/LabelStoreMax/.flutter-plugins-dependencies +++ b/LabelStoreMax/.flutter-plugins-dependencies @@ -1 +1 @@ -{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"device_info","dependencies":[]},{"name":"flutter_money_formatter","dependencies":[]},{"name":"flutter_web_browser","dependencies":[]},{"name":"package_info","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]},{"name":"woosignal_stripe","dependencies":[]}]} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"braintree_payment","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/braintree_payment-1.2.4/","dependencies":[]},{"name":"device_info","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-0.4.2+1/","dependencies":[]},{"name":"flutter_money_formatter","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_money_formatter-0.8.3/","dependencies":[]},{"name":"flutter_web_browser","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_web_browser-0.11.0/","dependencies":[]},{"name":"package_info","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/package_info-0.4.0+16/","dependencies":[]},{"name":"path_provider","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.3.0/","dependencies":[]},{"name":"shared_preferences","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.6+3/","dependencies":[]},{"name":"sqflite","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.1.6+5/","dependencies":[]},{"name":"url_launcher","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.5/","dependencies":[]},{"name":"woosignal_stripe","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/woosignal_stripe-0.0.4/","dependencies":[]}],"android":[{"name":"braintree_payment","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/braintree_payment-1.2.4/","dependencies":[]},{"name":"device_info","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/device_info-0.4.2+1/","dependencies":[]},{"name":"flutter_money_formatter","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_money_formatter-0.8.3/","dependencies":[]},{"name":"flutter_web_browser","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_web_browser-0.11.0/","dependencies":[]},{"name":"package_info","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/package_info-0.4.0+16/","dependencies":[]},{"name":"path_provider","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.3.0/","dependencies":[]},{"name":"shared_preferences","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.6+3/","dependencies":[]},{"name":"sqflite","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.1.6+5/","dependencies":[]},{"name":"url_launcher","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.5/","dependencies":[]},{"name":"woosignal_stripe","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/woosignal_stripe-0.0.4/","dependencies":[]}],"macos":[{"name":"shared_preferences_macos","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_macos-0.0.1+6/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+5/","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_web-0.1.2+4/","dependencies":[]},{"name":"url_launcher_web","path":"/Users/anthony/Documents/config/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.1+2/","dependencies":[]}]},"dependencyGraph":[{"name":"braintree_payment","dependencies":[]},{"name":"device_info","dependencies":[]},{"name":"flutter_money_formatter","dependencies":[]},{"name":"flutter_web_browser","dependencies":[]},{"name":"package_info","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"woosignal_stripe","dependencies":[]}],"date_created":"2020-04-30 21:50:05.674145","version":"1.15.17"} \ No newline at end of file diff --git a/LabelStoreMax/CHANGELOG.md b/LabelStoreMax/CHANGELOG.md index 7412433..04f2b16 100644 --- a/LabelStoreMax/CHANGELOG.md +++ b/LabelStoreMax/CHANGELOG.md @@ -1,3 +1,11 @@ +## [2.0.1] - 2020-04-30 + +* Login/register with WordPress +* Updated product view +* New account area +* pubspec.yaml update +* Bug fixes + ## [2.0.0] - 2020-04-10 * Flutter v1.12.13+hotfix.9 support diff --git a/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj b/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj index 109ea9b..0611d1c 100644 --- a/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj +++ b/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj @@ -263,9 +263,40 @@ files = ( ); 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", + "${BUILT_PRODUCTS_DIR}/device_info/device_info.framework", + "${BUILT_PRODUCTS_DIR}/flutter_money_formatter/flutter_money_formatter.framework", + "${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", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", + "${BUILT_PRODUCTS_DIR}/woosignal_stripe/woosignal_stripe.framework", ); 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", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_money_formatter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_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}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/woosignal_stripe.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/LabelStoreMax/ios/Runner/AppDelegate.swift b/LabelStoreMax/ios/Runner/AppDelegate.swift index 70693e4..349cce6 100644 --- a/LabelStoreMax/ios/Runner/AppDelegate.swift +++ b/LabelStoreMax/ios/Runner/AppDelegate.swift @@ -1,8 +1,10 @@ import UIKit import Flutter +import Braintree @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { + override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? @@ -10,4 +12,5 @@ import Flutter GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + } diff --git a/LabelStoreMax/ios/Runner/Runner-Bridging-Header.h b/LabelStoreMax/ios/Runner/Runner-Bridging-Header.h index 7335fdf..308a2a5 100644 --- a/LabelStoreMax/ios/Runner/Runner-Bridging-Header.h +++ b/LabelStoreMax/ios/Runner/Runner-Bridging-Header.h @@ -1 +1 @@ -#import "GeneratedPluginRegistrant.h" \ No newline at end of file +#import "GeneratedPluginRegistrant.h" diff --git a/LabelStoreMax/lang/en.json b/LabelStoreMax/lang/en.json index d2dc0a2..079703c 100644 --- a/LabelStoreMax/lang/en.json +++ b/LabelStoreMax/lang/en.json @@ -92,5 +92,42 @@ "Product variation does not exist": "Product variation does not exist", "This variation is unavailable": "This variation is unavailable", "Sorry, something went wrong": "Sorry, something went wrong", - "Back": "Back" + "Back": "Back", + "Profile": "Profile", + "Forgot Password": "Forgot Password", + "Create an account": "Create an account", + "Login": "Login", + "Password": "Password", + "Oops!": "Oops!", + "Invalid login credentials": "Invalid login credentials", + "That email address is not valid": "That email address is not valid", + "Password must be a min 6 characters": "Password must be a min 6 characters", + "Please check your details": "Please check your details", + "Invalid": "Invalid", + "Actions": "Actions", + "View Terms and Conditions or Privacy policy": "View Terms and Conditions or Privacy policy", + "Terms and Conditions": "Terms and Conditions", + "Privacy Policy": "Privacy Policy", + "terms and conditions": "terms and conditions", + "and": "and", + "By tapping \"Register\" you agree to ": "By tapping \"Register\" you agree to ", + "privacy policy": "privacy policy", + "Sign up": "Sign up", + "Email": "Email", + "Update details": "Update details", + "Settings": "Settings", + "Account": "Account", + "Logout": "Logout", + "No orders found": "No orders found", + "items": "items", + "Update Details": "Update Details", + "Invalid details": "Invalid details", + "Please check your email and password": "Please check your email and password", + "Something went wrong, please try again.": "Something went wrong, please try again.", + "Done": "Done", + "Billing Details": "Billing Details", + "Shipping Details": "Shipping Details", + "State": "State", + "Country": "Country", + "UPDATE DETAILS": "UPDATE DETAILS" } \ No newline at end of file diff --git a/LabelStoreMax/lib/app_country_options.dart b/LabelStoreMax/lib/app_country_options.dart index 4d3c54b..ca7803b 100644 --- a/LabelStoreMax/lib/app_country_options.dart +++ b/LabelStoreMax/lib/app_country_options.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/app_payment_methods.dart b/LabelStoreMax/lib/app_payment_methods.dart index 15adf97..fc0d964 100644 --- a/LabelStoreMax/lib/app_payment_methods.dart +++ b/LabelStoreMax/lib/app_payment_methods.dart @@ -1,9 +1,18 @@ +// 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:label_storemax/helpers/tools.dart'; import 'package:label_storemax/models/payment_type.dart'; import 'package:label_storemax/providers/stripe_pay.dart'; // Payment methods available for uses in the app -// To use use a payment method, include the PaymentType "name" in the app_payment_methods variable in #labelconfig.dart List arrPaymentMethods = [ addPayment( diff --git a/LabelStoreMax/lib/helpers/app_localizations.dart b/LabelStoreMax/lib/helpers/app_localizations.dart index 44c8ce3..9fdbc98 100644 --- a/LabelStoreMax/lib/helpers/app_localizations.dart +++ b/LabelStoreMax/lib/helpers/app_localizations.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/helpers/app_themes.dart b/LabelStoreMax/lib/helpers/app_themes.dart index 9f251ca..bab11c3 100644 --- a/LabelStoreMax/lib/helpers/app_themes.dart +++ b/LabelStoreMax/lib/helpers/app_themes.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -151,17 +151,18 @@ TextTheme textThemeAppBar() { ColorScheme colorSchemeButton() { return ColorScheme.light( - primary: const Color(0xff6200ee), - primaryVariant: const Color(0xff3700b3), - secondary: const Color(0xff03dac6), - secondaryVariant: const Color(0xff018786), - surface: Colors.white, - background: Colors.white, - error: const Color(0xffb00020), - onPrimary: Colors.white, - onSecondary: Colors.black, - onSurface: Colors.black, - onBackground: Colors.black, - onError: Colors.white, - brightness: Brightness.light); + primary: const Color(0xff6200ee), + primaryVariant: const Color(0xff3700b3), + secondary: const Color(0xff03dac6), + secondaryVariant: const Color(0xff018786), + surface: Colors.white, + background: Colors.white, + error: const Color(0xffb00020), + onPrimary: Colors.white, + onSecondary: Colors.black, + onSurface: Colors.black, + onBackground: Colors.black, + onError: Colors.white, + brightness: Brightness.light, + ); } diff --git a/LabelStoreMax/lib/helpers/data/order_wc.dart b/LabelStoreMax/lib/helpers/data/order_wc.dart index d8e5c2b..b0a7162 100644 --- a/LabelStoreMax/lib/helpers/data/order_wc.dart +++ b/LabelStoreMax/lib/helpers/data/order_wc.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -10,6 +10,7 @@ import 'dart:io'; +import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart'; import 'package:label_storemax/labelconfig.dart'; import 'package:label_storemax/models/billing_details.dart'; import 'package:label_storemax/models/cart.dart'; @@ -32,6 +33,8 @@ Future buildOrderWC({TaxRate taxRate}) async { orderWC.setPaid = true; orderWC.status = "pending"; orderWC.currency = app_currency_iso.toUpperCase(); + orderWC.customerId = + (use_wp_login == true) ? int.parse(await readUserId()) : 0; List lineItems = []; List cartItems = await Cart.getInstance.getCart(); @@ -44,7 +47,8 @@ Future buildOrderWC({TaxRate taxRate}) async { tmpLineItem.variationId = cartItem.variationId; } - tmpLineItem.total = cartItem.total; + tmpLineItem.total = + (cartItem.quantity > 1 ? cartItem.getCartTotal() : cartItem.subtotal); tmpLineItem.subtotal = cartItem.subtotal; lineItems.add(tmpLineItem); diff --git a/LabelStoreMax/lib/helpers/lifecycle_event_handler.dart b/LabelStoreMax/lib/helpers/lifecycle_event_handler.dart deleted file mode 100644 index 7440893..0000000 --- a/LabelStoreMax/lib/helpers/lifecycle_event_handler.dart +++ /dev/null @@ -1,40 +0,0 @@ -// Label StoreMAX -// -// Created by Anthony Gordon. -// Copyright © 2020 WooSignal. 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/cupertino.dart'; -import 'package:flutter/foundation.dart'; - -class LifecycleEventHandler extends WidgetsBindingObserver { - final AsyncCallback resumeCallBack; - final AsyncCallback suspendingCallBack; - - LifecycleEventHandler({ - this.resumeCallBack, - this.suspendingCallBack, - }); - - @override - Future didChangeAppLifecycleState(AppLifecycleState state) async { - switch (state) { - case AppLifecycleState.resumed: - if (resumeCallBack != null) { - await resumeCallBack(); - } - break; - case AppLifecycleState.inactive: - case AppLifecycleState.paused: - case AppLifecycleState.detached: - if (suspendingCallBack != null) { - await suspendingCallBack(); - } - break; - } - } -} diff --git a/LabelStoreMax/lib/helpers/shared_pref.dart b/LabelStoreMax/lib/helpers/shared_pref.dart index f3a0cb2..131c980 100644 --- a/LabelStoreMax/lib/helpers/shared_pref.dart +++ b/LabelStoreMax/lib/helpers/shared_pref.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/helpers/shared_pref/sp_auth.dart b/LabelStoreMax/lib/helpers/shared_pref/sp_auth.dart new file mode 100644 index 0000000..e4df759 --- /dev/null +++ b/LabelStoreMax/lib/helpers/shared_pref/sp_auth.dart @@ -0,0 +1,42 @@ +// 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/cupertino.dart'; +import 'package:label_storemax/helpers/shared_pref.dart'; +import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:label_storemax/models/cart.dart'; + +const keyAuthCheck = "DEFAULT_SP_AUTHCHECK"; + +Future authCheck() async { + SharedPref sharedPref = SharedPref(); + String val = await sharedPref.read(keyAuthCheck); + return val != null ? true : false; +} + +authUser(String v) async { + SharedPref sharedPref = SharedPref(); + await sharedPref.save(keyAuthCheck, v); +} + +Future readAuthToken() async { + SharedPref sharedPref = SharedPref(); + dynamic val = await sharedPref.read(keyAuthCheck); + return val.toString(); +} + +authLogout(BuildContext context) async { + SharedPref sharedPref = SharedPref(); + await sharedPref.save(keyAuthCheck, null); + destroyUserId(context); + Cart.getInstance.clear(); + navigatorPush(context, routeName: "/account-landing", forgetAll: true); +} diff --git a/LabelStoreMax/lib/helpers/shared_pref/sp_user_id.dart b/LabelStoreMax/lib/helpers/shared_pref/sp_user_id.dart new file mode 100644 index 0000000..33a87bc --- /dev/null +++ b/LabelStoreMax/lib/helpers/shared_pref/sp_user_id.dart @@ -0,0 +1,30 @@ +// 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/cupertino.dart'; +import 'package:label_storemax/helpers/shared_pref.dart'; + +const keyUserId = "DEFAULT_SP_USERID"; + +storeUserId(String v) async { + SharedPref sharedPref = SharedPref(); + await sharedPref.save(keyUserId, v); +} + +Future readUserId() async { + SharedPref sharedPref = SharedPref(); + String val = await sharedPref.read(keyUserId); + return val; +} + +destroyUserId(BuildContext context) async { + SharedPref sharedPref = SharedPref(); + await sharedPref.save(keyUserId, null); +} diff --git a/LabelStoreMax/lib/helpers/tools.dart b/LabelStoreMax/lib/helpers/tools.dart index 30aedf1..105cddd 100644 --- a/LabelStoreMax/lib/helpers/tools.dart +++ b/LabelStoreMax/lib/helpers/tools.dart @@ -1,13 +1,14 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 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:intl/intl.dart'; import 'package:label_storemax/app_payment_methods.dart'; import 'package:label_storemax/helpers/app_localizations.dart'; import 'package:flutter/material.dart'; @@ -22,6 +23,7 @@ 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:math_expressions/math_expressions.dart'; +import 'package:platform_alert_dialog/platform_alert_dialog.dart'; import 'package:status_alert/status_alert.dart'; import 'package:woosignal/models/response/tax_rate.dart'; import 'package:woosignal/woosignal.dart'; @@ -52,12 +54,6 @@ class HexColor extends Color { HexColor(final String hexColor) : super(_getColorFromHex(hexColor)); } -String truncateWithEllipsis(int cutoff, String myString) { - return (myString.length <= cutoff) - ? myString - : '${myString.substring(0, cutoff)}...'; -} - showStatusAlert(context, {@required String title, String subtitle, IconData icon, int duration}) { StatusAlert.show( @@ -141,7 +137,7 @@ String formatDoubleCurrency({double total}) { return fmf.output.symbolOnLeft; } -String formatStringCurrency({String total}) { +String formatStringCurrency({@required String total}) { double tmpVal; if (total == null || total == "") { tmpVal = 0; @@ -345,3 +341,112 @@ RegExp defaultRegex( multiLine: false, ); } + +bool isEmail(String em) { + String p = + r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'; + RegExp regExp = new RegExp(p); + return regExp.hasMatch(em); +} + +// 6 LENGTH, 1 DIGIT +bool validPassword(String pw) { + String p = r'^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,}$'; + RegExp regExp = new RegExp(p); + return regExp.hasMatch(pw); +} + +navigatorPush(BuildContext context, + {@required String routeName, Object arguments, bool forgetAll = false}) { + if (forgetAll) { + Navigator.of(context).pushNamedAndRemoveUntil( + routeName, (Route route) => false, + arguments: arguments ?? null); + } else { + Navigator.of(context).pushNamed(routeName, arguments: arguments ?? null); + } +} + +PlatformDialogAction dialogAction(BuildContext context, + {@required title, ActionType actionType, Function() action}) { + return PlatformDialogAction( + actionType: actionType ?? ActionType.Default, + child: Text(title ?? ""), + onPressed: action ?? + () { + Navigator.of(context).pop(); + }, + ); +} + +showPlatformAlertDialog(BuildContext context, + {String title, + String subtitle, + List actions, + bool showDoneAction = true}) { + if (showDoneAction) { + actions + .add(dialogAction(context, title: trans(context, "Done"), action: () { + Navigator.of(context).pop(); + })); + } + showDialog( + context: context, + builder: (BuildContext context) { + return PlatformAlertDialog( + title: Text(title ?? ""), + content: SingleChildScrollView( + child: ListBody( + children: [ + Text(subtitle ?? ""), + ], + ), + ), + actions: actions, + ); + }, + ); +} + +DateTime parseDateTime(String strDate) { + return DateTime.parse(strDate); +} + +DateFormat formatDateTime(String format) { + return DateFormat(format); +} + +String dateFormatted({@required String date, @required String formatType}) { + return formatDateTime(formatType).format(parseDateTime(date)); +} + +enum FormatType { + DateTime, + + Date, + + Time, +} + +String formatForDateTime(FormatType formatType) { + switch (formatType) { + case FormatType.Date: + { + return "yyyy-MM-dd"; + } + case FormatType.DateTime: + { + return "dd-MM-yyyy hh:mm a"; + } + case FormatType.Time: + { + return "hh:mm a"; + } + default: + { + return ""; + } + } +} + +String capitalize(String s) => s[0].toUpperCase() + s.substring(1); diff --git a/LabelStoreMax/lib/labelconfig.dart b/LabelStoreMax/lib/labelconfig.dart index 362d629..f93e80d 100644 --- a/LabelStoreMax/lib/labelconfig.dart +++ b/LabelStoreMax/lib/labelconfig.dart @@ -3,7 +3,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -14,7 +14,7 @@ Developer Notes SUPPORT EMAIL - support@woosignal.com - VERSION - 2.0.0 + VERSION - 2.0.1 https://woosignal.com */ @@ -22,21 +22,34 @@ const app_name = "MyApp"; -const app_key = "Your App Key"; +const app_key = "your app key"; // Your App key from WooSignal // link: https://woosignal.com/dashboard/apps -const app_logo_url = "https://woosignal.com/images/120x120_woosignal.png"; +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_terms_url = "https://yourdomain.com/terms"; const app_privacy_url = "https://yourdomain.com/privacy"; +/**/ + +// Allows customers to login/register, view account, purchase items as a user. +// #1 Install the "WP JSON API" plugin on WordPress via https://woosignal.com/plugins/wordpress/wpapp-json-api +// #2 Next activate the plugin on your WordPress and enable "use_wp_login = true" +// link: https://woosignal.com/dashboard/plugins + +const use_wp_login = false; +const app_base_url = "https://mysite.com"; // change to your url +const app_forgot_password_url = "https://mysite.com/my-account/lost-password"; // change to your forgot password url +const app_wp_api_path = "/wp-json"; // By default "/wp-json" should work + /**/ -const app_stripe_account = "Your Stripe Key"; // 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 diff --git a/LabelStoreMax/lib/main.dart b/LabelStoreMax/lib/main.dart index 91bec8a..c458467 100644 --- a/LabelStoreMax/lib/main.dart +++ b/LabelStoreMax/lib/main.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -10,10 +10,20 @@ 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'; +import 'package:label_storemax/pages/account_order_detail.dart'; +import 'package:label_storemax/pages/account_profile_update.dart'; +import 'package:label_storemax/pages/account_register.dart'; +import 'package:label_storemax/pages/account_shipping_details.dart'; import 'package:label_storemax/pages/error_page.dart'; +import 'package:label_storemax/pages/product_image_viewer_page.dart'; import 'package:woosignal/models/response/order.dart'; import 'package:woosignal/models/response/product_category.dart'; import 'package:woosignal/models/response/products.dart'; +import 'package:wp_json_api/wp_json_api.dart'; import 'labelconfig.dart'; import 'package:label_storemax/pages/checkout_details.dart'; import 'package:label_storemax/pages/home.dart'; @@ -41,17 +51,36 @@ 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"; + } + runApp( new MaterialApp( title: app_name, color: Colors.white, debugShowCheckedModeBanner: false, - initialRoute: "/home", + initialRoute: initialRoute, routes: { '/home': (BuildContext context) => new HomePage(), '/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(), + '/account-update': (BuildContext context) => + new AccountProfileUpdatePage(), + '/account-billing-details': (BuildContext context) => + new AccountBillingDetailsPage(), + '/account-shipping-details': (BuildContext context) => + new AccountShippingDetailsPage(), }, onGenerateRoute: (settings) { switch (settings.name) { @@ -95,6 +124,30 @@ void main() async { type: PageTransitionType.fade, ); + case '/product-images': + if (settings.arguments != null) { + final Map args = settings.arguments; + return PageTransition( + child: ProductImageViewerPage( + initialIndex: args["index"], arrImageSrc: args["images"]), + type: PageTransitionType.fade); + } + return PageTransition( + child: ErrorPage(), type: PageTransitionType.rightToLeft); + + case '/account-order-detail': + if (settings.arguments != null) { + final int orderId = settings.arguments as int; + return PageTransition( + child: AccountOrderDetailPage(orderId: orderId), + type: PageTransitionType.rightToLeftWithFade, + ); + } + return PageTransition( + child: ErrorPage(), + type: PageTransitionType.fade, + ); + case '/checkout-status': if (settings.arguments != null) { final Order order = settings.arguments as Order; diff --git a/LabelStoreMax/lib/models/billing_details.dart b/LabelStoreMax/lib/models/billing_details.dart index 2640493..e60ada6 100644 --- a/LabelStoreMax/lib/models/billing_details.dart +++ b/LabelStoreMax/lib/models/billing_details.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/models/cart.dart b/LabelStoreMax/lib/models/cart.dart index f18389a..d8c4502 100644 --- a/LabelStoreMax/lib/models/cart.dart +++ b/LabelStoreMax/lib/models/cart.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -66,7 +66,7 @@ class Cart { if (withFormat != null && withFormat == true) { return formatDoubleCurrency(total: total); } - return total.toString(); + return total.toStringAsFixed(2); } Future getSubtotal({bool withFormat}) async { @@ -78,7 +78,7 @@ class Cart { if (withFormat != null && withFormat == true) { return formatDoubleCurrency(total: subtotal); } - return subtotal.toString(); + return subtotal.toStringAsFixed(2); } void updateQuantity( @@ -176,6 +176,6 @@ class Cart { if (shippingTotal != 0) { total += ((double.parse(taxRate.rate) * shippingTotal) / 100); } - return (total).toString(); + return (total).toStringAsFixed(2); } } diff --git a/LabelStoreMax/lib/models/cart_line_item.dart b/LabelStoreMax/lib/models/cart_line_item.dart index 0cf6035..1a8f782 100644 --- a/LabelStoreMax/lib/models/cart_line_item.dart +++ b/LabelStoreMax/lib/models/cart_line_item.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -44,6 +44,10 @@ class CartLineItem { this.total, this.metaData}); + String getCartTotal() { + return (quantity * double.parse(subtotal)).toString(); + } + CartLineItem.fromJson(Map json) : name = json['name'], productId = json['product_id'], diff --git a/LabelStoreMax/lib/models/checkout_session.dart b/LabelStoreMax/lib/models/checkout_session.dart index 5b30d10..efe6e00 100644 --- a/LabelStoreMax/lib/models/checkout_session.dart +++ b/LabelStoreMax/lib/models/checkout_session.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/models/customer_address.dart b/LabelStoreMax/lib/models/customer_address.dart index e7347e7..fe754e1 100644 --- a/LabelStoreMax/lib/models/customer_address.dart +++ b/LabelStoreMax/lib/models/customer_address.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/models/payment_type.dart b/LabelStoreMax/lib/models/payment_type.dart index 82b0b85..786f81a 100644 --- a/LabelStoreMax/lib/models/payment_type.dart +++ b/LabelStoreMax/lib/models/payment_type.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/models/shipping_type.dart b/LabelStoreMax/lib/models/shipping_type.dart index 4c3dad5..50a70cc 100644 --- a/LabelStoreMax/lib/models/shipping_type.dart +++ b/LabelStoreMax/lib/models/shipping_type.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/about.dart b/LabelStoreMax/lib/pages/about.dart index b184119..3ad0288 100644 --- a/LabelStoreMax/lib/pages/about.dart +++ b/LabelStoreMax/lib/pages/about.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/account_billing_details.dart b/LabelStoreMax/lib/pages/account_billing_details.dart new file mode 100644 index 0000000..337686b --- /dev/null +++ b/LabelStoreMax/lib/pages/account_billing_details.dart @@ -0,0 +1,257 @@ +// 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/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/widgets/app_loader.dart'; +import 'package:label_storemax/widgets/buttons.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; +import 'package:wp_json_api/models/responses/WCCustomerInfoResponse.dart'; +import 'package:wp_json_api/models/responses/WCCustomerUpdatedResponse.dart'; +import 'package:wp_json_api/wp_json_api.dart'; + +class AccountBillingDetailsPage extends StatefulWidget { + AccountBillingDetailsPage(); + + @override + _AccountBillingDetailsPageState createState() => + _AccountBillingDetailsPageState(); +} + +class _AccountBillingDetailsPageState extends State { + _AccountBillingDetailsPageState(); + + // BILLING TEXT CONTROLLERS + TextEditingController _txtShippingFirstName; + TextEditingController _txtShippingLastName; + TextEditingController _txtShippingAddressLine; + TextEditingController _txtShippingCity; + TextEditingController _txtShippingState; + TextEditingController _txtShippingPostalCode; + TextEditingController _txtShippingCountry; + + bool _isLoading; + bool _isUpdating; + + @override + void initState() { + super.initState(); + + _txtShippingFirstName = TextEditingController(); + _txtShippingLastName = TextEditingController(); + _txtShippingAddressLine = TextEditingController(); + _txtShippingCity = TextEditingController(); + _txtShippingState = TextEditingController(); + _txtShippingPostalCode = TextEditingController(); + _txtShippingCountry = TextEditingController(); + + _isLoading = true; + _isUpdating = false; + + _fetchUserDetails(); + } + + _fetchUserDetails() async { + WCCustomerInfoResponse wcCustomerInfoResponse = + await WPJsonAPI.instance.api((request) async { + return request.wcCustomerInfo(await readAuthToken()); + }); + + Billing billing = wcCustomerInfoResponse.data.billing; + _txtShippingFirstName.text = billing.firstName; + _txtShippingLastName.text = billing.lastName; + + _txtShippingAddressLine.text = billing.address1; + _txtShippingCity.text = billing.city; + _txtShippingState.text = billing.state; + _txtShippingPostalCode.text = billing.postcode; + _txtShippingCountry.text = billing.country; + + setState(() { + _isLoading = false; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: Colors.transparent, + title: Text( + trans(context, "Billing Details"), + style: Theme.of(context).primaryTextTheme.subhead, + ), + centerTitle: true, + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: GestureDetector( + onTap: () { + FocusScope.of(context).requestFocus(new FocusNode()); + }, + child: _isLoading + ? showAppLoader() + : LayoutBuilder( + builder: (context, constraints) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Row( + children: [ + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "First Name"), + controller: _txtShippingFirstName, + shouldAutoFocus: true, + ), + ), + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "Last Name"), + controller: _txtShippingLastName, + ), + ), + ], + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + ), + wsTextEditingRow( + context, + heading: trans(context, "Address Line"), + controller: _txtShippingAddressLine, + ), + Row(children: [ + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "City"), + controller: _txtShippingCity, + ), + ), + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "State"), + keyboardType: TextInputType.emailAddress, + controller: _txtShippingState), + ), + ]), + Row( + children: [ + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "Postal code"), + controller: _txtShippingPostalCode, + ), + ), + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "Country"), + keyboardType: + TextInputType.emailAddress, + controller: _txtShippingCountry), + ), + ], + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + ) + ], + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: HexColor("#e8e8e8"), + blurRadius: 15.0, + // has the effect of softening the shadow + spreadRadius: 0, + offset: Offset( + 0, + 0, + ), + ) + ], + ), + padding: EdgeInsets.all(8), + ), + height: + (constraints.maxHeight - constraints.minHeight) * + 0.6, + ), + Column( + children: [ + wsPrimaryButton(context, + title: trans(context, "UPDATE DETAILS"), + action: + _isUpdating ? null : _updateBillingDetails), + ], + ), + ], + ), + ), + ), + ), + ); + } + + _updateBillingDetails() async { + String firstName = _txtShippingFirstName.text; + String lastName = _txtShippingLastName.text; + String addressLine = _txtShippingAddressLine.text; + String city = _txtShippingCity.text; + String state = _txtShippingState.text; + String postalCode = _txtShippingPostalCode.text; + String country = _txtShippingCountry.text; + + String userToken = await readAuthToken(); + + setState(() { + _isUpdating = true; + }); + + WCCustomerUpdatedResponse wcCustomerUpdatedResponse = await WPJsonAPI + .instance + .api((request) => request.wcUpdateCustomerInfo(userToken, + billingFirstName: firstName, + billingLastName: lastName, + billingAddress1: addressLine, + billingCity: city, + billingState: state, + billingPostcode: postalCode, + billingCountry: country)); + + setState(() { + _isUpdating = false; + }); + + if (wcCustomerUpdatedResponse.status != 200) { + showEdgeAlertWith(context, + title: trans(context, "Oops!"), + desc: trans(context, "Something went wrong"), + style: EdgeAlertStyle.WARNING); + return; + } + Navigator.pop(context); + } +} diff --git a/LabelStoreMax/lib/pages/account_detail.dart b/LabelStoreMax/lib/pages/account_detail.dart new file mode 100644 index 0000000..e0e114f --- /dev/null +++ b/LabelStoreMax/lib/pages/account_detail.dart @@ -0,0 +1,392 @@ +// 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:bubble_tab_indicator/bubble_tab_indicator.dart'; +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/shared_pref/sp_user_id.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:label_storemax/widgets/app_loader.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; +import 'package:woosignal/models/response/order.dart'; +import 'package:wp_json_api/models/responses/WCCustomerInfoResponse.dart'; +import 'package:wp_json_api/wp_json_api.dart'; + +class AccountDetailPage extends StatefulWidget { + @override + _AccountDetailPageState createState() => _AccountDetailPageState(); +} + +class _AccountDetailPageState extends State + with SingleTickerProviderStateMixin { + int _page; + List _orders; + WCCustomerInfoResponse _wcCustomerInfoResponse; + bool _isLoading; + bool _isLoadingOrders; + int _currentTabIndex = 0; + Widget _activeBody; + + TabController _tabController; + List _tabs = []; + + @override + void initState() { + super.initState(); + _isLoading = true; + _isLoadingOrders = true; + _page = 1; + _orders = []; + _tabs = [ + new Tab(text: "Orders"), + new Tab(text: "Settings"), + ]; + _tabController = TabController(vsync: this, length: _tabs.length); + _activeBody = showAppLoader(); + _fetchWpUserData(); + _fetchOrders(); + } + + _fetchWpUserData() async { + WCCustomerInfoResponse wcCustomerInfoResponse = + await WPJsonAPI.instance.api((request) async { + return request.wcCustomerInfo(await readAuthToken()); + }); + + if (wcCustomerInfoResponse != null) { + _wcCustomerInfoResponse = wcCustomerInfoResponse; + } + setState(() { + _isLoading = false; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + leading: Container( + child: IconButton( + icon: Icon(Icons.arrow_back_ios), + onPressed: () { + Navigator.pop(context); + }, + ), + margin: EdgeInsets.only(left: 0), + ), + title: Text( + trans(context, "Account"), + style: Theme.of(context).primaryTextTheme.title, + ), + centerTitle: true, + ), + resizeToAvoidBottomPadding: false, + body: SafeArea( + minimum: safeAreaDefault(), + child: _isLoading + ? showAppLoader() + : Column( + children: [ + Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + padding: EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Container( + margin: EdgeInsets.only(top: 10), + child: CircleAvatar( + backgroundImage: NetworkImage( + _wcCustomerInfoResponse.data.avatar, + ), + ), + height: 90, + width: 90, + ), + Expanded( + child: Padding( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + Text( + (_wcCustomerInfoResponse == null + ? "" + : [ + _wcCustomerInfoResponse + .data.firstName, + _wcCustomerInfoResponse + .data.lastName + ] + .where((t) => + (t != null || t != "")) + .toList() + .join(" ")), + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + ), + ), + ], + ) + ], + ), + padding: EdgeInsets.only(left: 16), + ), + ), + ], + ), + Padding( + child: TabBar( + tabs: _tabs, + controller: _tabController, + indicatorSize: TabBarIndicatorSize.tab, + labelColor: Colors.white, + unselectedLabelColor: Colors.black87, + indicator: new BubbleTabIndicator( + indicatorHeight: 25.0, + indicatorColor: Colors.black87, + tabBarIndicatorSize: TabBarIndicatorSize.tab, + ), + onTap: _tabsTapped, + ), + padding: EdgeInsets.symmetric(vertical: 8), + ), + ], + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + boxShadow: wsBoxShadow(), + color: Colors.white, + ), + ), + Expanded(child: _activeBody), + ], + ), + ), + ); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + _tabsTapped(int i) { + _currentTabIndex = i; + setState(() { + if (_currentTabIndex == 0) { + _activeBody = _widgetOrders(); + } else { + _activeBody = _widgetSettings(); + } + }); + } + + ListView _widgetSettings() { + return ListView( + children: [ + Card( + child: ListTile( + leading: Icon(Icons.account_circle), + title: Text(trans(context, "Update details")), + onTap: () { + Navigator.pushNamed(context, "/account-update"); + }, + ), + ), + Card( + child: ListTile( + leading: Icon(Icons.local_shipping), + title: Text(trans(context, "Shipping Details")), + onTap: () { + Navigator.pushNamed(context, "/account-shipping-details"); + }, + ), + ), + Card( + child: ListTile( + leading: Icon(Icons.credit_card), + title: Text(trans(context, "Billing Details")), + onTap: () { + Navigator.pushNamed(context, "/account-billing-details"); + }, + ), + ), + Card( + child: ListTile( + leading: Icon(Icons.exit_to_app), + title: Text(trans(context, "Logout")), + onTap: () { + authLogout(context); + }, + ), + ), + ], + ); + } + + _fetchOrders() async { + String userId = await readUserId(); + + if (userId == null) { + setState(() { + _isLoadingOrders = false; + _activeBody = _widgetOrders(); + }); + return; + } + _orders = await appWooSignal((api) { + return api.getOrders( + customer: int.parse(userId), page: _page, perPage: 100); + }); + setState(() { + _isLoadingOrders = false; + _activeBody = _widgetOrders(); + }); + } + + Widget _widgetOrders() { + return _isLoadingOrders + ? showAppLoader() + : _orders.length <= 0 + ? Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.shopping_cart, + color: Colors.black54, + size: 40, + ), + Text( + trans(context, "No orders found"), + ), + ], + ), + ) + : ListView.builder( + itemBuilder: (cxt, i) { + return Card( + child: ListTile( + contentPadding: + EdgeInsets.only(top: 5, bottom: 5, left: 8, right: 6), + title: Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: HexColor("#fcfcfc"), width: 1), + ), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "#" + _orders[i].id.toString(), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + Text( + capitalize(_orders[i].status), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + subtitle: Padding( + padding: const EdgeInsets.only(top: 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + formatStringCurrency(total: _orders[i].total), + style: Theme.of(context) + .primaryTextTheme + .body1 + .copyWith( + fontWeight: FontWeight.w600, + color: Colors.black), + textAlign: TextAlign.left, + ), + Text( + _orders[i].lineItems.length.toString() + + " " + + trans(context, "items"), + style: Theme.of(context) + .primaryTextTheme + .body2 + .copyWith( + fontWeight: FontWeight.w600, + color: Colors.black), + textAlign: TextAlign.left, + ), + ], + ), + Text( + dateFormatted( + date: _orders[i].dateCreated, + formatType: + formatForDateTime(FormatType.Date)) + + "\n" + + dateFormatted( + date: _orders[i].dateCreated, + formatType: + formatForDateTime(FormatType.Time)), + textAlign: TextAlign.right, + style: Theme.of(context) + .primaryTextTheme + .bodyText1 + .copyWith( + fontWeight: FontWeight.w400, + color: Colors.black), + ), + ], + ), + ), + trailing: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.chevron_right), + ], + ), + onTap: () { + int orderId = _orders[i].id; + Navigator.pushNamed(context, "/account-order-detail", + arguments: orderId); + }, + ), + ); + }, + itemCount: _orders.length, + ); + } +} diff --git a/LabelStoreMax/lib/pages/account_landing.dart b/LabelStoreMax/lib/pages/account_landing.dart new file mode 100644 index 0000000..9230b14 --- /dev/null +++ b/LabelStoreMax/lib/pages/account_landing.dart @@ -0,0 +1,173 @@ +// 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/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/shared_pref/sp_auth.dart'; +import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:label_storemax/labelconfig.dart'; +import 'package:label_storemax/widgets/buttons.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:wp_json_api/models/responses/WPUserLoginResponse.dart'; +import 'package:wp_json_api/wp_json_api.dart'; + +class AccountLandingPage extends StatefulWidget { + AccountLandingPage(); + + @override + _AccountLandingPageState createState() => _AccountLandingPageState(); +} + +class _AccountLandingPageState extends State { + bool _hasTappedLogin; + TextEditingController _tfEmailController; + TextEditingController _tfPasswordController; + + @override + void initState() { + super.initState(); + + _hasTappedLogin = false; + _tfEmailController = TextEditingController(); + _tfPasswordController = TextEditingController(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + resizeToAvoidBottomPadding: false, + body: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + storeLogo(height: 100), + Flexible( + child: Container( + height: 70, + padding: EdgeInsets.only(bottom: 20), + margin: EdgeInsets.symmetric(horizontal: 20), + alignment: Alignment.bottomLeft, + child: Text( + trans(context, "Login"), + textAlign: TextAlign.left, + style: Theme.of(context) + .primaryTextTheme + .display1 + .copyWith( + fontSize: 24, + fontWeight: FontWeight.w700, + ), + ), + ), + ), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + boxShadow: wsBoxShadow(), + color: Colors.white), + padding: EdgeInsets.symmetric(vertical: 18, horizontal: 8), + margin: EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + wsTextEditingRow(context, + heading: trans(context, "Email"), + controller: _tfEmailController, + keyboardType: TextInputType.emailAddress), + wsTextEditingRow(context, + heading: trans(context, "Password"), + controller: _tfPasswordController, + keyboardType: TextInputType.visiblePassword, + obscureText: true), + wsPrimaryButton( + context, + title: trans(context, "Login"), + action: _hasTappedLogin == true ? null : _loginUser, + ), + ], + ), + ), + ], + ), + ), + FlatButton( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.account_circle, + color: Colors.black38, + ), + Padding( + child: Text( + trans(context, "Create an account"), + style: Theme.of(context).primaryTextTheme.body2, + ), + padding: EdgeInsets.only(left: 8), + ) + ], + ), + onPressed: () { + Navigator.pushNamed(context, "/account-register"); + }, + ), + wsLinkButton(context, title: trans(context, "Forgot Password"), + action: () { + launch(app_forgot_password_url); + }), + ], + ), + ), + ); + } + + _loginUser() async { + String email = _tfEmailController.text; + String password = _tfPasswordController.text; + + if (_hasTappedLogin == false) { + setState(() { + _hasTappedLogin = true; + }); + + WPUserLoginResponse wpUserLoginResponse = await WPJsonAPI.instance + .api((request) => request.wpLogin(email: email, password: password)); + _hasTappedLogin = false; + + if (wpUserLoginResponse != null) { + String token = wpUserLoginResponse.data.userToken; + authUser(token); + storeUserId(wpUserLoginResponse.data.userId.toString()); + + navigatorPush(context, routeName: "/home", forgetAll: true); + } else { + showEdgeAlertWith(context, + title: trans(context, "Oops!"), + desc: trans(context, "Invalid login credentials"), + style: EdgeAlertStyle.WARNING, + icon: Icons.account_circle); + setState(() { + _hasTappedLogin = false; + }); + } + } + } +} diff --git a/LabelStoreMax/lib/pages/account_order_detail.dart b/LabelStoreMax/lib/pages/account_order_detail.dart new file mode 100644 index 0000000..a28e614 --- /dev/null +++ b/LabelStoreMax/lib/pages/account_order_detail.dart @@ -0,0 +1,209 @@ +// 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/cupertino.dart'; +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/woosignal_ui.dart'; +import 'package:woosignal/models/response/order.dart'; + +class AccountOrderDetailPage extends StatefulWidget { + final int orderId; + + AccountOrderDetailPage({Key key, this.orderId}) : super(key: key); + + @override + _AccountOrderDetailPageState createState() => + _AccountOrderDetailPageState(this.orderId); +} + +class _AccountOrderDetailPageState extends State { + _AccountOrderDetailPageState(this._orderId); + + int _orderId; + Order _order; + bool _isLoading; + + @override + void initState() { + super.initState(); + _isLoading = true; + _fetchOrder(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + leading: Container( + child: IconButton( + icon: Icon(Icons.arrow_back_ios), + onPressed: () { + Navigator.pop(context); + }, + ), + margin: EdgeInsets.only(left: 0), + ), + title: Text( + "Order #" + _orderId.toString(), + style: Theme.of(context).primaryTextTheme.title, + ), + centerTitle: true, + ), + resizeToAvoidBottomPadding: false, + body: SafeArea( + minimum: safeAreaDefault(), + child: _isLoading + ? showAppLoader() + : Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Ordered date: " + + dateFormatted( + date: _order.dateCreated, + formatType: formatForDateTime(FormatType.Date))), + Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible(child: Text("Ships to:")), + Flexible( + child: Text( + [ + [ + _order.shipping.firstName, + _order.shipping.lastName + ].where((t) => t != null).toList().join(" "), + _order.shipping.address1, + _order.shipping.address2, + _order.shipping.city, + _order.shipping.state, + _order.shipping.postcode, + _order.shipping.country, + ] + .where((t) => (t != "" && t != null)) + .toList() + .join("\n"), + textAlign: TextAlign.right, + ), + ), + ], + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + boxShadow: wsBoxShadow(), + color: Colors.white, + ), + ), + Expanded( + child: ListView.builder( + itemBuilder: (cxt, i) { + return Card( + child: ListTile( + contentPadding: EdgeInsets.only( + top: 5, bottom: 5, left: 8, right: 6), + title: Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: HexColor("#fcfcfc"), width: 1), + ), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + _order.lineItems[i].name, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + Text( + capitalize(formatStringCurrency( + total: _order.lineItems[i].price)), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + subtitle: Padding( + padding: const EdgeInsets.only(top: 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + formatStringCurrency( + total: _order.lineItems[i].total), + style: Theme.of(context) + .primaryTextTheme + .body1 + .copyWith( + fontWeight: FontWeight.w600, + color: Colors.black), + textAlign: TextAlign.left, + ), + Text( + "x" + + _order.lineItems[i].quantity + .toString(), + style: Theme.of(context) + .primaryTextTheme + .body2 + .copyWith( + fontWeight: FontWeight.w600, + color: Colors.black), + textAlign: TextAlign.left, + ), + ], + ), + ], + ), + ), + ), + ); + }, + itemCount: _order.lineItems.length, + )), + ], + ), + ), + ); + } + + @override + void dispose() { + super.dispose(); + } + + _fetchOrder() async { + _order = await appWooSignal((api) { + return api.retrieveOrder(_orderId); + }); + if (_order != null) { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/LabelStoreMax/lib/pages/account_profile_update.dart b/LabelStoreMax/lib/pages/account_profile_update.dart new file mode 100644 index 0000000..f0738fb --- /dev/null +++ b/LabelStoreMax/lib/pages/account_profile_update.dart @@ -0,0 +1,166 @@ +// 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/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/widgets/app_loader.dart'; +import 'package:label_storemax/widgets/buttons.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; +import 'package:wp_json_api/models/responses/WPUserInfoResponse.dart'; +import 'package:wp_json_api/models/responses/WPUserInfoUpdatedResponse.dart'; +import 'package:wp_json_api/wp_json_api.dart'; + +class AccountProfileUpdatePage extends StatefulWidget { + AccountProfileUpdatePage(); + + @override + _AccountProfileUpdatePageState createState() => + _AccountProfileUpdatePageState(); +} + +class _AccountProfileUpdatePageState extends State { + _AccountProfileUpdatePageState(); + + bool isLoading; + TextEditingController _tfFirstName; + TextEditingController _tfLastName; + + @override + void dispose() { + super.dispose(); + } + + @override + void initState() { + super.initState(); + + isLoading = true; + _tfFirstName = TextEditingController(); + _tfLastName = TextEditingController(); + + _fetchUserDetails(); + } + + _fetchUserDetails() async { + WPUserInfoResponse wpUserInfoResponse = + await WPJsonAPI.instance.api((request) async { + return request.wpGetUserInfo(await readAuthToken()); + }); + + _tfFirstName.text = wpUserInfoResponse.data.firstName; + _tfLastName.text = wpUserInfoResponse.data.lastName; + setState(() { + isLoading = false; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + title: Text( + trans(context, "Update Details"), + style: TextStyle( + fontSize: 20, + ), + ), + centerTitle: true, + elevation: 1, + ), + body: isLoading + ? showAppLoader() + : SafeArea( +// minimum: safeAreaDefault(), + child: Column( + children: [ + Expanded( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Flexible( + child: Row( + children: [ + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "First Name"), + controller: _tfFirstName, + keyboardType: TextInputType.text)), + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "Last Name"), + controller: _tfLastName, + keyboardType: TextInputType.text), + ), + ], + ), + ), + Padding( + padding: EdgeInsets.only(top: 5), + ), + Padding( + padding: EdgeInsets.only(top: 10), + ), + wsPrimaryButton(context, + title: trans(context, "Update details"), + action: _updateDetails) + ], + ), + margin: EdgeInsets.all(8), + padding: EdgeInsets.all(8), + color: Colors.white, + ), + ), + ], + ), + ), + ); + } + + bool _isNetworking = false; + _updateDetails() async { + String firstName = _tfFirstName.text; + String lastName = _tfLastName.text; + + if (_isNetworking == false) { + setState(() { + _isNetworking = true; + isLoading = true; + }); + + WPUserInfoUpdatedResponse wpUserInfoUpdatedResponse = + await WPJsonAPI.instance.api((request) async { + return request.wpUpdateUserInfo(await readAuthToken(), + firstName: firstName, lastName: lastName); + }); + + if (wpUserInfoUpdatedResponse != null && + wpUserInfoUpdatedResponse.status == 200) { + showEdgeAlertWith(context, + title: trans(context, "Success"), + desc: trans(context, "Account updated"), + style: EdgeAlertStyle.SUCCESS); + } else { + showEdgeAlertWith(context, + title: trans(context, "Invalid details"), + desc: trans(context, "Please check your email and password"), + style: EdgeAlertStyle.WARNING); + } + setState(() { + _isNetworking = false; + isLoading = false; + }); + } + } +} diff --git a/LabelStoreMax/lib/pages/account_register.dart b/LabelStoreMax/lib/pages/account_register.dart new file mode 100644 index 0000000..550764c --- /dev/null +++ b/LabelStoreMax/lib/pages/account_register.dart @@ -0,0 +1,224 @@ +// 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/material.dart'; +import 'package:label_storemax/helpers/shared_pref/sp_auth.dart'; +import 'package:label_storemax/helpers/shared_pref/sp_user_id.dart'; +import 'package:label_storemax/helpers/tools.dart'; +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'; + +class AccountRegistrationPage extends StatefulWidget { + AccountRegistrationPage(); + + @override + _AccountRegistrationPageState createState() => + _AccountRegistrationPageState(); +} + +class _AccountRegistrationPageState extends State { + _AccountRegistrationPageState(); + + bool _hasTappedRegister; + TextEditingController _tfEmailAddressController; + TextEditingController _tfPasswordController; + TextEditingController _tfFirstNameController; + TextEditingController _tfLastNameController; + + @override + void initState() { + super.initState(); + + _hasTappedRegister = false; + _tfEmailAddressController = TextEditingController(); + _tfPasswordController = TextEditingController(); + _tfFirstNameController = TextEditingController(); + _tfLastNameController = TextEditingController(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + leading: IconButton( + icon: Icon(Icons.close), + onPressed: () { + Navigator.pop(context); + }, + ), + title: Text( + "Register", + style: Theme.of(context).primaryTextTheme.title, + ), + centerTitle: true, + ), + resizeToAvoidBottomPadding: false, + body: SafeArea( + minimum: safeAreaDefault(), + child: Column( + children: [ + Container( + margin: EdgeInsets.only(top: 10), + child: Row( + children: [ + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "First Name"), + controller: _tfFirstNameController, + shouldAutoFocus: true, + keyboardType: TextInputType.text), + ), + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "Last Name"), + controller: _tfLastNameController, + shouldAutoFocus: false, + keyboardType: TextInputType.text), + ), + ], + )), + wsTextEditingRow( + context, + heading: trans(context, "Email address"), + controller: _tfEmailAddressController, + shouldAutoFocus: false, + keyboardType: TextInputType.emailAddress, + ), + wsTextEditingRow( + context, + heading: trans(context, "Password"), + controller: _tfPasswordController, + shouldAutoFocus: true, + obscureText: true, + ), + Padding( + child: wsPrimaryButton(context, + title: trans(context, "Sign up"), + action: _hasTappedRegister ? null : _signUpTapped), + padding: EdgeInsets.only(top: 10), + ), + Padding( + child: InkWell( + child: RichText( + text: TextSpan( + text: trans( + context, "By tapping \"Register\" you agree to ") + + app_name + + '\'s ', + children: [ + TextSpan( + text: trans(context, "terms and conditions"), + style: TextStyle(fontWeight: FontWeight.bold)), + TextSpan(text: ' ' + trans(context, "and") + ' '), + TextSpan( + text: trans(context, "privacy policy"), + style: TextStyle(fontWeight: FontWeight.bold)), + ], + style: TextStyle(color: Colors.black45), + ), + textAlign: TextAlign.center, + ), + onTap: _viewTOSModal, + ), + padding: EdgeInsets.symmetric(vertical: 16), + ), + ], + ), + ), + ); + } + + _signUpTapped() async { + String email = _tfEmailAddressController.text; + String password = _tfPasswordController.text; + String firstName = _tfFirstNameController.text; + String lastName = _tfLastNameController.text; + + if (!isEmail(email)) { + showEdgeAlertWith(context, + title: trans(context, "Oops"), + desc: trans(context, "That email address is not valid"), + style: EdgeAlertStyle.DANGER); + return; + } + + if (password.length <= 5) { + showEdgeAlertWith(context, + title: trans(context, "Oops"), + desc: trans(context, "Password must be a min 6 characters"), + style: EdgeAlertStyle.DANGER); + return; + } + + if (_hasTappedRegister == false) { + setState(() { + _hasTappedRegister = true; + }); + + String username = + (email.replaceAll(new RegExp(r'(@|\.)'), "")) + randomStr(4); + + WPUserRegisterResponse wpUserRegisterResponse = await WPJsonAPI.instance + .api((request) => request.wpRegister( + email: email, 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)); + + navigatorPush(context, routeName: "/home", forgetAll: true); + } else { + setState(() { + showEdgeAlertWith(context, + title: trans(context, "Invalid"), + desc: trans(context, "Please check your details"), + style: EdgeAlertStyle.WARNING); + _hasTappedRegister = false; + }); + } + } + } + + _viewTOSModal() { + showPlatformAlertDialog(context, + title: trans(context, "Actions"), + subtitle: trans(context, "View Terms and Conditions or Privacy policy"), + actions: [ + dialogAction(context, + title: trans(context, "Terms and Conditions"), + action: _viewTermsConditions), + dialogAction(context, + title: trans(context, "Privacy Policy"), + action: _viewPrivacyPolicy), + ]); + } + + void _viewTermsConditions() { + Navigator.pop(context); + openBrowserTab(url: app_terms_url); + } + + void _viewPrivacyPolicy() { + Navigator.pop(context); + openBrowserTab(url: app_privacy_url); + } +} diff --git a/LabelStoreMax/lib/pages/account_shipping_details.dart b/LabelStoreMax/lib/pages/account_shipping_details.dart new file mode 100644 index 0000000..45e9004 --- /dev/null +++ b/LabelStoreMax/lib/pages/account_shipping_details.dart @@ -0,0 +1,255 @@ +// 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/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/widgets/app_loader.dart'; +import 'package:label_storemax/widgets/buttons.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; +import 'package:wp_json_api/models/responses/WCCustomerInfoResponse.dart'; +import 'package:wp_json_api/models/responses/WCCustomerUpdatedResponse.dart'; +import 'package:wp_json_api/wp_json_api.dart'; + +class AccountShippingDetailsPage extends StatefulWidget { + AccountShippingDetailsPage(); + + @override + _AccountShippingDetailsPageState createState() => + _AccountShippingDetailsPageState(); +} + +class _AccountShippingDetailsPageState + extends State { + _AccountShippingDetailsPageState(); + + // BILLING TEXT CONTROLLERS + TextEditingController _txtShippingFirstName; + TextEditingController _txtShippingLastName; + TextEditingController _txtShippingAddressLine; + TextEditingController _txtShippingCity; + TextEditingController _txtShippingPostalCode; + TextEditingController _txtShippingState; + TextEditingController _txtShippingCountry; + + bool _isLoading; + bool _isUpdating; + + @override + void initState() { + super.initState(); + + _txtShippingFirstName = TextEditingController(); + _txtShippingLastName = TextEditingController(); + _txtShippingAddressLine = TextEditingController(); + _txtShippingCity = TextEditingController(); + _txtShippingPostalCode = TextEditingController(); + _txtShippingState = TextEditingController(); + _txtShippingCountry = TextEditingController(); + + _isLoading = true; + _isUpdating = false; + + _fetchUserDetails(); + } + + _fetchUserDetails() async { + WCCustomerInfoResponse wcCustomerInfoResponse = + await WPJsonAPI.instance.api((request) async { + return request.wcCustomerInfo(await readAuthToken()); + }); + + Shipping shipping = wcCustomerInfoResponse.data.shipping; + _txtShippingFirstName.text = shipping.firstName; + _txtShippingLastName.text = shipping.lastName; + + _txtShippingAddressLine.text = shipping.address1; + _txtShippingCity.text = shipping.city; + _txtShippingState.text = shipping.state; + _txtShippingPostalCode.text = shipping.postcode; + _txtShippingCountry.text = shipping.country; + + setState(() { + _isLoading = false; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: Colors.transparent, + title: Text( + trans(context, "Shipping Details"), + style: Theme.of(context).primaryTextTheme.subhead, + ), + centerTitle: true, + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: GestureDetector( + onTap: () { + FocusScope.of(context).requestFocus(new FocusNode()); + }, + child: _isLoading + ? showAppLoader() + : LayoutBuilder( + builder: (context, constraints) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Row( + children: [ + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "First Name"), + controller: _txtShippingFirstName, + shouldAutoFocus: true, + ), + ), + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "Last Name"), + controller: _txtShippingLastName, + ), + ), + ], + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + ), + wsTextEditingRow( + context, + heading: trans(context, "Address Line"), + controller: _txtShippingAddressLine, + ), + Row(children: [ + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "City"), + controller: _txtShippingCity, + ), + ), + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "State"), + controller: _txtShippingState, + ), + ), + ]), + Row( + children: [ + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "Postal code"), + controller: _txtShippingPostalCode, + ), + ), + Flexible( + child: wsTextEditingRow( + context, + heading: trans(context, "Country"), + controller: _txtShippingCountry, + ), + ), + ], + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + ) + ], + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: HexColor("#e8e8e8"), + blurRadius: 15.0, + // has the effect of softening the shadow + spreadRadius: 0, + offset: Offset( + 0, + 0, + ), + ) + ], + ), + padding: EdgeInsets.all(8), + ), + height: + (constraints.maxHeight - constraints.minHeight) * + 0.6, + ), + Column( + children: [ + wsPrimaryButton(context, + title: trans(context, "UPDATE DETAILS"), + action: + _isUpdating ? null : _updateShippingDetails), + ], + ), + ], + ), + ), + ), + ), + ); + } + + _updateShippingDetails() async { + String firstName = _txtShippingFirstName.text; + String lastName = _txtShippingLastName.text; + String addressLine = _txtShippingAddressLine.text; + String city = _txtShippingCity.text; + String state = _txtShippingState.text; + String postalCode = _txtShippingPostalCode.text; + String country = _txtShippingCountry.text; + + String userToken = await readAuthToken(); + + setState(() { + _isUpdating = true; + }); + + WCCustomerUpdatedResponse wcCustomerUpdatedResponse = await WPJsonAPI + .instance + .api((request) => request.wcUpdateCustomerInfo(userToken, + shippingFirstName: firstName, + shippingLastName: lastName, + shippingAddress1: addressLine, + shippingCity: city, + shippingState: state, + shippingPostcode: postalCode, + shippingCountry: country)); + + if (wcCustomerUpdatedResponse.status != 200) { + showEdgeAlertWith(context, + title: trans(context, "Oops!"), + desc: trans(context, "Something went wrong"), + style: EdgeAlertStyle.WARNING); + return; + } + Navigator.pop(context); + } +} diff --git a/LabelStoreMax/lib/pages/browse_category.dart b/LabelStoreMax/lib/pages/browse_category.dart index b6cc741..0719588 100644 --- a/LabelStoreMax/lib/pages/browse_category.dart +++ b/LabelStoreMax/lib/pages/browse_category.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/browse_search.dart b/LabelStoreMax/lib/pages/browse_search.dart index 23332d0..07988f5 100644 --- a/LabelStoreMax/lib/pages/browse_search.dart +++ b/LabelStoreMax/lib/pages/browse_search.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/cart.dart b/LabelStoreMax/lib/pages/cart.dart index 32971e3..7e757f2 100644 --- a/LabelStoreMax/lib/pages/cart.dart +++ b/LabelStoreMax/lib/pages/cart.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -184,10 +184,11 @@ class _CartPageState extends State { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Image( - image: AssetImage("assets/images/cart_empty.png"), - height: 150, - alignment: Alignment.center), + Icon( + Icons.shopping_cart, + size: 100, + color: Colors.black45, + ), Padding( child: Text(trans(context, "Empty Basket"), style: Theme.of(context).primaryTextTheme.body1), diff --git a/LabelStoreMax/lib/pages/checkout_confirmation.dart b/LabelStoreMax/lib/pages/checkout_confirmation.dart index 9e07503..3d859a5 100644 --- a/LabelStoreMax/lib/pages/checkout_confirmation.dart +++ b/LabelStoreMax/lib/pages/checkout_confirmation.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -50,6 +50,8 @@ class CheckoutConfirmationPageState extends State { _getTaxes(); } + _fetchUserId() {} + void reloadState({bool showLoader}) { setState(() { _showFullLoader = showLoader ?? false; @@ -110,7 +112,9 @@ class CheckoutConfirmationPageState extends State { icon: Icons.local_shipping); return; } - Navigator.pushNamed(context, "/checkout-shipping-type"); + Navigator.pushNamed(context, "/checkout-shipping-type").then((value) { + setState(() {}); + }); } @override @@ -156,12 +160,9 @@ class CheckoutConfirmationPageState extends State { .billingDetails.billingAddress .hasMissingFields() ? "Billing address is incomplete" - : truncateWithEllipsis( - 30, - CheckoutSession.getInstance - .billingDetails.billingAddress - .addressFull(), - )), + : CheckoutSession.getInstance + .billingDetails.billingAddress + .addressFull()), action: _actionCheckoutDetails, showBorderBottom: true) : wsCheckoutRow(context, diff --git a/LabelStoreMax/lib/pages/checkout_details.dart b/LabelStoreMax/lib/pages/checkout_details.dart index e356e5f..47b79b9 100644 --- a/LabelStoreMax/lib/pages/checkout_details.dart +++ b/LabelStoreMax/lib/pages/checkout_details.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -28,12 +28,12 @@ class _CheckoutDetailsPageState extends State { _CheckoutDetailsPageState(); // BILLING TEXT CONTROLLERS - TextEditingController _txtBillingFirstName; - TextEditingController _txtBillingLastName; - TextEditingController _txtBillingAddressLine; - TextEditingController _txtBillingCity; - TextEditingController _txtBillingPostalCode; - TextEditingController _txtBillingEmailAddress; + TextEditingController _txtShippingFirstName; + TextEditingController _txtShippingLastName; + TextEditingController _txtShippingAddressLine; + TextEditingController _txtShippingCity; + TextEditingController _txtShippingPostalCode; + TextEditingController _txtShippingEmailAddress; String _strBillingCountry; var valRememberDetails = true; @@ -42,12 +42,12 @@ class _CheckoutDetailsPageState extends State { void initState() { super.initState(); - _txtBillingFirstName = TextEditingController(); - _txtBillingLastName = TextEditingController(); - _txtBillingAddressLine = TextEditingController(); - _txtBillingCity = TextEditingController(); - _txtBillingPostalCode = TextEditingController(); - _txtBillingEmailAddress = TextEditingController(); + _txtShippingFirstName = TextEditingController(); + _txtShippingLastName = TextEditingController(); + _txtShippingAddressLine = TextEditingController(); + _txtShippingCity = TextEditingController(); + _txtShippingPostalCode = TextEditingController(); + _txtShippingEmailAddress = TextEditingController(); if (CheckoutSession.getInstance.billingDetails.billingAddress == null) { CheckoutSession.getInstance.billingDetails.initSession(); @@ -55,12 +55,12 @@ class _CheckoutDetailsPageState extends State { CheckoutSession.getInstance.billingDetails.billingAddress.initAddress(); } BillingDetails billingDetails = CheckoutSession.getInstance.billingDetails; - _txtBillingFirstName.text = billingDetails.billingAddress.firstName; - _txtBillingLastName.text = billingDetails.billingAddress.lastName; - _txtBillingAddressLine.text = billingDetails.billingAddress.addressLine; - _txtBillingCity.text = billingDetails.billingAddress.city; - _txtBillingPostalCode.text = billingDetails.billingAddress.postalCode; - _txtBillingEmailAddress.text = billingDetails.billingAddress.emailAddress; + _txtShippingFirstName.text = billingDetails.billingAddress.firstName; + _txtShippingLastName.text = billingDetails.billingAddress.lastName; + _txtShippingAddressLine.text = billingDetails.billingAddress.addressLine; + _txtShippingCity.text = billingDetails.billingAddress.city; + _txtShippingPostalCode.text = billingDetails.billingAddress.postalCode; + _txtShippingEmailAddress.text = billingDetails.billingAddress.emailAddress; _strBillingCountry = billingDetails.billingAddress.country; valRememberDetails = billingDetails.rememberDetails ?? true; @@ -72,12 +72,12 @@ class _CheckoutDetailsPageState extends State { await CheckoutSession.getInstance.getBillingAddress(); if (sfCustomerAddress != null) { CustomerAddress customerAddress = sfCustomerAddress; - _txtBillingFirstName.text = customerAddress.firstName; - _txtBillingLastName.text = customerAddress.lastName; - _txtBillingAddressLine.text = customerAddress.addressLine; - _txtBillingCity.text = customerAddress.city; - _txtBillingPostalCode.text = customerAddress.postalCode; - _txtBillingEmailAddress.text = customerAddress.emailAddress; + _txtShippingFirstName.text = customerAddress.firstName; + _txtShippingLastName.text = customerAddress.lastName; + _txtShippingAddressLine.text = customerAddress.addressLine; + _txtShippingCity.text = customerAddress.city; + _txtShippingPostalCode.text = customerAddress.postalCode; + _txtShippingEmailAddress.text = customerAddress.emailAddress; _strBillingCountry = customerAddress.country; } } @@ -152,7 +152,7 @@ class _CheckoutDetailsPageState extends State { child: wsTextEditingRow( context, heading: trans(context, "First Name"), - controller: _txtBillingFirstName, + controller: _txtShippingFirstName, shouldAutoFocus: true, ), ), @@ -160,7 +160,7 @@ class _CheckoutDetailsPageState extends State { child: wsTextEditingRow( context, heading: trans(context, "Last Name"), - controller: _txtBillingLastName, + controller: _txtShippingLastName, ), ), ], @@ -170,21 +170,21 @@ class _CheckoutDetailsPageState extends State { wsTextEditingRow( context, heading: trans(context, "Address Line"), - controller: _txtBillingAddressLine, + controller: _txtShippingAddressLine, ), Row(children: [ Flexible( child: wsTextEditingRow( context, heading: trans(context, "City"), - controller: _txtBillingCity, + controller: _txtShippingCity, ), ), Flexible( child: wsTextEditingRow( context, heading: trans(context, "Postal code"), - controller: _txtBillingPostalCode, + controller: _txtShippingPostalCode, ), ), ]), @@ -194,7 +194,7 @@ class _CheckoutDetailsPageState extends State { child: wsTextEditingRow(context, heading: trans(context, "Email address"), keyboardType: TextInputType.emailAddress, - controller: _txtBillingEmailAddress), + controller: _txtShippingEmailAddress), ), Flexible( child: Padding( @@ -256,14 +256,15 @@ class _CheckoutDetailsPageState extends State { title: trans(context, "USE SHIPPING ADDRESS"), action: () { CustomerAddress customerAddress = new CustomerAddress(); - customerAddress.firstName = _txtBillingFirstName.text; - customerAddress.lastName = _txtBillingLastName.text; - customerAddress.addressLine = _txtBillingAddressLine.text; - customerAddress.city = _txtBillingCity.text; - customerAddress.postalCode = _txtBillingPostalCode.text; + customerAddress.firstName = _txtShippingFirstName.text; + customerAddress.lastName = _txtShippingLastName.text; + customerAddress.addressLine = + _txtShippingAddressLine.text; + customerAddress.city = _txtShippingCity.text; + customerAddress.postalCode = _txtShippingPostalCode.text; customerAddress.country = _strBillingCountry; customerAddress.emailAddress = - _txtBillingEmailAddress.text; + _txtShippingEmailAddress.text; CheckoutSession.getInstance.billingDetails .shippingAddress = customerAddress; diff --git a/LabelStoreMax/lib/pages/checkout_payment_type.dart b/LabelStoreMax/lib/pages/checkout_payment_type.dart index 7553c6d..efd288c 100644 --- a/LabelStoreMax/lib/pages/checkout_payment_type.dart +++ b/LabelStoreMax/lib/pages/checkout_payment_type.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/checkout_shipping_type.dart b/LabelStoreMax/lib/pages/checkout_shipping_type.dart index 6119db1..6b57661 100644 --- a/LabelStoreMax/lib/pages/checkout_shipping_type.dart +++ b/LabelStoreMax/lib/pages/checkout_shipping_type.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/checkout_status.dart b/LabelStoreMax/lib/pages/checkout_status.dart index 1a03c39..0efbd36 100644 --- a/LabelStoreMax/lib/pages/checkout_status.dart +++ b/LabelStoreMax/lib/pages/checkout_status.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/error_page.dart b/LabelStoreMax/lib/pages/error_page.dart index 2367f1c..69dc746 100644 --- a/LabelStoreMax/lib/pages/error_page.dart +++ b/LabelStoreMax/lib/pages/error_page.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/home.dart b/LabelStoreMax/lib/pages/home.dart index 4205fb2..264cf77 100644 --- a/LabelStoreMax/lib/pages/home.dart +++ b/LabelStoreMax/lib/pages/home.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/home_menu.dart b/LabelStoreMax/lib/pages/home_menu.dart index f853207..af4ce9b 100644 --- a/LabelStoreMax/lib/pages/home_menu.dart +++ b/LabelStoreMax/lib/pages/home_menu.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -9,6 +9,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import 'package:flutter/material.dart'; +import 'package:label_storemax/labelconfig.dart'; import 'package:label_storemax/widgets/menu_item.dart'; import 'package:label_storemax/helpers/tools.dart'; @@ -36,7 +37,7 @@ class _HomeMenuPageState extends State { backgroundColor: Colors.transparent, elevation: 0.0, title: Text(trans(context, "Menu"), - style: Theme.of(context).primaryTextTheme.subhead), + style: Theme.of(context).primaryTextTheme.title), leading: IconButton( icon: Icon(Icons.close), onPressed: () { @@ -57,6 +58,12 @@ class _HomeMenuPageState extends State { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + (use_wp_login + ? wsMenuItem(context, + title: trans(context, "Profile"), + leading: Icon(Icons.account_circle), + action: _actionProfile) + : Container()), wsMenuItem(context, title: trans(context, "Cart"), leading: Icon(Icons.shopping_cart), @@ -81,4 +88,8 @@ class _HomeMenuPageState extends State { void _actionAboutUs() { Navigator.pushNamed(context, "/about"); } + + void _actionProfile() { + Navigator.pushNamed(context, "/account-detail"); + } } diff --git a/LabelStoreMax/lib/pages/home_search.dart b/LabelStoreMax/lib/pages/home_search.dart index ba2c32f..8551b41 100644 --- a/LabelStoreMax/lib/pages/home_search.dart +++ b/LabelStoreMax/lib/pages/home_search.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software diff --git a/LabelStoreMax/lib/pages/product_detail.dart b/LabelStoreMax/lib/pages/product_detail.dart index ba94d3c..35d840c 100644 --- a/LabelStoreMax/lib/pages/product_detail.dart +++ b/LabelStoreMax/lib/pages/product_detail.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -305,9 +305,7 @@ class _ProductDetailState extends State { itemCount: _product.images.length, viewportFraction: 0.85, scale: 0.9, - onTap: (i) { - setState(() {}); - }, + onTap: _productImageTapped, ), ), ), @@ -541,4 +539,12 @@ class _ProductDetailState extends State { icon: Icons.local_shipping); } } + + _productImageTapped(int i) { + Map obj = { + "index": i, + "images": _product.images.map((f) => f.src).toList() + }; + Navigator.pushNamed(context, "/product-images", arguments: obj); + } } diff --git a/LabelStoreMax/lib/pages/product_image_viewer_page.dart b/LabelStoreMax/lib/pages/product_image_viewer_page.dart new file mode 100644 index 0000000..bbfa233 --- /dev/null +++ b/LabelStoreMax/lib/pages/product_image_viewer_page.dart @@ -0,0 +1,79 @@ +// PRODUCT DETAIL NEW +// 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/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:flutter_swiper/flutter_swiper.dart'; +import 'package:cached_network_image/cached_network_image.dart'; + +class ProductImageViewerPage extends StatefulWidget { + final int initialIndex; + final List arrImageSrc; + + const ProductImageViewerPage({Key key, this.initialIndex, this.arrImageSrc}) + : super(key: key); + + @override + _ProductImageViewerPageState createState() => + _ProductImageViewerPageState(this.initialIndex, this.arrImageSrc); +} + +class _ProductImageViewerPageState extends State { + _ProductImageViewerPageState(this._initialIndex, this._arrImageSrc); + + int _initialIndex; + List _arrImageSrc; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + minimum: safeAreaDefault(), + child: Column( + children: [ + Expanded( + child: Swiper( + 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); + }, + itemCount: _arrImageSrc.length, + viewportFraction: 0.9, + scale: 0.95, + ), + ), + Container( + child: IconButton( + icon: Icon(Icons.close), + onPressed: () { + Navigator.pop(context); + }, + ), + ) + ], + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/providers/stripe_pay.dart b/LabelStoreMax/lib/providers/stripe_pay.dart index 4f5ef39..c55277a 100644 --- a/LabelStoreMax/lib/providers/stripe_pay.dart +++ b/LabelStoreMax/lib/providers/stripe_pay.dart @@ -3,13 +3,14 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 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/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:label_storemax/helpers/data/order_wc.dart'; @@ -57,8 +58,8 @@ stripePay(context, if (rsp == null) { showEdgeAlertWith(context, - title: "Oops!", - desc: "Something went wrong, please try again.", + title: trans(context, "Oops!"), + desc: trans(context, "Something went wrong, please try again."), icon: Icons.payment, style: EdgeAlertStyle.WARNING); state.reloadState(showLoader: false); @@ -86,7 +87,9 @@ stripePay(context, context, title: trans(context, "Error"), desc: trans( - context, "Something went wrong, please contact our store"), + context, + trans( + context, "Something went wrong, please contact our store")), ); state.reloadState(showLoader: false); } diff --git a/LabelStoreMax/lib/widgets/app_loader.dart b/LabelStoreMax/lib/widgets/app_loader.dart index 0370660..1a24d64 100644 --- a/LabelStoreMax/lib/widgets/app_loader.dart +++ b/LabelStoreMax/lib/widgets/app_loader.dart @@ -1,3 +1,13 @@ +// 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:flutter_spinkit/flutter_spinkit.dart'; import '../helpers/tools.dart'; diff --git a/LabelStoreMax/lib/widgets/buttons.dart b/LabelStoreMax/lib/widgets/buttons.dart index 3cb88dc..d9a1496 100644 --- a/LabelStoreMax/lib/widgets/buttons.dart +++ b/LabelStoreMax/lib/widgets/buttons.dart @@ -1,3 +1,13 @@ +// 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/cupertino.dart'; import 'package:flutter/material.dart'; @@ -42,11 +52,12 @@ Widget wsLinkButton(BuildContext context, height: 60, margin: EdgeInsets.only(top: 10), child: MaterialButton( - padding: EdgeInsets.all(10), - child: Text(title, - style: Theme.of(context).primaryTextTheme.body2, - textAlign: TextAlign.left), - onPressed: action, - elevation: 0), + padding: EdgeInsets.all(10), + child: Text(title, + style: Theme.of(context).primaryTextTheme.body2, + textAlign: TextAlign.left), + onPressed: action, + elevation: 0, + ), ); } diff --git a/LabelStoreMax/lib/widgets/cart_icon.dart b/LabelStoreMax/lib/widgets/cart_icon.dart index 6030f3e..a2964ef 100644 --- a/LabelStoreMax/lib/widgets/cart_icon.dart +++ b/LabelStoreMax/lib/widgets/cart_icon.dart @@ -1,3 +1,13 @@ +// 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/material.dart'; import 'package:label_storemax/models/cart.dart'; import 'package:label_storemax/models/cart_line_item.dart'; diff --git a/LabelStoreMax/lib/widgets/menu_item.dart b/LabelStoreMax/lib/widgets/menu_item.dart index 3b13523..d97b4ab 100644 --- a/LabelStoreMax/lib/widgets/menu_item.dart +++ b/LabelStoreMax/lib/widgets/menu_item.dart @@ -1,3 +1,13 @@ +// 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/material.dart'; Widget wsMenuItem(BuildContext context, diff --git a/LabelStoreMax/lib/widgets/woosignal_ui.dart b/LabelStoreMax/lib/widgets/woosignal_ui.dart index 49a5aa6..ae86b89 100644 --- a/LabelStoreMax/lib/widgets/woosignal_ui.dart +++ b/LabelStoreMax/lib/widgets/woosignal_ui.dart @@ -1,7 +1,7 @@ // Label StoreMAX // // Created by Anthony Gordon. -// Copyright © 2020 WooSignal. All rights reserved. +// 2020, WooSignal Ltd. All rights reserved. // // Unless required by applicable law or agreed to in writing, software @@ -73,27 +73,34 @@ Widget wsCheckoutRow(BuildContext context, style: Theme.of(context).primaryTextTheme.body1), padding: EdgeInsets.only(bottom: 8), ), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - leadImage, - Container( - child: Text(leadTitle, - style: Theme.of(context).primaryTextTheme.subhead, - maxLines: 2, - overflow: TextOverflow.ellipsis, - softWrap: false), - padding: EdgeInsets.only(left: 15), - ) - ], - ), - Icon(Icons.arrow_forward_ios) - ], + Flexible( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + leadImage, + Flexible( + child: Container( + child: Text(leadTitle, + style: + Theme.of(context).primaryTextTheme.subhead, + maxLines: 2, + overflow: TextOverflow.ellipsis, + softWrap: false), + padding: EdgeInsets.only(left: 15), + ), + ) + ], + ), + ), + Icon(Icons.arrow_forward_ios) + ], + ), ) ], ), @@ -115,23 +122,30 @@ Widget wsTextEditingRow(BuildContext context, {heading: String, TextEditingController controller, bool shouldAutoFocus, - TextInputType keyboardType}) { + TextInputType keyboardType, + bool obscureText}) { return Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - Padding( - child: Text(heading, style: Theme.of(context).primaryTextTheme.body2), - padding: EdgeInsets.only(bottom: 2), + Flexible( + child: Padding( + child: + Text(heading, style: Theme.of(context).primaryTextTheme.body2), + padding: EdgeInsets.only(bottom: 2), + ), ), - TextField( - controller: controller, - style: Theme.of(context).primaryTextTheme.subhead, - keyboardType: keyboardType ?? TextInputType.text, - autocorrect: false, - autofocus: shouldAutoFocus ?? false, - textCapitalization: TextCapitalization.sentences) + Flexible( + child: TextField( + controller: controller, + style: Theme.of(context).primaryTextTheme.subhead, + keyboardType: keyboardType ?? TextInputType.text, + autocorrect: false, + autofocus: shouldAutoFocus ?? false, + obscureText: obscureText ?? false, + textCapitalization: TextCapitalization.sentences), + ) ], ), padding: EdgeInsets.all(2), @@ -385,6 +399,7 @@ Widget wsCardCartItem(BuildContext context, void Function() actionDecrementQuantity, void Function() actionRemoveItem}) { return Container( + margin: EdgeInsets.only(bottom: 7), decoration: BoxDecoration( color: Colors.white, border: Border( @@ -493,12 +508,13 @@ Widget storeLogo({double height, double width}) { Widget cachedImage(image, {double height, Widget placeholder, BoxFit fit}) { return CachedNetworkImage( - imageUrl: image, - placeholder: (context, url) => - placeholder ?? new CircularProgressIndicator(), - errorWidget: (context, url, error) => new Icon(Icons.error), - height: height ?? null, - width: null, - alignment: Alignment.center, - fit: fit); + imageUrl: image, + placeholder: (context, url) => + placeholder ?? new CircularProgressIndicator(), + errorWidget: (context, url, error) => new Icon(Icons.error), + height: height ?? null, + width: null, + alignment: Alignment.center, + fit: fit, + ); } diff --git a/LabelStoreMax/pubspec.lock b/LabelStoreMax/pubspec.lock index 97cb2e1..2db22a6 100644 --- a/LabelStoreMax/pubspec.lock +++ b/LabelStoreMax/pubspec.lock @@ -29,6 +29,20 @@ packages: 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" + bubble_tab_indicator: + dependency: "direct main" + description: + name: bubble_tab_indicator + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" cached_network_image: dependency: "direct main" description: @@ -195,7 +209,7 @@ packages: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.12.0+2" + version: "0.12.0+4" http_parser: dependency: transitive description: @@ -217,6 +231,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.16.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.1+1" matcher: dependency: transitive description: @@ -287,6 +308,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.2.1" + platform_alert_dialog: + dependency: "direct main" + description: + name: platform_alert_dialog + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0+2" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" quiver: dependency: transitive description: @@ -389,7 +424,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: @@ -404,6 +439,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.6" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + url: "https://pub.dartlang.org" + source: hosted + version: "5.4.5" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+5" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.6" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.1+2" uuid: dependency: transitive description: @@ -432,6 +495,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.0.4" + wp_json_api: + dependency: "direct main" + description: + path: "../../wp_json_mobile_api" + relative: true + source: path + version: "0.0.2" xml: dependency: transitive description: diff --git a/LabelStoreMax/pubspec.yaml b/LabelStoreMax/pubspec.yaml index 6c7936a..acc9029 100644 --- a/LabelStoreMax/pubspec.yaml +++ b/LabelStoreMax/pubspec.yaml @@ -25,21 +25,27 @@ environment: dependencies: woosignal: ^1.0.6 woosignal_stripe: ^0.0.4 + wp_json_api: + path: ../../wp_json_mobile_api shared_preferences: ^0.5.6+3 cached_network_image: ^2.0.0 page_transition: ^1.1.5 package_info: ^0.4.0+16 + url_launcher: ^5.4.5 flutter_money_formatter: ^0.8.3 + platform_alert_dialog: ^1.0.0+2 flutter_web_browser: ^0.11.0 dio: ^3.0.9 - intl: ^0.15.8 + intl: ^0.16.1 flutter_swiper: ^1.1.6 edge_alert: ^0.0.1 + bubble_tab_indicator: ^0.1.4 status_alert: ^0.1.1 math_expressions: ^2.0.0 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