Changes and tweaks

This commit is contained in:
Anthony 2020-03-28 04:53:06 +00:00
parent b578ac63d4
commit b3eef2047d
46 changed files with 2277 additions and 1612 deletions

View File

@ -0,0 +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":"fluttertoast","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":[]}]}

View File

@ -25,6 +25,12 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 28
@ -37,7 +43,6 @@ android {
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.woosignal.label_storemax"
minSdkVersion 28
targetSdkVersion 28
@ -47,13 +52,20 @@ android {
multiDexEnabled = true
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
signingConfig signingConfigs.release
}
}
}
flutter {

View File

@ -0,0 +1,4 @@
storePassword=<password>
keyPassword=<password>
keyAlias=key
storeFile=<location of the key store file, e.g. /Users/<user name>/key.jks>

View File

@ -0,0 +1,18 @@
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
#
Pod::Spec.new do |s|
s.name = 'Flutter'
s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.'
s.description = <<-DESC
Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
DESC
s.homepage = 'https://flutter.io'
s.license = { :type => 'MIT' }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.vendored_frameworks = 'Flutter.framework'
end

90
LabelStoreMax/ios/Podfile Normal file
View File

@ -0,0 +1,90 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
end
generated_key_values = {}
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) do |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
generated_key_values[podname] = podpath
else
puts "Invalid plugin specification: #{line}"
end
end
generated_key_values
end
target 'Runner' do
use_frameworks!
use_modular_headers!
# Flutter Pod
copied_flutter_dir = File.join(__dir__, 'Flutter')
copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
# Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
# That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
# CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
unless File.exist?(generated_xcode_build_settings_path)
raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
unless File.exist?(copied_framework_path)
FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
end
unless File.exist?(copied_podspec_path)
FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
end
end
# Keep pod path relative so it can be checked into Podfile.lock.
pod 'Flutter', :path => 'Flutter'
# Plugin Pods
# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
system('rm -rf .symlinks')
system('mkdir -p .symlinks/plugins')
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.each do |name, path|
symlink = File.join('.symlinks', 'plugins', name)
File.symlink(path, symlink)
pod name, :path => File.join(symlink, 'ios')
end
end
# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
install! 'cocoapods', :disable_input_output_paths => true
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end

View File

@ -0,0 +1,95 @@
PODS:
- device_info (0.0.1):
- Flutter
- Flutter (1.0.0)
- flutter_money_formatter (0.0.1):
- Flutter
- flutter_web_browser (0.11.0):
- Flutter
- fluttertoast (0.0.2):
- Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- package_info (0.0.1):
- Flutter
- path_provider (0.0.1):
- Flutter
- shared_preferences (0.0.1):
- Flutter
- shared_preferences_macos (0.0.1):
- Flutter
- shared_preferences_web (0.0.1):
- Flutter
- sqflite (0.0.1):
- Flutter
- FMDB (~> 2.7.2)
- Stripe (19.0.1)
- woosignal_stripe (0.0.4):
- Flutter
- Stripe (= 19.0.1)
DEPENDENCIES:
- device_info (from `.symlinks/plugins/device_info/ios`)
- Flutter (from `Flutter`)
- flutter_money_formatter (from `.symlinks/plugins/flutter_money_formatter/ios`)
- flutter_web_browser (from `.symlinks/plugins/flutter_web_browser/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`)
- shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- woosignal_stripe (from `.symlinks/plugins/woosignal_stripe/ios`)
SPEC REPOS:
trunk:
- FMDB
- Stripe
EXTERNAL SOURCES:
device_info:
:path: ".symlinks/plugins/device_info/ios"
Flutter:
:path: Flutter
flutter_money_formatter:
:path: ".symlinks/plugins/flutter_money_formatter/ios"
flutter_web_browser:
:path: ".symlinks/plugins/flutter_web_browser/ios"
fluttertoast:
:path: ".symlinks/plugins/fluttertoast/ios"
package_info:
:path: ".symlinks/plugins/package_info/ios"
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
shared_preferences:
:path: ".symlinks/plugins/shared_preferences/ios"
shared_preferences_macos:
:path: ".symlinks/plugins/shared_preferences_macos/ios"
shared_preferences_web:
:path: ".symlinks/plugins/shared_preferences_web/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
woosignal_stripe:
:path: ".symlinks/plugins/woosignal_stripe/ios"
SPEC CHECKSUMS:
device_info: cbf09d2ec12aa7110e0b09fabe54b5bd6c8efe74
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
flutter_money_formatter: d0d18ddc5be333fad8d09964d741b59fa11a91dc
flutter_web_browser: bdea232160dec44dec86540bee05168cc844ef7c
fluttertoast: b644586ef3b16f67fae9a1f8754cef6b2d6b634b
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
package_info: 48b108e75b8802c2d5e126f208ef540561c98aef
path_provider: f96fff6166a8867510d2c25fdcc346327cc4b259
shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01
shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087
shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9
sqflite: ff1d9da63c06588cc8d1faf7256d741f16989d5a
Stripe: 03313f9520a0786e2c00d9a7a2672c11e08821af
woosignal_stripe: 55c9a08f483aae42ca1c9769f5c474802b865f17
PODFILE CHECKSUM: 1b66dae606f75376c5f2135a8290850eeb09ae83
COCOAPODS: 1.9.1

View File

@ -90,5 +90,7 @@
"About Us": "About Us",
"Something went wrong": "Something went wrong",
"Product variation does not exist": "Product variation does not exist",
"This variation is unavailable": "This variation is unavailable"
"This variation is unavailable": "This variation is unavailable",
"Sorry, something went wrong": "Sorry, something went wrong",
"Back": "Back"
}

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -0,0 +1,29 @@
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<PaymentType> arrPaymentMethods = [
addPayment(
PaymentType(
id: 1,
name: "Stripe",
desc: "Debit or Credit Card",
assetImage: "dark_powered_by_stripe.png",
pay: stripePay,),
),
// e.g. add more here
// addPayment(
// PaymentType(
// id: 2,
// name: "MyNewPaymentMethod",
// desc: "Debit or Credit Card",
// assetImage: "add icon image to assets/images/myimage.png",
// pay: stripePay
// ),
// ),
];

View File

@ -1,72 +0,0 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 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.
var appCountryOptions = [
{"code": "*", "title": "Match all states"},
{"code": "AL", "title": "Alabama"},
{"code": "AK", "title": "Alaska"},
{"code": "AS", "title": "American Samoa"},
{"code": "AZ", "title": "Arizona"},
{"code": "AR", "title": "Arkansas"},
{"code": "CA", "title": "California"},
{"code": "CO", "title": "Colorado"},
{"code": "CT", "title": "Connecticut"},
{"code": "DE", "title": "Delaware"},
{"code": "DC", "title": "District Of Columbia"},
{"code": "FM", "title": "Federated States Of Micronesia"},
{"code": "FL", "title": "Florida"},
{"code": "GA", "title": "Georgia"},
{"code": "GU", "title": "Guam"},
{"code": "HI", "title": "Hawaii"},
{"code": "ID", "title": "Idaho"},
{"code": "IL", "title": "Illinois"},
{"code": "IN", "title": "Indiana"},
{"code": "IA", "title": "Iowa"},
{"code": "KS", "title": "Kansas"},
{"code": "KY", "title": "Kentucky"},
{"code": "LA", "title": "Louisiana"},
{"code": "ME", "title": "Maine"},
{"code": "MH", "title": "Marshall Islands"},
{"code": "MD", "title": "Maryland"},
{"code": "MA", "title": "Massachusetts"},
{"code": "MI", "title": "Michigan"},
{"code": "MN", "title": "Minnesota"},
{"code": "MS", "title": "Mississippi"},
{"code": "MO", "title": "Missouri"},
{"code": "MT", "title": "Montana"},
{"code": "NE", "title": "Nebraska"},
{"code": "NV", "title": "Nevada"},
{"code": "NH", "title": "New Hampshire"},
{"code": "NJ", "title": "New Jersey"},
{"code": "NM", "title": "New Mexico"},
{"code": "NY", "title": "New York"},
{"code": "NC", "title": "North Carolina"},
{"code": "ND", "title": "North Dakota"},
{"code": "MP", "title": "Northern Mariana Islands"},
{"code": "OH", "title": "Ohio"},
{"code": "OK", "title": "Oklahoma"},
{"code": "OR", "title": "Oregon"},
{"code": "PW", "title": "Palau"},
{"code": "PA", "title": "Pennsylvania"},
{"code": "PR", "title": "Puerto Rico"},
{"code": "RI", "title": "Rhode Island"},
{"code": "SC", "title": "South Carolina"},
{"code": "SD", "title": "South Dakota"},
{"code": "TN", "title": "Tennessee"},
{"code": "TX", "title": "Texas"},
{"code": "UT", "title": "Utah"},
{"code": "VT", "title": "Vermont"},
{"code": "VI", "title": "Virgin Islands"},
{"code": "VA", "title": "Virginia"},
{"code": "WA", "title": "Washington"},
{"code": "WV", "title": "West Virginia"},
{"code": "WI", "title": "Wisconsin"},
{"code": "WY", "title": "Wyoming"}
];

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -14,6 +14,8 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../labelconfig.dart';
class AppLocalizations {
final Locale locale;
@ -48,7 +50,8 @@ class _AppLocalizationsDelegate
const _AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode);
bool isSupported(Locale locale) =>
app_locales_supported.contains(locale.languageCode);
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software

View File

@ -0,0 +1,100 @@
// 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 'dart:io';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/billing_details.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/tax_rate.dart';
Future<OrderWC> buildOrderWC({TaxRate taxRate}) async {
OrderWC orderWC = OrderWC();
String paymentMethodName = CheckoutSession.getInstance.paymentType.name ?? "";
orderWC.paymentMethod = Platform.isAndroid
? "$paymentMethodName - Android App"
: "$paymentMethodName - IOS App";
orderWC.paymentMethodTitle = paymentMethodName.toLowerCase();
orderWC.setPaid = true;
orderWC.status = "pending";
orderWC.currency = app_currency_iso.toUpperCase();
List<LineItems> lineItems = [];
List<CartLineItem> cartItems = await Cart.getInstance.getCart();
cartItems.forEach((cartItem) {
LineItems tmpLineItem = LineItems();
tmpLineItem.quantity = cartItem.quantity;
tmpLineItem.name = cartItem.name;
tmpLineItem.productId = cartItem.productId;
if (cartItem.variationId != null && cartItem.variationId != 0) {
tmpLineItem.variationId = cartItem.variationId;
}
tmpLineItem.total = cartItem.total;
tmpLineItem.subtotal = cartItem.subtotal;
lineItems.add(tmpLineItem);
});
orderWC.lineItems = lineItems;
BillingDetails billingDetails = CheckoutSession.getInstance.billingDetails;
Billing billing = Billing();
billing.firstName = billingDetails.billingAddress.firstName;
billing.lastName = billingDetails.billingAddress.lastName;
billing.address1 = billingDetails.billingAddress.addressLine;
billing.city = billingDetails.billingAddress.city;
billing.postcode = billingDetails.billingAddress.postalCode;
billing.country = billingDetails.billingAddress.country;
billing.email = billingDetails.billingAddress.emailAddress;
orderWC.billing = billing;
Shipping shipping = Shipping();
shipping.firstName = billingDetails.shippingAddress.firstName;
shipping.lastName = billingDetails.shippingAddress.lastName;
shipping.address1 = billingDetails.shippingAddress.addressLine;
shipping.city = billingDetails.shippingAddress.city;
shipping.postcode = billingDetails.shippingAddress.postalCode;
shipping.country = billingDetails.shippingAddress.country;
orderWC.shipping = shipping;
orderWC.shippingLines = [];
Map<String, dynamic> shippingLineFeeObj =
CheckoutSession.getInstance.shippingType.toShippingLineFee();
if (shippingLineFeeObj != null) {
ShippingLines shippingLine = ShippingLines();
shippingLine.methodId = shippingLineFeeObj['method_id'];
shippingLine.methodTitle = shippingLineFeeObj['method_title'];
shippingLine.total = shippingLineFeeObj['total'];
orderWC.shippingLines.add(shippingLine);
}
if (taxRate != null) {
orderWC.feeLines = [];
FeeLines feeLines = FeeLines();
feeLines.name = taxRate.name;
feeLines.total = await Cart.getInstance.taxAmount(taxRate);
feeLines.taxClass = "";
feeLines.taxStatus = "taxable";
orderWC.feeLines.add(feeLines);
}
return orderWC;
}

View File

@ -0,0 +1,28 @@
// 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:shared_preferences/shared_preferences.dart';
class SharedPref {
read(String key) async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(key);
}
save(String key, value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, value);
}
remove(String key) async {
final prefs = await SharedPreferences.getInstance();
prefs.remove(key);
}
}

View File

@ -1,50 +1,42 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// 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:label_storemax/app_payment_methods.dart';
import 'package:label_storemax/helpers/app_localizations.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:edge_alert/edge_alert.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:label_storemax/models/billing_details.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/models/payment_type.dart';
import 'package:html/parser.dart';
import 'package:flutter_web_browser/flutter_web_browser.dart';
import 'dart:convert';
import 'package:flutter_money_formatter/flutter_money_formatter.dart';
import 'package:woosignal/models/response/shipping_method.dart';
import 'package:status_alert/status_alert.dart';
import 'package:woosignal/models/response/tax_rate.dart';
import 'package:woosignal/woosignal.dart';
// CONFIG FOR WOOSIGNAL API
var wsConfig = {"appKey": app_key, "debugMode": app_debug};
// MARK: PaymentMethodType
class PaymentType {
int id;
String name;
String assetImage;
PaymentType({this.id, this.name, this.assetImage});
appWooSignal(Function(WooSignal) api) async {
WooSignal wooSignal = await WooSignal.getInstance(
config: {"appKey": app_key, "debugMode": app_debug});
return await api(wooSignal);
}
List<PaymentType> arrPaymentMethods = [
(paymentMethods.contains("Stripe")
? (PaymentType(
id: 1,
name: "Debit or Credit Card",
assetImage: "dark_powered_by_stripe.png"))
: null)
];
List<PaymentType> getPaymentTypes() {
return arrPaymentMethods;
return arrPaymentMethods.where((v) => v != null).toList();
}
PaymentType addPayment(PaymentType paymentType) {
return app_payment_methods.contains(paymentType.name) ? paymentType : null;
}
class HexColor extends Color {
@ -65,29 +57,12 @@ String truncateWithEllipsis(int cutoff, String myString) {
: '${myString.substring(0, cutoff)}...';
}
class TextFieldMaker extends TextField {
static TextField makeWith(labelTitle) {
return TextField(
decoration: InputDecoration(
labelText: labelTitle,
labelStyle: TextStyle(
fontFamily: 'Overpass',
fontWeight: FontWeight.bold,
color: Colors.grey),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.green))),
keyboardAppearance: Brightness.light,
keyboardType: TextInputType.emailAddress,
);
}
}
void showToastWith({String message, String statusType}) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 3,
timeInSecForIosWeb: 3,
backgroundColor:
(statusType == "error" ? HexColor("#b5123a") : Colors.grey),
textColor: (statusType == "error" ? Colors.white : Colors.black),
@ -98,26 +73,15 @@ void showToastNetworkError() {
showToastWith(message: "Oops, something went wrong");
}
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);
}
Widget showAppLoader() {
return SpinKitDoubleBounce(color: HexColor("#393318"));
}
Future delayFunction(void Function() action) {
return Future.delayed(const Duration(milliseconds: 300), action);
showStatusAlert(context,
{@required String title, String subtitle, IconData icon, int duration}) {
StatusAlert.show(
context,
duration: Duration(seconds: duration ?? 2),
title: title,
subtitle: subtitle,
configuration: IconConfiguration(icon: icon ?? Icons.done, size: 50),
);
}
class PaymentMethodType {
@ -176,218 +140,19 @@ void showEdgeAlertWith(context,
}
}
void errorWithNetworkDefault(BuildContext context) {
showEdgeAlertWith(context,
title: trans(context, "Oops"),
desc: trans(context, "Something went wrong"),
style: EdgeAlertStyle.DANGER);
}
String parseHtmlString(String htmlString) {
var document = parse(htmlString);
String parsedString = parse(document.body.text).documentElement.text;
return parsedString;
}
class CartLineItem {
String name;
int productId;
int variationId;
int quantity;
bool isManagedStock;
int stockQuantity;
String shippingClassId;
String taxStatus;
String taxClass;
bool shippingIsTaxable;
String subtotal;
String total;
String imageSrc;
String variationOptions;
String stockStatus;
Object metaData = {};
CartLineItem(
{this.name,
this.productId,
this.variationId,
this.isManagedStock,
this.stockQuantity,
this.quantity,
this.stockStatus,
this.shippingClassId,
this.taxStatus,
this.taxClass,
this.shippingIsTaxable,
this.variationOptions,
this.imageSrc,
this.subtotal,
this.total,
this.metaData});
CartLineItem.fromJson(Map<String, dynamic> json)
: name = json['name'],
productId = json['product_id'],
variationId = json['variation_id'],
quantity = json['quantity'],
shippingClassId = json['shipping_class_id'].toString(),
taxStatus = json['tax_status'],
stockQuantity = json['stock_quantity'],
isManagedStock = json['is_managed_stock'],
shippingIsTaxable = json['shipping_is_taxable'],
subtotal = json['subtotal'],
total = json['total'],
taxClass = json['tax_class'],
stockStatus = json['stock_status'],
imageSrc = json['image_src'],
variationOptions = json['variation_options'],
metaData = json['metaData'];
Map<String, dynamic> toJson() => {
'name': name,
'product_id': productId,
'variation_id': variationId,
'quantity': quantity,
'shipping_class_id': shippingClassId,
'tax_status': taxStatus,
'tax_class': taxClass,
'stock_status': stockStatus,
'is_managed_stock': isManagedStock,
'stock_quantity': stockQuantity,
'shipping_is_taxable': shippingIsTaxable,
'image_src': imageSrc,
'variation_options': variationOptions,
'subtotal': subtotal,
'total': total,
'meta_data': metaData,
};
}
class SharedPref {
read(String key) async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString(key);
}
save(String key, value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, value);
}
remove(String key) async {
final prefs = await SharedPreferences.getInstance();
prefs.remove(key);
}
}
class CustomerAddress {
String firstName;
String lastName;
String addressLine;
String city;
String postalCode;
String country;
String emailAddress;
CustomerAddress(
{this.firstName,
this.lastName,
this.addressLine,
this.city,
this.postalCode,
this.country,
this.emailAddress});
void initAddress() {
firstName = "";
lastName = "";
addressLine = "";
city = "";
postalCode = "";
country = "";
emailAddress = "";
}
bool hasMissingFields() {
return (this.firstName.isEmpty ||
this.lastName.isEmpty ||
this.addressLine.isEmpty ||
this.city.isEmpty ||
this.postalCode.isEmpty);
}
String addressFull() {
List<String> tmpArrAddress = new List<String>();
if (addressLine != "") {
tmpArrAddress.add(addressLine);
}
if (city != "") {
tmpArrAddress.add(city);
}
if (postalCode != "") {
tmpArrAddress.add(postalCode);
}
if (country != "") {
tmpArrAddress.add(country);
}
return tmpArrAddress.join(", ");
}
String nameFull() {
List<String> tmpArrName = new List<String>();
if (firstName != "") {
tmpArrName.add(firstName);
}
if (lastName != "") {
tmpArrName.add(lastName);
}
return tmpArrName.join(", ");
}
CustomerAddress.fromJson(Map<String, dynamic> json) {
firstName = json['first_name'];
lastName = json['last_name'];
addressLine = json['address_line'];
city = json['city'];
postalCode = json['postal_code'];
country = json['country'];
emailAddress = json['email_address'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['first_name'] = this.firstName;
data['last_name'] = this.lastName;
data['address_line'] = this.addressLine;
data['city'] = this.city;
data['postal_code'] = this.postalCode;
data['country'] = this.country;
data['email_address'] = this.emailAddress;
return data;
}
}
class BillingDetails {
CustomerAddress billingAddress;
CustomerAddress shippingAddress;
bool rememberDetails;
void initSession() {
billingAddress = CustomerAddress();
shippingAddress = CustomerAddress();
}
}
class PaymentDetails {
String method;
}
String formatDoubleCurrency({double total}) {
FlutterMoneyFormatter fmf = FlutterMoneyFormatter(
amount: total,
settings: MoneyFormatterSettings(
symbol: app_currency_symbol,
));
),
);
return fmf.output.symbolOnLeft;
}
@ -402,335 +167,12 @@ String formatStringCurrency({String total}) {
amount: tmpVal,
settings: MoneyFormatterSettings(
symbol: app_currency_symbol,
));
),
);
return fmf.output.symbolOnLeft;
}
class ShippingType {
String methodId;
String cost;
dynamic object;
ShippingType({this.methodId, this.object, this.cost});
Map<String, dynamic> toJson() =>
{'methodId': methodId, 'object': object, 'cost': cost};
String getTotal({bool withFormatting}) {
if (this.methodId != null && this.object != null) {
switch (this.methodId) {
case "flat_rate":
FlatRate flatRate = (this.object as FlatRate);
return (withFormatting == true
? formatStringCurrency(total: cost)
: flatRate.cost);
case "free_shipping":
FreeShipping freeShipping = (this.object as FreeShipping);
return (withFormatting == true
? formatStringCurrency(total: cost)
: freeShipping.cost);
case "local_pickup":
LocalPickup localPickup = (this.object as LocalPickup);
return (withFormatting == true
? formatStringCurrency(total: cost)
: localPickup.cost);
default:
return "0";
break;
}
}
return "0";
}
String getTitle() {
if (this.methodId != null && this.object != null) {
switch (this.methodId) {
case "flat_rate":
FlatRate flatRate = (this.object as FlatRate);
return flatRate.title;
case "free_shipping":
FreeShipping freeShipping = (this.object as FreeShipping);
return freeShipping.title;
case "local_pickup":
LocalPickup localPickup = (this.object as LocalPickup);
return localPickup.title;
default:
return "";
break;
}
}
return "";
}
Map<String, dynamic> toShippingLineFee() {
if (this.methodId != null && this.object != null) {
Map<String, dynamic> tmpShippingLinesObj = {};
switch (this.methodId) {
case "flat_rate":
FlatRate flatRate = (this.object as FlatRate);
tmpShippingLinesObj["method_title"] = flatRate.title;
tmpShippingLinesObj["method_id"] = flatRate.methodId;
tmpShippingLinesObj["total"] = this.cost;
break;
case "free_shipping":
FreeShipping freeShipping = (this.object as FreeShipping);
tmpShippingLinesObj["method_title"] = freeShipping.title;
tmpShippingLinesObj["method_id"] = freeShipping.methodId;
tmpShippingLinesObj["total"] = this.cost;
break;
case "local_pickup":
LocalPickup localPickup = (this.object as LocalPickup);
tmpShippingLinesObj["method_title"] = localPickup.title;
tmpShippingLinesObj["method_id"] = localPickup.methodId;
tmpShippingLinesObj["total"] = this.cost;
break;
default:
return null;
break;
}
return tmpShippingLinesObj;
}
return null;
}
}
class CheckoutSession {
String sfKeyCheckout = "CS_BILLING_DETAILS";
CheckoutSession._privateConstructor();
static final CheckoutSession getInstance =
CheckoutSession._privateConstructor();
BillingDetails billingDetails;
ShippingType shippingType;
PaymentType paymentType;
void initSession() {
billingDetails = BillingDetails();
shippingType = null;
}
void saveBillingAddress() {
SharedPref sharedPref = SharedPref();
CustomerAddress customerAddress =
CheckoutSession.getInstance.billingDetails.billingAddress;
String billingAddress = jsonEncode(customerAddress.toJson());
sharedPref.save(sfKeyCheckout, billingAddress);
}
Future<CustomerAddress> getBillingAddress() async {
SharedPref sharedPref = SharedPref();
String strCheckoutDetails = await sharedPref.read(sfKeyCheckout);
if (strCheckoutDetails != null && strCheckoutDetails != "") {
return CustomerAddress.fromJson(jsonDecode(strCheckoutDetails));
}
return null;
}
void clearBillingAddress() {
SharedPref sharedPref = SharedPref();
sharedPref.remove(sfKeyCheckout);
}
Future<String> total({bool withFormat, TaxRate taxRate}) async {
double totalCart = double.parse(await Cart.getInstance.getTotal());
double totalShipping = 0;
if (shippingType != null && shippingType.object != null) {
switch (shippingType.methodId) {
case "flat_rate":
totalShipping = double.parse(shippingType.cost);
break;
case "free_shipping":
totalShipping = double.parse(shippingType.cost);
break;
case "local_pickup":
totalShipping = double.parse(shippingType.cost);
break;
default:
break;
}
}
double total = totalCart + totalShipping;
if (taxRate != null) {
String taxAmount = await Cart.getInstance.taxAmount(taxRate);
total += double.parse(taxAmount);
}
if (withFormat != null && withFormat == true) {
return formatDoubleCurrency(total: total);
}
return total.toString();
}
}
class Cart {
String _keyCart = "CART_SESSION";
Cart._privateConstructor();
static final Cart getInstance = Cart._privateConstructor();
Future<List<CartLineItem>> getCart() async {
List<CartLineItem> cartLineItems = [];
SharedPref sharedPref = SharedPref();
String currentCartArrJSON = (await sharedPref.read(_keyCart) as String);
if (currentCartArrJSON == null) {
cartLineItems = List<CartLineItem>();
} else {
cartLineItems = (jsonDecode(currentCartArrJSON) as List<dynamic>)
.map((i) => CartLineItem.fromJson(i))
.toList();
}
return cartLineItems;
}
void addToCart({CartLineItem cartLineItem}) async {
List<CartLineItem> cartLineItems = await getCart();
var firstCartItem = cartLineItems.firstWhere(
(i) =>
i.productId == cartLineItem.productId ||
i.productId == cartLineItem.productId &&
i.variationId == cartLineItem.variationId, orElse: () {
return null;
});
if (firstCartItem != null) {
return;
}
cartLineItems.add(cartLineItem);
saveCartToPref(cartLineItems: cartLineItems);
}
Future<String> getTotal({bool withFormat}) async {
List<CartLineItem> cartLineItems = await getCart();
double total = 0;
cartLineItems.forEach((cartItem) {
total += (double.parse(cartItem.total) * cartItem.quantity);
});
if (withFormat != null && withFormat == true) {
return formatDoubleCurrency(total: total);
}
return total.toString();
}
Future<String> getSubtotal({bool withFormat}) async {
List<CartLineItem> cartLineItems = await getCart();
double subtotal = 0;
cartLineItems.forEach((cartItem) {
subtotal += (double.parse(cartItem.subtotal) * cartItem.quantity);
});
if (withFormat != null && withFormat == true) {
return formatDoubleCurrency(total: subtotal);
}
return subtotal.toString();
}
void updateQuantity(
{CartLineItem cartLineItem, int incrementQuantity}) async {
List<CartLineItem> cartLineItems = await getCart();
List<CartLineItem> tmpCartItem = new List<CartLineItem>();
cartLineItems.forEach((cartItem) {
if (cartItem.variationId == cartLineItem.variationId &&
cartItem.productId == cartLineItem.productId) {
if ((cartItem.quantity + incrementQuantity) > 0) {
cartItem.quantity += incrementQuantity;
}
}
tmpCartItem.add(cartItem);
});
saveCartToPref(cartLineItems: tmpCartItem);
}
Future<String> cartShortDesc() async {
List<CartLineItem> cartLineItems = await getCart();
var tmpShortItemDesc = [];
cartLineItems.forEach((cartItem) {
tmpShortItemDesc
.add(cartItem.quantity.toString() + " x | " + cartItem.name);
});
return tmpShortItemDesc.join(",");
}
void removeCartItemForIndex({int index}) async {
List<CartLineItem> cartLineItems = await getCart();
cartLineItems.removeAt(index);
saveCartToPref(cartLineItems: cartLineItems);
}
void clear() {
SharedPref sharedPref = SharedPref();
List<CartLineItem> cartLineItems = new List<CartLineItem>();
String jsonArrCartItems =
jsonEncode(cartLineItems.map((i) => i.toJson()).toList());
sharedPref.save(_keyCart, jsonArrCartItems);
}
void saveCartToPref({List<CartLineItem> cartLineItems}) {
SharedPref sharedPref = SharedPref();
String jsonArrCartItems =
jsonEncode(cartLineItems.map((i) => i.toJson()).toList());
sharedPref.save(_keyCart, jsonArrCartItems);
}
Future<String> taxAmount(TaxRate taxRate) async {
double subtotal = 0;
double shippingTotal = 0;
List<CartLineItem> cartItems = await Cart.getInstance.getCart();
if (cartItems.every((c) => c.taxStatus == 'none')) {
return "0";
}
List<CartLineItem> taxableCartLines =
cartItems.where((c) => c.taxStatus == 'taxable').toList();
double cartSubtotal = 0;
if (taxableCartLines.length > 0) {
cartSubtotal = taxableCartLines
.map<double>((m) => double.parse(m.subtotal))
.reduce((a, b) => a + b);
}
subtotal = cartSubtotal;
ShippingType shippingType = CheckoutSession.getInstance.shippingType;
if (shippingType != null) {
switch (shippingType.methodId) {
case "flat_rate":
FlatRate flatRate = (shippingType.object as FlatRate);
if (flatRate.taxable != null && flatRate.taxable) {
shippingTotal += double.parse(shippingType.cost);
}
break;
case "local_pickup":
LocalPickup localPickup = (shippingType.object as LocalPickup);
if (localPickup.taxable != null && localPickup.taxable) {
shippingTotal += double.parse(localPickup.cost);
}
break;
default:
break;
}
}
double total = 0;
if (subtotal != 0) {
total += ((double.parse(taxRate.rate) * subtotal) / 100);
}
if (shippingTotal != 0) {
total += ((double.parse(taxRate.rate) * shippingTotal) / 100);
}
return (total).toString();
}
}
openBrowserTab({String url}) async {
openBrowserTab({@required String url}) async {
await FlutterWebBrowser.openWebPage(
url: url, androidToolbarColor: Colors.white70);
}
@ -739,26 +181,21 @@ EdgeInsets safeAreaDefault() {
return EdgeInsets.only(left: 16, right: 16, bottom: 8);
}
class SlideRightRoute extends PageRouteBuilder {
final Widget widget;
SlideRightRoute({this.widget})
: super(pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return widget;
}, transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return new SlideTransition(
position: new Tween<Offset>(
begin: const Offset(-1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child,
);
});
}
String trans(BuildContext context, String key) {
return AppLocalizations.of(context).trans(key);
}
bool isNumeric(String str) {
if (str == null) {
return false;
}
return double.tryParse(str) != null;
}
checkout(TaxRate taxRate, Function(String total, BillingDetails billingDetails, Cart cart) completeCheckout) async {
String cartTotal = await CheckoutSession.getInstance
.total(withFormat: false, taxRate: taxRate);
BillingDetails billingDetails = CheckoutSession.getInstance.billingDetails;
Cart cart = Cart.getInstance;
return await completeCheckout(cartTotal, billingDetails, cart);
}

View File

@ -3,7 +3,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. 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 - 1.0
VERSION - 2.0
https://woosignal.com
*/
@ -22,7 +22,8 @@
const app_name = "MyApp";
const app_key = "your app key";
const app_key =
"app_affb6434339b34443a297c2e40a3edab7102137e6d67de9abfe612b749bd";
const app_logo_url = "https://woosignal.com/images/120x120_woosignal.png";
@ -31,7 +32,9 @@ const app_privacy_url = "https://yourdomain.com/privacy";
/*<! ------ STRIPE (OPTIONAL) ------!>*/
const app_stripe_account = "your StripeAccount key"; // Your StripeAccount key from WooSignal
const app_stripe_account =
"acct_1DNNUgADlQ9NE89O"; // Your StripeAccount key from WooSignal
const app_stripe_live_mode = false; // SET true for live payments
/*<! ------ APP CURRENCY ------!>*/
@ -40,7 +43,7 @@ const app_currency_symbol = "\£";
const app_currency_iso = "gbp";
const app_locales_supported = ['en'];
const paymentMethods = ["Stripe"];
const app_payment_methods = ["Stripe", "RazorPay"];
/*<! ------ DEBUGGER ENABLED ------!>*/

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,6 +10,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:label_storemax/pages/error_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 'labelconfig.dart';
import 'package:label_storemax/pages/checkout_details.dart';
import 'package:label_storemax/pages/home.dart';
@ -46,43 +50,106 @@ void main() async {
routes: <String, WidgetBuilder>{
'/home': (BuildContext context) => new HomePage(),
'/cart': (BuildContext context) => new CartPage(),
'/browse-category': (BuildContext context) => new BrowseCategoryPage(),
'/product-search': (BuildContext context) => new BrowseSearchPage(),
'/product-detail': (BuildContext context) => new ProductDetailPage(),
'/error': (BuildContext context) => new ErrorPage(),
'/checkout': (BuildContext context) => new CheckoutConfirmationPage(),
'/checkout-status': (BuildContext context) => new CheckoutStatusPage(),
},
onGenerateRoute: (settings) {
switch (settings.name) {
case '/browse-category':
if (settings.arguments != null) {
final ProductCategory category =
settings.arguments as ProductCategory;
return PageTransition(
child: BrowseCategoryPage(productCategory: category),
type: PageTransitionType.fade,
);
}
return PageTransition(
child: ErrorPage(),
type: PageTransitionType.fade,
);
case '/product-search':
if (settings.arguments != null) {
final String search = settings.arguments as String;
return PageTransition(
child: BrowseSearchPage(search: search),
type: PageTransitionType.fade,
);
}
return PageTransition(
child: ErrorPage(),
type: PageTransitionType.fade,
);
case '/product-detail':
if (settings.arguments != null) {
final Product product = settings.arguments as Product;
return PageTransition(
child: ProductDetailPage(product: product),
type: PageTransitionType.rightToLeftWithFade,
);
}
return PageTransition(
child: ErrorPage(),
type: PageTransitionType.fade,
);
case '/checkout-status':
if (settings.arguments != null) {
final Order order = settings.arguments as Order;
return PageTransition(
child: CheckoutStatusPage(order: order),
type: PageTransitionType.rightToLeftWithFade,
);
}
return PageTransition(
child: ErrorPage(),
type: PageTransitionType.fade,
);
case '/home-menu':
return PageTransition(
child: HomeMenuPage(), type: PageTransitionType.leftToRight);
child: HomeMenuPage(),
type: PageTransitionType.leftToRightWithFade,
);
case '/checkout-details':
return PageTransition(
child: CheckoutDetailsPage(),
type: PageTransitionType.downToUp);
type: PageTransitionType.downToUp,
);
case '/about':
return PageTransition(
child: AboutPage(), type: PageTransitionType.leftToRight);
child: AboutPage(),
type: PageTransitionType.leftToRightWithFade,
);
case '/checkout-payment-type':
return PageTransition(
child: CheckoutPaymentTypePage(),
type: PageTransitionType.downToUp);
type: PageTransitionType.downToUp,
);
case '/checkout-shipping-type':
return PageTransition(
child: CheckoutShippingTypePage(),
type: PageTransitionType.downToUp);
type: PageTransitionType.downToUp,
);
case '/home-search':
return PageTransition(
child: HomeSearchPage(), type: PageTransitionType.downToUp);
child: HomeSearchPage(),
type: PageTransitionType.downToUp,
);
default:
return null;
}
},
supportedLocales: [Locale('en')],
supportedLocales: [
Locale('en'),
],
localizationsDelegates: [
AppLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
@ -113,7 +180,8 @@ void main() async {
iconTheme: IconThemeData(color: Colors.black),
actionsIconTheme: IconThemeData(
color: Colors.black,
)),
),
),
accentColor: Colors.black,
accentTextTheme: textThemeAccent(),
textTheme: textThemeMain(),

View File

@ -0,0 +1,22 @@
// 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:label_storemax/models/customer_address.dart';
class BillingDetails {
CustomerAddress billingAddress;
CustomerAddress shippingAddress;
bool rememberDetails;
void initSession() {
billingAddress = CustomerAddress();
shippingAddress = CustomerAddress();
}
}

View File

@ -0,0 +1,181 @@
// 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 'dart:convert';
import 'package:label_storemax/helpers/shared_pref.dart';
import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/models/shipping_type.dart';
import 'package:woosignal/models/response/shipping_method.dart';
import 'package:woosignal/models/response/tax_rate.dart';
import '../helpers/tools.dart';
class Cart {
String _keyCart = "CART_SESSION";
Cart._privateConstructor();
static final Cart getInstance = Cart._privateConstructor();
Future<List<CartLineItem>> getCart() async {
List<CartLineItem> cartLineItems = [];
SharedPref sharedPref = SharedPref();
String currentCartArrJSON = (await sharedPref.read(_keyCart) as String);
if (currentCartArrJSON == null) {
cartLineItems = List<CartLineItem>();
} else {
cartLineItems = (jsonDecode(currentCartArrJSON) as List<dynamic>)
.map((i) => CartLineItem.fromJson(i))
.toList();
}
return cartLineItems;
}
void addToCart({CartLineItem cartLineItem}) async {
List<CartLineItem> cartLineItems = await getCart();
var firstCartItem = cartLineItems.firstWhere(
(i) =>
i.productId == cartLineItem.productId ||
i.productId == cartLineItem.productId &&
i.variationId == cartLineItem.variationId, orElse: () {
return null;
});
if (firstCartItem != null) {
return;
}
cartLineItems.add(cartLineItem);
saveCartToPref(cartLineItems: cartLineItems);
}
Future<String> getTotal({bool withFormat}) async {
List<CartLineItem> cartLineItems = await getCart();
double total = 0;
cartLineItems.forEach((cartItem) {
total += (double.parse(cartItem.total) * cartItem.quantity);
});
if (withFormat != null && withFormat == true) {
return formatDoubleCurrency(total: total);
}
return total.toString();
}
Future<String> getSubtotal({bool withFormat}) async {
List<CartLineItem> cartLineItems = await getCart();
double subtotal = 0;
cartLineItems.forEach((cartItem) {
subtotal += (double.parse(cartItem.subtotal) * cartItem.quantity);
});
if (withFormat != null && withFormat == true) {
return formatDoubleCurrency(total: subtotal);
}
return subtotal.toString();
}
void updateQuantity(
{CartLineItem cartLineItem, int incrementQuantity}) async {
List<CartLineItem> cartLineItems = await getCart();
List<CartLineItem> tmpCartItem = new List<CartLineItem>();
cartLineItems.forEach((cartItem) {
if (cartItem.variationId == cartLineItem.variationId &&
cartItem.productId == cartLineItem.productId) {
if ((cartItem.quantity + incrementQuantity) > 0) {
cartItem.quantity += incrementQuantity;
}
}
tmpCartItem.add(cartItem);
});
saveCartToPref(cartLineItems: tmpCartItem);
}
Future<String> cartShortDesc() async {
List<CartLineItem> cartLineItems = await getCart();
var tmpShortItemDesc = [];
cartLineItems.forEach((cartItem) {
tmpShortItemDesc
.add(cartItem.quantity.toString() + " x | " + cartItem.name);
});
return tmpShortItemDesc.join(",");
}
void removeCartItemForIndex({int index}) async {
List<CartLineItem> cartLineItems = await getCart();
cartLineItems.removeAt(index);
saveCartToPref(cartLineItems: cartLineItems);
}
void clear() {
SharedPref sharedPref = SharedPref();
List<CartLineItem> cartLineItems = new List<CartLineItem>();
String jsonArrCartItems =
jsonEncode(cartLineItems.map((i) => i.toJson()).toList());
sharedPref.save(_keyCart, jsonArrCartItems);
}
void saveCartToPref({List<CartLineItem> cartLineItems}) {
SharedPref sharedPref = SharedPref();
String jsonArrCartItems =
jsonEncode(cartLineItems.map((i) => i.toJson()).toList());
sharedPref.save(_keyCart, jsonArrCartItems);
}
Future<String> taxAmount(TaxRate taxRate) async {
double subtotal = 0;
double shippingTotal = 0;
List<CartLineItem> cartItems = await Cart.getInstance.getCart();
if (cartItems.every((c) => c.taxStatus == 'none')) {
return "0";
}
List<CartLineItem> taxableCartLines =
cartItems.where((c) => c.taxStatus == 'taxable').toList();
double cartSubtotal = 0;
if (taxableCartLines.length > 0) {
cartSubtotal = taxableCartLines
.map<double>((m) => double.parse(m.subtotal))
.reduce((a, b) => a + b);
}
subtotal = cartSubtotal;
ShippingType shippingType = CheckoutSession.getInstance.shippingType;
if (shippingType != null) {
switch (shippingType.methodId) {
case "flat_rate":
FlatRate flatRate = (shippingType.object as FlatRate);
if (flatRate.taxable != null && flatRate.taxable) {
shippingTotal += double.parse(shippingType.cost);
}
break;
case "local_pickup":
LocalPickup localPickup = (shippingType.object as LocalPickup);
if (localPickup.taxable != null && localPickup.taxable) {
shippingTotal += double.parse(localPickup.cost);
}
break;
default:
break;
}
}
double total = 0;
if (subtotal != 0) {
total += ((double.parse(taxRate.rate) * subtotal) / 100);
}
if (shippingTotal != 0) {
total += ((double.parse(taxRate.rate) * shippingTotal) / 100);
}
return (total).toString();
}
}

View File

@ -0,0 +1,83 @@
// 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.
class CartLineItem {
String name;
int productId;
int variationId;
int quantity;
bool isManagedStock;
int stockQuantity;
String shippingClassId;
String taxStatus;
String taxClass;
bool shippingIsTaxable;
String subtotal;
String total;
String imageSrc;
String variationOptions;
String stockStatus;
Object metaData = {};
CartLineItem(
{this.name,
this.productId,
this.variationId,
this.isManagedStock,
this.stockQuantity,
this.quantity,
this.stockStatus,
this.shippingClassId,
this.taxStatus,
this.taxClass,
this.shippingIsTaxable,
this.variationOptions,
this.imageSrc,
this.subtotal,
this.total,
this.metaData});
CartLineItem.fromJson(Map<String, dynamic> json)
: name = json['name'],
productId = json['product_id'],
variationId = json['variation_id'],
quantity = json['quantity'],
shippingClassId = json['shipping_class_id'].toString(),
taxStatus = json['tax_status'],
stockQuantity = json['stock_quantity'],
isManagedStock = json['is_managed_stock'],
shippingIsTaxable = json['shipping_is_taxable'],
subtotal = json['subtotal'],
total = json['total'],
taxClass = json['tax_class'],
stockStatus = json['stock_status'],
imageSrc = json['image_src'],
variationOptions = json['variation_options'],
metaData = json['metaData'];
Map<String, dynamic> toJson() => {
'name': name,
'product_id': productId,
'variation_id': variationId,
'quantity': quantity,
'shipping_class_id': shippingClassId,
'tax_status': taxStatus,
'tax_class': taxClass,
'stock_status': stockStatus,
'is_managed_stock': isManagedStock,
'stock_quantity': stockQuantity,
'shipping_is_taxable': shippingIsTaxable,
'image_src': imageSrc,
'variation_options': variationOptions,
'subtotal': subtotal,
'total': total,
'meta_data': metaData,
};
}

View File

@ -0,0 +1,94 @@
// 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 'dart:convert';
import 'package:label_storemax/helpers/shared_pref.dart';
import 'package:label_storemax/models/billing_details.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/customer_address.dart';
import 'package:label_storemax/models/payment_type.dart';
import 'package:label_storemax/models/shipping_type.dart';
import 'package:woosignal/models/response/tax_rate.dart';
import '../helpers/tools.dart';
class CheckoutSession {
String sfKeyCheckout = "CS_BILLING_DETAILS";
CheckoutSession._privateConstructor();
static final CheckoutSession getInstance =
CheckoutSession._privateConstructor();
BillingDetails billingDetails;
ShippingType shippingType;
PaymentType paymentType;
void initSession() {
billingDetails = BillingDetails();
shippingType = null;
}
void saveBillingAddress() {
SharedPref sharedPref = SharedPref();
CustomerAddress customerAddress =
CheckoutSession.getInstance.billingDetails.billingAddress;
String billingAddress = jsonEncode(customerAddress.toJson());
sharedPref.save(sfKeyCheckout, billingAddress);
}
Future<CustomerAddress> getBillingAddress() async {
SharedPref sharedPref = SharedPref();
String strCheckoutDetails = await sharedPref.read(sfKeyCheckout);
if (strCheckoutDetails != null && strCheckoutDetails != "") {
return CustomerAddress.fromJson(jsonDecode(strCheckoutDetails));
}
return null;
}
void clearBillingAddress() {
SharedPref sharedPref = SharedPref();
sharedPref.remove(sfKeyCheckout);
}
Future<String> total({bool withFormat, TaxRate taxRate}) async {
double totalCart = double.parse(await Cart.getInstance.getTotal());
double totalShipping = 0;
if (shippingType != null && shippingType.object != null) {
switch (shippingType.methodId) {
case "flat_rate":
totalShipping = double.parse(shippingType.cost);
break;
case "free_shipping":
totalShipping = double.parse(shippingType.cost);
break;
case "local_pickup":
totalShipping = double.parse(shippingType.cost);
break;
default:
break;
}
}
double total = totalCart + totalShipping;
if (taxRate != null) {
String taxAmount = await Cart.getInstance.taxAmount(taxRate);
total += double.parse(taxAmount);
}
if (withFormat != null && withFormat == true) {
return formatDoubleCurrency(total: total);
}
return total.toString();
}
}

View File

@ -0,0 +1,96 @@
// 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.
class CustomerAddress {
String firstName;
String lastName;
String addressLine;
String city;
String postalCode;
String country;
String emailAddress;
CustomerAddress(
{this.firstName,
this.lastName,
this.addressLine,
this.city,
this.postalCode,
this.country,
this.emailAddress});
void initAddress() {
firstName = "";
lastName = "";
addressLine = "";
city = "";
postalCode = "";
country = "";
emailAddress = "";
}
bool hasMissingFields() {
return (this.firstName.isEmpty ||
this.lastName.isEmpty ||
this.addressLine.isEmpty ||
this.city.isEmpty ||
this.postalCode.isEmpty);
}
String addressFull() {
List<String> tmpArrAddress = new List<String>();
if (addressLine != "") {
tmpArrAddress.add(addressLine);
}
if (city != "") {
tmpArrAddress.add(city);
}
if (postalCode != "") {
tmpArrAddress.add(postalCode);
}
if (country != "") {
tmpArrAddress.add(country);
}
return tmpArrAddress.join(", ");
}
String nameFull() {
List<String> tmpArrName = new List<String>();
if (firstName != "") {
tmpArrName.add(firstName);
}
if (lastName != "") {
tmpArrName.add(lastName);
}
return tmpArrName.join(", ");
}
CustomerAddress.fromJson(Map<String, dynamic> json) {
firstName = json['first_name'];
lastName = json['last_name'];
addressLine = json['address_line'];
city = json['city'];
postalCode = json['postal_code'];
country = json['country'];
emailAddress = json['email_address'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['first_name'] = this.firstName;
data['last_name'] = this.lastName;
data['address_line'] = this.addressLine;
data['city'] = this.city;
data['postal_code'] = this.postalCode;
data['country'] = this.country;
data['email_address'] = this.emailAddress;
return data;
}
}

View File

@ -0,0 +1,19 @@
// 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.
class PaymentType {
int id;
String name;
String desc;
String assetImage;
Function pay;
PaymentType({this.id, this.name, this.desc, this.assetImage, this.pay});
}

View File

@ -0,0 +1,103 @@
// 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:woosignal/models/response/shipping_method.dart';
import '../helpers/tools.dart';
class ShippingType {
String methodId;
String cost;
dynamic object;
ShippingType({this.methodId, this.object, this.cost});
Map<String, dynamic> toJson() =>
{'methodId': methodId, 'object': object, 'cost': cost};
String getTotal({bool withFormatting}) {
if (this.methodId != null && this.object != null) {
switch (this.methodId) {
case "flat_rate":
FlatRate flatRate = (this.object as FlatRate);
return (withFormatting == true
? formatStringCurrency(total: cost)
: flatRate.cost);
case "free_shipping":
FreeShipping freeShipping = (this.object as FreeShipping);
return (withFormatting == true
? formatStringCurrency(total: cost)
: freeShipping.cost);
case "local_pickup":
LocalPickup localPickup = (this.object as LocalPickup);
return (withFormatting == true
? formatStringCurrency(total: cost)
: localPickup.cost);
default:
return "0";
break;
}
}
return "0";
}
String getTitle() {
if (this.methodId != null && this.object != null) {
switch (this.methodId) {
case "flat_rate":
FlatRate flatRate = (this.object as FlatRate);
return flatRate.title;
case "free_shipping":
FreeShipping freeShipping = (this.object as FreeShipping);
return freeShipping.title;
case "local_pickup":
LocalPickup localPickup = (this.object as LocalPickup);
return localPickup.title;
default:
return "";
break;
}
}
return "";
}
Map<String, dynamic> toShippingLineFee() {
if (this.methodId != null && this.object != null) {
Map<String, dynamic> tmpShippingLinesObj = {};
switch (this.methodId) {
case "flat_rate":
FlatRate flatRate = (this.object as FlatRate);
tmpShippingLinesObj["method_title"] = flatRate.title;
tmpShippingLinesObj["method_id"] = flatRate.methodId;
tmpShippingLinesObj["total"] = this.cost;
break;
case "free_shipping":
FreeShipping freeShipping = (this.object as FreeShipping);
tmpShippingLinesObj["method_title"] = freeShipping.title;
tmpShippingLinesObj["method_id"] = freeShipping.methodId;
tmpShippingLinesObj["total"] = this.cost;
break;
case "local_pickup":
LocalPickup localPickup = (this.object as LocalPickup);
tmpShippingLinesObj["method_title"] = localPickup.title;
tmpShippingLinesObj["method_id"] = localPickup.methodId;
tmpShippingLinesObj["total"] = this.cost;
break;
default:
return null;
break;
}
return tmpShippingLinesObj;
}
return null;
}
}

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -11,6 +11,7 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/widgets/menu_item.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:package_info/package_info.dart';

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,20 +10,23 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:woosignal/models/response/product_category.dart';
import 'package:woosignal/models/response/products.dart' as WS;
import 'package:woosignal/woosignal.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
class BrowseCategoryPage extends StatefulWidget {
BrowseCategoryPage();
final ProductCategory productCategory;
const BrowseCategoryPage({Key key, @required this.productCategory})
: super(key: key);
@override
_BrowseCategoryPageState createState() => _BrowseCategoryPageState();
_BrowseCategoryPageState createState() =>
_BrowseCategoryPageState(productCategory);
}
class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
_BrowseCategoryPageState();
_BrowseCategoryPageState(this._selectedCategory);
List<WS.Product> _products = [];
var _productsController = ScrollController();
@ -44,6 +47,11 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
_shouldStopRequests = false;
waitForNextRequest = false;
_fetchProductsForCategory();
_addScrollListener();
}
_addScrollListener() async {
_productsController.addListener(() {
double maxScroll = _productsController.position.maxScrollExtent;
double currentScroll = _productsController.position.pixels;
@ -55,44 +63,35 @@ class _BrowseCategoryPageState extends State<BrowseCategoryPage> {
if (waitForNextRequest) {
return;
}
WooSignal.getInstance(config: wsConfig).then((wcStore) {
_fetchMoreProducts();
}
});
}
_fetchMoreProducts() async {
waitForNextRequest = true;
List<WS.Product> products = await appWooSignal((api) {
return api.getProducts(perPage: 50, page: _page, status: "publish");
});
_products.addAll(products);
waitForNextRequest = false;
_page = _page + 1;
wcStore
.getProducts(perPage: 50, page: _page, status: "publish")
.then((products) {
waitForNextRequest = false;
if (products.length == 0) {
_shouldStopRequests = true;
}
_products.addAll(products.toList());
setState(() {});
});
});
}
});
}
_fetchProductsForCategory() {
WooSignal.getInstance(config: wsConfig).then((wcStore) {
wcStore
.getProducts(category: _selectedCategory.id.toString(), perPage: 50)
.then((products) {
_products = products;
_fetchProductsForCategory() async {
_products = await appWooSignal((api) {
return api.getProducts(
category: _selectedCategory.id.toString(), perPage: 50);
});
setState(() {
_isLoading = false;
});
});
});
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_isLoading) {
_selectedCategory = ModalRoute.of(context).settings.arguments;
_fetchProductsForCategory();
}
}
@override

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,19 +10,20 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:woosignal/models/response/products.dart' as WS;
import 'package:woosignal/woosignal.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
class BrowseSearchPage extends StatefulWidget {
BrowseSearchPage();
final String search;
BrowseSearchPage({Key key, @required this.search}) : super(key: key);
@override
_BrowseSearchState createState() => _BrowseSearchState();
_BrowseSearchState createState() => _BrowseSearchState(search);
}
class _BrowseSearchState extends State<BrowseSearchPage> {
_BrowseSearchState();
_BrowseSearchState(this._search);
var _productsController = ScrollController();
List<WS.Product> _products = [];
@ -41,6 +42,11 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
_shouldStopRequests = false;
waitForNextRequest = false;
_fetchProductsForSearch(_page);
_addScrollListener();
}
_addScrollListener() async {
_productsController.addListener(() {
double maxScroll = _productsController.position.maxScrollExtent;
double currentScroll = _productsController.position.pixels;
@ -57,33 +63,20 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
});
}
_fetchProductsForSearch(int page) {
WooSignal.getInstance(config: wsConfig).then((wcStore) {
_fetchProductsForSearch(int page) async {
waitForNextRequest = true;
List<WS.Product> products = await appWooSignal((api) {
_page = _page + 1;
wcStore
.getProducts(
search: _search, perPage: 100, page: page, status: "publish")
.then((products) {
waitForNextRequest = false;
return api.getProducts(
search: _search, perPage: 100, page: page, status: "publish");
});
if (products.length == 0) {
_shouldStopRequests = true;
}
_products.addAll(products.toList());
setState(() {
_products.addAll(products.toList());
_isLoading = false;
});
});
});
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_isLoading) {
_search = ModalRoute.of(context).settings.arguments;
_fetchProductsForSearch(_page);
}
}
@override
@ -122,10 +115,14 @@ class _BrowseSearchState extends State<BrowseSearchPage> {
? GridView.count(
crossAxisCount: 2,
controller: _productsController,
children: List.generate(_products.length, (index) {
children: List.generate(
_products.length,
(index) {
return wsCardProductItem(context,
index: index, product: _products[index]);
}))
},
),
)
: wsNoResults(context)),
flex: 1,
),

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -11,8 +11,13 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/models/customer_address.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:woosignal/woosignal.dart';
class CartPage extends StatefulWidget {
CartPage();
@ -45,10 +50,12 @@ class _CartPageState extends State<CartPage> {
});
return [];
}
WooSignal wooSignal = await WooSignal.getInstance(config: wsConfig);
List<Map<String, dynamic>> cartJSON = cart.map((c) => c.toJson()).toList();
List<dynamic> cartRes = await wooSignal.cartCheck(cartJSON);
List<dynamic> cartRes = await appWooSignal((api) {
return api.cartCheck(cartJSON);
});
_cartLines = cartRes.map((json) => CartLineItem.fromJson(json)).toList();
if (_cartLines.length > 0) {
Cart.getInstance.saveCartToPref(cartLineItems: _cartLines);

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -9,27 +9,28 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/material.dart';
import 'package:label_storemax/app_payment_methods.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/models/customer_address.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:woosignal/models/response/tax_rate.dart';
import 'package:woosignal_stripe/woosignal_stripe.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart' as WS;
import 'package:woosignal/woosignal.dart';
import 'dart:io';
import 'package:label_storemax/app_country_options.dart';
class CheckoutConfirmationPage extends StatefulWidget {
CheckoutConfirmationPage();
CheckoutConfirmationPage({Key key}) : super(key: key);
@override
_CheckoutConfirmationPageState createState() =>
_CheckoutConfirmationPageState();
CheckoutConfirmationPageState createState() =>
CheckoutConfirmationPageState();
}
class _CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
_CheckoutConfirmationPageState();
class CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
CheckoutConfirmationPageState();
GlobalKey<CheckoutConfirmationPageState> _key = GlobalKey<CheckoutConfirmationPageState>();
bool _showFullLoader;
@ -48,9 +49,17 @@ class _CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
_getTaxes();
}
void reloadState({bool showLoader}) {
setState(() {
_showFullLoader = showLoader ?? false;
});
}
_getTaxes() async {
WooSignal wooSignal = await WooSignal.getInstance(config: wsConfig);
_taxRates = await wooSignal.getTaxRates(page: 1, perPage: 100);
_taxRates = await appWooSignal((api) {
return api.getTaxRates(page: 1, perPage: 100);
});
if (CheckoutSession.getInstance.billingDetails.shippingAddress == null) {
setState(() {
_showFullLoader = false;
@ -150,7 +159,8 @@ class _CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
30,
CheckoutSession.getInstance
.billingDetails.billingAddress
.addressFull())),
.addressFull(),
)),
action: _actionCheckoutDetails,
showBorderBottom: true)
: wsCheckoutRow(context,
@ -170,7 +180,7 @@ class _CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
.paymentType.assetImage),
width: 70),
leadTitle: CheckoutSession
.getInstance.paymentType.name,
.getInstance.paymentType.desc,
action: _actionPayWith,
showBorderBottom: true)
: wsCheckoutRow(context,
@ -236,8 +246,13 @@ class _CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
showAppLoader(),
Text(trans(context, "One moment") + "...",
style: Theme.of(context).primaryTextTheme.subhead)
Padding(
padding: const EdgeInsets.only(top: 15),
child: Text(
trans(context, "One moment") + "...",
style: Theme.of(context).primaryTextTheme.subhead,
),
)
],
),
),
@ -284,168 +299,7 @@ class _CheckoutConfirmationPageState extends State<CheckoutConfirmationPage> {
return;
}
_pay();
}
Future<OrderWC> _buildOrderWC() async {
OrderWC orderWC = OrderWC();
if (Platform.isAndroid) {
orderWC.paymentMethod = "Stripe - Android App";
orderWC.paymentMethodTitle = "stripe";
} else if (Platform.isIOS) {
orderWC.paymentMethod = "Stripe - IOS App";
orderWC.paymentMethodTitle = "stripe";
}
orderWC.setPaid = true;
orderWC.status = "pending";
orderWC.currency = app_currency_iso.toUpperCase();
List<LineItems> lineItems = [];
List<CartLineItem> cartItems = await Cart.getInstance.getCart();
cartItems.forEach((cartItem) {
LineItems tmpLineItem = LineItems();
tmpLineItem.quantity = cartItem.quantity;
tmpLineItem.name = cartItem.name;
tmpLineItem.productId = cartItem.productId;
if (cartItem.variationId != null && cartItem.variationId != 0) {
tmpLineItem.variationId = cartItem.variationId;
}
tmpLineItem.total = cartItem.total;
tmpLineItem.subtotal = cartItem.subtotal;
lineItems.add(tmpLineItem);
});
orderWC.lineItems = lineItems;
BillingDetails billingDetails = CheckoutSession.getInstance.billingDetails;
Billing billing = Billing();
billing.firstName = billingDetails.billingAddress.firstName;
billing.lastName = billingDetails.billingAddress.lastName;
billing.address1 = billingDetails.billingAddress.addressLine;
billing.city = billingDetails.billingAddress.city;
billing.postcode = billingDetails.billingAddress.postalCode;
billing.country = billingDetails.billingAddress.country;
billing.email = billingDetails.billingAddress.emailAddress;
orderWC.billing = billing;
Shipping shipping = Shipping();
shipping.firstName = billingDetails.shippingAddress.firstName;
shipping.lastName = billingDetails.shippingAddress.lastName;
shipping.address1 = billingDetails.shippingAddress.addressLine;
shipping.city = billingDetails.shippingAddress.city;
shipping.postcode = billingDetails.shippingAddress.postalCode;
shipping.country = billingDetails.shippingAddress.country;
orderWC.shipping = shipping;
orderWC.shippingLines = [];
Map<String, dynamic> shippingLineFeeObj =
CheckoutSession.getInstance.shippingType.toShippingLineFee();
if (shippingLineFeeObj != null) {
ShippingLines shippingLine = ShippingLines();
shippingLine.methodId = shippingLineFeeObj['method_id'];
shippingLine.methodTitle = shippingLineFeeObj['method_title'];
shippingLine.total = shippingLineFeeObj['total'];
orderWC.shippingLines.add(shippingLine);
}
if (_taxRate != null) {
orderWC.feeLines = [];
FeeLines feeLines = FeeLines();
feeLines.name = _taxRate.name;
feeLines.total = await Cart.getInstance.taxAmount(_taxRate);
feeLines.taxClass = "";
feeLines.taxStatus = "taxable";
orderWC.feeLines.add(feeLines);
}
return orderWC;
}
_pay() async {
WooSignal wsStore = await WooSignal.getInstance(config: wsConfig);
String cartTotal = await CheckoutSession.getInstance
.total(withFormat: false, taxRate: _taxRate);
FlutterStripePayment.setStripeSettings(
stripeAccount: app_stripe_account, liveMode: app_stripe_live_mode);
var paymentResponse = await FlutterStripePayment.addPaymentMethod();
if (paymentResponse.status == PaymentResponseStatus.succeeded) {
setState(() {
_showFullLoader = true;
});
BillingDetails checkoutDetails =
CheckoutSession.getInstance.billingDetails;
Map<String, dynamic> address = {
"name": checkoutDetails.billingAddress.nameFull(),
"line1": checkoutDetails.shippingAddress.addressLine,
"city": checkoutDetails.shippingAddress.city,
"postal_code": checkoutDetails.shippingAddress.postalCode,
"country": checkoutDetails.shippingAddress.country
};
String cartShortDesc = await Cart.getInstance.cartShortDesc();
dynamic rsp = await wsStore.stripePaymentIntent(
amount: cartTotal,
email: checkoutDetails.billingAddress.emailAddress,
desc: cartShortDesc,
shipping: address);
if (rsp == null) {
showToastNetworkError();
setState(() {
_showFullLoader = false;
});
return false;
}
String clientSecret = rsp["client_secret"];
var intentResponse = await FlutterStripePayment.confirmPaymentIntent(
clientSecret,
paymentResponse.paymentMethodId,
(double.parse(cartTotal) * 100));
if (intentResponse.status == PaymentResponseStatus.succeeded) {
OrderWC orderWC = await _buildOrderWC();
WS.Order order = await wsStore.createOrder(orderWC);
if (order != null) {
Cart.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
showEdgeAlertWith(context,
title: trans(context, "Error"),
desc: trans(
context, "Something went wrong, please contact our store"));
setState(() {
_showFullLoader = false;
});
}
} else if (intentResponse.status == PaymentResponseStatus.failed) {
if (app_debug) {
print(intentResponse.errorMessage);
}
showEdgeAlertWith(context,
title: trans(context, "Error"), desc: intentResponse.errorMessage);
setState(() {
_showFullLoader = false;
});
} else {
setState(() {
_showFullLoader = false;
});
}
}
CheckoutSession.getInstance.paymentType
.pay(context, state: this, taxRate: _taxRate);
}
}

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,6 +10,10 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/billing_details.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/models/customer_address.dart';
import 'package:label_storemax/widgets/buttons.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:label_storemax/app_country_options.dart';
@ -82,7 +86,7 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
wsModalBottom(context,
title: trans(context, "Select a country"),
bodyWidget: Expanded(
child: ListView.builder(
child: ListView.separated(
itemCount: appCountryOptions.length,
itemBuilder: (BuildContext context, int index) {
Map<String, String> strName = appCountryOptions[index];
@ -102,7 +106,14 @@ class _CheckoutDetailsPageState extends State<CheckoutDetailsPage> {
});
},
);
}),
},
separatorBuilder: (cxt, i) {
return Divider(
height: 0,
color: Colors.black12,
);
},
),
));
}

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,6 +10,8 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/widgets/buttons.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
class CheckoutPaymentTypePage extends StatefulWidget {
@ -26,6 +28,12 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
@override
void initState() {
super.initState();
if (CheckoutSession.getInstance.paymentType == null) {
if (getPaymentTypes() != null && getPaymentTypes().length > 0) {
CheckoutSession.getInstance.paymentType = getPaymentTypes().first;
}
}
}
@override
@ -78,12 +86,16 @@ class _CheckoutPaymentTypePageState extends State<CheckoutPaymentTypePage> {
width: 60,
fit: BoxFit.fitHeight,
alignment: Alignment.center),
title: Text(getPaymentTypes()[index].name,
title: Text(getPaymentTypes()[index].desc,
style: Theme.of(context)
.primaryTextTheme
.subhead),
selected: true,
trailing: Icon(Icons.check),
trailing: (CheckoutSession
.getInstance.paymentType ==
getPaymentTypes()[index]
? Icon(Icons.check)
: null),
onTap: () {
CheckoutSession.getInstance.paymentType =
getPaymentTypes()[index];

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,9 +10,14 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/models/customer_address.dart';
import 'package:label_storemax/models/shipping_type.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:label_storemax/widgets/buttons.dart';
import 'package:woosignal/models/response/shipping_method.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:woosignal/woosignal.dart';
import 'package:label_storemax/app_country_options.dart';
class CheckoutShippingTypePage extends StatefulWidget {
@ -43,8 +48,9 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
}
_getShippingMethods() async {
WooSignal wooSignal = await WooSignal.getInstance(config: wsConfig);
List<WSShipping> wsShipping = await wooSignal.getShippingMethods();
List<WSShipping> wsShipping = await appWooSignal((api) {
return api.getShippingMethods();
});
CustomerAddress customerAddress =
CheckoutSession.getInstance.billingDetails.shippingAddress;
String postalCode = customerAddress.postalCode;
@ -96,7 +102,7 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
if (_shipping.methods.freeShipping != null) {
_shipping.methods.freeShipping.forEach((freeShipping) {
if (_isNumeric(freeShipping.cost)) {
if (isNumeric(freeShipping.cost)) {
Map<String, dynamic> tmpShippingOption = {};
tmpShippingOption = {
"id": freeShipping.id,
@ -120,13 +126,6 @@ class _CheckoutShippingTypePageState extends State<CheckoutShippingTypePage> {
});
}
bool _isNumeric(String str) {
if(str == null) {
return false;
}
return double.tryParse(str) != null;
}
Future<String> _getShippingPrice(int index) async {
double total = 0;
List<CartLineItem> cartLineItem = await Cart.getInstance.getCart();

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,19 +10,21 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:woosignal/models/response/products.dart' as WS;
import 'package:woosignal/models/response/order.dart' as WS;
import '../widgets/woosignal_ui.dart';
class CheckoutStatusPage extends StatefulWidget {
CheckoutStatusPage();
final WS.Order order;
CheckoutStatusPage({Key key, @required this.order}) : super(key: key);
@override
_CheckoutStatusState createState() => _CheckoutStatusState();
_CheckoutStatusState createState() => _CheckoutStatusState(this.order);
}
class _CheckoutStatusState extends State<CheckoutStatusPage> {
_CheckoutStatusState();
_CheckoutStatusState(this._order);
WS.Order _order;
@ -31,19 +33,13 @@ class _CheckoutStatusState extends State<CheckoutStatusPage> {
super.initState();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_order = ModalRoute.of(context).settings.arguments;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0.0,
title: Image.network(app_logo_url, height: 100),
title: storeLogo(height: 60),
automaticallyImplyLeading: false,
centerTitle: true,
),

View File

@ -0,0 +1,62 @@
// 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/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/widgets/buttons.dart';
class ErrorPage extends StatefulWidget {
ErrorPage();
@override
_ErrorPageState createState() => _ErrorPageState();
}
class _ErrorPageState extends State<ErrorPage> {
_ErrorPageState();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
minimum: safeAreaDefault(),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(
Icons.error_outline,
size: 100,
color: Colors.black54,
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
trans(context, "Sorry, something went wrong"),
style: Theme.of(context).primaryTextTheme.body1,
textAlign: TextAlign.center,
),
),
wsLinkButton(context, title: trans(context, "Back"), action: () {
Navigator.pop(context);
}),
],
),
),
),
);
}
}

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,9 +10,10 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:label_storemax/widgets/cart_icon.dart';
import 'package:woosignal/models/response/product_category.dart' as WS;
import 'package:woosignal/models/response/products.dart' as WS;
import 'package:woosignal/woosignal.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
class HomePage extends StatefulWidget {
@ -42,9 +43,33 @@ class _HomePageState extends State<HomePage> {
_isLoading = true;
_page = 1;
_home();
_addScrollListener();
}
_home() async {
await _fetchProducts();
await _fetchCategories();
_shouldStopRequests = false;
waitForNextRequest = false;
setState(() {
_isLoading = false;
});
}
_fetchProducts() async {
_products = await appWooSignal((api) {
return api.getProducts(perPage: 50, page: _page, status: "publish");
});
}
_fetchCategories() async {
_categories = await appWooSignal((api) {
return api.getProductCategories();
});
}
_addScrollListener() async {
_productsController.addListener(() {
double maxScroll = _productsController.position.maxScrollExtent;
double currentScroll = _productsController.position.pixels;
@ -56,37 +81,22 @@ class _HomePageState extends State<HomePage> {
if (waitForNextRequest) {
return;
}
WooSignal.getInstance(config: wsConfig).then((wcStore) {
_fetchMoreProducts();
}
});
}
_fetchMoreProducts() async {
waitForNextRequest = true;
List<WS.Product> products = await appWooSignal((api) {
_page = _page + 1;
wcStore
.getProducts(perPage: 50, page: _page, status: "publish")
.then((products) {
waitForNextRequest = false;
return api.getProducts(perPage: 50, page: _page, status: "publish");
});
if (products.length == 0) {
_shouldStopRequests = true;
}
_products.addAll(products.toList());
setState(() {});
});
});
}
});
WooSignal.getInstance(config: wsConfig).then((wcStore) {
wcStore
.getProducts(perPage: 50, page: _page, status: "publish")
.then((products) {
_products = products;
setState(() {
_isLoading = false;
});
});
wcStore.getProductCategories().then((categories) {
_categories = categories;
setState(() {});
});
_products.addAll(products.toList());
});
}
@ -105,7 +115,8 @@ class _HomePageState extends State<HomePage> {
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0))),
topRight: const Radius.circular(10.0)),
),
child: Column(
children: <Widget>[
Text(trans(context, "Categories"),
@ -122,20 +133,23 @@ class _HomePageState extends State<HomePage> {
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: HexColor("#f2f2f2"),
width: 2))),
color: HexColor("#f2f2f2"), width: 2),
),
),
),
onTap: () {
Navigator.pushNamed(context, "/browse-category",
arguments: _categories[index]);
},
);
}))
}),
)
],
),
),
);
});
},
);
}
@override
@ -212,7 +226,8 @@ class _HomePageState extends State<HomePage> {
children: List.generate(_products.length, (index) {
return wsCardProductItem(context,
index: index, product: _products[index]);
})),
}),
),
flex: 1,
)),
],

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -9,10 +9,11 @@
// 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/woosignal_ui.dart';
import 'package:label_storemax/widgets/menu_item.dart';
import 'package:label_storemax/helpers/tools.dart';
import '../widgets/woosignal_ui.dart';
class HomeMenuPage extends StatefulWidget {
HomeMenuPage();
@ -50,7 +51,7 @@ class _HomeMenuPageState extends State<HomeMenuPage> {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Image.network(app_logo_url, height: 100),
storeLogo(height: 100),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,8 +10,9 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:label_storemax/widgets/buttons.dart';
import '../widgets/woosignal_ui.dart';
class HomeSearchPage extends StatefulWidget {
HomeSearchPage();
@ -45,8 +46,7 @@ class _HomeSearchPageState extends State<HomeSearchPage> {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
title: Image.network(app_logo_url,
height: 60, alignment: Alignment.center),
title: storeLogo(height: 60),
centerTitle: true,
),
body: SafeArea(
@ -65,9 +65,16 @@ class _HomeSearchPageState extends State<HomeSearchPage> {
keyboardType: TextInputType.text,
autocorrect: false,
autofocus: true,
textCapitalization: TextCapitalization.sentences),
wsPrimaryButton(context,
title: trans(context, "Search"), action: _actionSearch)
textCapitalization: TextCapitalization.sentences,
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: wsPrimaryButton(
context,
title: trans(context, "Search"),
action: _actionSearch,
),
)
],
),
),

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -9,27 +9,53 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:label_storemax/widgets/buttons.dart';
import 'package:label_storemax/widgets/cart_icon.dart';
import 'package:woosignal/models/response/product_variation.dart' as WS;
import 'package:woosignal/models/response/products.dart' as WS;
import 'package:woosignal/woosignal.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import 'package:label_storemax/widgets/woosignal_ui.dart';
import 'package:cached_network_image/cached_network_image.dart';
class ProductDetailPage extends StatefulWidget {
final WS.Product product;
const ProductDetailPage({Key key, @required this.product}) : super(key: key);
@override
_ProductDetailState createState() => _ProductDetailState(this.product);
}
class _ProductDetailState extends State<ProductDetailPage> {
_ProductDetailState();
_ProductDetailState(this._product);
bool _isLoading;
WS.Product _product;
int _quantityIndicator = 1;
List<WS.ProductVariation> _productVariations = [];
@override
void initState() {
super.initState();
if (_product.type == "variable") {
_isLoading = true;
_fetchProductVariations();
} else {
_isLoading = false;
}
}
_fetchProductVariations() async {
_productVariations = await appWooSignal((api) {
return api.getProductVariations(_product.id);
});
setState(() {
_isLoading = false;
});
}
Map<int, dynamic> _tmpAttributeObj = {};
@ -94,12 +120,17 @@ class _ProductDetailState extends State<ProductDetailPage> {
_itemAddToCart({CartLineItem cartLineItem}) {
Cart.getInstance.addToCart(cartLineItem: cartLineItem);
showToastWith(message: trans(context, "Added to cart"), statusType: "");
showStatusAlert(context,
title: "Success",
subtitle: trans(context, "Added to cart"),
duration: 1,
icon: Icons.add_shopping_cart);
setState(() {});
}
void _modalBottomSheetAttributes() {
wsModalBottom(context,
wsModalBottom(
context,
title: trans(context, "Options"),
bodyWidget: Expanded(
child: ListView.separated(
@ -214,39 +245,21 @@ class _ProductDetailState extends State<ProductDetailPage> {
],
),
margin: EdgeInsets.only(bottom: 10),
));
),
);
}
void _modalBottomSheetMenu() {
wsModalBottom(context,
wsModalBottom(
context,
title: trans(context, "Description"),
bodyWidget: Expanded(
child: SingleChildScrollView(
child: Text(parseHtmlString(_product.description)),
),
flex: 1,
));
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_isLoading) {
_product = ModalRoute.of(context).settings.arguments;
if (_product.type == "variable") {
WooSignal.getInstance(config: wsConfig).then((wcStore) {
wcStore.getProductVariations(_product.id).then((productVariations) {
_productVariations = productVariations;
_isLoading = false;
setState(() {});
});
});
} else {
_isLoading = false;
setState(() {});
}
}
),
);
}
@override
@ -254,20 +267,24 @@ class _ProductDetailState extends State<ProductDetailPage> {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
actions: <Widget>[wsCartIcon(context)],
title: storeLogo(height: 50),
actions: <Widget>[
wsCartIcon(context),
],
title: storeLogo(height: 55),
centerTitle: true,
),
body: SafeArea(
minimum: safeAreaDefault(),
child: _isLoading
? showAppLoader()
: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Flexible(
flex: 3,
Expanded(
child: ListView(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height * 0.40,
child: SizedBox(
child: new Swiper(
itemBuilder: (BuildContext context, int index) {
@ -276,13 +293,15 @@ class _ProductDetailState extends State<ProductDetailPage> {
placeholder: (context, url) =>
new CircularProgressIndicator(
strokeWidth: 2,
backgroundColor: Colors.black12),
backgroundColor: Colors.black12,
),
errorWidget: (context, url, error) =>
new Icon(Icons.error),
fit: BoxFit.contain);
fit: BoxFit.contain,
);
},
itemCount: _product.images.length,
viewportFraction: 0.8,
viewportFraction: 0.85,
scale: 0.9,
onTap: (i) {
setState(() {});
@ -290,17 +309,22 @@ class _ProductDetailState extends State<ProductDetailPage> {
),
),
),
Padding(
padding: EdgeInsets.only(top: 10),
Container(
height: 100,
padding: EdgeInsets.symmetric(
vertical: 10, horizontal: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Text(
_product.name,
style: Theme.of(context).primaryTextTheme.body2,
style:
Theme.of(context).primaryTextTheme.body2,
textAlign: TextAlign.left,
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
flex: 4,
),
@ -310,16 +334,14 @@ class _ProductDetailState extends State<ProductDetailPage> {
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
formatStringCurrency(total: _product.price),
style:
Theme.of(context).primaryTextTheme.subhead,
textAlign: TextAlign.right,
formatStringCurrency(
total: _product.price),
style: Theme.of(context)
.primaryTextTheme
.display1
.copyWith(
fontSize: 20,
),
Text(
((_product.stockStatus != "instock"
? trans(context, "Out of stock")
: trans(context, "In Stock"))),
style: Theme.of(context).primaryTextTheme.body1,
textAlign: TextAlign.right,
),
],
@ -329,29 +351,35 @@ class _ProductDetailState extends State<ProductDetailPage> {
],
),
),
Divider(
color: Colors.black12,
thickness: 1,
),
Expanded(
Container(
color: Colors.white,
padding:
EdgeInsets.symmetric(vertical: 4, horizontal: 16),
height: 180,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
trans(context, "Description"),
style: Theme.of(context).primaryTextTheme.body1,
style: Theme.of(context)
.primaryTextTheme
.caption
.copyWith(fontSize: 18),
textAlign: TextAlign.left,
),
MaterialButton(
child: Text(
trans(context, "Full description"),
style:
Theme.of(context).primaryTextTheme.caption,
style: Theme.of(context)
.primaryTextTheme
.body1
.copyWith(fontSize: 14),
textAlign: TextAlign.right,
),
height: 50,
@ -366,23 +394,126 @@ class _ProductDetailState extends State<ProductDetailPage> {
child: Text(
(_product.shortDescription != null &&
_product.shortDescription != ""
? parseHtmlString(_product.shortDescription)
? parseHtmlString(
_product.shortDescription)
: parseHtmlString(_product.description)),
),
flex: 3,
),
],
),
flex: 1,
),
wsPrimaryButton(
],
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 15.0,
spreadRadius: -17,
offset: Offset(
0,
-10,
),
)
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Quantity",
style: Theme.of(context).primaryTextTheme.body2,
),
Row(
children: <Widget>[
IconButton(
icon: Icon(
Icons.remove_circle_outline,
size: 28,
),
onPressed: () {
if ((_quantityIndicator - 1) >= 1) {
setState(() {
_quantityIndicator--;
});
}
},
),
Text(
_quantityIndicator.toString(),
style:
Theme.of(context).primaryTextTheme.body2,
),
IconButton(
icon: Icon(
Icons.add_circle_outline,
size: 28,
),
onPressed: () {
if (_quantityIndicator != 0) {
setState(() {
_quantityIndicator++;
});
}
},
),
],
)
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Flexible(
child: Align(
child: Text(
formatStringCurrency(
total: (double.parse(_product.price) *
_quantityIndicator)
.toString()),
style:
Theme.of(context).primaryTextTheme.display1,
textAlign: TextAlign.center,
),
alignment: Alignment.centerLeft,
)),
Flexible(
child: wsPrimaryButton(
context,
title: trans(context, "ADD TO CART"),
title: trans(context, "Add to cart"),
action: () {
_addItemToCart();
},
),
),
],
),
],
),
height: 140,
),
],
),
),
);
}
_addItemToCart() {
CartLineItem cartLineItem = CartLineItem(
name: _product.name,
productId: _product.id,
quantity: 1,
quantity: _quantityIndicator,
taxStatus: _product.taxStatus,
shippingClassId: _product.shippingClassId.toString(),
subtotal: _product.price,
@ -390,8 +521,9 @@ class _ProductDetailState extends State<ProductDetailPage> {
isManagedStock: _product.manageStock,
stockQuantity: _product.stockQuantity,
shippingIsTaxable: _product.shippingTaxable,
imageSrc: _product.images.length == 0 ? "" : _product.images.first.src,
total: _product.price);
imageSrc: _product.images.first.src,
total: _product.price,
);
if (_product.type != "simple") {
_modalBottomSheetAttributes();
@ -406,18 +538,5 @@ class _ProductDetailState extends State<ProductDetailPage> {
style: EdgeAlertStyle.WARNING,
icon: Icons.local_shipping);
}
},
),
],
),
),
);
}
}
class ProductDetailPage extends StatefulWidget {
ProductDetailPage();
@override
_ProductDetailState createState() => _ProductDetailState();
}

View File

@ -0,0 +1,106 @@
//
// LabelCore
// 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:label_storemax/helpers/data/order_wc.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/pages/checkout_confirmation.dart';
import 'package:woosignal/models/payload/order_wc.dart';
import 'package:woosignal/models/response/order.dart';
import 'package:woosignal/models/response/tax_rate.dart';
import 'package:woosignal_stripe/woosignal_stripe.dart';
stripePay(context,
{@required CheckoutConfirmationPageState state,
TaxRate taxRate}) async {
// CONFIGURE STRIPE
FlutterStripePayment.setStripeSettings(
stripeAccount: app_stripe_account, liveMode: app_stripe_live_mode);
var paymentResponse = await FlutterStripePayment.addPaymentMethod();
// CHECK STATUS FROM STRIPE
if (paymentResponse.status == PaymentResponseStatus.succeeded) {
state.reloadState(showLoader: true);
// CHECKOUT HELPER
await checkout(taxRate, (total, billingDetails, cart) async {
Map<String, dynamic> address = {
"name": billingDetails.billingAddress.nameFull(),
"line1": billingDetails.shippingAddress.addressLine,
"city": billingDetails.shippingAddress.city,
"postal_code": billingDetails.shippingAddress.postalCode,
"country": billingDetails.shippingAddress.country
};
String cartShortDesc = await cart.cartShortDesc();
dynamic rsp = await appWooSignal((api) {
return api.stripePaymentIntent(
amount: total,
email: billingDetails.billingAddress.emailAddress,
desc: cartShortDesc,
shipping: address,
);
});
if (rsp == null) {
showToastNetworkError();
state.reloadState(showLoader: false);
return;
}
String clientSecret = rsp["client_secret"];
var intentResponse = await FlutterStripePayment.confirmPaymentIntent(
clientSecret,
paymentResponse.paymentMethodId,
(double.parse(total) * 100),
);
if (intentResponse.status == PaymentResponseStatus.succeeded) {
OrderWC orderWC = await buildOrderWC(taxRate: taxRate);
Order order = await appWooSignal((api) {
return api.createOrder(orderWC);
});
if (order != null) {
Cart.getInstance.clear();
Navigator.pushNamed(context, "/checkout-status", arguments: order);
} else {
showEdgeAlertWith(
context,
title: trans(context, "Error"),
desc:
trans(context, "Something went wrong, please contact our store"),
);
state.reloadState(showLoader: false);
}
} else if (intentResponse.status == PaymentResponseStatus.failed) {
if (app_debug) {
print(intentResponse.errorMessage);
}
showEdgeAlertWith(
context,
title: trans(context, "Error"),
desc: intentResponse.errorMessage,
);
state.reloadState(showLoader: false);
} else {
state.reloadState(showLoader: false);
}
});
}
}

View File

@ -0,0 +1,7 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import '../helpers/tools.dart';
Widget showAppLoader() {
return SpinKitDoubleBounce(color: HexColor("#393318"));
}

View File

@ -0,0 +1,52 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../helpers/tools.dart';
Widget wsPrimaryButton(BuildContext context,
{@required String title, void Function() action}) {
return Container(
height: 55,
child: RaisedButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
padding: EdgeInsets.all(8),
child: Text(
title,
style: Theme.of(context).primaryTextTheme.button.copyWith(fontSize: 16),
),
onPressed: action ?? null,
elevation: 0,
),
);
}
Widget wsSecondaryButton(BuildContext context,
{String title, void Function() action}) {
return Container(
height: 60,
margin: EdgeInsets.only(top: 10),
child: RaisedButton(
padding: EdgeInsets.all(10),
child: Text(title,
style: Theme.of(context).primaryTextTheme.body2,
textAlign: TextAlign.center),
onPressed: action,
color: HexColor("#f6f6f9"),
elevation: 0),
);
}
Widget wsLinkButton(BuildContext context,
{String title, void Function() action}) {
return Container(
height: 60,
margin: EdgeInsets.only(top: 10),
child: MaterialButton(
padding: EdgeInsets.all(10),
child: Text(title,
style: Theme.of(context).primaryTextTheme.body2,
textAlign: TextAlign.left),
onPressed: action,
elevation: 0),
);
}

View File

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart';
Widget wsCartIcon(BuildContext context) {
return IconButton(
icon: Stack(
children: <Widget>[
Positioned.fill(
child: Align(
child: Icon(Icons.shopping_cart, size: 20, color: Colors.black87),
alignment: Alignment.bottomCenter,
),
bottom: 0),
Positioned.fill(
child: Align(
child: FutureBuilder<List<CartLineItem>>(
future: Cart.getInstance.getCart(),
builder: (BuildContext context,
AsyncSnapshot<List<CartLineItem>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text("");
default:
if (snapshot.hasError)
return Text("");
else
return new Text(
snapshot.data.length.toString(),
style: Theme.of(context).primaryTextTheme.body2,
textAlign: TextAlign.center,
);
}
},
),
alignment: Alignment.topCenter,
),
top: 0)
],
),
onPressed: () {
Navigator.pushNamed(context, "/cart");
},
);
}

View File

@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
Widget wsMenuItem(BuildContext context,
{String title, Widget leading, void Function() action}) {
return Flexible(
child: InkWell(
child: Card(
child: Container(
width: double.infinity,
padding: EdgeInsets.only(top: 15, bottom: 15),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
leading,
Text(" " + title,
style: Theme.of(context).primaryTextTheme.body1),
],
),
),
elevation: 1,
margin: EdgeInsets.only(top: 8, bottom: 8, left: 8, right: 8),
),
onTap: action,
),
);
}

View File

@ -1,7 +1,7 @@
// Label StoreMAX
//
// Created by Anthony Gordon.
// Copyright © 2019 WooSignal. All rights reserved.
// Copyright © 2020 WooSignal. All rights reserved.
//
// Unless required by applicable law or agreed to in writing, software
@ -10,6 +10,10 @@
import 'package:flutter/material.dart';
import 'package:label_storemax/labelconfig.dart';
import 'package:label_storemax/models/cart.dart';
import 'package:label_storemax/models/cart_line_item.dart';
import 'package:label_storemax/models/checkout_session.dart';
import 'package:label_storemax/widgets/app_loader.dart';
import 'package:woosignal/models/response/products.dart';
import 'package:label_storemax/helpers/tools.dart';
import 'package:cached_network_image/cached_network_image.dart';
@ -17,118 +21,6 @@ import 'package:woosignal/models/response/tax_rate.dart';
const appFontFamily = "Overpass";
Widget wsCartIcon(BuildContext context) {
return IconButton(
icon: Stack(
children: <Widget>[
Positioned.fill(
child: Align(
child: Icon(Icons.shopping_cart, size: 20, color: Colors.black87),
alignment: Alignment.bottomCenter,
),
bottom: 0),
Positioned.fill(
child: Align(
child: FutureBuilder<List<CartLineItem>>(
future: Cart.getInstance.getCart(),
builder: (BuildContext context,
AsyncSnapshot<List<CartLineItem>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text("");
default:
if (snapshot.hasError)
return Text("");
else
return new Text(
snapshot.data.length.toString(),
style: Theme.of(context).primaryTextTheme.body2,
textAlign: TextAlign.center,
);
}
},
),
alignment: Alignment.topCenter,
),
top: 0)
],
),
onPressed: () {
Navigator.pushNamed(context, "/cart");
},
);
}
Widget wsMenuItem(BuildContext context,
{String title, Widget leading, void Function() action}) {
return Flexible(
child: InkWell(
child: Card(
child: Container(
width: double.infinity,
padding: EdgeInsets.only(top: 15, bottom: 15),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
leading,
Text(" " + title,
style: Theme.of(context).primaryTextTheme.body1),
],
),
),
elevation: 1,
margin: EdgeInsets.only(top: 8, bottom: 8, left: 8, right: 8),
),
onTap: action,
),
);
}
Widget wsPrimaryButton(BuildContext context,
{String title, void Function() action}) {
return Container(
height: 60,
margin: EdgeInsets.only(top: 10),
child: RaisedButton(
padding: EdgeInsets.all(10),
child: Text(title, style: Theme.of(context).primaryTextTheme.button),
onPressed: action,
elevation: 0),
);
}
Widget wsSecondaryButton(BuildContext context,
{String title, void Function() action}) {
return Container(
height: 60,
margin: EdgeInsets.only(top: 10),
child: RaisedButton(
padding: EdgeInsets.all(10),
child: Text(title,
style: Theme.of(context).primaryTextTheme.body2,
textAlign: TextAlign.center),
onPressed: action,
color: HexColor("#f6f6f9"),
elevation: 0),
);
}
Widget wsLinkButton(BuildContext context,
{String title, void Function() action}) {
return Container(
height: 60,
margin: EdgeInsets.only(top: 10),
child: MaterialButton(
padding: EdgeInsets.all(10),
child: Text(title,
style: Theme.of(context).primaryTextTheme.body2,
textAlign: TextAlign.left),
onPressed: action,
elevation: 0),
);
}
Widget wsRow2Text(BuildContext context, {String text1, String text2}) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
@ -142,7 +34,11 @@ Widget wsRow2Text(BuildContext context, {String text1, String text2}) {
),
Flexible(
child: Container(
child: Text(text2, style: Theme.of(context).primaryTextTheme.body2),
child: Text(text2,
style: Theme.of(context)
.primaryTextTheme
.body2
.copyWith(fontSize: 16, color: Colors.black87)),
),
flex: 3,
)
@ -204,9 +100,10 @@ Widget wsCheckoutRow(BuildContext context,
padding: EdgeInsets.all(8),
decoration: showBorderBottom == true
? BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.black12, width: 1)))
: BoxDecoration()),
border:
Border(bottom: BorderSide(color: Colors.black12, width: 1)))
: BoxDecoration(),
),
onTap: action,
borderRadius: BorderRadius.circular(8),
),
@ -338,11 +235,15 @@ void wsModalBottom(BuildContext context,
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0))),
topRight: const Radius.circular(10.0)),
),
child: Column(
children: <Widget>[
Text(title,
style: Theme.of(context).primaryTextTheme.display1,
style: Theme.of(context)
.primaryTextTheme
.display1
.copyWith(fontSize: 20),
textAlign: TextAlign.left),
bodyWidget,
extraWidget ?? Container()
@ -481,12 +382,13 @@ Widget wsCardCartItem(BuildContext context,
void Function() actionRemoveItem}) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(
color: Colors.black12,
width: 1,
))),
padding: EdgeInsets.all(8),
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
child: Column(
children: <Widget>[
Row(
@ -508,8 +410,12 @@ Widget wsCardCartItem(BuildContext context,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(cartLineItem.name,
style: Theme.of(context).primaryTextTheme.subhead),
Text(
cartLineItem.name,
style: Theme.of(context).primaryTextTheme.subhead,
overflow: TextOverflow.ellipsis,
maxLines: 3,
),
(cartLineItem.variationOptions != null
? Text(cartLineItem.variationOptions,
style: Theme.of(context).primaryTextTheme.body2)
@ -575,9 +481,10 @@ Widget wsCardCartItem(BuildContext context,
));
}
Widget storeLogo({double height}) {
Widget storeLogo({double height, double width}) {
return cachedImage(app_logo_url,
height: height, placeholder: Container(height: height, width: height));
height: height,
placeholder: Container(height: height ?? 100, width: width ?? 100));
}
Widget cachedImage(image, {double height, Widget placeholder, BoxFit fit}) {

View File

@ -7,7 +7,7 @@ packages:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.10"
version: "2.0.11"
args:
dependency: transitive
description:
@ -21,7 +21,7 @@ packages:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
version: "2.4.0"
boolean_selector:
dependency: transitive
description:
@ -35,7 +35,7 @@ packages:
name: cached_network_image
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
version: "2.0.0"
charcode:
dependency: transitive
description:
@ -50,13 +50,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.11"
connectivity:
dependency: "direct main"
description:
name: connectivity
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.4"
convert:
dependency: transitive
description:
@ -98,7 +91,7 @@ packages:
name: dio
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.4"
version: "3.0.9"
edge_alert:
dependency: "direct main"
description:
@ -106,6 +99,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1"
flare_dart:
dependency: transitive
description:
name: flare_dart
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.3"
flare_flutter:
dependency: transitive
description:
name: flare_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.3"
flutter:
dependency: "direct main"
description: flutter
@ -117,14 +124,14 @@ packages:
name: flutter_cache_manager
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
version: "1.1.3"
flutter_launcher_icons:
dependency: "direct main"
description:
name: flutter_launcher_icons
url: "https://pub.dartlang.org"
source: hosted
version: "0.7.3"
version: "0.7.4"
flutter_localizations:
dependency: "direct main"
description: flutter
@ -150,7 +157,7 @@ packages:
name: flutter_spinkit
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
version: "4.1.2+1"
flutter_swiper:
dependency: "direct main"
description:
@ -170,13 +177,18 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
fluttertoast:
dependency: "direct main"
description:
name: fluttertoast
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.3"
version: "4.0.1"
html:
dependency: "direct main"
description:
@ -204,49 +216,42 @@ packages:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
version: "2.1.4"
intl:
dependency: transitive
dependency: "direct overridden"
description:
name: intl
url: "https://pub.dartlang.org"
source: hosted
version: "0.15.8"
json_annotation:
dependency: transitive
description:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.5"
version: "0.12.6"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.7"
version: "1.1.8"
package_info:
dependency: "direct main"
description:
name: package_info
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0+6"
version: "0.4.0+16"
page_transition:
dependency: "direct main"
description:
name: page_transition
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.4"
version: "1.1.5"
path:
dependency: transitive
description:
@ -282,13 +287,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
pref_dessert:
dependency: "direct main"
description:
name: pref_dessert
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0+1"
quiver:
dependency: transitive
description:
@ -302,7 +300,28 @@ packages:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.4+3"
version: "0.5.6+3"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1+6"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2+4"
sky_engine:
dependency: transitive
description: flutter
@ -329,6 +348,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.3"
status_alert:
dependency: "direct main"
description:
name: status_alert
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.1"
stream_channel:
dependency: transitive
description:
@ -363,7 +389,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.5"
version: "0.2.11"
transformer_page_view:
dependency: transitive
description:
@ -405,7 +431,7 @@ packages:
name: woosignal_stripe
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.2"
version: "0.0.4"
xml:
dependency: transitive
description:
@ -421,5 +447,5 @@ packages:
source: hosted
version: "2.2.0"
sdks:
dart: ">2.4.0 <3.0.0"
flutter: ">=1.6.7 <2.0.0"
dart: ">=2.5.0 <3.0.0"
flutter: ">=1.12.13+hotfix.4 <2.0.0"

View File

@ -24,21 +24,20 @@ environment:
dependencies:
woosignal: ^1.0.2
woosignal_stripe: ^0.0.2
connectivity: ^0.4.4
shared_preferences: ^0.5.3+4
woosignal_stripe: ^0.0.4
shared_preferences: ^0.5.6+3
cached_network_image: ^2.0.0
page_transition: ^1.1.4
package_info: ^0.4.0+6
flutter_money_formatter: ^0.8.2
page_transition: ^1.1.5
package_info: ^0.4.0+16
flutter_money_formatter: ^0.8.3
flutter_web_browser: ^0.11.0
dio: ^3.0.2
dio: ^3.0.9
flutter_swiper: ^1.1.6
edge_alert: ^0.0.1
fluttertoast: ^3.1.3
flutter_spinkit: ^4.0.0
pref_dessert: ^0.4.0+1
flutter_launcher_icons: ^0.7.3
status_alert: ^0.1.1
fluttertoast: ^4.0.1
flutter_spinkit: ^4.1.2+1
flutter_launcher_icons: ^0.7.4
html: ^0.14.0+3
flutter:
sdk: flutter