v6.6.0 updates
This commit is contained in:
parent
004c146967
commit
da2301a2af
@ -49,4 +49,6 @@ RAZORPAY_API_KEY=""
|
||||
# *<! ------ EXTRAS ------!>*
|
||||
|
||||
PRODUCT_PLACEHOLDER_IMAGE="https://woosignal.com/images/woocommerce-placeholder.png"
|
||||
# Sets the default placeholder image for products with no image
|
||||
# Sets the default placeholder image for products with no image
|
||||
|
||||
AUTH_USER_KEY="AUTH_USER"
|
||||
@ -1,3 +1,9 @@
|
||||
## [6.6.0] - 2023-05-18
|
||||
|
||||
* Nylo v5.0.0 migration
|
||||
* Refactor project
|
||||
* Flutter v3.10.0 compatibility
|
||||
|
||||
## [6.5.1] - 2023-03-04
|
||||
|
||||
* New translation added.
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
# WooCommerce App: Label StoreMax
|
||||
|
||||
### Label StoreMax - v6.5.1
|
||||
### Label StoreMax - v6.6.0
|
||||
|
||||
|
||||
[Official WooSignal WooCommerce App](https://woosignal.com)
|
||||
@ -44,7 +44,7 @@ Full documentation this available [here](https://woosignal.com/docs/app/label-st
|
||||
- Browse products, make orders, customer login (via WordPress)
|
||||
- Change app name, logo, customize default language, currency + more
|
||||
- Light and dark mode
|
||||
- Stripe, Cash On Delivery, PayPal, RazorPay
|
||||
- Stripe, Cash On Delivery, PayPal
|
||||
- Localized for en, es, pt, it, hi, fr, zh, tr, nl, de
|
||||
- Orders show as normal in WooCommerce
|
||||
|
||||
|
||||
@ -204,6 +204,7 @@
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
@ -16,12 +18,8 @@
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>You can take photos of your payment details.</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
@ -39,11 +37,17 @@
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>You can take photos of your payment details.</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
@ -61,9 +65,5 @@
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@ -10,18 +10,16 @@
|
||||
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
class User extends Storable {
|
||||
class User extends Model {
|
||||
String? userId;
|
||||
String? token;
|
||||
|
||||
User();
|
||||
User.fromUserAuthResponse({this.userId, this.token});
|
||||
|
||||
@override
|
||||
toStorage() => {"token": token, "user_id": userId};
|
||||
toJson() => {"token": token, "user_id": userId};
|
||||
|
||||
@override
|
||||
fromStorage(dynamic data) {
|
||||
fromJson(dynamic data) {
|
||||
token = data['token'];
|
||||
userId = data['user_id'];
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import 'package:nylo_framework/nylo_framework.dart';
|
||||
| ApiService
|
||||
| -------------------------------------------------------------------------
|
||||
| Define your API endpoints
|
||||
| Learn more https://nylo.dev/docs/4.x/networking
|
||||
| Learn more https://nylo.dev/docs/5.x/networking
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
@ -4,8 +4,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_app/bootstrap/app_helper.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/config/decoders.dart';
|
||||
import 'package:flutter_app/config/design.dart';
|
||||
import 'package:flutter_app/config/theme.dart';
|
||||
import 'package:flutter_app/config/validation_rules.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
import 'package:flutter_app/config/localization.dart';
|
||||
import 'package:woosignal/models/response/woosignal_app.dart';
|
||||
@ -112,12 +114,14 @@ class AppProvider implements NyProvider {
|
||||
nylo.appLoader = loader;
|
||||
nylo.appLogo = logo;
|
||||
|
||||
String initialRoute = AppHelper.instance.appConfig!.appStatus != null
|
||||
? '/home'
|
||||
: '/no-connection';
|
||||
|
||||
nylo.initialRoute = initialRoute;
|
||||
nylo.addModelDecoders(modelDecoders);
|
||||
nylo.addValidationRules(validationRules);
|
||||
|
||||
return nylo;
|
||||
}
|
||||
|
||||
@override
|
||||
afterBoot(Nylo nylo) async {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,4 +8,9 @@ class EventProvider implements NyProvider {
|
||||
|
||||
return nylo;
|
||||
}
|
||||
|
||||
@override
|
||||
afterBoot(Nylo nylo) async {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,81 +0,0 @@
|
||||
//
|
||||
// LabelCore
|
||||
// Label StoreMAX
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2023, 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_app/app/models/cart.dart';
|
||||
import 'package:flutter_app/bootstrap/data/order_wc.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/resources/pages/checkout_confirmation_page.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
import 'package:razorpay_flutter/razorpay_flutter.dart';
|
||||
import 'package:woosignal/models/response/tax_rate.dart';
|
||||
import 'package:woosignal/models/payload/order_wc.dart';
|
||||
import 'package:woosignal/models/response/order.dart';
|
||||
|
||||
razorPay(context,
|
||||
{required CheckoutConfirmationPageState state, TaxRate? taxRate}) async {
|
||||
Razorpay razorpay = Razorpay();
|
||||
|
||||
razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS,
|
||||
(PaymentSuccessResponse response) async {
|
||||
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
|
||||
|
||||
Order? order = await appWooSignal((api) => api.createOrder(orderWC));
|
||||
|
||||
if (order != null) {
|
||||
Cart.getInstance.clear();
|
||||
Navigator.pushNamed(context, "/checkout-status", arguments: order);
|
||||
} else {
|
||||
showToastNotification(
|
||||
context,
|
||||
title: "Error".tr(),
|
||||
description: trans("Something went wrong, please contact our store"),
|
||||
);
|
||||
state.reloadState(showLoader: false);
|
||||
}
|
||||
});
|
||||
|
||||
razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, (PaymentFailureResponse response) {
|
||||
showToastNotification(context,
|
||||
title: trans("Error"),
|
||||
description: response.message ?? "",
|
||||
style: ToastNotificationStyleType.WARNING);
|
||||
state.reloadState(showLoader: false);
|
||||
});
|
||||
|
||||
razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet);
|
||||
|
||||
// CHECKOUT HELPER
|
||||
await checkout(taxRate, (total, billingDetails, cart) async {
|
||||
var options = {
|
||||
'key': getEnv('RAZORPAY_API_KEY'),
|
||||
'amount': (double.parse(total) * 100).toInt(),
|
||||
'name': getEnv('APP_NAME'),
|
||||
'description': await cart.cartShortDesc(),
|
||||
'prefill': {
|
||||
"name": [
|
||||
billingDetails!.billingAddress?.firstName,
|
||||
billingDetails.billingAddress?.lastName
|
||||
].where((t) => t != null || t != "").toList().join(" "),
|
||||
"method": "card",
|
||||
'email': billingDetails.billingAddress?.emailAddress ?? ""
|
||||
}
|
||||
};
|
||||
|
||||
state.reloadState(showLoader: true);
|
||||
|
||||
razorpay.open(options);
|
||||
});
|
||||
}
|
||||
|
||||
void _handleExternalWallet(ExternalWalletResponse response) {}
|
||||
@ -1,3 +1,4 @@
|
||||
import 'package:flutter_app/bootstrap/app_helper.dart';
|
||||
import 'package:flutter_app/routes/router.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
@ -8,4 +9,12 @@ class RouteProvider implements NyProvider {
|
||||
|
||||
return nylo;
|
||||
}
|
||||
|
||||
@override
|
||||
afterBoot(Nylo nylo) async {
|
||||
String initialRoute = AppHelper.instance.appConfig!.appStatus != null
|
||||
? '/home'
|
||||
: '/no-connection';
|
||||
nylo.setInitialRoute(initialRoute);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,8 @@
|
||||
// import 'package:firebase_core/firebase_core.dart';
|
||||
// import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
// import 'package:flutter_app/firebase_options.dart';
|
||||
|
||||
/// boot application
|
||||
import 'package:flutter_app/config/providers.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
class Boot {
|
||||
static Future<Nylo> nylo() async => await bootApplication(providers);
|
||||
static Future<void> finished(Nylo nylo) async => await bootFinished(nylo);
|
||||
static Future<void> finished(Nylo nylo) async => await bootFinished(nylo, providers);
|
||||
}
|
||||
|
||||
@ -138,3 +138,37 @@ extension NyText on Text {
|
||||
style: style != null ? this.style?.merge(style) ?? style : this.style);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the [Product] is new.
|
||||
extension DateTimeExtension on DateTime? {
|
||||
bool? isAfterOrEqualTo(DateTime dateTime) {
|
||||
final date = this;
|
||||
if (date != null) {
|
||||
final isAtSameMomentAs = dateTime.isAtSameMomentAs(date);
|
||||
return isAtSameMomentAs | date.isAfter(dateTime);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool? isBeforeOrEqualTo(DateTime dateTime) {
|
||||
final date = this;
|
||||
if (date != null) {
|
||||
final isAtSameMomentAs = dateTime.isAtSameMomentAs(date);
|
||||
return isAtSameMomentAs | date.isBefore(dateTime);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool? isBetween(
|
||||
DateTime fromDateTime,
|
||||
DateTime toDateTime,
|
||||
) {
|
||||
final date = this;
|
||||
if (date != null) {
|
||||
final isAfter = date.isAfterOrEqualTo(fromDateTime) ?? false;
|
||||
final isBefore = date.isBeforeOrEqualTo(toDateTime) ?? false;
|
||||
return isAfter && isBefore;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -20,6 +20,7 @@ import 'package:flutter_app/app/models/payment_type.dart';
|
||||
import 'package:flutter_app/app/models/user.dart';
|
||||
import 'package:flutter_app/bootstrap/app_helper.dart';
|
||||
import 'package:flutter_app/bootstrap/enums/symbol_position_enums.dart';
|
||||
import 'package:flutter_app/bootstrap/extensions.dart';
|
||||
import 'package:flutter_app/bootstrap/shared_pref/shared_key.dart';
|
||||
import 'package:flutter_app/config/currency.dart';
|
||||
import 'package:flutter_app/config/decoders.dart';
|
||||
@ -45,7 +46,7 @@ import '../resources/themes/styles/color_styles.dart';
|
||||
import 'package:flutter/services.dart' show rootBundle;
|
||||
|
||||
Future<User?> getUser() async =>
|
||||
(await (NyStorage.read<User>(SharedKey.authUser, model: User())));
|
||||
(await (NyStorage.read<User>(SharedKey.authUser)));
|
||||
|
||||
Future appWooSignal(Function(WooSignal) api) async {
|
||||
return await api(WooSignal.instance);
|
||||
@ -156,6 +157,7 @@ String moneyFormatter(double amount) {
|
||||
amount: amount,
|
||||
settings: MoneyFormatterSettings(
|
||||
symbol: AppHelper.instance.appConfig!.currencyMeta!.symbolNative,
|
||||
symbolAndNumberSeparator: ""
|
||||
),
|
||||
);
|
||||
if (appCurrencySymbolPosition == SymbolPositionType.left) {
|
||||
@ -486,7 +488,7 @@ Widget refreshableScroll(context,
|
||||
return StaggeredGridTile.fit(
|
||||
crossAxisCellCount: 1,
|
||||
child: Container(
|
||||
height: 200,
|
||||
height: 350,
|
||||
child: ProductItemContainer(
|
||||
product: product,
|
||||
onTap: onTap,
|
||||
@ -654,3 +656,15 @@ api<T>(dynamic Function(T) request, {BuildContext? context}) async =>
|
||||
|
||||
/// Event helper
|
||||
event<T>({Map? data}) async => nyEvent<T>(params: data, events: events);
|
||||
|
||||
/// Check if the [Product] is new.
|
||||
bool isProductNew(Product? product) {
|
||||
if (product?.dateCreatedGMT == null) false;
|
||||
try {
|
||||
DateTime dateTime = DateTime.parse(product!.dateCreatedGMT!);
|
||||
return dateTime.isBetween(DateTime.now().subtract(Duration(days: 2)), DateTime.now()) ?? false;
|
||||
} on Exception catch (e) {
|
||||
NyLogger.error(e.toString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -6,7 +6,7 @@ import 'package:flutter_app/app/networking/dio/base_api_service.dart';
|
||||
| Model Decoders
|
||||
| -------------------------------------------------------------------------
|
||||
| Model decoders are used in 'app/networking/' for morphing json payloads
|
||||
| into Models. Learn more https://nylo.dev/docs/4.x/decoders#model-decoders
|
||||
| into Models. Learn more https://nylo.dev/docs/5.x/decoders#model-decoders
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -20,7 +20,7 @@ final Map<Type, dynamic> modelDecoders = {
|
||||
| -------------------------------------------------------------------------
|
||||
| API decoders are used when you need to access an API service using the
|
||||
| 'api' helper. E.g. api<MyApiService>((request) => request.fetchData());
|
||||
| Learn more https://nylo.dev/docs/4.x/decoders#api-decoders
|
||||
| Learn more https://nylo.dev/docs/5.x/decoders#api-decoders
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
| Design
|
||||
| Contains widgets used in the Nylo framework.
|
||||
|
|
||||
| Learn more: https://nylo.dev/docs/4.x/themes
|
||||
| Learn more: https://nylo.dev/docs/5.x/themes
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import 'package:nylo_framework/nylo_framework.dart';
|
||||
| Add your "app/events" here.
|
||||
| Events can be fired using: event<MyEvent>();
|
||||
|
|
||||
| Learn more: https://nylo.dev/docs/4.x/events
|
||||
| Learn more: https://nylo.dev/docs/5.x/events
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import 'package:flutter_app/app/models/payment_type.dart';
|
||||
import 'package:flutter_app/app/providers/payments/cash_on_delivery.dart';
|
||||
import 'package:flutter_app/app/providers/payments/paypal_pay.dart';
|
||||
import 'package:flutter_app/app/providers/payments/razorpay_pay.dart';
|
||||
import 'package:flutter_app/app/providers/payments/stripe_pay.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
@ -44,14 +43,6 @@ List<PaymentType> paymentTypeList = [
|
||||
pay: payPalPay,
|
||||
),
|
||||
|
||||
addPayment(
|
||||
id: 5,
|
||||
name: "RazorPay",
|
||||
description: trans("Debit or Credit Card"),
|
||||
assetImage: "razorpay.png",
|
||||
pay: razorPay,
|
||||
),
|
||||
|
||||
// e.g. add more here
|
||||
|
||||
// addPayment(
|
||||
|
||||
@ -9,7 +9,7 @@ import 'package:nylo_framework/nylo_framework.dart';
|
||||
| Add your "app/providers" here.
|
||||
| Providers are booted when your application start.
|
||||
|
|
||||
| Learn more: https://nylo.dev/docs/4.x/providers
|
||||
| Learn more: https://nylo.dev/docs/5.x/providers
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
@ -5,12 +5,15 @@
|
||||
| E.g. static String userCoins = "USER_COINS";
|
||||
| String coins = NyStorage.read( StorageKey.userCoins );
|
||||
|
|
||||
| Learn more: https://nylo.dev/docs/4.x/storage#storage-keys
|
||||
| Learn more: https://nylo.dev/docs/5.x/storage#storage-keys
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
class StorageKey {
|
||||
static String userToken = "USER_TOKEN";
|
||||
static String authUser = getEnv('AUTH_USER_KEY', defaultValue: 'AUTH_USER');
|
||||
|
||||
/// Add your storage keys here...
|
||||
}
|
||||
|
||||
37
LabelStoreMax/lib/config/validation_rules.dart
Normal file
37
LabelStoreMax/lib/config/validation_rules.dart
Normal file
@ -0,0 +1,37 @@
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validation Rules
|
||||
| -------------------------------------------------------------------------
|
||||
| Add custom validation rules for your project in this file.
|
||||
| Learn more https://nylo.dev/docs/5.x/validation#custom-validation-rules
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
final Map<Type, dynamic> validationRules = {
|
||||
/// Example
|
||||
// SimplePassword: (attribute) => SimplePassword(attribute)
|
||||
};
|
||||
|
||||
/// Example validation class
|
||||
// class SimplePassword extends ValidationRule {
|
||||
// SimplePassword(String attribute)
|
||||
// : super(
|
||||
// attribute: attribute,
|
||||
// signature: "simple_password", // Use this signature for the validator
|
||||
// description: "The $attribute field must be between 4 and 8 digits long and include at least one numeric digit", // Toast description when an error occurs
|
||||
// textFieldMessage: "Must be between 4 and 8 digits long with one numeric digit"); // TextField description when an error occurs
|
||||
//
|
||||
// @override
|
||||
// handle(Map<String, dynamic> info) {
|
||||
// super.handle(info);
|
||||
//
|
||||
// /// info['rule'] = Validation rule i.e "min".
|
||||
// /// info['data'] = Data the user has passed into the validation.
|
||||
// /// info['message'] = Overriding message to be displayed for validation (optional).
|
||||
//
|
||||
// RegExp regExp = RegExp(r'^(?=.*\d).{4,8}$');
|
||||
// return regExp.hasMatch(info['data']);
|
||||
// }
|
||||
// }
|
||||
@ -11,7 +11,7 @@ void main() async {
|
||||
AppBuild(
|
||||
navigatorKey: NyNavigator.instance.router.navigatorKey,
|
||||
onGenerateRoute: nylo.router!.generator(),
|
||||
initialRoute: nylo.initialRoute,
|
||||
initialRoute: nylo.getInitialRoute(),
|
||||
debugShowCheckedModeBanner: false,
|
||||
),
|
||||
);
|
||||
|
||||
@ -35,11 +35,6 @@ class _AccountLandingPageState extends NyState<AccountLandingPage> {
|
||||
final TextEditingController _tfEmailController = TextEditingController(),
|
||||
_tfPasswordController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -231,7 +226,7 @@ class _AccountLandingPageState extends NyState<AccountLandingPage> {
|
||||
String? token = wpUserLoginResponse.data!.userToken;
|
||||
String userId = wpUserLoginResponse.data!.userId.toString();
|
||||
User user = User.fromUserAuthResponse(token: token, userId: userId);
|
||||
await user.save(SharedKey.authUser);
|
||||
await Auth.set(user, key: SharedKey.authUser);
|
||||
|
||||
showToastNotification(context,
|
||||
title: trans("Hello"),
|
||||
|
||||
@ -48,11 +48,6 @@ class _AccountRegistrationPageState extends NyState<AccountRegistrationPage> {
|
||||
|
||||
final WooSignalApp? _wooSignalApp = AppHelper.instance.appConfig;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -241,7 +236,7 @@ class _AccountRegistrationPageState extends NyState<AccountRegistrationPage> {
|
||||
String? token = wpUserRegisterResponse.data!.userToken;
|
||||
String userId = wpUserRegisterResponse.data!.userId.toString();
|
||||
User user = User.fromUserAuthResponse(token: token, userId: userId);
|
||||
await user.save(SharedKey.authUser);
|
||||
await Auth.set(user, key: SharedKey.authUser);
|
||||
|
||||
await WPJsonAPI.instance.api((request) => request.wpUpdateUserInfo(token,
|
||||
firstName: firstName, lastName: lastName));
|
||||
|
||||
@ -85,7 +85,8 @@ class _BrowseCategoryPageState extends NyState<BrowseCategoryPage> {
|
||||
onRefresh: _onRefresh,
|
||||
onLoading: _onLoading,
|
||||
products: _productCategorySearchLoaderController.getResults(),
|
||||
onTap: _showProduct),
|
||||
onTap: _showProduct,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -135,42 +135,41 @@ class _LeaveReviewPageState extends NyState<LeaveReviewPage> {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
validator(rules: {"review": "min:5"}, data: {"review": review});
|
||||
|
||||
ProductReview? productReview =
|
||||
await validate(
|
||||
rules: {"review": "min:5"},
|
||||
data: {"review": review},
|
||||
onSuccess: () async {
|
||||
ProductReview? productReview =
|
||||
await (appWooSignal((api) => api.createProductReview(
|
||||
productId: _lineItem!.productId,
|
||||
verified: true,
|
||||
review: review,
|
||||
status: "approved",
|
||||
reviewer: [
|
||||
_order!.billing!.firstName,
|
||||
_order!.billing!.lastName
|
||||
].join(" "),
|
||||
rating: _rating,
|
||||
reviewerEmail: _order!.billing!.email,
|
||||
)));
|
||||
productId: _lineItem!.productId,
|
||||
verified: true,
|
||||
review: review,
|
||||
status: "approved",
|
||||
reviewer: [
|
||||
_order!.billing!.firstName,
|
||||
_order!.billing!.lastName
|
||||
].join(" "),
|
||||
rating: _rating,
|
||||
reviewerEmail: _order!.billing!.email,
|
||||
)));
|
||||
|
||||
if (productReview == null) {
|
||||
showToastNotification(context,
|
||||
title: trans("Oops"),
|
||||
description: trans("Something went wrong"),
|
||||
style: ToastNotificationStyleType.INFO);
|
||||
return;
|
||||
}
|
||||
showToastNotification(context,
|
||||
title: trans("Success"),
|
||||
description: trans("Your review has been submitted"),
|
||||
style: ToastNotificationStyleType.SUCCESS);
|
||||
pop(result: _lineItem);
|
||||
} on ValidationException catch (e) {
|
||||
NyLogger.error(e.toString());
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
if (productReview == null) {
|
||||
showToastNotification(context,
|
||||
title: trans("Oops"),
|
||||
description: trans("Something went wrong"),
|
||||
style: ToastNotificationStyleType.INFO);
|
||||
return;
|
||||
}
|
||||
showToastNotification(context,
|
||||
title: trans("Success"),
|
||||
description: trans("Your review has been submitted"),
|
||||
style: ToastNotificationStyleType.SUCCESS);
|
||||
pop(result: _lineItem);
|
||||
});
|
||||
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
Future<wc_customer_info.Data?> _fetchWpUserData() async {
|
||||
|
||||
@ -17,7 +17,6 @@ import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/buttons.dart';
|
||||
import 'package:flutter_app/resources/widgets/cart_icon_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/future_build_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/product_detail_body_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/product_detail_footer_actions_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
@ -232,9 +231,9 @@ class _ProductDetailState extends NyState<ProductDetailPage> {
|
||||
appBar: AppBar(
|
||||
actions: <Widget>[
|
||||
if (_wooSignalApp!.wishlistEnabled!)
|
||||
FutureBuildWidget(
|
||||
asyncFuture: hasAddedWishlistProduct(_product!.id),
|
||||
onValue: (dynamic isInFavourites) {
|
||||
NyFutureBuilder(
|
||||
future: hasAddedWishlistProduct(_product!.id),
|
||||
child: (context, dynamic isInFavourites) {
|
||||
return isInFavourites
|
||||
? IconButton(
|
||||
onPressed: () => widget.controller.toggleWishList(
|
||||
|
||||
@ -29,6 +29,7 @@ ThemeData lightTheme(ColorStyles lightColors) {
|
||||
getAppTextTheme(appFont, defaultTextTheme.merge(_textTheme(lightColors)));
|
||||
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
primaryColor: lightColors.primaryContent,
|
||||
primaryColorLight: lightColors.primaryAccent,
|
||||
focusColor: lightColors.primaryContent,
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
import 'package:package_info/package_info.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
class AppVersionWidget extends StatelessWidget {
|
||||
const AppVersionWidget({Key? key}) : super(key: key);
|
||||
|
||||
@ -23,45 +23,48 @@ class CartIconWidget extends StatefulWidget {
|
||||
class _CartIconWidgetState extends State<CartIconWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IconButton(
|
||||
icon: Stack(
|
||||
children: <Widget>[
|
||||
Positioned.fill(
|
||||
child: Align(
|
||||
child: Icon(Icons.shopping_cart, size: 20),
|
||||
alignment: Alignment.bottomCenter,
|
||||
),
|
||||
bottom: 0,
|
||||
),
|
||||
Positioned.fill(
|
||||
child: Align(
|
||||
child: NyFutureBuilder<List<CartLineItem>>(
|
||||
future: Cart.getInstance.getCart(),
|
||||
child: (BuildContext context,
|
||||
data) {
|
||||
List<int?> cartItems =
|
||||
data.map((e) => e.quantity).toList();
|
||||
String cartValue = "0";
|
||||
if (cartItems.isNotEmpty) {
|
||||
cartValue = cartItems
|
||||
.reduce((value, element) => value! + element!)
|
||||
.toString();
|
||||
}
|
||||
return Text(
|
||||
cartValue,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
},
|
||||
return Container(
|
||||
width: 70,
|
||||
child: IconButton(
|
||||
icon: Stack(
|
||||
children: <Widget>[
|
||||
Positioned.fill(
|
||||
child: Align(
|
||||
child: Icon(Icons.shopping_cart, size: 20),
|
||||
alignment: Alignment.bottomCenter,
|
||||
),
|
||||
alignment: Alignment.topCenter,
|
||||
bottom: 0,
|
||||
),
|
||||
top: 0,
|
||||
)
|
||||
],
|
||||
Positioned.fill(
|
||||
child: Align(
|
||||
child: NyFutureBuilder<List<CartLineItem>>(
|
||||
future: Cart.getInstance.getCart(),
|
||||
child: (BuildContext context,
|
||||
data) {
|
||||
List<int?> cartItems =
|
||||
data.map((e) => e.quantity).toList();
|
||||
String cartValue = "0";
|
||||
if (cartItems.isNotEmpty) {
|
||||
cartValue = cartItems
|
||||
.reduce((value, element) => value! + element!)
|
||||
.toString();
|
||||
}
|
||||
return Text(
|
||||
cartValue,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
},
|
||||
),
|
||||
alignment: Alignment.topCenter,
|
||||
),
|
||||
top: 0,
|
||||
)
|
||||
],
|
||||
),
|
||||
onPressed: () => Navigator.pushNamed(context, "/cart")
|
||||
.then((value) => setState(() {})),
|
||||
),
|
||||
onPressed: () => Navigator.pushNamed(context, "/cart")
|
||||
.then((value) => setState(() {})),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
// Label StoreMax
|
||||
//
|
||||
// Created by Anthony Gordon.
|
||||
// 2023, 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';
|
||||
|
||||
class FutureBuildWidget<T> extends StatelessWidget {
|
||||
const FutureBuildWidget(
|
||||
{Key? key,
|
||||
required this.asyncFuture,
|
||||
required this.onValue,
|
||||
this.onLoading})
|
||||
: super(key: key);
|
||||
|
||||
final Widget Function(T? value) onValue;
|
||||
final Widget? onLoading;
|
||||
final Future asyncFuture;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<T>(
|
||||
future: asyncFuture.then((value) => value as T),
|
||||
builder: (BuildContext context, AsyncSnapshot<T> snapshot) {
|
||||
switch (snapshot.connectionState) {
|
||||
case ConnectionState.waiting:
|
||||
return onLoading ?? Container();
|
||||
default:
|
||||
if (snapshot.hasError) {
|
||||
return SizedBox.shrink();
|
||||
} else {
|
||||
return onValue(snapshot.data);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -10,8 +10,6 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/future_build_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
import 'package:woosignal/models/response/products.dart';
|
||||
@ -53,10 +51,10 @@ class ProductDetailRelatedProductsWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 200,
|
||||
child: FutureBuildWidget<List<Product>>(
|
||||
asyncFuture: fetchRelated(),
|
||||
onValue: (relatedProducts) {
|
||||
height: 300,
|
||||
child: NyFutureBuilder<List<Product>>(
|
||||
future: fetchRelated(),
|
||||
child: (context, relatedProducts) {
|
||||
if (relatedProducts == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
@ -70,7 +68,6 @@ class ProductDetailRelatedProductsWidget extends StatelessWidget {
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
onLoading: AppLoaderWidget(),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@ -12,7 +12,6 @@ import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_app/bootstrap/helpers.dart';
|
||||
import 'package:flutter_app/resources/widgets/future_build_widget.dart';
|
||||
import 'package:flutter_app/resources/widgets/product_detail_review_tile_widget.dart';
|
||||
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
|
||||
import 'package:nylo_framework/nylo_framework.dart';
|
||||
@ -91,12 +90,9 @@ class _ProductDetailReviewsWidgetState
|
||||
initiallyExpanded: false,
|
||||
children: [
|
||||
if (_ratingExpanded == true)
|
||||
FutureBuildWidget<List<ProductReview>>(
|
||||
asyncFuture: fetchReviews(),
|
||||
onValue: (reviews) {
|
||||
if (reviews == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
NyFutureBuilder<List<ProductReview>>(
|
||||
future: fetchReviews(),
|
||||
child: (context, reviews) {
|
||||
int reviewsCount = reviews.length;
|
||||
List<Widget> childrenWidgets = [];
|
||||
List<ProductDetailReviewTileWidget> children = reviews
|
||||
@ -137,7 +133,7 @@ class _ProductDetailReviewsWidgetState
|
||||
: childrenWidgets,
|
||||
);
|
||||
},
|
||||
onLoading: Padding(
|
||||
loading: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: CupertinoActivityIndicator(),
|
||||
),
|
||||
@ -149,9 +145,9 @@ class _ProductDetailReviewsWidgetState
|
||||
}
|
||||
|
||||
Future<List<ProductReview>> fetchReviews() async {
|
||||
return await (appWooSignal(
|
||||
return await appWooSignal(
|
||||
(api) => api.getProductReviews(
|
||||
perPage: 5, product: [widget.product!.id!], status: "approved"),
|
||||
));
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ class _ProductDetailUpsellWidgetState extends State<ProductDetailUpsellWidget> {
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 200,
|
||||
height: 300,
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
|
||||
@ -315,6 +315,7 @@ class ProductItemContainer extends StatelessWidget {
|
||||
if (product == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
|
||||
return LayoutBuilder(
|
||||
builder: (cxt, constraints) => InkWell(
|
||||
child: Container(
|
||||
@ -324,7 +325,7 @@ class ProductItemContainer extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
height: constraints.maxHeight / 2,
|
||||
height: constraints.maxHeight / 1.6,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(3.0),
|
||||
child: Stack(
|
||||
@ -338,10 +339,12 @@ class ProductItemContainer extends StatelessWidget {
|
||||
image: (product!.images.isNotEmpty
|
||||
? product!.images.first.src
|
||||
: getEnv("PRODUCT_PLACEHOLDER_IMAGE")),
|
||||
fit: BoxFit.contain,
|
||||
height: constraints.maxHeight / 2,
|
||||
fit: BoxFit.cover,
|
||||
height: constraints.maxHeight / 1.6,
|
||||
width: double.infinity,
|
||||
),
|
||||
if (isProductNew(product))
|
||||
Container(padding: EdgeInsets.all(4), child: Text("New", style: TextStyle(color: Colors.white),), decoration: BoxDecoration(color: Colors.black),),
|
||||
if (product!.onSale! && product!.type != "variable")
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
@ -351,7 +354,7 @@ class ProductItemContainer extends StatelessWidget {
|
||||
padding: EdgeInsets.all(3),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white70,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
// borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
@ -366,8 +369,8 @@ class ProductItemContainer extends StatelessWidget {
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.copyWith(
|
||||
color: Colors.black87,
|
||||
fontSize: 11,
|
||||
color: Colors.black,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -393,16 +396,17 @@ class ProductItemContainer extends StatelessWidget {
|
||||
),
|
||||
Flexible(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(top: 4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
AutoSizeText(
|
||||
"${formatStringCurrency(total: product!.price)} ",
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.copyWith(fontWeight: FontWeight.w600),
|
||||
.bodyLarge!
|
||||
.copyWith(fontWeight: FontWeight.w800),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
if (product!.onSale! && product!.type != "variable")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
# Official WooSignal App Template for WooCommerce
|
||||
|
||||
# Label StoreMax
|
||||
# Version: 6.5.1
|
||||
# Version: 6.6.0
|
||||
# Author: Anthony Gordon
|
||||
# Homepage: https://woosignal.com
|
||||
# Documentation: https://woosignal.com/docs/app/label-storemax
|
||||
@ -22,27 +22,29 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: '>=2.19.0 <3.0.0'
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
|
||||
dependencies:
|
||||
google_fonts: ^4.0.3
|
||||
analyzer: ^4.2.0
|
||||
intl: ^0.17.0
|
||||
nylo_framework: ^4.1.4
|
||||
woosignal: ^3.3.0
|
||||
flutter_stripe: ^8.0.0+1
|
||||
analyzer: ^5.12.0
|
||||
intl: ^0.18.0
|
||||
nylo_framework: ^5.0.0
|
||||
# woosignal: ^3.3.0
|
||||
woosignal:
|
||||
path: /Users/anthony/StudioProjects/woosignal-api
|
||||
# flutter_stripe: ^9.2.0
|
||||
wp_json_api: ^3.3.2
|
||||
cached_network_image: ^3.2.3
|
||||
package_info: ^2.0.2
|
||||
package_info_plus: ^4.0.0
|
||||
money_formatter: ^0.0.3
|
||||
flutter_web_browser: ^0.17.1
|
||||
webview_flutter: ^3.0.4
|
||||
pull_to_refresh_flutter3: 2.0.1
|
||||
url_launcher: ^6.1.6
|
||||
bubble_tab_indicator: ^0.1.5
|
||||
razorpay_flutter: ^1.3.4
|
||||
status_alert: ^1.0.1
|
||||
math_expressions: ^2.3.1
|
||||
math_expressions: ^2.4.0
|
||||
validated: ^2.0.0
|
||||
flutter_spinkit: ^5.1.0
|
||||
auto_size_text: ^3.0.0
|
||||
@ -51,8 +53,8 @@ dependencies:
|
||||
flutter_rating_bar: ^4.0.1
|
||||
flutter_staggered_grid_view: ^0.6.2
|
||||
flutter_swiper_view: ^1.1.8
|
||||
firebase_messaging: ^14.2.5
|
||||
firebase_core: ^2.7.0
|
||||
firebase_messaging: ^14.4.1
|
||||
firebase_core: ^2.10.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_localizations:
|
||||
@ -62,15 +64,16 @@ dependencies:
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.5
|
||||
collection: ^1.15.0
|
||||
flutter_stripe: ^9.1.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_launcher_icons: ^0.12.0
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
lints: ^2.0.0
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# APP ICON
|
||||
flutter_icons:
|
||||
flutter_launcher_icons:
|
||||
android: true
|
||||
ios: true
|
||||
image_path: "public/assets/app_icon/appicon.png"
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
# WooCommerce App: Label StoreMax
|
||||
|
||||
### Label StoreMax - v6.5.1
|
||||
### Label StoreMax - v6.6.0
|
||||
|
||||
|
||||
[Official WooSignal WooCommerce App](https://woosignal.com)
|
||||
@ -45,7 +45,7 @@ Full documentation this available [here](https://woosignal.com/docs/app/ios/labe
|
||||
- Change app name, logo, customize default language, currency + more
|
||||
- Light and dark mode
|
||||
- Theme customization
|
||||
- Stripe, Cash On Delivery, PayPal and RazorPay
|
||||
- Stripe, Cash On Delivery, PayPal
|
||||
- Localized for en, es, pt, it, hi, fr, zh, tr, nl
|
||||
- Orders show as normal in WooCommerce
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user