v6.5.0 updates

This commit is contained in:
Anthony 2023-03-04 12:41:33 +07:00
parent 95c9697830
commit c980407287
47 changed files with 738 additions and 475 deletions

View File

@ -1,3 +1,10 @@
## [6.5.0] - 2023-03-04
* When making payments via Stripe, it will now save the card for later.
* Small UI changes to the checkout confirmation page.
* New translation added.
* Pubspec.yaml dependency updates.
## [6.4.1] - 2023-02-23
* Upgrade to Nylo v4.1.3

View File

@ -4,7 +4,7 @@
# WooCommerce App: Label StoreMax
### Label StoreMax - v6.4.1
### Label StoreMax - v6.5.0
[Official WooSignal WooCommerce App](https://woosignal.com)

View File

@ -227,5 +227,6 @@
"Are you sure?": "Bist du dir sicher?",
"Yes, delete my account": "Ja, lösche mein Konto",
"Account deleted": "Konto gelöscht",
"Shipping is not supported for your location, sorry": "Der Versand wird für Ihren Standort nicht unterstützt, tut mir leid"
"Shipping is not supported for your location, sorry": "Der Versand wird für Ihren Standort nicht unterstützt, tut mir leid",
"Order Summary": "Bestellübersicht"
}

View File

@ -227,5 +227,6 @@
"Are you sure?": "Are you sure?",
"Yes, delete my account": "Yes, delete my account",
"Account deleted": "Account deleted",
"Shipping is not supported for your location, sorry": "Shipping is not supported for your location, sorry"
"Shipping is not supported for your location, sorry": "Shipping is not supported for your location, sorry",
"Order Summary": "Order Summary"
}

View File

@ -227,5 +227,6 @@
"Are you sure?": "¿Está seguro?",
"Yes, delete my account": "Sí, eliminar mi cuenta",
"Account deleted": "Cuenta borrada",
"Shipping is not supported for your location, sorry": "El envío no es compatible para su ubicación, lo siento"
"Shipping is not supported for your location, sorry": "El envío no es compatible para su ubicación, lo siento",
"Order Summary": "Resumen del pedido"
}

View File

@ -227,5 +227,6 @@
"Are you sure?": "Êtes-vous sûr?",
"Yes, delete my account": "Oui, supprimer mon compte",
"Account deleted": "Compte supprimé",
"Shipping is not supported for your location, sorry": "L'expédition n'est pas prise en charge pour votre emplacement, désolé"
"Shipping is not supported for your location, sorry": "L'expédition n'est pas prise en charge pour votre emplacement, désolé",
"Order Summary": "Récapitulatif de la commande"
}

View File

@ -227,5 +227,6 @@
"Are you sure?": "kya aapako yakeen hai?",
"Yes, delete my account": "haan, mera akaunt dileet kar do",
"Account deleted": "khaata hataaya gaya",
"Shipping is not supported for your location, sorry": "aapake sthaan ke lie shiping samarthit nahin hai, kshama karen"
"Shipping is not supported for your location, sorry": "aapake sthaan ke lie shiping samarthit nahin hai, kshama karen",
"Order Summary": "aadesh saaraansh"
}

View File

@ -227,5 +227,6 @@
"Are you sure?": "Sei sicuro?",
"Yes, delete my account": "Sì, elimina il mio account",
"Account deleted": "Account cancellato",
"Shipping is not supported for your location, sorry": "La spedizione non è supportata per la tua posizione, mi dispiace"
"Shipping is not supported for your location, sorry": "La spedizione non è supportata per la tua posizione, mi dispiace",
"Order Summary": "Riepilogo dell'ordine"
}

View File

@ -227,5 +227,6 @@
"Are you sure?": "Weet je het zeker?",
"Yes, delete my account": "Ja, verwijder mijn account",
"Account deleted": "Account verwijderd",
"Shipping is not supported for your location, sorry": "Verzending wordt niet ondersteund voor uw locatie, sorry"
"Shipping is not supported for your location, sorry": "Verzending wordt niet ondersteund voor uw locatie, sorry",
"Order Summary": "Overzicht van de bestelling"
}

View File

@ -227,5 +227,6 @@
"Are you sure?": "Tem certeza?",
"Yes, delete my account": "Sim, excluir minha conta",
"Account deleted": "Conta excluída",
"Shipping is not supported for your location, sorry": "O envio não é suportado para a sua localização, desculpe"
"Shipping is not supported for your location, sorry": "O envio não é suportado para a sua localização, desculpe",
"Order Summary": "Resumo do pedido"
}

View File

@ -227,5 +227,6 @@
"Are you sure?": "Emin misin?",
"Yes, delete my account": "Evet, hesabımı sil",
"Account deleted": "Hesap silindi",
"Shipping is not supported for your location, sorry": "Bulunduğunuz yer için gönderim desteklenmiyor, üzgünüm"
"Shipping is not supported for your location, sorry": "Bulunduğunuz yer için gönderim desteklenmiyor, üzgünüm",
"Order Summary": "Sipariş özeti"
}

View File

@ -227,5 +227,6 @@
"Are you sure?": "你确定吗?",
"Yes, delete my account": "是的,删除我的帐户",
"Account deleted": "帐号已删除",
"Shipping is not supported for your location, sorry": "您所在的位置不支持送货,抱歉"
"Shipping is not supported for your location, sorry": "您所在的位置不支持送货,抱歉",
"Order Summary": "订单摘要"
}

View File

@ -22,6 +22,37 @@ class BillingDetails {
shippingAddress = CustomerAddress();
}
Map<String, dynamic> createStripeDetails() => {
'address': {
if (billingAddress?.addressLine != null)
'line1': billingAddress?.addressLine,
if (billingAddress?.city != null) 'city': billingAddress?.city,
if (billingAddress?.postalCode != null)
'postal_code': billingAddress?.postalCode,
if (billingAddress?.customerCountry?.state?.name != null)
'state': billingAddress?.customerCountry?.state?.name,
if (billingAddress?.customerCountry?.countryCode != null)
'country': billingAddress?.customerCountry?.countryCode,
},
'shipping': {
if (shippingAddress?.nameFull() != null)
'name': shippingAddress?.nameFull(),
if (shippingAddress?.city != null) 'city': shippingAddress?.city,
if (shippingAddress?.postalCode != null)
'postal_code': shippingAddress?.postalCode,
if (shippingAddress?.customerCountry?.state?.name != null)
'state': shippingAddress?.customerCountry?.state?.name,
if (shippingAddress?.customerCountry?.countryCode != null)
'country': shippingAddress?.customerCountry?.countryCode,
},
if (billingAddress?.emailAddress != null)
'email': billingAddress?.emailAddress,
if (billingAddress?.nameFull() != null)
'name': billingAddress?.nameFull(),
if (billingAddress?.phoneNumber != null)
'phone': billingAddress?.phoneNumber
};
Map<String, String?> getShippingAddressStripe() => {
"name": shippingAddress?.nameFull(),
"line1": shippingAddress!.addressLine,

View File

@ -167,8 +167,7 @@ class CustomerAddress {
WpMetaData(key: "${type}_phone", value: phoneNumber),
if (type != "shipping")
WpMetaData(key: "${type}_email", value: emailAddress),
WpMetaData(
key: "${type}_country", value: customerCountry?.countryCode),
WpMetaData(key: "${type}_country", value: customerCountry?.countryCode),
WpMetaData(
key: "${type}_state",
value: customerCountry?.state?.code

View File

@ -14,7 +14,6 @@ class BaseApiService extends NyBaseApiService {
/// Default interceptors
@override
final interceptors = {
if (getEnv('APP_DEBUG') == true)
LoggingInterceptor: LoggingInterceptor()
if (getEnv('APP_DEBUG') == true) LoggingInterceptor: LoggingInterceptor()
};
}

View File

@ -47,16 +47,17 @@ stripePay(context,
}
try {
dynamic rsp = {};
Map<String, dynamic>? rsp = {};
// // CHECKOUT HELPER
await checkout(taxRate, (total, billingDetails, cart) async {
String cartShortDesc = await cart.cartShortDesc();
rsp = await appWooSignal((api) => api.stripePaymentIntent(
rsp = await appWooSignal((api) => api.stripePaymentIntentV2(
amount: total,
email: billingDetails?.billingAddress?.emailAddress,
desc: cartShortDesc,
shipping: billingDetails?.getShippingAddressStripe(),
customerDetails: billingDetails?.createStripeDetails(),
));
});
@ -71,17 +72,37 @@ stripePay(context,
}
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
style: Theme.of(state.context).brightness == Brightness.light
? ThemeMode.light
: ThemeMode.dark,
merchantDisplayName:
envVal('APP_NAME', defaultValue: wooSignalApp?.appName),
paymentIntentClientSecret: rsp['client_secret'],
));
paymentSheetParameters: SetupPaymentSheetParameters(
style: Theme.of(state.context).brightness == Brightness.light
? ThemeMode.light
: ThemeMode.dark,
merchantDisplayName:
envVal('APP_NAME', defaultValue: wooSignalApp?.appName),
customerId: rsp!['customer'],
paymentIntentClientSecret: rsp!['client_secret'],
customerEphemeralKeySecret: rsp!['ephemeral_key'],
setupIntentClientSecret: rsp!['setup_intent_secret']),
);
await Stripe.instance.presentPaymentSheet();
PaymentIntent paymentIntent =
await Stripe.instance.retrievePaymentIntent(rsp!['client_secret']);
if (paymentIntent.status == PaymentIntentsStatus.Unknown) {
showToastNotification(
context,
title: trans("Oops!"),
description: trans("Something went wrong, please try again."),
icon: Icons.payment,
style: ToastNotificationStyleType.WARNING,
);
}
if (paymentIntent.status != PaymentIntentsStatus.Succeeded) {
return;
}
state.reloadState(showLoader: true);
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);

View File

@ -60,7 +60,8 @@ class AppBuild extends StatelessWidget {
@override
Widget build(BuildContext context) {
Nylo nylo = Backpack.instance.read('nylo');
List<AppTheme> appThemes = nylo.appThemes.map((appTheme) => appTheme.toAppTheme()).toList();
List<AppTheme> appThemes =
nylo.appThemes.map((appTheme) => appTheme.toAppTheme()).toList();
return LocalizedApp(
child: ThemeProvider(
themes: appThemes,
@ -89,7 +90,12 @@ class AppBuild extends StatelessWidget {
title: title ?? "",
initialRoute: initialRoute,
onGenerateRoute: onGenerateRoute,
darkTheme: darkTheme ?? appThemes.firstWhere((theme) => theme.id == getEnv('DARK_THEME_ID'), orElse: () => appThemes.first).data,
darkTheme: darkTheme ??
appThemes
.firstWhere(
(theme) => theme.id == getEnv('DARK_THEME_ID'),
orElse: () => appThemes.first)
.data,
theme: themeData ?? ThemeProvider.themeOf(context).data,
localeResolutionCallback:
(Locale? locale, Iterable<Locale> supportedLocales) {

View File

@ -0,0 +1,140 @@
import 'package:flutter/material.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/themes/styles/color_styles.dart';
extension NyText on Text {
/// Set the Style to use [displayLarge].
Text displayLarge(BuildContext context) {
return setStyle(Theme.of(context).textTheme.displayLarge);
}
/// Set the Style to use [displayMedium].
Text displayMedium(BuildContext context) {
return setStyle(Theme.of(context).textTheme.displayMedium);
}
/// Set the Style to use [displaySmall].
Text displaySmall(BuildContext context) {
return setStyle(Theme.of(context).textTheme.displaySmall);
}
/// Set the Style to use [headlineLarge].
Text headingLarge(BuildContext context) {
return setStyle(Theme.of(context).textTheme.headlineLarge);
}
/// Set the Style to use [headlineMedium].
Text headingMedium(BuildContext context) {
return setStyle(Theme.of(context).textTheme.headlineMedium);
}
/// Set the Style to use [headlineSmall].
Text headingSmall(BuildContext context) {
return setStyle(Theme.of(context).textTheme.headlineSmall);
}
/// Set the Style to use [titleLarge].
Text titleLarge(BuildContext context) {
return setStyle(Theme.of(context).textTheme.titleLarge);
}
/// Set the Style to use [titleMedium].
Text titleMedium(BuildContext context) {
return setStyle(Theme.of(context).textTheme.titleMedium);
}
/// Set the Style to use [titleSmall].
Text titleSmall(BuildContext context) {
return setStyle(Theme.of(context).textTheme.titleSmall);
}
/// Set the Style to use [bodyLarge].
Text large(BuildContext context) {
return setStyle(Theme.of(context).textTheme.bodyLarge);
}
/// Set the Style to use [bodyMedium].
Text medium(BuildContext context) {
return setStyle(Theme.of(context).textTheme.bodyMedium);
}
/// Set the Style to use [bodySmall].
Text small(BuildContext context) {
return setStyle(Theme.of(context).textTheme.bodySmall);
}
/// Make the font bold.
Text fontWeightBold() {
return copyWith(style: TextStyle(fontWeight: FontWeight.bold));
}
/// Make the font light.
Text fontWeightLight() {
return copyWith(style: TextStyle(fontWeight: FontWeight.w300));
}
/// Change the [style].
Text setStyle(TextStyle? style) => copyWith(style: style);
/// Sets the color from your [ColorStyles] or [Color].
Text setColor(
BuildContext context, Color Function(ColorStyles color) newColor,
{String? themeId}) {
return copyWith(
style: TextStyle(
color: newColor(ThemeColor.get(context, themeId: themeId))));
}
/// Aligns text to the left.
Text alignLeft() {
return copyWith(textAlign: TextAlign.left);
}
/// Aligns text to the right.
Text alignRight() {
return copyWith(textAlign: TextAlign.right);
}
/// Aligns text to the center.
Text alignCenter() {
return copyWith(textAlign: TextAlign.center);
}
/// Aligns text to the center.
Text setMaxLines(int maxLines) {
return copyWith(maxLines: maxLines);
}
/// Change the [fontFamily].
Text setFontFamily(String fontFamily) =>
copyWith(style: TextStyle(fontFamily: fontFamily));
/// Helper to apply changes.
Text copyWith(
{Key? key,
StrutStyle? strutStyle,
TextAlign? textAlign,
TextDirection? textDirection = TextDirection.ltr,
Locale? locale,
bool? softWrap,
TextOverflow? overflow,
double? textScaleFactor,
int? maxLines,
String? semanticsLabel,
TextWidthBasis? textWidthBasis,
TextStyle? style}) {
return Text(data ?? "",
key: key ?? this.key,
strutStyle: strutStyle ?? this.strutStyle,
textAlign: textAlign ?? this.textAlign,
textDirection: textDirection ?? this.textDirection,
locale: locale ?? this.locale,
softWrap: softWrap ?? this.softWrap,
overflow: overflow ?? this.overflow,
textScaleFactor: textScaleFactor ?? this.textScaleFactor,
maxLines: maxLines ?? this.maxLines,
semanticsLabel: semanticsLabel ?? this.semanticsLabel,
textWidthBasis: textWidthBasis ?? this.textWidthBasis,
style: style != null ? this.style?.merge(style) ?? style : this.style);
}
}

View File

@ -54,20 +54,24 @@ Future appWooSignal(Function(WooSignal) api) async {
/// helper to find correct color from the [context].
class ThemeColor {
static ColorStyles get(BuildContext context, {String? themeId}) {
Nylo nylo = Backpack.instance.read('nylo');
List<BaseThemeConfig<ColorStyles>> appThemes = nylo.appThemes as List<BaseThemeConfig<ColorStyles>>;
List<BaseThemeConfig<ColorStyles>> appThemes =
nylo.appThemes as List<BaseThemeConfig<ColorStyles>>;
if (themeId == null) {
BaseThemeConfig<ColorStyles> themeFound = appThemes
.firstWhere(
(theme) => theme.id == getEnv(Theme.of(context).brightness == Brightness.light ? 'LIGHT_THEME_ID' : 'DARK_THEME_ID'),
orElse: () => appThemes.first
);
BaseThemeConfig<ColorStyles> themeFound = appThemes.firstWhere(
(theme) =>
theme.id ==
getEnv(Theme.of(context).brightness == Brightness.light
? 'LIGHT_THEME_ID'
: 'DARK_THEME_ID'),
orElse: () => appThemes.first);
return themeFound.colors;
}
BaseThemeConfig<ColorStyles> baseThemeConfig = appThemes.firstWhere((theme) => theme.id == themeId, orElse: () => appThemes.first);
BaseThemeConfig<ColorStyles> baseThemeConfig = appThemes.firstWhere(
(theme) => theme.id == themeId,
orElse: () => appThemes.first);
return baseThemeConfig.colors;
}
}
@ -80,7 +84,7 @@ extension ColorsHelper on TextStyle {
}
}
List<PaymentType?> getPaymentTypes() {
Future<List<PaymentType?>> getPaymentTypes() async {
List<PaymentType?> paymentTypes = [];
for (var appPaymentGateway in appPaymentGateways) {
if (paymentTypes.firstWhere(
@ -501,7 +505,8 @@ class UserAuth {
}
Future<List<DefaultShipping>> getDefaultShipping() async {
String data = await rootBundle.loadString('public/assets/json/default_shipping.json');
String data =
await rootBundle.loadString('public/assets/json/default_shipping.json');
dynamic dataJson = json.decode(data);
List<DefaultShipping> shipping = [];
@ -520,30 +525,40 @@ Future<List<DefaultShipping>> getDefaultShipping() async {
}
Future<DefaultShipping?> findCountryMetaForShipping(String countryCode) async {
List<DefaultShipping> defaultShipping = await getDefaultShipping();
List<DefaultShipping> shippingByCountryCode = defaultShipping.where((element) => element.code == countryCode).toList();
List<DefaultShipping> defaultShipping = await getDefaultShipping();
List<DefaultShipping> shippingByCountryCode =
defaultShipping.where((element) => element.code == countryCode).toList();
if (shippingByCountryCode.isNotEmpty) {
return shippingByCountryCode.first;
}
return null;
}
DefaultShippingState? findDefaultShippingStateByCode(DefaultShipping defaultShipping, String code) {
List<DefaultShippingState> defaultShippingStates = defaultShipping.states.where((state) => state.code == code).toList();
DefaultShippingState? findDefaultShippingStateByCode(
DefaultShipping defaultShipping, String code) {
List<DefaultShippingState> defaultShippingStates =
defaultShipping.states.where((state) => state.code == code).toList();
if (defaultShippingStates.isEmpty) {
return null;
}
DefaultShippingState defaultShippingState = defaultShippingStates.first;
return DefaultShippingState(code: defaultShippingState.code, name: defaultShippingState.name);
return DefaultShippingState(
code: defaultShippingState.code, name: defaultShippingState.name);
}
bool hasKeyInMeta(WPUserInfoResponse wpUserInfoResponse, String key) {
return (wpUserInfoResponse.data!.metaData ?? []).where((meta) => meta.key == key).toList().isNotEmpty;
return (wpUserInfoResponse.data!.metaData ?? [])
.where((meta) => meta.key == key)
.toList()
.isNotEmpty;
}
String fetchValueInMeta(WPUserInfoResponse wpUserInfoResponse, String key) {
String value = "";
List<dynamic>? metaDataValue = (wpUserInfoResponse.data!.metaData ?? []).where((meta) => meta.key == key).first.value;
List<dynamic>? metaDataValue = (wpUserInfoResponse.data!.metaData ?? [])
.where((meta) => meta.key == key)
.first
.value;
if (metaDataValue != null && metaDataValue.isNotEmpty) {
return metaDataValue.first ?? "";
}
@ -592,7 +607,8 @@ removeWishlistProduct({required Product? product}) async {
await NyStorage.store(SharedKey.wishlistProducts, json);
}
Future<BillingDetails> billingDetailsFromWpUserInfoResponse(wpUserInfoResponse) async {
Future<BillingDetails> billingDetailsFromWpUserInfoResponse(
wpUserInfoResponse) async {
List<String> metaDataAddress = [
'billing_first_name',
'billing_last_name',

View File

@ -0,0 +1,16 @@
/*
|--------------------------------------------------------------------------
| Storage Keys
| Add your storage keys here and then use them later to retrieve data.
| E.g. static String userCoins = "USER_COINS";
| String coins = NyStorage.read( StorageKey.userCoins );
|
| Learn more: https://nylo.dev/docs/4.x/storage#storage-keys
|--------------------------------------------------------------------------
*/
class StorageKey {
static String userToken = "USER_TOKEN";
/// Add your storage keys here...
}

View File

@ -64,7 +64,10 @@ class _AccountLandingPageState extends NyState<AccountLandingPage> {
child: Text(
trans("Login"),
textAlign: TextAlign.left,
style: Theme.of(context).textTheme.headlineMedium!.copyWith(
style: Theme.of(context)
.textTheme
.headlineMedium!
.copyWith(
fontSize: 24,
fontWeight: FontWeight.w700,
),

View File

@ -62,7 +62,8 @@ class _BrowseCategoryPageState extends NyState<BrowseCategoryPage> {
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(trans("Browse"), style: Theme.of(context).textTheme.titleMedium),
Text(trans("Browse"),
style: Theme.of(context).textTheme.titleMedium),
Text(parseHtmlString(productCategory!.name))
],
),

View File

@ -266,26 +266,16 @@ class _CartPageState extends State<CartPage> {
Divider(
color: Colors.black45,
),
FutureBuilder<String>(
NyFutureBuilder<String>(
future: Cart.getInstance.getTotal(withFormat: true),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text("");
default:
if (snapshot.hasError) {
return Text("");
} else {
return Padding(
child: TextRowWidget(
title: trans("Total"),
text: (_isLoading ? "" : snapshot.data),
),
padding: EdgeInsets.only(bottom: 15, top: 15),
);
}
}
},
child: (BuildContext context, data) => Padding(
child: TextRowWidget(
title: trans("Total"),
text: (_isLoading ? "" : data),
),
padding: EdgeInsets.only(bottom: 15, top: 15),
),
loading: SizedBox.shrink(),
),
PrimaryButton(
title: trans("PROCEED TO CHECKOUT"),

View File

@ -9,12 +9,14 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:collection/collection.dart' show IterableExtension;
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/app/models/cart.dart';
import 'package:flutter_app/app/models/checkout_session.dart';
import 'package:flutter_app/app/models/customer_country.dart';
import 'package:flutter_app/app/models/payment_type.dart';
import 'package:flutter_app/bootstrap/app_helper.dart';
import 'package:flutter_app/bootstrap/extensions.dart';
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';
@ -38,23 +40,26 @@ class CheckoutConfirmationPage extends StatefulWidget {
CheckoutConfirmationPageState();
}
class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
class CheckoutConfirmationPageState extends NyState<CheckoutConfirmationPage> {
CheckoutConfirmationPageState();
bool _showFullLoader = true, _isProcessingPayment = false;
final List<TaxRate> _taxRates = [];
TaxRate? _taxRate;
final WooSignalApp? _wooSignalApp = AppHelper.instance.appConfig;
@override
void initState() {
super.initState();
init() async {
super.init();
CheckoutSession.getInstance.coupon = null;
List<PaymentType?> paymentTypes = getPaymentTypes();
List<PaymentType?> paymentTypes = await getPaymentTypes();
if (CheckoutSession.getInstance.paymentType == null &&
paymentTypes.isNotEmpty) {
CheckoutSession.getInstance.paymentType = paymentTypes.first;
CheckoutSession.getInstance.paymentType = paymentTypes.firstWhere(
(paymentType) => paymentType?.id == 20,
orElse: () => paymentTypes.first);
print(CheckoutSession.getInstance.paymentType?.name);
}
_getTaxes();
}
@ -176,8 +181,15 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
return Scaffold(
appBar: AppBar(
title: Text(trans("Checkout")),
centerTitle: true,
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(trans("Checkout")),
Text(_wooSignalApp?.appName ?? getEnv('APP_NAME')).small(context),
],
),
centerTitle: false,
leading: Container(
child: IconButton(
icon: Icon(Icons.arrow_back_ios),
@ -191,95 +203,154 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
),
resizeToAvoidBottomInset: false,
body: SafeAreaWidget(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.only(left: 10, right: 10),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: ListView(
shrinkWrap: true,
children: [
CheckoutStoreHeadingWidget(),
CheckoutUserDetailsWidget(
context: context,
checkoutSession: checkoutSession,
resetState: () {
setState(() {
_showFullLoader = true;
});
_getTaxes();
},
),
CheckoutPaymentTypeWidget(
context: context,
checkoutSession: checkoutSession,
resetState: () => setState(() {}),
),
CheckoutShippingTypeWidget(
context: context,
checkoutSession: checkoutSession,
resetState: () => setState(() {}),
wooSignalApp: _wooSignalApp,
),
if (_wooSignalApp!.couponEnabled == true)
CheckoutSelectCouponWidget(
context: context,
checkoutSession: checkoutSession,
resetState: () => setState(() {}),
),
Container(
decoration: BoxDecoration(
boxShadow: wsBoxShadow(),
color: Colors.white,
// borderRadius: BorderRadius.circular(16)
),
padding: EdgeInsets.symmetric(vertical: 16),
margin: EdgeInsets.only(top: 20),
child: Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Row(
children: [
Icon(Icons.receipt),
Padding(padding: EdgeInsets.only(right: 8),),
Text(trans("Order Summary")).fontWeightBold()
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(padding: EdgeInsets.only(top: 16)),
CheckoutSubtotal(
title: trans("Subtotal"),
),
CheckoutCouponAmountWidget(
checkoutSession: checkoutSession),
if (_wooSignalApp!.disableShipping != 1)
CheckoutMetaLine(
title: trans("Shipping fee"),
amount: CheckoutSession
.getInstance.shippingType ==
null
? trans("Select shipping")
: CheckoutSession
.getInstance.shippingType!
.getTotal(withFormatting: true)),
if (_taxRate != null)
CheckoutTaxTotal(taxRate: _taxRate),
Padding(padding: EdgeInsets.only(top: 8, left: 8, right: 8)),
Padding(padding: EdgeInsets.symmetric(horizontal: 8), child: RichText(
textAlign: TextAlign.left,
text: TextSpan(
text:
'By completing this order, I agree to all ',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontSize: 12,
),
children: <TextSpan>[
TextSpan(
recognizer: TapGestureRecognizer()..onTap = _openTermsLink,
text: "terms & conditions",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
color: ThemeColor.get(context)
.primaryAccent,
fontSize: 12,
),
),
TextSpan(
text: ".",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
color: Colors.black87,
fontSize: 12,
),
),
],
),
)),
],
),
],
),
)
],
),
),
Container(
decoration: BoxDecoration(
color: ThemeColor.get(context).backgroundContainer,
borderRadius: BorderRadius.circular(10),
boxShadow: (Theme.of(context).brightness == Brightness.light)
? wsBoxShadow()
: null,
borderRadius: BorderRadius.circular(16)
),
margin: EdgeInsets.only(top: 5, bottom: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
CheckoutStoreHeadingWidget(),
CheckoutUserDetailsWidget(
context: context,
checkoutSession: checkoutSession,
resetState: () {
setState(() {
_showFullLoader = true;
});
_getTaxes();
},
),
CheckoutPaymentTypeWidget(
context: context,
checkoutSession: checkoutSession,
resetState: () => setState(() {}),
),
CheckoutShippingTypeWidget(
context: context,
checkoutSession: checkoutSession,
resetState: () => setState(() {}),
wooSignalApp: _wooSignalApp,
),
]),
),
),
if (_wooSignalApp!.couponEnabled == true)
CheckoutSelectCouponWidget(
context: context,
checkoutSession: checkoutSession,
resetState: () => setState(() {}),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Divider(
color: Colors.black12,
thickness: 1,
children: [
CheckoutTotal(title: trans("Total"), taxRate: _taxRate),
Padding(padding: EdgeInsets.only(bottom: 8)),
PrimaryButton(
title: _isProcessingPayment
? "${trans("PROCESSING")}..."
: trans("CHECKOUT"),
action: _isProcessingPayment ? null : _handleCheckout,
),
],
),
CheckoutSubtotal(
title: trans("Subtotal"),
),
CheckoutCouponAmountWidget(checkoutSession: checkoutSession),
if (_wooSignalApp!.disableShipping != 1)
CheckoutMetaLine(
title: trans("Shipping fee"),
amount: CheckoutSession.getInstance.shippingType == null
? trans("Select shipping")
: CheckoutSession.getInstance.shippingType!
.getTotal(withFormatting: true)),
if (_taxRate != null) CheckoutTaxTotal(taxRate: _taxRate),
CheckoutTotal(title: trans("Total"), taxRate: _taxRate),
Divider(
color: Colors.black12,
thickness: 1,
),
],
),
PrimaryButton(
title: _isProcessingPayment
? "${trans("PROCESSING")}..."
: trans("CHECKOUT"),
action: _isProcessingPayment ? null : _handleCheckout,
),
],
)
],
),
),
),
);
}
_openTermsLink() => openBrowserTab(url: AppHelper.instance.appConfig?.appTermsLink ?? "");
_handleCheckout() async {
CheckoutSession checkoutSession = CheckoutSession.getInstance;
if (checkoutSession.billingDetails!.billingAddress == null) {
@ -368,8 +439,12 @@ class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
_isProcessingPayment = true;
});
await checkoutSession.paymentType!
.pay(context, state: this, taxRate: _taxRate);
try {
await checkoutSession.paymentType!
.pay(context, state: this, taxRate: _taxRate);
} on Exception catch (e) {
print(e.toString());
}
setState(() {
_isProcessingPayment = false;

View File

@ -25,28 +25,35 @@ class CheckoutPaymentTypePage extends StatefulWidget {
_CheckoutPaymentTypePageState();
}
class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
class _CheckoutPaymentTypePageState extends NyState<CheckoutPaymentTypePage> {
_CheckoutPaymentTypePageState();
@override
void initState() {
super.initState();
List<PaymentType?> _paymentTypes = [];
@override
init() async {
super.init();
_paymentTypes = await getPaymentTypes();
if (_paymentTypes.isEmpty &&
getEnv('APP_DEBUG', defaultValue: false) == true) {
NyLogger.info(
'You have no payment methods set. Visit the WooSignal dashboard (https://woosignal.com/dashboard) to set a payment method.');
}
// print(CheckoutSession.getInstance.paymentType?.name);
if (CheckoutSession.getInstance.paymentType == null) {
if (getPaymentTypes().isNotEmpty) {
CheckoutSession.getInstance.paymentType = getPaymentTypes().first;
if (_paymentTypes.isNotEmpty) {
CheckoutSession.getInstance.paymentType = _paymentTypes.firstWhere(
(paymentType) => paymentType?.id == 20,
orElse: () => _paymentTypes.first);
}
}
}
@override
Widget build(BuildContext context) {
List<PaymentType?> paymentTypes = getPaymentTypes();
if (paymentTypes.isEmpty &&
getEnv('APP_DEBUG', defaultValue: false) == true) {
NyLogger.info(
'You have no payment methods set. Visit the WooSignal dashboard (https://woosignal.com/dashboard) to set a payment method.');
}
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
@ -76,7 +83,7 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Expanded(
child: paymentTypes.isEmpty
child: _paymentTypes.isEmpty
? Container(
padding: EdgeInsets.only(top: 20),
child: Text(
@ -86,11 +93,12 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
),
)
: ListView.separated(
itemCount: paymentTypes.length,
itemCount: _paymentTypes.length,
itemBuilder:
(BuildContext context, int index) {
PaymentType paymentType =
paymentTypes[index]!;
_paymentTypes[index]!;
return ListTile(
contentPadding: EdgeInsets.only(
top: 10,
@ -114,9 +122,9 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
.textTheme
.titleMedium),
selected: true,
trailing: (CheckoutSession
.getInstance.paymentType ==
paymentType
trailing: (CheckoutSession.getInstance
.paymentType?.id ==
paymentType.id
? Icon(Icons.check)
: null),
onTap: () {

View File

@ -288,62 +288,48 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
),
),
selected: true,
subtitle: FutureBuilder<String>(
subtitle: NyFutureBuilder<String>(
future: _getShippingPrice(index),
builder: (BuildContext context,
AsyncSnapshot<String>
snapshot) {
switch (
snapshot.connectionState) {
case ConnectionState.none:
return Text('');
case ConnectionState.active:
case ConnectionState.waiting:
return Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return Text('');
} else {
Map<String, dynamic>
shippingOption =
_wsShippingOptions[
index];
return RichText(
text: TextSpan(
text: '',
style: Theme.of(context)
.textTheme
.bodyMedium,
children: <TextSpan>[
(shippingOption[
"object"]
is FreeShipping
? TextSpan(
text: trans(
"Free postage"),
)
: TextSpan(
text:
"${trans("Price")}: ${formatStringCurrency(total: snapshot.data)}",
)),
if (shippingOption[
"min_amount"] !=
null)
TextSpan(
text:
"\n${trans("Spend a minimum of")} ${formatStringCurrency(total: shippingOption["min_amount"])}",
style: Theme.of(
context)
.textTheme
.bodyMedium!
.copyWith(
fontSize:
14))
],
),
);
}
}
child: (BuildContext context,
data) {
Map<String, dynamic>
shippingOption =
_wsShippingOptions[
index];
return RichText(
text: TextSpan(
text: '',
style: Theme.of(context)
.textTheme
.bodyMedium,
children: <TextSpan>[
(shippingOption[
"object"]
is FreeShipping
? TextSpan(
text: trans(
"Free postage"),
)
: TextSpan(
text:
"${trans("Price")}: ${formatStringCurrency(total: data)}",
)),
if (shippingOption[
"min_amount"] !=
null)
TextSpan(
text:
"\n${trans("Spend a minimum of")} ${formatStringCurrency(total: shippingOption["min_amount"])}",
style: Theme.of(
context)
.textTheme
.bodyMedium!
.copyWith(
fontSize:
14))
],
),
);
},
),
trailing: (CheckoutSession.getInstance

View File

@ -125,46 +125,51 @@ class _CheckoutStatusState extends NyState<CheckoutStatusPage> {
itemBuilder: (BuildContext context, int index) {
ws_order.LineItems lineItem = _order!.lineItems![index];
return Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
lineItem.name!,
style:
Theme.of(context).textTheme.bodyLarge,
softWrap: false,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
Text(
"x${lineItem.quantity.toString()}",
style:
Theme.of(context).textTheme.bodyMedium,
),
],
),
),
Text(
formatStringCurrency(
total: lineItem.total.toString(),
),
style: Theme.of(context).textTheme.bodyLarge,
)
],
),
padding: EdgeInsets.all(16),
margin: EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
boxShadow: wsBoxShadow(),
color:
(Theme.of(context).brightness == Brightness.light)
? Colors.white
: null);
: null,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
lineItem.name!,
style:
Theme.of(context).textTheme.bodyLarge,
softWrap: false,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
Text(
"x${lineItem.quantity.toString()}",
style:
Theme.of(context).textTheme.bodyMedium,
),
],
),
),
Text(
formatStringCurrency(
total: lineItem.total.toString(),
),
style: Theme.of(context).textTheme.bodyLarge,
)
],
),
padding: EdgeInsets.all(16),
margin: EdgeInsets.all(8),
);
}),
),
Align(

View File

@ -25,8 +25,8 @@ ThemeData darkTheme(ColorStyles darkColors) {
}
}
TextTheme darkTheme = getAppTextTheme(
appFont, defaultTextTheme.merge(_textTheme(darkColors)));
TextTheme darkTheme =
getAppTextTheme(appFont, defaultTextTheme.merge(_textTheme(darkColors)));
return ThemeData(
primaryColor: darkColors.primaryContent,
primaryColorDark: darkColors.primaryContent,
@ -64,7 +64,8 @@ ThemeData darkTheme(ColorStyles darkColors) {
TextStyle(color: darkColors.bottomTabBarLabelSelected),
selectedItemColor: darkColors.bottomTabBarLabelSelected,
),
textTheme: darkTheme, colorScheme: ColorScheme.dark().copyWith(background: darkColors.background),
textTheme: darkTheme,
colorScheme: ColorScheme.dark().copyWith(background: darkColors.background),
);
}
@ -81,6 +82,5 @@ TextTheme _textTheme(ColorStyles colors) {
titleLarge: TextStyle(color: primaryContent.withOpacity(0.8)),
labelLarge: TextStyle(color: primaryContent.withOpacity(0.8)),
bodySmall: TextStyle(color: primaryContent.withOpacity(0.8)),
bodyMedium: TextStyle(color: primaryContent.withOpacity(0.8))
);
bodyMedium: TextStyle(color: primaryContent.withOpacity(0.8)));
}

View File

@ -25,8 +25,8 @@ ThemeData lightTheme(ColorStyles lightColors) {
}
}
TextTheme lightTheme = getAppTextTheme(
appFont, defaultTextTheme.merge(_textTheme(lightColors)));
TextTheme lightTheme =
getAppTextTheme(appFont, defaultTextTheme.merge(_textTheme(lightColors)));
return ThemeData(
primaryColor: lightColors.primaryContent,
@ -66,7 +66,9 @@ ThemeData lightTheme(ColorStyles lightColors) {
TextStyle(color: lightColors.bottomTabBarLabelSelected),
selectedItemColor: lightColors.bottomTabBarLabelSelected,
),
textTheme: lightTheme, colorScheme: ColorScheme.light().copyWith(background: lightColors.background),
textTheme: lightTheme,
colorScheme:
ColorScheme.light().copyWith(background: lightColors.background),
);
}
@ -80,7 +82,7 @@ TextTheme _textTheme(ColorStyles colors) {
Color primaryContent = colors.primaryContent;
TextTheme textTheme = TextTheme().apply(displayColor: primaryContent);
return textTheme.copyWith(
labelLarge: TextStyle(color: primaryContent.withOpacity(0.8)),
bodyMedium: TextStyle(color: primaryContent.withOpacity(0.8)),
labelLarge: TextStyle(color: primaryContent.withOpacity(0.8)),
bodyMedium: TextStyle(color: primaryContent.withOpacity(0.8)),
);
}

View File

@ -17,27 +17,17 @@ class AppVersionWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FutureBuilder<PackageInfo>(
return NyFutureBuilder<PackageInfo>(
future: PackageInfo.fromPlatform(),
builder: (BuildContext context, AsyncSnapshot<PackageInfo> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text("");
case ConnectionState.active:
case ConnectionState.waiting:
return Text("");
case ConnectionState.done:
if (snapshot.hasError) return Text("");
return Padding(
child: Text("${trans("Version")}: ${snapshot.data!.version}",
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(fontWeight: FontWeight.w300)),
padding: EdgeInsets.only(top: 15, bottom: 15),
);
}
},
child: (BuildContext context, data) => Padding(
child: Text("${trans("Version")}: ${data.version}",
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(fontWeight: FontWeight.w300)),
padding: EdgeInsets.only(top: 15, bottom: 15),
),
loading: SizedBox.shrink(),
);
}
}

View File

@ -120,7 +120,8 @@ class WooSignalButton extends StatelessWidget {
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
), backgroundColor: bgColor,
),
backgroundColor: bgColor,
padding: EdgeInsets.all(8),
elevation: 0,
shadowColor: Colors.transparent,

View File

@ -11,6 +11,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_app/app/models/cart.dart';
import 'package:flutter_app/app/models/cart_line_item.dart';
import 'package:nylo_framework/nylo_framework.dart';
class CartIconWidget extends StatefulWidget {
CartIconWidget({Key? key}) : super(key: key);
@ -34,32 +35,23 @@ class _CartIconWidgetState extends State<CartIconWidget> {
),
Positioned.fill(
child: Align(
child: FutureBuilder<List<CartLineItem>>(
child: NyFutureBuilder<List<CartLineItem>>(
future: Cart.getInstance.getCart(),
builder: (BuildContext context,
AsyncSnapshot<List<CartLineItem>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text("");
default:
if (snapshot.hasError) {
return Text("");
} else {
List<int?> cartItems =
snapshot.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,
);
}
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,

View File

@ -12,7 +12,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_app/app/models/cart.dart';
import 'package:flutter_app/app/models/checkout_session.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
import 'package:flutter_app/resources/widgets/woosignal_ui.dart';
import 'package:nylo_framework/nylo_framework.dart';
@ -24,29 +23,18 @@ class CheckoutCouponAmountWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FutureBuilder<String>(
if (checkoutSession.coupon == null) {
return SizedBox.shrink();
}
return NyFutureBuilder<String>(
future: Cart.getInstance.couponDiscountAmount(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return AppLoaderWidget();
default:
if (snapshot.hasError) {
return Text("");
} else {
if (checkoutSession.coupon == null) {
return SizedBox.shrink();
}
return Padding(
child: CheckoutMetaLine(
title: "${trans('Coupon')}: ${checkoutSession.coupon!.code}",
amount: "-" + formatStringCurrency(total: snapshot.data),
),
padding: EdgeInsets.only(bottom: 0, top: 0),
);
}
}
},
child: (BuildContext context, data) => Padding(
child: CheckoutMetaLine(
title: "${trans('Coupon')}: ${checkoutSession.coupon?.code}",
amount: "-" + formatStringCurrency(total: data),
),
padding: EdgeInsets.only(bottom: 0, top: 0),
),
);
}
}

View File

@ -44,7 +44,7 @@ class CheckoutShippingTypeWidget extends StatelessWidget {
? checkoutSession.shippingType!.getTitle()
: trans("Select a shipping option"),
action: _actionSelectShipping,
showBorderBottom: false,
showBorderBottom: true,
);
}

View File

@ -18,9 +18,6 @@ class CheckoutStoreHeadingWidget extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
boxShadow: (Theme.of(context).brightness == Brightness.light)
? wsBoxShadow(blurRadius: 10)
: null,
color: Colors.transparent,
),
padding: EdgeInsets.all(2),

View File

@ -47,10 +47,10 @@ class _CompoHomeWidgetState extends State<CompoHomeWidget> {
for (var category in categories) {
List<Product> products = await (appWooSignal(
(api) => api.getProducts(
perPage: 10,
category: category.id.toString(),
status: "publish",
stockStatus: "instock",
perPage: 10,
category: category.id.toString(),
status: "publish",
stockStatus: "instock",
),
));
if (products.isNotEmpty) {
@ -138,7 +138,7 @@ class _CompoHomeWidgetState extends State<CompoHomeWidget> {
children: [
Expanded(
child: AutoSizeText(
catProds.key.name!,
parseHtmlString(catProds.key.name!),
style: Theme.of(context)
.textTheme
.titleMedium!

View File

@ -146,7 +146,9 @@ class _NoticHomeWidgetState extends State<NoticHomeWidget> {
Flexible(
child: Text(
trans("Our selection of new items"),
style: Theme.of(context).textTheme.headlineMedium,
style: Theme.of(context)
.textTheme
.headlineMedium,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),

View File

@ -40,8 +40,10 @@ class ProductDetailDescriptionWidget extends StatelessWidget {
children: <Widget>[
Text(
trans("Description"),
style:
Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 18),
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(fontSize: 18),
textAlign: TextAlign.left,
),
if (product!.shortDescription!.isNotEmpty &&

View File

@ -43,8 +43,10 @@ class ProductDetailRelatedProductsWidget extends StatelessWidget {
children: <Widget>[
Text(
trans("Related products"),
style:
Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 18),
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(fontSize: 18),
textAlign: TextAlign.left,
),
],

View File

@ -65,8 +65,10 @@ class _ProductDetailUpsellWidgetState extends State<ProductDetailUpsellWidget> {
children: <Widget>[
Text(
trans("${trans('You may also like')}"),
style:
Theme.of(context).textTheme.bodySmall!.copyWith(fontSize: 18),
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(fontSize: 18),
textAlign: TextAlign.left,
),
],

View File

@ -16,7 +16,6 @@ import 'package:flutter_app/app/models/cart_line_item.dart';
import 'package:flutter_app/app/models/checkout_session.dart';
import 'package:flutter_app/bootstrap/app_helper.dart';
import 'package:flutter_app/bootstrap/helpers.dart';
import 'package:flutter_app/resources/widgets/app_loader_widget.dart';
import 'package:flutter_app/resources/widgets/cached_image_widget.dart';
import 'package:flutter_app/resources/widgets/no_results_for_products_widget.dart';
import 'package:flutter_app/resources/widgets/top_nav_widget.dart';
@ -142,6 +141,7 @@ class CheckoutRowLine extends StatelessWidget {
Widget build(BuildContext context) => Flexible(
child: InkWell(
child: Container(
height: 125,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
@ -171,7 +171,8 @@ class CheckoutRowLine extends StatelessWidget {
child: Container(
child: Text(
leadTitle!,
style: Theme.of(context).textTheme.titleMedium,
style:
Theme.of(context).textTheme.titleMedium,
maxLines: 2,
overflow: TextOverflow.ellipsis,
softWrap: false,
@ -227,18 +228,17 @@ class TextEditingRow extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
child: Padding(
child: AutoSizeText(
heading!,
style: Theme.of(context)
.textTheme
.bodyLarge!
.copyWith(color: ThemeColor.get(context).primaryContent),
if (heading != null)
Flexible(
child: Padding(
child: AutoSizeText(
heading!,
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
color: ThemeColor.get(context).primaryContent),
),
padding: EdgeInsets.only(bottom: 2),
),
padding: EdgeInsets.only(bottom: 2),
),
),
Flexible(
child: TextField(
controller: controller,
@ -253,7 +253,7 @@ class TextEditingRow extends StatelessWidget {
],
),
padding: EdgeInsets.all(2),
height: 78,
height: heading == null ? 50 : 78,
);
}
@ -263,26 +263,29 @@ class CheckoutMetaLine extends StatelessWidget {
final String? title, amount;
@override
Widget build(BuildContext context) => Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Container(
child: AutoSizeText(title!,
style: Theme.of(context).textTheme.bodyMedium),
Widget build(BuildContext context) => Container(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Container(
child: AutoSizeText(title!,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontWeight: FontWeight.bold)),
),
flex: 3,
),
flex: 3,
),
Flexible(
child: Container(
child:
Text(amount!, style: Theme.of(context).textTheme.bodyLarge),
),
flex: 3,
)
],
);
Flexible(
child: Container(
child:
Text(amount!, style: Theme.of(context).textTheme.bodyLarge),
),
flex: 3,
)
],
),
);
}
List<BoxShadow> wsBoxShadow({double? blurRadius}) => [
@ -507,25 +510,15 @@ class CheckoutTotal extends StatelessWidget {
final TaxRate? taxRate;
@override
Widget build(BuildContext context) => FutureBuilder<String>(
future: CheckoutSession.getInstance
.total(withFormat: true, taxRate: taxRate),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return AppLoaderWidget();
default:
if (snapshot.hasError) {
return Text("");
} else {
return Padding(
child: CheckoutMetaLine(title: title, amount: snapshot.data),
padding: EdgeInsets.only(bottom: 0, top: 15),
);
}
}
},
);
Widget build(BuildContext context) => NyFutureBuilder<String>(
future: CheckoutSession.getInstance
.total(withFormat: true, taxRate: taxRate),
child: (BuildContext context, data) => Padding(
child: CheckoutMetaLine(title: title, amount: data),
padding: EdgeInsets.only(bottom: 0, top: 15),
),
loading: SizedBox.shrink(),
);
}
class CheckoutTaxTotal extends StatelessWidget {
@ -534,28 +527,17 @@ class CheckoutTaxTotal extends StatelessWidget {
final TaxRate? taxRate;
@override
Widget build(BuildContext context) => FutureBuilder<String>(
Widget build(BuildContext context) => NyFutureBuilder<String>(
future: Cart.getInstance.taxAmount(taxRate),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return AppLoaderWidget();
default:
if (snapshot.hasError) {
return Text("");
} else {
return (snapshot.data == "0"
? Container()
: Padding(
child: CheckoutMetaLine(
title: trans("Tax"),
amount: formatStringCurrency(total: snapshot.data),
),
padding: EdgeInsets.only(bottom: 0, top: 0),
));
}
}
},
child: (BuildContext context, data) => (data == "0"
? Container()
: Padding(
child: CheckoutMetaLine(
title: trans("Tax"),
amount: formatStringCurrency(total: data),
),
padding: EdgeInsets.only(bottom: 0, top: 0),
)),
);
}
@ -565,26 +547,16 @@ class CheckoutSubtotal extends StatelessWidget {
final String? title;
@override
Widget build(BuildContext context) => FutureBuilder<String>(
Widget build(BuildContext context) => NyFutureBuilder<String>(
future: Cart.getInstance.getSubtotal(withFormat: true),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return AppLoaderWidget();
default:
if (snapshot.hasError) {
return Text("");
} else {
return Padding(
child: CheckoutMetaLine(
title: title,
amount: snapshot.data,
),
padding: EdgeInsets.only(bottom: 0, top: 0),
);
}
}
},
child: (BuildContext context, data) => Padding(
child: CheckoutMetaLine(
title: title,
amount: data,
),
padding: EdgeInsets.only(bottom: 0, top: 0),
),
loading: SizedBox.shrink(),
);
}

View File

@ -106,4 +106,4 @@ appRouter() => nyRoutes((router) {
router.route("/account-shipping-details",
(context) => AccountShippingDetailsPage());
});
});

View File

@ -205,10 +205,10 @@ packages:
dependency: transitive
description:
name: dio
sha256: "9fdbf71baeb250fc9da847f6cb2052196f62c19906a3657adfc18631a667d316"
sha256: "3709d74615bba5e443eb141f6a7f4bcc4788f8fae6f743edadfb79c2a8e6287e"
url: "https://pub.dev"
source: hosted
version: "5.0.0"
version: "5.0.1"
eventify:
dependency: transitive
description:
@ -330,10 +330,10 @@ packages:
dependency: "direct dev"
description:
name: flutter_launcher_icons
sha256: ce0e501cfc258907842238e4ca605e74b7fd1cdf04b3b43e86c43f3e40a1592c
sha256: "02dcaf49d405f652b7160e882bacfc02cb497041bb2eab2a49b1c393cf9aac12"
url: "https://pub.dev"
source: hosted
version: "0.11.0"
version: "0.12.0"
flutter_localizations:
dependency: "direct main"
description: flutter
@ -529,10 +529,10 @@ packages:
dependency: transitive
description:
name: image
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
sha256: "483a389d6ccb292b570c31b3a193779b1b0178e7eb571986d9a49904b6861227"
url: "https://pub.dev"
source: hosted
version: "3.3.0"
version: "4.0.15"
intl:
dependency: "direct main"
description:
@ -625,18 +625,18 @@ packages:
dependency: "direct main"
description:
name: nylo_framework
sha256: "3cc0379e73a56b2f2864f5fd850fdc582fc1908c5c8025e96a3ae7dbd3efa2f2"
sha256: "9ed065fdd5570de42c5e96f6269740de7b568593c2af78584cdc38572cf52ebe"
url: "https://pub.dev"
source: hosted
version: "4.1.3"
version: "4.1.4"
nylo_support:
dependency: transitive
description:
name: nylo_support
sha256: b662441b463a1e68c1642cd2711af026f66fb2122ecc1ae331fc8300a7bc4be7
sha256: e710481287d8c4db42b51e10a1a726cc6da7239fdd334e204eadda635a9766ff
url: "https://pub.dev"
source: hosted
version: "4.3.0"
version: "4.3.1"
octo_image:
dependency: transitive
description:
@ -865,10 +865,10 @@ packages:
dependency: transitive
description:
name: shared_preferences
sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9"
sha256: ee6257848f822b8481691f20c3e6d2bfee2e9eccb2a3d249907fcfb198c55b41
url: "https://pub.dev"
source: hosted
version: "2.0.17"
version: "2.0.18"
shared_preferences_android:
dependency: transitive
description:
@ -1182,10 +1182,10 @@ packages:
dependency: "direct main"
description:
name: woosignal
sha256: "0236c5a4568d39140be544b44cbabd9932a425f28285694e99d6daec85809fef"
sha256: "888629274da9083aca94102b45e963c92f820c8d6b8154eebf0424adfc4089c6"
url: "https://pub.dev"
source: hosted
version: "3.2.3"
version: "3.3.0"
wp_json_api:
dependency: "direct main"
description:
@ -1219,5 +1219,5 @@ packages:
source: hosted
version: "3.1.1"
sdks:
dart: ">=2.19.0 <4.0.0"
dart: ">=2.19.0 <3.0.0"
flutter: ">=3.7.0-0"

View File

@ -1,7 +1,7 @@
# Official WooSignal App Template for WooCommerce
# Label StoreMax
# Version: 6.4.1
# Version: 6.5.0
# Author: Anthony Gordon
# Homepage: https://woosignal.com
# Documentation: https://woosignal.com/docs/app/label-storemax
@ -28,8 +28,8 @@ dependencies:
google_fonts: ^4.0.3
analyzer: ^4.2.0
intl: ^0.17.0
nylo_framework: ^4.1.3
woosignal: ^3.2.3
nylo_framework: ^4.1.4
woosignal: ^3.3.0
flutter_stripe: ^8.0.0+1
wp_json_api: ^3.3.2
cached_network_image: ^3.2.3
@ -64,7 +64,7 @@ dependencies:
collection: ^1.15.0
dev_dependencies:
flutter_launcher_icons: ^0.11.0
flutter_launcher_icons: ^0.12.0
lints: ^2.0.0
flutter_test:
sdk: flutter

View File

@ -4,7 +4,7 @@
# WooCommerce App: Label StoreMax
### Label StoreMax - v6.3.1
### Label StoreMax - v6.5.0
[Official WooSignal WooCommerce App](https://woosignal.com)