diff --git a/LabelStoreMax/.gitignore b/LabelStoreMax/.gitignore new file mode 100644 index 0000000..2ddde2a --- /dev/null +++ b/LabelStoreMax/.gitignore @@ -0,0 +1,73 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/LabelStoreMax/.metadata b/LabelStoreMax/.metadata new file mode 100644 index 0000000..aeb01ee --- /dev/null +++ b/LabelStoreMax/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f + channel: stable + +project_type: app diff --git a/LabelStoreMax/CHANGELOG.md b/LabelStoreMax/CHANGELOG.md new file mode 100644 index 0000000..da55fa6 --- /dev/null +++ b/LabelStoreMax/CHANGELOG.md @@ -0,0 +1,3 @@ +## [1.0.0] - 2019-11-01 + +* Initial Release \ No newline at end of file diff --git a/LabelStoreMax/README.md b/LabelStoreMax/README.md new file mode 100644 index 0000000..2070cd9 --- /dev/null +++ b/LabelStoreMax/README.md @@ -0,0 +1,30 @@ +# label_storemax + +LabelStoreMAX +Created by Anthony Gordon. + +[Official WooSignal App Template](https://woosignal.com) + +## Getting Started + +1. Connect your WooCommerce store +Click connect above to link your WooCommerce store to our site, all you'll need to do is add your url to provide WooSignal access. + +2. Generate an AppKey for the app +Next go to [manage apps page](https://woosignal.com/dashboard/apps) and click "Generate new key" for your app and copy it to somewhere safe, it's important that you don't share is with anyone. + +3. Add the AppKey to the project +Look for the labelconfig.dart file and change the AppKey to the one your generated. + +4. Build and run the app +If you have done all of the above you should have a basic setup to get started, you'll see products from your WooCommerce store appearing in the app. + +5. Uploading to the App Store/Google Play Store? +Uploading your app release to IOS [IOS guide](https://flutter.dev/docs/deployment/ios) + +Uploading your app release to Android [Android guide](https://flutter.dev/docs/deployment/android) + +## Need help uploading the app? +Check out our YouTube series to help you with uploading the app and other tips + +[Support](https://woosignal.com/support) \ No newline at end of file diff --git a/LabelStoreMax/android/app/build.gradle b/LabelStoreMax/android/app/build.gradle new file mode 100644 index 0000000..afc015b --- /dev/null +++ b/LabelStoreMax/android/app/build.gradle @@ -0,0 +1,68 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 28 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + 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 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + multiDexEnabled = true + } + + 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 + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' +} diff --git a/LabelStoreMax/android/app/src/debug/AndroidManifest.xml b/LabelStoreMax/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..53c1bbc --- /dev/null +++ b/LabelStoreMax/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/LabelStoreMax/android/app/src/main/AndroidManifest.xml b/LabelStoreMax/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7fc2bc3 --- /dev/null +++ b/LabelStoreMax/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LabelStoreMax/android/app/src/main/kotlin/com/woosignal/label_storemax/MainActivity.kt b/LabelStoreMax/android/app/src/main/kotlin/com/woosignal/label_storemax/MainActivity.kt new file mode 100644 index 0000000..72d2edb --- /dev/null +++ b/LabelStoreMax/android/app/src/main/kotlin/com/woosignal/label_storemax/MainActivity.kt @@ -0,0 +1,13 @@ +package com.woosignal.label_storemax + +import android.os.Bundle + +import io.flutter.app.FlutterActivity +import io.flutter.plugins.GeneratedPluginRegistrant + +class MainActivity: FlutterActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + GeneratedPluginRegistrant.registerWith(this) + } +} diff --git a/LabelStoreMax/android/app/src/main/res/drawable/launch_background.xml b/LabelStoreMax/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/LabelStoreMax/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/LabelStoreMax/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/LabelStoreMax/android/app/src/main/res/mipmap-hdpi/launcher_icon.png new file mode 100644 index 0000000..0decf36 Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-hdpi/launcher_icon.png differ diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/LabelStoreMax/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-mdpi/launcher_icon.png b/LabelStoreMax/android/app/src/main/res/mipmap-mdpi/launcher_icon.png new file mode 100644 index 0000000..67bdf48 Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-mdpi/launcher_icon.png differ diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/LabelStoreMax/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/LabelStoreMax/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png new file mode 100644 index 0000000..3d538fd Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png differ diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/LabelStoreMax/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/LabelStoreMax/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png new file mode 100644 index 0000000..c766323 Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png differ diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/LabelStoreMax/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/LabelStoreMax/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/LabelStoreMax/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png new file mode 100644 index 0000000..2b2b297 Binary files /dev/null and b/LabelStoreMax/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png differ diff --git a/LabelStoreMax/android/app/src/main/res/values/styles.xml b/LabelStoreMax/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..00fa441 --- /dev/null +++ b/LabelStoreMax/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/LabelStoreMax/android/app/src/profile/AndroidManifest.xml b/LabelStoreMax/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..53c1bbc --- /dev/null +++ b/LabelStoreMax/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/LabelStoreMax/android/build.gradle b/LabelStoreMax/android/build.gradle new file mode 100644 index 0000000..3151321 --- /dev/null +++ b/LabelStoreMax/android/build.gradle @@ -0,0 +1,34 @@ +buildscript { + ext.kotlin_version = '1.3.10' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + maven { + url "https://maven.google.com" + } + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/LabelStoreMax/android/gradle.properties b/LabelStoreMax/android/gradle.properties new file mode 100644 index 0000000..755300e --- /dev/null +++ b/LabelStoreMax/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M + +android.useAndroidX=true +android.enableJetifier=true diff --git a/LabelStoreMax/android/gradle/wrapper/gradle-wrapper.properties b/LabelStoreMax/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..17932ee --- /dev/null +++ b/LabelStoreMax/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Oct 28 17:45:00 GMT 2019 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/LabelStoreMax/android/settings.gradle b/LabelStoreMax/android/settings.gradle new file mode 100644 index 0000000..5a2f14f --- /dev/null +++ b/LabelStoreMax/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/LabelStoreMax/assets/fonts/Overpass/OFL.txt b/LabelStoreMax/assets/fonts/Overpass/OFL.txt new file mode 100755 index 0000000..fdaf13c --- /dev/null +++ b/LabelStoreMax/assets/fonts/Overpass/OFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2016 by Red Hat, Inc. All rights reserved. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-Black.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-Black.ttf new file mode 100755 index 0000000..aa9e740 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-Black.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-BlackItalic.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-BlackItalic.ttf new file mode 100755 index 0000000..c0a82ca Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-BlackItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-Bold.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-Bold.ttf new file mode 100755 index 0000000..c5ed6f8 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-Bold.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-BoldItalic.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-BoldItalic.ttf new file mode 100755 index 0000000..c648ae9 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-BoldItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraBold.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraBold.ttf new file mode 100755 index 0000000..40daed2 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraBold.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraBoldItalic.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraBoldItalic.ttf new file mode 100755 index 0000000..0ba125b Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraBoldItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraLight.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraLight.ttf new file mode 100755 index 0000000..c57a7f2 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraLight.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraLightItalic.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraLightItalic.ttf new file mode 100755 index 0000000..504cc76 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-ExtraLightItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-Light.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-Light.ttf new file mode 100755 index 0000000..be884dd Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-Light.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-LightItalic.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-LightItalic.ttf new file mode 100755 index 0000000..2b1352d Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-LightItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-Regular.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-Regular.ttf new file mode 100755 index 0000000..0deeda5 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-Regular.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-RegularItalic.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-RegularItalic.ttf new file mode 100755 index 0000000..78032b1 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-RegularItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-SemiBold.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-SemiBold.ttf new file mode 100755 index 0000000..f690d8e Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-SemiBold.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-SemiBoldItalic.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-SemiBoldItalic.ttf new file mode 100755 index 0000000..4a1c4a4 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-SemiBoldItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-Thin.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-Thin.ttf new file mode 100755 index 0000000..f01017a Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-Thin.ttf differ diff --git a/LabelStoreMax/assets/fonts/Overpass/Overpass-ThinItalic.ttf b/LabelStoreMax/assets/fonts/Overpass/Overpass-ThinItalic.ttf new file mode 100755 index 0000000..2a5d951 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Overpass/Overpass-ThinItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/OFL.txt b/LabelStoreMax/assets/fonts/Source_Sans_Pro/OFL.txt new file mode 100755 index 0000000..72d81ab --- /dev/null +++ b/LabelStoreMax/assets/fonts/Source_Sans_Pro/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2010, 2012, 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name ‘Source’. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Black.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Black.ttf new file mode 100755 index 0000000..4569f24 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Black.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-BlackItalic.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-BlackItalic.ttf new file mode 100755 index 0000000..3477e16 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-BlackItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Bold.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Bold.ttf new file mode 100755 index 0000000..1f430e2 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Bold.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-BoldItalic.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-BoldItalic.ttf new file mode 100755 index 0000000..98089fd Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-BoldItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-ExtraLight.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-ExtraLight.ttf new file mode 100755 index 0000000..caf2673 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-ExtraLight.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-ExtraLightItalic.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-ExtraLightItalic.ttf new file mode 100755 index 0000000..b0362f3 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-ExtraLightItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf new file mode 100755 index 0000000..348871a Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-LightItalic.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-LightItalic.ttf new file mode 100755 index 0000000..989dc8e Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-LightItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf new file mode 100755 index 0000000..b422bf4 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-RegularItalic.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-RegularItalic.ttf new file mode 100755 index 0000000..e7b9182 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-RegularItalic.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf new file mode 100755 index 0000000..2908e0d Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf differ diff --git a/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-SemiBoldItalic.ttf b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-SemiBoldItalic.ttf new file mode 100755 index 0000000..990cf91 Binary files /dev/null and b/LabelStoreMax/assets/fonts/Source_Sans_Pro/SourceSansPro-SemiBoldItalic.ttf differ diff --git a/LabelStoreMax/assets/icon/appicon.png b/LabelStoreMax/assets/icon/appicon.png new file mode 100644 index 0000000..a5c257c Binary files /dev/null and b/LabelStoreMax/assets/icon/appicon.png differ diff --git a/LabelStoreMax/assets/images/camion.gif b/LabelStoreMax/assets/images/camion.gif new file mode 100644 index 0000000..a71eb64 Binary files /dev/null and b/LabelStoreMax/assets/images/camion.gif differ diff --git a/LabelStoreMax/assets/images/cart_empty.png b/LabelStoreMax/assets/images/cart_empty.png new file mode 100644 index 0000000..7e9595d Binary files /dev/null and b/LabelStoreMax/assets/images/cart_empty.png differ diff --git a/LabelStoreMax/assets/images/credit_cards.png b/LabelStoreMax/assets/images/credit_cards.png new file mode 100644 index 0000000..1904d25 Binary files /dev/null and b/LabelStoreMax/assets/images/credit_cards.png differ diff --git a/LabelStoreMax/assets/images/dark_powered_by_stripe.png b/LabelStoreMax/assets/images/dark_powered_by_stripe.png new file mode 100644 index 0000000..396dfd9 Binary files /dev/null and b/LabelStoreMax/assets/images/dark_powered_by_stripe.png differ diff --git a/LabelStoreMax/assets/images/shipping_icon.png b/LabelStoreMax/assets/images/shipping_icon.png new file mode 100644 index 0000000..17f1318 Binary files /dev/null and b/LabelStoreMax/assets/images/shipping_icon.png differ diff --git a/LabelStoreMax/ios/Flutter/AppFrameworkInfo.plist b/LabelStoreMax/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..6b4c0f7 --- /dev/null +++ b/LabelStoreMax/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/LabelStoreMax/ios/Flutter/Debug.xcconfig b/LabelStoreMax/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..e8efba1 --- /dev/null +++ b/LabelStoreMax/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/LabelStoreMax/ios/Flutter/Release.xcconfig b/LabelStoreMax/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..399e934 --- /dev/null +++ b/LabelStoreMax/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/LabelStoreMax/ios/Podfile b/LabelStoreMax/ios/Podfile new file mode 100644 index 0000000..8317100 --- /dev/null +++ b/LabelStoreMax/ios/Podfile @@ -0,0 +1,77 @@ +# Using a CDN with CocoaPods 1.7.2 or later can save a lot of time on pod installation, but it's experimental rather than the default. +# source 'https://cdn.cocoapods.org/' + +# Uncomment this line to define a global platform for your project +platform :ios, '11.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 + pods_ary = [] + skip_line_start_symbols = ["#", "/"] + File.foreach(file_abs_path) { |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) + pods_ary.push({:name => podname, :path => podpath}); + else + puts "Invalid plugin specification: #{line}" + end + } + return pods_ary +end + +target 'Runner' do + use_frameworks! + + # 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') + + # Flutter Pods + generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') + if generated_xcode_build_settings.empty? + puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first." + end + generated_xcode_build_settings.map { |p| + if p[:name] == 'FLUTTER_FRAMEWORK_DIR' + symlink = File.join('.symlinks', 'flutter') + File.symlink(File.dirname(p[:path]), symlink) + pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) + end + } + + # Plugin Pods + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.map { |p| + symlink = File.join('.symlinks', 'plugins', p[:name]) + File.symlink(p[:path], symlink) + pod p[:name], :path => File.join(symlink, 'ios') + } +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 diff --git a/LabelStoreMax/ios/Podfile.lock b/LabelStoreMax/ios/Podfile.lock new file mode 100644 index 0000000..d5dab93 --- /dev/null +++ b/LabelStoreMax/ios/Podfile.lock @@ -0,0 +1,93 @@ +PODS: + - connectivity (0.0.1): + - Flutter + - Reachability + - 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 + - Reachability (3.2) + - shared_preferences (0.0.1): + - Flutter + - sqflite (0.0.1): + - Flutter + - FMDB (~> 2.7.2) + - Stripe (17.0.1) + - woosignal_stripe (0.0.1): + - Flutter + - Stripe (= 17.0.1) + +DEPENDENCIES: + - connectivity (from `.symlinks/plugins/connectivity/ios`) + - device_info (from `.symlinks/plugins/device_info/ios`) + - Flutter (from `.symlinks/flutter/ios`) + - 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`) + - sqflite (from `.symlinks/plugins/sqflite/ios`) + - woosignal_stripe (from `.symlinks/plugins/woosignal_stripe/ios`) + +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - FMDB + - Reachability + - Stripe + +EXTERNAL SOURCES: + connectivity: + :path: ".symlinks/plugins/connectivity/ios" + device_info: + :path: ".symlinks/plugins/device_info/ios" + Flutter: + :path: ".symlinks/flutter/ios" + 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" + sqflite: + :path: ".symlinks/plugins/sqflite/ios" + woosignal_stripe: + :path: ".symlinks/plugins/woosignal_stripe/ios" + +SPEC CHECKSUMS: + connectivity: c72716e202a1225ec4810740d5cb56b8ae3bf4cc + device_info: cbf09d2ec12aa7110e0b09fabe54b5bd6c8efe74 + Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + flutter_money_formatter: d0d18ddc5be333fad8d09964d741b59fa11a91dc + flutter_web_browser: bdea232160dec44dec86540bee05168cc844ef7c + fluttertoast: b644586ef3b16f67fae9a1f8754cef6b2d6b634b + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + package_info: 78cabb3c322943c55d39676f4a5bfc748c01d055 + path_provider: f96fff6166a8867510d2c25fdcc346327cc4b259 + Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 + shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01 + sqflite: ff1d9da63c06588cc8d1faf7256d741f16989d5a + Stripe: b8e845e12fd6dbc9cb010422b3b6b212e803d308 + woosignal_stripe: 90b61ac1aff30eb7ac10e00c2a96224a9d252175 + +PODFILE CHECKSUM: fb3ad6b1acd0fbd619b8375ed808d3ee1f62f340 + +COCOAPODS: 1.6.0 diff --git a/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj b/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..54f6cf1 --- /dev/null +++ b/LabelStoreMax/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,592 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + D86A9FCC0FDE40E749D2F6CC /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 41358261A3745FB464B72CE9 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 1BA921103C32B79944361E71 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 41358261A3745FB464B72CE9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 87F77F819B61E54C61672D11 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E107F71D46A779B424A08899 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + D86A9FCC0FDE40E749D2F6CC /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3E3E1C811B47477CF4A9A315 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 41358261A3745FB464B72CE9 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + A759088B62C60268D25F841F /* Pods */, + 3E3E1C811B47477CF4A9A315 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + A759088B62C60268D25F841F /* Pods */ = { + isa = PBXGroup; + children = ( + E107F71D46A779B424A08899 /* Pods-Runner.debug.xcconfig */, + 87F77F819B61E54C61672D11 /* Pods-Runner.release.xcconfig */, + 1BA921103C32B79944361E71 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 7A4371A0EF7EDBC9E03FB2D7 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + C10A9485E174060F4694B3D0 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0910; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + }; + 7A4371A0EF7EDBC9E03FB2D7 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + C10A9485E174060F4694B3D0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.woosignal.label-StoreMax"; + PRODUCT_NAME = Runner; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.woosignal.label-StoreMax"; + PRODUCT_NAME = Runner; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.woosignal.label-StoreMax"; + PRODUCT_NAME = Runner; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = 1; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/LabelStoreMax/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/LabelStoreMax/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/LabelStoreMax/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/LabelStoreMax/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/LabelStoreMax/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..fb2dffc --- /dev/null +++ b/LabelStoreMax/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LabelStoreMax/ios/Runner.xcworkspace/contents.xcworkspacedata b/LabelStoreMax/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/LabelStoreMax/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/LabelStoreMax/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/LabelStoreMax/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/LabelStoreMax/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/LabelStoreMax/ios/Runner/AppDelegate.swift b/LabelStoreMax/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/LabelStoreMax/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..7b1e87e Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..de26486 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..d187375 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..c7675b1 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4ff2ce4 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..96a26cd Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..69425ef Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..d187375 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..073e5ab Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..65dca33 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..65dca33 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..8c442e1 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..f8a0515 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..1720f00 Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..98b06fb Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/LabelStoreMax/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/LabelStoreMax/ios/Runner/Base.lproj/LaunchScreen.storyboard b/LabelStoreMax/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/LabelStoreMax/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LabelStoreMax/ios/Runner/Base.lproj/Main.storyboard b/LabelStoreMax/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/LabelStoreMax/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LabelStoreMax/ios/Runner/Info.plist b/LabelStoreMax/ios/Runner/Info.plist new file mode 100644 index 0000000..30a62dd --- /dev/null +++ b/LabelStoreMax/ios/Runner/Info.plist @@ -0,0 +1,61 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + label_storemax + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLName + 3ds.stripesdk.io + CFBundleURLSchemes + + stripesdk + + + + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/LabelStoreMax/ios/Runner/Runner-Bridging-Header.h b/LabelStoreMax/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..7335fdf --- /dev/null +++ b/LabelStoreMax/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/LabelStoreMax/lang/en.json b/LabelStoreMax/lang/en.json new file mode 100644 index 0000000..ddb4a1e --- /dev/null +++ b/LabelStoreMax/lang/en.json @@ -0,0 +1,94 @@ +{ + "Categories": "Categories", + "Shop": "Shop", + "Newest": "Newest", + "Browse categories": "Browse categories", + "Cart": "Cart", + "You need items in your cart to checkout": "You need items in your cart to checkout", + "Updated": "Updated", + "Item removed": "Item removed", + "Success": "Success", + "Cart cleared": "Cart cleared", + "Shopping Cart": "Shopping Cart", + "Clear Cart": "Clear Cart", + "Empty Basket": "Empty Basket", + "PROCEED TO CHECKOUT": "PROCEED TO CHECKOUT", + "Browse": "Browse", + "Search results for": "Search results for", + "Select a": "Select a", + "Added to cart": "Added to cart", + "Options": "Options", + "Price": "Price", + "Choose your options": "Choose your options", + "Out of stock": "Out of stock", + "In Stock": "In Stock", + "Add to cart": "Add to cart", + "Oops": "Oops", + "Please select valid options first": "Please select valid options first", + "Sorry": "Sorry", + "This item is not in stock": "This item is not in stock", + "Description": "Description", + "Full description": "Full description", + "ADD TO CART": "ADD TO CART", + "This item is out of stock": "This item is out of stock", + "Add your shipping details first": "Add your shipping details first", + "Checkout": "Checkout", + "Billing/shipping details": "Billing/shipping details", + "Add billing & shipping details": "Add billing & shipping details", + "Payment method": "Payment method", + "Pay with": "Pay with", + "Select a payment method": "Select a payment method", + "Shipping selected": "Shipping selected", + "Select shipping": "Select shipping", + "Select a shipping option": "Select a shipping option", + "Shipping fee": "Shipping fee", + "Subtotal": "Subtotal", + "Total": "Total", + "CHECKOUT": "CHECKOUT", + "One moment": "One moment", + "Please select add your billing/shipping address to proceed": "Please select add your billing/shipping address to proceed", + "Your billing/shipping details are incomplete": "Your billing/shipping details are incomplete", + "Please select a shipping method to proceed": "Please select a shipping method to proceed", + "Please select a payment method to proceed": "Please select a payment method to proceed", + "Something went wrong, please contact our store": "Something went wrong, please contact our store", + "Error": "Error", + "Order Status": "Order Status", + "Thank You!": "Thank You!", + "Your transaction details": "Your transaction details", + "Order Ref": "Order Ref", + "Items": "Items", + "Back to Home": "Back to Home", + "Orders": "Orders", + "Billing & Shipping Details": "Billing & Shipping Details", + "First Name": "First Name", + "Last Name": "Last Name", + "Address Line": "Address Line", + "City": "City", + "Postal code": "Postal code", + "Email address": "Email address", + "Selected": "Selected", + "Select country": "Select country", + "Remember my details": "Remember my details", + "USE SHIPPING ADDRESS": "USE SHIPPING ADDRESS", + "About": "About", + "Privacy policy": "Privacy policy", + "Terms and conditions": "Terms and conditions", + "Version": "Version", + "Payment Method": "Payment Method", + "CANCEL": "CANCEL", + "Shipping Methods": "Shipping Methods", + "Shipping is not supported for your country, sorry": "Shipping is not supported for your country, sorry", + "Search": "Search", + "Debit or Credit Card": "Debit or Credit Card", + "Oops, something went wrong": "Oops, something went wrong", + "Tax": "Tax", + "No results": "No results", + "There is an item out of stock": "There is an item out of stock", + "Maximum stock reached": "Maximum stock reached", + "Select a country": "Select a country", + "Menu": "Menu", + "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" +} \ No newline at end of file diff --git a/LabelStoreMax/lib/app_country_options.dart b/LabelStoreMax/lib/app_country_options.dart new file mode 100644 index 0000000..a953468 --- /dev/null +++ b/LabelStoreMax/lib/app_country_options.dart @@ -0,0 +1,257 @@ +// 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. + +// COUNTRY OPTIONS + +var appCountryOptions = [ + {"name": "United Kingdom", "code": "GB"}, + {"name": "United States", "code": "US"}, + {"name": "Afghanistan", "code": "AF"}, + {"name": "Åland Islands", "code": "AX"}, + {"name": "Albania", "code": "AL"}, + {"name": "Algeria", "code": "DZ"}, + {"name": "American Samoa", "code": "AS"}, + {"name": "AndorrA", "code": "AD"}, + {"name": "Angola", "code": "AO"}, + {"name": "Anguilla", "code": "AI"}, + {"name": "Antarctica", "code": "AQ"}, + {"name": "Antigua and Barbuda", "code": "AG"}, + {"name": "Argentina", "code": "AR"}, + {"name": "Armenia", "code": "AM"}, + {"name": "Aruba", "code": "AW"}, + {"name": "Australia", "code": "AU"}, + {"name": "Austria", "code": "AT"}, + {"name": "Azerbaijan", "code": "AZ"}, + {"name": "Bahamas", "code": "BS"}, + {"name": "Bahrain", "code": "BH"}, + {"name": "Bangladesh", "code": "BD"}, + {"name": "Barbados", "code": "BB"}, + {"name": "Belarus", "code": "BY"}, + {"name": "Belgium", "code": "BE"}, + {"name": "Belize", "code": "BZ"}, + {"name": "Benin", "code": "BJ"}, + {"name": "Bermuda", "code": "BM"}, + {"name": "Bhutan", "code": "BT"}, + {"name": "Bolivia", "code": "BO"}, + {"name": "Bosnia and Herzegovina", "code": "BA"}, + {"name": "Botswana", "code": "BW"}, + {"name": "Bouvet Island", "code": "BV"}, + {"name": "Brazil", "code": "BR"}, + {"name": "British Indian Ocean Territory", "code": "IO"}, + {"name": "Brunei Darussalam", "code": "BN"}, + {"name": "Bulgaria", "code": "BG"}, + {"name": "Burkina Faso", "code": "BF"}, + {"name": "Burundi", "code": "BI"}, + {"name": "Cambodia", "code": "KH"}, + {"name": "Cameroon", "code": "CM"}, + {"name": "Canada", "code": "CA"}, + {"name": "Cape Verde", "code": "CV"}, + {"name": "Cayman Islands", "code": "KY"}, + {"name": "Central African Republic", "code": "CF"}, + {"name": "Chad", "code": "TD"}, + {"name": "Chile", "code": "CL"}, + {"name": "China", "code": "CN"}, + {"name": "Christmas Island", "code": "CX"}, + {"name": "Cocos (Keeling) Islands", "code": "CC"}, + {"name": "Colombia", "code": "CO"}, + {"name": "Comoros", "code": "KM"}, + {"name": "Congo", "code": "CG"}, + {"name": "Congo, The Democratic Republic of the", "code": "CD"}, + {"name": "Cook Islands", "code": "CK"}, + {"name": "Costa Rica", "code": "CR"}, + {"name": "Cote D\"Ivoire", "code": "CI"}, + {"name": "Croatia", "code": "HR"}, + {"name": "Cuba", "code": "CU"}, + {"name": "Cyprus", "code": "CY"}, + {"name": "Czech Republic", "code": "CZ"}, + {"name": "Denmark", "code": "DK"}, + {"name": "Djibouti", "code": "DJ"}, + {"name": "Dominica", "code": "DM"}, + {"name": "Dominican Republic", "code": "DO"}, + {"name": "Ecuador", "code": "EC"}, + {"name": "Egypt", "code": "EG"}, + {"name": "El Salvador", "code": "SV"}, + {"name": "Equatorial Guinea", "code": "GQ"}, + {"name": "Eritrea", "code": "ER"}, + {"name": "Estonia", "code": "EE"}, + {"name": "Ethiopia", "code": "ET"}, + {"name": "Falkland Islands (Malvinas)", "code": "FK"}, + {"name": "Faroe Islands", "code": "FO"}, + {"name": "Fiji", "code": "FJ"}, + {"name": "Finland", "code": "FI"}, + {"name": "France", "code": "FR"}, + {"name": "French Guiana", "code": "GF"}, + {"name": "French Polynesia", "code": "PF"}, + {"name": "French Southern Territories", "code": "TF"}, + {"name": "Gabon", "code": "GA"}, + {"name": "Gambia", "code": "GM"}, + {"name": "Georgia", "code": "GE"}, + {"name": "Germany", "code": "DE"}, + {"name": "Ghana", "code": "GH"}, + {"name": "Gibraltar", "code": "GI"}, + {"name": "Greece", "code": "GR"}, + {"name": "Greenland", "code": "GL"}, + {"name": "Grenada", "code": "GD"}, + {"name": "Guadeloupe", "code": "GP"}, + {"name": "Guam", "code": "GU"}, + {"name": "Guatemala", "code": "GT"}, + {"name": "Guernsey", "code": "GG"}, + {"name": "Guinea", "code": "GN"}, + {"name": "Guinea-Bissau", "code": "GW"}, + {"name": "Guyana", "code": "GY"}, + {"name": "Haiti", "code": "HT"}, + {"name": "Heard Island and Mcdonald Islands", "code": "HM"}, + {"name": "Holy See (Vatican City State)", "code": "VA"}, + {"name": "Honduras", "code": "HN"}, + {"name": "Hong Kong", "code": "HK"}, + {"name": "Hungary", "code": "HU"}, + {"name": "Iceland", "code": "IS"}, + {"name": "India", "code": "IN"}, + {"name": "Indonesia", "code": "ID"}, + {"name": "Iran, Islamic Republic Of", "code": "IR"}, + {"name": "Iraq", "code": "IQ"}, + {"name": "Ireland", "code": "IE"}, + {"name": "Isle of Man", "code": "IM"}, + {"name": "Israel", "code": "IL"}, + {"name": "Italy", "code": "IT"}, + {"name": "Jamaica", "code": "JM"}, + {"name": "Japan", "code": "JP"}, + {"name": "Jersey", "code": "JE"}, + {"name": "Jordan", "code": "JO"}, + {"name": "Kazakhstan", "code": "KZ"}, + {"name": "Kenya", "code": "KE"}, + {"name": "Kiribati", "code": "KI"}, + {"name": "Korea, Democratic People\"S Republic of", "code": "KP"}, + {"name": "Korea, Republic of", "code": "KR"}, + {"name": "Kuwait", "code": "KW"}, + {"name": "Kyrgyzstan", "code": "KG"}, + {"name": "Lao People\"S Democratic Republic", "code": "LA"}, + {"name": "Latvia", "code": "LV"}, + {"name": "Lebanon", "code": "LB"}, + {"name": "Lesotho", "code": "LS"}, + {"name": "Liberia", "code": "LR"}, + {"name": "Libyan Arab Jamahiriya", "code": "LY"}, + {"name": "Liechtenstein", "code": "LI"}, + {"name": "Lithuania", "code": "LT"}, + {"name": "Luxembourg", "code": "LU"}, + {"name": "Macao", "code": "MO"}, + {"name": "Macedonia, The Former Yugoslav Republic of", "code": "MK"}, + {"name": "Madagascar", "code": "MG"}, + {"name": "Malawi", "code": "MW"}, + {"name": "Malaysia", "code": "MY"}, + {"name": "Maldives", "code": "MV"}, + {"name": "Mali", "code": "ML"}, + {"name": "Malta", "code": "MT"}, + {"name": "Marshall Islands", "code": "MH"}, + {"name": "Martinique", "code": "MQ"}, + {"name": "Mauritania", "code": "MR"}, + {"name": "Mauritius", "code": "MU"}, + {"name": "Mayotte", "code": "YT"}, + {"name": "Mexico", "code": "MX"}, + {"name": "Micronesia, Federated States of", "code": "FM"}, + {"name": "Moldova, Republic of", "code": "MD"}, + {"name": "Monaco", "code": "MC"}, + {"name": "Mongolia", "code": "MN"}, + {"name": "Montserrat", "code": "MS"}, + {"name": "Morocco", "code": "MA"}, + {"name": "Mozambique", "code": "MZ"}, + {"name": "Myanmar", "code": "MM"}, + {"name": "Namibia", "code": "NA"}, + {"name": "Nauru", "code": "NR"}, + {"name": "Nepal", "code": "NP"}, + {"name": "Netherlands", "code": "NL"}, + {"name": "Netherlands Antilles", "code": "AN"}, + {"name": "New Caledonia", "code": "NC"}, + {"name": "New Zealand", "code": "NZ"}, + {"name": "Nicaragua", "code": "NI"}, + {"name": "Niger", "code": "NE"}, + {"name": "Nigeria", "code": "NG"}, + {"name": "Niue", "code": "NU"}, + {"name": "Norfolk Island", "code": "NF"}, + {"name": "Northern Mariana Islands", "code": "MP"}, + {"name": "Norway", "code": "NO"}, + {"name": "Oman", "code": "OM"}, + {"name": "Pakistan", "code": "PK"}, + {"name": "Palau", "code": "PW"}, + {"name": "Palestinian Territory, Occupied", "code": "PS"}, + {"name": "Panama", "code": "PA"}, + {"name": "Papua New Guinea", "code": "PG"}, + {"name": "Paraguay", "code": "PY"}, + {"name": "Peru", "code": "PE"}, + {"name": "Philippines", "code": "PH"}, + {"name": "Pitcairn", "code": "PN"}, + {"name": "Poland", "code": "PL"}, + {"name": "Portugal", "code": "PT"}, + {"name": "Puerto Rico", "code": "PR"}, + {"name": "Qatar", "code": "QA"}, + {"name": "Reunion", "code": "RE"}, + {"name": "Romania", "code": "RO"}, + {"name": "Russian Federation", "code": "RU"}, + {"name": "RWANDA", "code": "RW"}, + {"name": "Saint Helena", "code": "SH"}, + {"name": "Saint Kitts and Nevis", "code": "KN"}, + {"name": "Saint Lucia", "code": "LC"}, + {"name": "Saint Pierre and Miquelon", "code": "PM"}, + {"name": "Saint Vincent and the Grenadines", "code": "VC"}, + {"name": "Samoa", "code": "WS"}, + {"name": "San Marino", "code": "SM"}, + {"name": "Sao Tome and Principe", "code": "ST"}, + {"name": "Saudi Arabia", "code": "SA"}, + {"name": "Senegal", "code": "SN"}, + {"name": "Serbia and Montenegro", "code": "CS"}, + {"name": "Seychelles", "code": "SC"}, + {"name": "Sierra Leone", "code": "SL"}, + {"name": "Singapore", "code": "SG"}, + {"name": "Slovakia", "code": "SK"}, + {"name": "Slovenia", "code": "SI"}, + {"name": "Solomon Islands", "code": "SB"}, + {"name": "Somalia", "code": "SO"}, + {"name": "South Africa", "code": "ZA"}, + {"name": "South Georgia and the South Sandwich Islands", "code": "GS"}, + {"name": "Spain", "code": "ES"}, + {"name": "Sri Lanka", "code": "LK"}, + {"name": "Sudan", "code": "SD"}, + {"name": "Suriname", "code": "SR"}, + {"name": "Svalbard and Jan Mayen", "code": "SJ"}, + {"name": "Swaziland", "code": "SZ"}, + {"name": "Sweden", "code": "SE"}, + {"name": "Switzerland", "code": "CH"}, + {"name": "Syrian Arab Republic", "code": "SY"}, + {"name": "Taiwan, Province of China", "code": "TW"}, + {"name": "Tajikistan", "code": "TJ"}, + {"name": "Tanzania, United Republic of", "code": "TZ"}, + {"name": "Thailand", "code": "TH"}, + {"name": "Timor-Leste", "code": "TL"}, + {"name": "Togo", "code": "TG"}, + {"name": "Tokelau", "code": "TK"}, + {"name": "Tonga", "code": "TO"}, + {"name": "Trinidad and Tobago", "code": "TT"}, + {"name": "Tunisia", "code": "TN"}, + {"name": "Turkey", "code": "TR"}, + {"name": "Turkmenistan", "code": "TM"}, + {"name": "Turks and Caicos Islands", "code": "TC"}, + {"name": "Tuvalu", "code": "TV"}, + {"name": "Uganda", "code": "UG"}, + {"name": "Ukraine", "code": "UA"}, + {"name": "United Arab Emirates", "code": "AE"}, + {"name": "United States Minor Outlying Islands", "code": "UM"}, + {"name": "Uruguay", "code": "UY"}, + {"name": "Uzbekistan", "code": "UZ"}, + {"name": "Vanuatu", "code": "VU"}, + {"name": "Venezuela", "code": "VE"}, + {"name": "Viet Nam", "code": "VN"}, + {"name": "Virgin Islands, British", "code": "VG"}, + {"name": "Virgin Islands, U.S.", "code": "VI"}, + {"name": "Wallis and Futuna", "code": "WF"}, + {"name": "Western Sahara", "code": "EH"}, + {"name": "Yemen", "code": "YE"}, + {"name": "Zambia", "code": "ZM"}, + {"name": "Zimbabwe", "code": "ZW"} +]; diff --git a/LabelStoreMax/lib/app_tax_states_options.dart b/LabelStoreMax/lib/app_tax_states_options.dart new file mode 100644 index 0000000..36eb7b0 --- /dev/null +++ b/LabelStoreMax/lib/app_tax_states_options.dart @@ -0,0 +1,72 @@ +// 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"} +]; diff --git a/LabelStoreMax/lib/helpers/app_localizations.dart b/LabelStoreMax/lib/helpers/app_localizations.dart new file mode 100644 index 0000000..c320ca5 --- /dev/null +++ b/LabelStoreMax/lib/helpers/app_localizations.dart @@ -0,0 +1,61 @@ +// 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. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class AppLocalizations { + final Locale locale; + + AppLocalizations(this.locale); + + static AppLocalizations of(BuildContext context) { + return Localizations.of(context, AppLocalizations); + } + + static const LocalizationsDelegate delegate = + _AppLocalizationsDelegate(); + + Map _localizedStrings; + + Future load() async { + String jsonString = + await rootBundle.loadString('lang/${locale.languageCode}.json'); + Map jsonMap = json.decode(jsonString); + + _localizedStrings = jsonMap.map((k, v) { + return MapEntry(k, v.toString()); + }); + } + + String trans(String key) { + return _localizedStrings[key]; + } +} + +class _AppLocalizationsDelegate + extends LocalizationsDelegate { + const _AppLocalizationsDelegate(); + + @override + bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode); + + @override + bool shouldReload(_AppLocalizationsDelegate old) => false; + + Future load(Locale locale) async { + AppLocalizations localizations = new AppLocalizations(locale); + await localizations.load(); + return localizations; + } +} diff --git a/LabelStoreMax/lib/helpers/app_themes.dart b/LabelStoreMax/lib/helpers/app_themes.dart new file mode 100644 index 0000000..5b0e78d --- /dev/null +++ b/LabelStoreMax/lib/helpers/app_themes.dart @@ -0,0 +1,167 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; +import 'package:label_storemax/helpers/tools.dart'; + +TextTheme textThemeAccent() { + return TextTheme( + display1: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w800, + fontSize: 26), + display2: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w600), + display3: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w600), + display4: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w600), + headline: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + title: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + ), + subhead: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w800), + body2: new TextStyle( + color: HexColor("#606060"), + fontFamily: appFontFamily, + fontWeight: FontWeight.w700), + body1: new TextStyle( + color: HexColor("#a8a8a8"), + fontFamily: appFontFamily, + fontWeight: FontWeight.w700, + fontSize: 18), + caption: new TextStyle( + color: HexColor("#2a5080"), + fontFamily: appFontFamily, + fontWeight: FontWeight.w700, + fontSize: 14), + button: new TextStyle( + color: Colors.white, + fontFamily: appFontFamily, + fontWeight: FontWeight.w700), + ); +} + +TextTheme textThemePrimary() { + return TextTheme( + display1: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w800, + fontSize: 26), + display2: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w600), + display3: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w600), + display4: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w600), + headline: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + title: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + ), + subhead: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w800), + body2: new TextStyle( + color: HexColor("#606060"), + fontFamily: appFontFamily, + fontWeight: FontWeight.w700), + body1: new TextStyle( + color: HexColor("#a8a8a8"), + fontFamily: appFontFamily, + fontWeight: FontWeight.w700, + fontSize: 18), + caption: new TextStyle( + color: HexColor("#2a5080"), + fontFamily: appFontFamily, + fontWeight: FontWeight.w700, + fontSize: 14), + button: new TextStyle( + color: Colors.white, + fontFamily: appFontFamily, + fontWeight: FontWeight.w700), + ); +} + +TextTheme textThemeMain() { + return TextTheme( + display1: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + ), + display2: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + display3: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + display4: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + headline: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + title: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + subhead: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + body2: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + body1: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + caption: new TextStyle( + color: Colors.redAccent, fontSize: 16, fontFamily: appFontFamily), + button: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + ); +} + +TextTheme textThemeAppBar() { + return TextTheme( + display1: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + display2: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + display3: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + display4: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + headline: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + title: new TextStyle( + color: Colors.black, + fontFamily: appFontFamily, + fontWeight: FontWeight.w900), + subhead: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + body2: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + body1: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + caption: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + button: new TextStyle(color: Colors.black, fontFamily: appFontFamily), + ); +} + +ColorScheme colorSchemeButton() { + return ColorScheme.light( + primary: const Color(0xff6200ee), + primaryVariant: const Color(0xff3700b3), + secondary: const Color(0xff03dac6), + secondaryVariant: const Color(0xff018786), + surface: Colors.white, + background: Colors.white, + error: const Color(0xffb00020), + onPrimary: Colors.white, + onSecondary: Colors.black, + onSurface: Colors.black, + onBackground: Colors.black, + onError: Colors.white, + brightness: Brightness.light); +} diff --git a/LabelStoreMax/lib/helpers/tools.dart b/LabelStoreMax/lib/helpers/tools.dart new file mode 100644 index 0000000..1b158f0 --- /dev/null +++ b/LabelStoreMax/lib/helpers/tools.dart @@ -0,0 +1,764 @@ +// 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. + +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: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:woosignal/models/response/tax_rate.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}); +} + +List arrPaymentMethods = [ + (paymentMethods.contains("Stripe") + ? (PaymentType( + id: 1, + name: "Debit or Credit Card", + assetImage: "dark_powered_by_stripe.png")) + : null) +]; + +List getPaymentTypes() { + return arrPaymentMethods; +} + +class HexColor extends Color { + static int _getColorFromHex(String hexColor) { + hexColor = hexColor.toUpperCase().replaceAll("#", ""); + if (hexColor.length == 6) { + hexColor = "FF" + hexColor; + } + return int.parse(hexColor, radix: 16); + } + + HexColor(final String hexColor) : super(_getColorFromHex(hexColor)); +} + +String truncateWithEllipsis(int cutoff, String myString) { + return (myString.length <= cutoff) + ? 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, + backgroundColor: + (statusType == "error" ? HexColor("#b5123a") : Colors.grey), + textColor: (statusType == "error" ? Colors.white : Colors.black), + fontSize: 16.0); +} + +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); +} + +class PaymentMethodType { + static final int STRIPE = 1; + static final int APPLEPAY = 2; +} + +class EdgeAlertStyle { + static final int SUCCESS = 1; + static final int WARNING = 2; + static final int INFO = 3; + static final int DANGER = 4; +} + +void showEdgeAlertWith(context, + {title = "", desc = "", int gravity = 1, int style = 1, IconData icon}) { + switch (style) { + case 1: // SUCCESS + EdgeAlert.show(context, + title: title, + description: desc, + gravity: gravity, + backgroundColor: Colors.green, + icon: icon ?? Icons.check, + duration: EdgeAlert.LENGTH_LONG); + break; + case 2: // WARNING + EdgeAlert.show(context, + title: title, + description: desc, + gravity: gravity, + backgroundColor: Colors.orange, + icon: icon ?? Icons.error_outline, + duration: EdgeAlert.LENGTH_LONG); + break; + case 3: // INFO + EdgeAlert.show(context, + title: title, + description: desc, + gravity: gravity, + backgroundColor: Colors.teal, + icon: icon ?? Icons.info, + duration: EdgeAlert.LENGTH_LONG); + break; + case 4: // DANGER + EdgeAlert.show(context, + title: title, + description: desc, + gravity: gravity, + backgroundColor: Colors.redAccent, + icon: icon ?? Icons.warning, + duration: EdgeAlert.LENGTH_LONG); + break; + default: + break; + } +} + +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 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 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 tmpArrAddress = new List(); + 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 tmpArrName = new List(); + if (firstName != "") { + tmpArrName.add(firstName); + } + if (lastName != "") { + tmpArrName.add(lastName); + } + return tmpArrName.join(", "); + } + + CustomerAddress.fromJson(Map 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 toJson() { + final Map data = new Map(); + 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; +} + +String formatStringCurrency({String total}) { + double tmpVal; + if (total == null || total == "") { + tmpVal = 0; + } else { + tmpVal = double.parse(total); + } + FlutterMoneyFormatter fmf = FlutterMoneyFormatter( + 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 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 toShippingLineFee() { + if (this.methodId != null && this.object != null) { + Map 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 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 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> getCart() async { + List cartLineItems = []; + SharedPref sharedPref = SharedPref(); + String currentCartArrJSON = (await sharedPref.read(_keyCart) as String); + if (currentCartArrJSON == null) { + cartLineItems = List(); + } else { + cartLineItems = (jsonDecode(currentCartArrJSON) as List) + .map((i) => CartLineItem.fromJson(i)) + .toList(); + } + return cartLineItems; + } + + void addToCart({CartLineItem cartLineItem}) async { + List 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 getTotal({bool withFormat}) async { + List 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 getSubtotal({bool withFormat}) async { + List 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 cartLineItems = await getCart(); + List tmpCartItem = new List(); + 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 cartShortDesc() async { + List 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 cartLineItems = await getCart(); + cartLineItems.removeAt(index); + saveCartToPref(cartLineItems: cartLineItems); + } + + void clear() { + SharedPref sharedPref = SharedPref(); + List cartLineItems = new List(); + String jsonArrCartItems = + jsonEncode(cartLineItems.map((i) => i.toJson()).toList()); + sharedPref.save(_keyCart, jsonArrCartItems); + } + + void saveCartToPref({List cartLineItems}) { + SharedPref sharedPref = SharedPref(); + String jsonArrCartItems = + jsonEncode(cartLineItems.map((i) => i.toJson()).toList()); + sharedPref.save(_keyCart, jsonArrCartItems); + } + + Future taxAmount(TaxRate taxRate) async { + double subtotal = 0; + double shippingTotal = 0; + + List cartItems = await Cart.getInstance.getCart(); + if (cartItems.every((c) => c.taxStatus == 'none')) { + return "0"; + } + List taxableCartLines = + cartItems.where((c) => c.taxStatus == 'taxable').toList(); + double cartSubtotal = 0; + + if (taxableCartLines.length > 0) { + cartSubtotal = taxableCartLines + .map((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) { + shippingTotal += double.parse(shippingType.cost); + } + break; + case "local_pickup": + LocalPickup localPickup = (shippingType.object as LocalPickup); + if (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 { + await FlutterWebBrowser.openWebPage( + url: url, androidToolbarColor: Colors.white70); +} + +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 animation, + Animation secondaryAnimation) { + return widget; + }, transitionsBuilder: (BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child) { + return new SlideTransition( + position: new Tween( + 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); +} diff --git a/LabelStoreMax/lib/labelconfig.dart b/LabelStoreMax/lib/labelconfig.dart new file mode 100644 index 0000000..1792eb4 --- /dev/null +++ b/LabelStoreMax/lib/labelconfig.dart @@ -0,0 +1,47 @@ +// +// LabelCore +// 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. + +/* + Developer Notes + + SUPPORT EMAIL - support@woosignal.com + VERSION - 1.0 + https://woosignal.com + */ + +/**/ + +const app_name = "MyApp"; + +const app_key = "your app key"; + +const app_logo_url = "https://woosignal.com/images/120x120_woosignal.png"; + +const app_terms_url = "https://yourdomain.com/terms"; +const app_privacy_url = "https://yourdomain.com/privacy"; + +/**/ + +const app_stripe_account = "your StripeAccount key"; // Your StripeAccount key from WooSignal +const app_stripe_live_mode = false; // SET true for live payments + +/**/ + +const app_currency_symbol = "\£"; +const app_currency_iso = "gbp"; +const app_locales_supported = ['en']; + +const paymentMethods = ["Stripe"]; + +/**/ + +const app_debug = true; diff --git a/LabelStoreMax/lib/main.dart b/LabelStoreMax/lib/main.dart new file mode 100644 index 0000000..2bbcece --- /dev/null +++ b/LabelStoreMax/lib/main.dart @@ -0,0 +1,131 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'labelconfig.dart'; +import 'package:label_storemax/pages/checkout_details.dart'; +import 'package:label_storemax/pages/home.dart'; +import 'package:label_storemax/pages/about.dart'; +import 'package:label_storemax/pages/checkout_confirmation.dart'; +import 'package:label_storemax/pages/cart.dart'; +import 'package:label_storemax/pages/checkout_status.dart'; +import 'package:label_storemax/pages/checkout_payment_type.dart'; +import 'package:label_storemax/pages/checkout_shipping_type.dart'; +import 'package:label_storemax/pages/product_detail.dart'; +import 'package:label_storemax/pages/browse_search.dart'; +import 'package:label_storemax/pages/home_menu.dart'; +import 'package:label_storemax/pages/home_search.dart'; +import 'package:label_storemax/pages/browse_category.dart'; +import 'package:flutter/services.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:page_transition/page_transition.dart'; +import 'package:label_storemax/helpers/app_themes.dart'; +import 'package:label_storemax/helpers/app_localizations.dart'; + +void main() async { + Widget _defaultHome = new HomePage(); + + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]).then( + (_) { + _defaultHome = HomePage(); + + runApp( + new MaterialApp( + title: app_name, + color: Colors.white, + debugShowCheckedModeBanner: false, + routes: { + '/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(), + '/checkout': (BuildContext context) => + new CheckoutConfirmationPage(), + '/checkout-status': (BuildContext context) => + new CheckoutStatusPage(), + }, + onGenerateRoute: (settings) { + switch (settings.name) { + case '/home-menu': + return PageTransition( + child: HomeMenuPage(), + type: PageTransitionType.leftToRight); + case '/checkout-details': + return PageTransition( + child: CheckoutDetailsPage(), + type: PageTransitionType.downToUp); + case '/about': + return PageTransition( + child: AboutPage(), type: PageTransitionType.leftToRight); + + case '/checkout-payment-type': + return PageTransition( + child: CheckoutPaymentTypePage(), + type: PageTransitionType.downToUp); + + case '/checkout-shipping-type': + return PageTransition( + child: CheckoutShippingTypePage(), + type: PageTransitionType.downToUp); + + case '/home-search': + return PageTransition( + child: HomeSearchPage(), + type: PageTransitionType.downToUp); + default: + return null; + } + }, + supportedLocales: [Locale('en')], + localizationsDelegates: [ + AppLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalMaterialLocalizations.delegate + ], + localeResolutionCallback: + (Locale locale, Iterable supportedLocales) { + return locale; + }, + theme: ThemeData( + primaryColor: HexColor("#2f4ffe"), + backgroundColor: Colors.white, + buttonTheme: ButtonThemeData( + hoverColor: Colors.transparent, + buttonColor: HexColor("#529cda"), + colorScheme: colorSchemeButton(), + minWidth: double.infinity, + height: 70, + shape: RoundedRectangleBorder( + borderRadius: new BorderRadius.circular(5.0), + ), + ), + appBarTheme: AppBarTheme( + color: Colors.white, + textTheme: textThemeAppBar(), + elevation: 0.0, + brightness: Brightness.light, + iconTheme: IconThemeData(color: Colors.black), + actionsIconTheme: IconThemeData( + color: Colors.black, + )), + accentColor: Colors.black, + accentTextTheme: textThemeAccent(), + textTheme: textThemeMain(), + primaryTextTheme: textThemePrimary()), + home: _defaultHome), + ); + }, + ); +} diff --git a/LabelStoreMax/lib/pages/about.dart b/LabelStoreMax/lib/pages/about.dart new file mode 100644 index 0000000..92aee13 --- /dev/null +++ b/LabelStoreMax/lib/pages/about.dart @@ -0,0 +1,112 @@ +// 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. + +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:package_info/package_info.dart'; + +class AboutPage extends StatefulWidget { + AboutPage(); + + @override + _AboutPageState createState() => _AboutPageState(); +} + +class _AboutPageState extends State { + _AboutPageState(); + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + leading: IconButton( + icon: Icon(Icons.close), + onPressed: () { + Navigator.pop(context); + }, + ), + title: Text(trans(context, "About"), + style: Theme.of(context).primaryTextTheme.subhead), + centerTitle: true, + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Flexible( + child: storeLogo(), + flex: 2, + ), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + wsMenuItem(context, + title: trans(context, "Privacy policy"), + leading: Icon(Icons.people), + action: _actionPrivacy), + wsMenuItem(context, + title: trans(context, "Terms and conditions"), + leading: Icon(Icons.description), + action: _actionTerms), + FutureBuilder( + future: PackageInfo.fromPlatform(), + builder: (BuildContext context, + AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.none: + return Text(""); + case ConnectionState.active: + case ConnectionState.waiting: + return Text(""); + case ConnectionState.done: + if (snapshot.hasError) return Text(""); + return Padding( + child: Text( + trans(context, "Version") + + ": " + + snapshot.data.version, + style: + Theme.of(context).primaryTextTheme.body2), + padding: EdgeInsets.only(top: 15, bottom: 15), + ); + } + return null; // unreachable + }, + ) + ], + ), + flex: 2, + ), + ], + ), + ), + ); + } + + void _actionTerms() { + openBrowserTab(url: app_terms_url); + } + + void _actionPrivacy() { + openBrowserTab(url: app_privacy_url); + } +} diff --git a/LabelStoreMax/lib/pages/browse_category.dart b/LabelStoreMax/lib/pages/browse_category.dart new file mode 100644 index 0000000..887ef22 --- /dev/null +++ b/LabelStoreMax/lib/pages/browse_category.dart @@ -0,0 +1,146 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/tools.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(); + + @override + _BrowseCategoryPageState createState() => _BrowseCategoryPageState(); +} + +class _BrowseCategoryPageState extends State { + _BrowseCategoryPageState(); + + List _products = []; + var _productsController = ScrollController(); + + ProductCategory _selectedCategory; + bool _isLoading; + int _page; + bool _shouldStopRequests; + bool waitForNextRequest; + + @override + void initState() { + super.initState(); + + _isLoading = true; + + _page = 1; + _shouldStopRequests = false; + waitForNextRequest = false; + + _productsController.addListener(() { + double maxScroll = _productsController.position.maxScrollExtent; + double currentScroll = _productsController.position.pixels; + double delta = 50.0; + if (maxScroll - currentScroll <= delta) { + if (_shouldStopRequests) { + return; + } + if (waitForNextRequest) { + return; + } + WooSignal.getInstance(config: wsConfig).then((wcStore) { + waitForNextRequest = true; + _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; + setState(() { + _isLoading = false; + }); + }); + }); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + if (_isLoading) { + _selectedCategory = ModalRoute.of(context).settings.arguments; + _fetchProductsForCategory(); + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + title: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(trans(context, "Browse"), + style: Theme.of(context).primaryTextTheme.subhead), + Text(_selectedCategory.name, + style: Theme.of(context).primaryTextTheme.title) + ], + ), + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: _isLoading + ? Center( + child: showAppLoader(), + ) + : Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: (_products.length != null && _products.length > 0 + ? GridView.count( + crossAxisCount: 2, + controller: _productsController, + children: List.generate(_products.length, (index) { + return wsCardProductItem(context, + index: index, product: _products[index]); + })) + : wsNoResults(context)), + flex: 1, + ), + ], + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/pages/browse_search.dart b/LabelStoreMax/lib/pages/browse_search.dart new file mode 100644 index 0000000..5803524 --- /dev/null +++ b/LabelStoreMax/lib/pages/browse_search.dart @@ -0,0 +1,137 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/tools.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(); + + @override + _BrowseSearchState createState() => _BrowseSearchState(); +} + +class _BrowseSearchState extends State { + _BrowseSearchState(); + + var _productsController = ScrollController(); + List _products = []; + String _search; + bool _isLoading; + int _page; + bool _shouldStopRequests; + bool waitForNextRequest; + + @override + void initState() { + super.initState(); + + _isLoading = true; + _page = 1; + _shouldStopRequests = false; + waitForNextRequest = false; + + _productsController.addListener(() { + double maxScroll = _productsController.position.maxScrollExtent; + double currentScroll = _productsController.position.pixels; + double delta = 50.0; + if (maxScroll - currentScroll <= delta) { + if (_shouldStopRequests) { + return; + } + if (waitForNextRequest) { + return; + } + _fetchProductsForSearch(_page); + } + }); + } + + _fetchProductsForSearch(int page) { + WooSignal.getInstance(config: wsConfig).then((wcStore) { + waitForNextRequest = true; + _page = _page + 1; + wcStore + .getProducts( + search: _search, perPage: 100, page: page, status: "publish") + .then((products) { + waitForNextRequest = false; + if (products.length == 0) { + _shouldStopRequests = true; + } + _products.addAll(products.toList()); + setState(() { + _isLoading = false; + }); + }); + }); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + if (_isLoading) { + _search = ModalRoute.of(context).settings.arguments; + _fetchProductsForSearch(_page); + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + title: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(trans(context, "Search results for"), + style: Theme.of(context).primaryTextTheme.subhead), + Text("\"" + _search + "\"", + style: Theme.of(context).primaryTextTheme.title) + ], + ), + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: _isLoading + ? Center( + child: showAppLoader(), + ) + : Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: (_products.length != null && _products.length > 0 + ? GridView.count( + crossAxisCount: 2, + controller: _productsController, + children: List.generate(_products.length, (index) { + return wsCardProductItem(context, + index: index, product: _products[index]); + })) + : wsNoResults(context)), + flex: 1, + ), + ], + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/pages/cart.dart b/LabelStoreMax/lib/pages/cart.dart new file mode 100644 index 0000000..ba3cb14 --- /dev/null +++ b/LabelStoreMax/lib/pages/cart.dart @@ -0,0 +1,245 @@ +// 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. + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; +import 'package:woosignal/woosignal.dart'; + +class CartPage extends StatefulWidget { + CartPage(); + + @override + _CartPageState createState() => _CartPageState(); +} + +class _CartPageState extends State { + _CartPageState(); + + bool _isLoading = false; + bool _isCartEmpty = false; + List _cartLines; + + @override + void initState() { + super.initState(); + _cartLines = []; + _isLoading = true; + _cartCheck(); + } + + _cartCheck() async { + List cart = await Cart.getInstance.getCart(); + if (cart.length <= 0) { + setState(() { + _isLoading = false; + _isCartEmpty = (cart.length <= 0) ? true : false; + }); + return []; + } + WooSignal wooSignal = await WooSignal.getInstance(config: wsConfig); + List> cartJSON = cart.map((c) => c.toJson()).toList(); + + List cartRes = await wooSignal.cartCheck(cartJSON); + _cartLines = cartRes.map((json) => CartLineItem.fromJson(json)).toList(); + if (_cartLines.length > 0) { + Cart.getInstance.saveCartToPref(cartLineItems: _cartLines); + } + setState(() { + _isLoading = false; + }); + } + + void _actionProceedToCheckout() async { + List cartLineItems = await Cart.getInstance.getCart(); + if (cartLineItems.length <= 0) { + showEdgeAlertWith(context, + title: trans(context, "Cart"), + desc: trans(context, + trans(context, "You need items in your cart to checkout")), + style: EdgeAlertStyle.WARNING, + icon: Icons.shopping_cart); + return; + } + if (!cartLineItems.every( + (c) => c.stockStatus == 'instock' || c.stockStatus == 'onbackorder')) { + showEdgeAlertWith(context, + title: trans(context, "Cart"), + desc: trans(context, trans(context, "There is an item out of stock")), + style: EdgeAlertStyle.WARNING, + icon: Icons.shopping_cart); + return; + } + CheckoutSession.getInstance.initSession(); + CustomerAddress sfCustomerAddress = + await CheckoutSession.getInstance.getBillingAddress(); + if (sfCustomerAddress != null) { + CheckoutSession.getInstance.billingDetails.billingAddress = + sfCustomerAddress; + CheckoutSession.getInstance.billingDetails.shippingAddress = + sfCustomerAddress; + } + Navigator.pushNamed(context, "/checkout"); + } + + actionIncrementQuantity({CartLineItem cartLineItem}) { + if (cartLineItem.isManagedStock && + cartLineItem.quantity + 1 > cartLineItem.stockQuantity) { + showEdgeAlertWith(context, + title: trans(context, "Cart"), + desc: trans(context, trans(context, "Maximum stock reached")), + style: EdgeAlertStyle.WARNING, + icon: Icons.shopping_cart); + return; + } + Cart.getInstance + .updateQuantity(cartLineItem: cartLineItem, incrementQuantity: 1); + cartLineItem.quantity += 1; + setState(() {}); + } + + actionDecrementQuantity({CartLineItem cartLineItem}) { + if (cartLineItem.quantity - 1 <= 0) { + return; + } + Cart.getInstance + .updateQuantity(cartLineItem: cartLineItem, incrementQuantity: -1); + cartLineItem.quantity -= 1; + setState(() {}); + } + + actionRemoveItem({int index}) { + Cart.getInstance.removeCartItemForIndex(index: index); + _cartLines.removeAt(index); + showEdgeAlertWith(context, + title: trans(context, "Updated"), + desc: trans(context, "Item removed"), + style: EdgeAlertStyle.WARNING, + icon: Icons.remove_shopping_cart); + setState(() {}); + } + + void _clearCart() { + Cart.getInstance.clear(); + _cartLines = []; + showEdgeAlertWith(context, + title: trans(context, "Success"), + desc: trans(context, "Cart cleared"), + style: EdgeAlertStyle.SUCCESS, + icon: Icons.delete_outline); + setState(() {}); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + title: Text(trans(context, "Shopping Cart"), + style: Theme.of(context).appBarTheme.textTheme.title), + textTheme: Theme.of(context).textTheme, + actions: [ + InkWell( + highlightColor: Colors.transparent, + splashColor: Colors.transparent, + child: Align( + child: Padding( + child: Text(trans(context, "Clear Cart"), + style: Theme.of(context).primaryTextTheme.body2), + padding: EdgeInsets.only(right: 8), + ), + alignment: Alignment.centerLeft, + ), + onTap: _clearCart, + ) + ], + centerTitle: true, + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _isCartEmpty + ? Expanded( + child: FractionallySizedBox( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Image( + image: AssetImage("assets/images/cart_empty.png"), + height: 150, + alignment: Alignment.center), + Padding( + child: Text(trans(context, "Empty Basket"), + style: Theme.of(context).primaryTextTheme.body1), + padding: EdgeInsets.only(top: 10), + ) + ], + ), + heightFactor: 0.5, + widthFactor: 1, + )) + : (_isLoading + ? Expanded(child: showAppLoader()) + : Expanded( + child: ListView.builder( + padding: const EdgeInsets.all(8), + itemCount: _cartLines.length, + itemBuilder: (BuildContext context, int index) { + CartLineItem cartLineItem = _cartLines[index]; + return wsCardCartItem(context, + cartLineItem: cartLineItem, + actionIncrementQuantity: () { + actionIncrementQuantity( + cartLineItem: cartLineItem); + }, actionDecrementQuantity: () { + actionDecrementQuantity( + cartLineItem: cartLineItem); + }, actionRemoveItem: () { + actionRemoveItem(index: index); + }); + }), + flex: 3, + )), + Divider( + color: Colors.black45, + ), + FutureBuilder( + future: Cart.getInstance.getTotal(withFormat: true), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.waiting: + return Text(""); + default: + if (snapshot.hasError) + return Text(""); + else + return new Padding( + child: wsRow2Text(context, + text1: trans(context, "Total"), + text2: (_isLoading ? "" : snapshot.data)), + padding: EdgeInsets.only(bottom: 15, top: 15), + ); + } + }, + ), + wsPrimaryButton(context, + title: trans(context, "PROCEED TO CHECKOUT"), + action: _actionProceedToCheckout), + ], + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/pages/checkout_confirmation.dart b/LabelStoreMax/lib/pages/checkout_confirmation.dart new file mode 100644 index 0000000..9a2b20b --- /dev/null +++ b/LabelStoreMax/lib/pages/checkout_confirmation.dart @@ -0,0 +1,451 @@ +// 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. + +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: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(); + + @override + _CheckoutConfirmationPageState createState() => + _CheckoutConfirmationPageState(); +} + +class _CheckoutConfirmationPageState extends State { + _CheckoutConfirmationPageState(); + + bool _showFullLoader; + + List _taxRates; + TaxRate _taxRate; + + @override + void initState() { + super.initState(); + + _showFullLoader = true; + if (CheckoutSession.getInstance.paymentType == null) { + CheckoutSession.getInstance.paymentType = arrPaymentMethods.first; + } + + _getTaxes(); + } + + _getTaxes() async { + WooSignal wooSignal = await WooSignal.getInstance(config: wsConfig); + _taxRates = await wooSignal.getTaxRates(page: 1, perPage: 100); + if (CheckoutSession.getInstance.billingDetails.shippingAddress == null) { + setState(() { + _showFullLoader = false; + }); + return; + } + String country = + CheckoutSession.getInstance.billingDetails.shippingAddress.country; + Map countryMap = appCountryOptions + .firstWhere((c) => c['name'] == country, orElse: () => null); + if (countryMap == null) { + _showFullLoader = false; + setState(() {}); + return; + } + String countryCode = countryMap["code"]; + + TaxRate taxRate = _taxRates.firstWhere((t) => t.country == countryCode, + orElse: () => null); + + if (taxRate != null) { + _taxRate = taxRate; + } + setState(() { + _showFullLoader = false; + }); + } + + _actionCheckoutDetails() { + Navigator.pushNamed(context, "/checkout-details").then((e) { + _showFullLoader = true; + _getTaxes(); + }); + } + + _actionPayWith() { + Navigator.pushNamed(context, "/checkout-payment-type"); + } + + _actionSelectShipping() { + CustomerAddress shippingAddress = + CheckoutSession.getInstance.billingDetails.shippingAddress; + if (shippingAddress == null || shippingAddress.country == "") { + showEdgeAlertWith(context, + title: trans(context, "Oops"), + desc: trans(context, "Add your shipping details first"), + icon: Icons.local_shipping); + return; + } + Navigator.pushNamed(context, "/checkout-shipping-type"); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + title: storeLogo(height: 50), + centerTitle: true, + ), + resizeToAvoidBottomPadding: false, + body: SafeArea( + minimum: safeAreaDefault(), + child: !_showFullLoader + ? Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Center( + child: Text(trans(context, "Checkout"), + style: Theme.of(context).primaryTextTheme.subhead), + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 10, right: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: wsBoxShadow()), + margin: EdgeInsets.only(top: 5, bottom: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + ((CheckoutSession.getInstance.billingDetails + .billingAddress != + null) + ? wsCheckoutRow(context, + heading: trans( + context, "Billing/shipping details"), + leadImage: Icon(Icons.home), + leadTitle: (CheckoutSession.getInstance + .billingDetails.billingAddress + .hasMissingFields() + ? "Billing address is incomplete" + : truncateWithEllipsis( + 30, + CheckoutSession.getInstance + .billingDetails.billingAddress + .addressFull())), + action: _actionCheckoutDetails, + showBorderBottom: true) + : wsCheckoutRow(context, + heading: trans( + context, "Billing/shipping details"), + leadImage: Icon(Icons.home), + leadTitle: trans(context, + "Add billing & shipping details"), + action: _actionCheckoutDetails, + showBorderBottom: true)), + (CheckoutSession.getInstance.paymentType != null + ? wsCheckoutRow(context, + heading: trans(context, "Payment method"), + leadImage: Image( + image: AssetImage("assets/images/" + + CheckoutSession.getInstance + .paymentType.assetImage), + width: 70), + leadTitle: CheckoutSession + .getInstance.paymentType.name, + action: _actionPayWith, + showBorderBottom: true) + : wsCheckoutRow(context, + heading: trans(context, "Pay with"), + leadImage: Icon(Icons.payment), + leadTitle: + trans(context, "Select a payment method"), + action: _actionPayWith, + showBorderBottom: true)), + (CheckoutSession.getInstance.shippingType != null + ? wsCheckoutRow(context, + heading: trans(context, "Shipping selected"), + leadImage: Icon(Icons.local_shipping), + leadTitle: CheckoutSession + .getInstance.shippingType + .getTitle(), + action: _actionSelectShipping) + : wsCheckoutRow(context, + heading: trans(context, "Select shipping"), + leadImage: Icon(Icons.local_shipping), + leadTitle: trans( + context, "Select a shipping option"), + action: _actionSelectShipping)), + ], + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Divider( + color: Colors.black12, + thickness: 1, + ), + widgetCheckoutMeta(context, + title: trans(context, "Shipping fee"), + amount: + CheckoutSession.getInstance.shippingType == null + ? trans(context, "Select shipping") + : CheckoutSession.getInstance.shippingType + .getTotal(withFormatting: true)), + (_taxRate != null + ? wsCheckoutTaxAmountWidgetFB(taxRate: _taxRate) + : Container()), + wsCheckoutSubtotalWidgetFB( + title: trans(context, "Subtotal")), + wsCheckoutTotalWidgetFB( + title: trans(context, "Total"), taxRate: _taxRate), + Divider( + color: Colors.black12, + thickness: 1, + ), + ], + ), + wsPrimaryButton(context, + title: trans(context, "CHECKOUT"), + action: _handleCheckout), + ], + ) + : Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + showAppLoader(), + Text(trans(context, "One moment") + "...", + style: Theme.of(context).primaryTextTheme.subhead) + ], + ), + ), + ), + ); + } + + _handleCheckout() async { + if (CheckoutSession.getInstance.billingDetails.billingAddress == null) { + showEdgeAlertWith(context, + title: trans(context, "Oops"), + desc: trans(context, + "Please select add your billing/shipping address to proceed"), + style: EdgeAlertStyle.WARNING, + icon: Icons.local_shipping); + return; + } + + if (CheckoutSession.getInstance.billingDetails.billingAddress + .hasMissingFields()) { + showEdgeAlertWith(context, + title: trans(context, "Oops"), + desc: trans(context, "Your billing/shipping details are incomplete"), + style: EdgeAlertStyle.WARNING, + icon: Icons.local_shipping); + return; + } + + if (CheckoutSession.getInstance.shippingType == null) { + showEdgeAlertWith(context, + title: trans(context, "Oops"), + desc: trans(context, "Please select a shipping method to proceed"), + style: EdgeAlertStyle.WARNING, + icon: Icons.local_shipping); + return; + } + + if (CheckoutSession.getInstance.paymentType == null) { + showEdgeAlertWith(context, + title: trans(context, "Oops"), + desc: trans(context, "Please select a payment method to proceed"), + style: EdgeAlertStyle.WARNING, + icon: Icons.payment); + return; + } + + _pay(); + } + + Future _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 = []; + List 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 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 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; + }); + } + } + } +} diff --git a/LabelStoreMax/lib/pages/checkout_details.dart b/LabelStoreMax/lib/pages/checkout_details.dart new file mode 100644 index 0000000..20f7ee3 --- /dev/null +++ b/LabelStoreMax/lib/pages/checkout_details.dart @@ -0,0 +1,269 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; +import 'package:label_storemax/app_country_options.dart'; + +class CheckoutDetailsPage extends StatefulWidget { + CheckoutDetailsPage(); + + @override + _CheckoutDetailsPageState createState() => _CheckoutDetailsPageState(); +} + +class _CheckoutDetailsPageState extends State { + _CheckoutDetailsPageState(); + + // BILLING TEXT CONTROLLERS + TextEditingController _txtBillingFirstName; + TextEditingController _txtBillingLastName; + TextEditingController _txtBillingAddressLine; + TextEditingController _txtBillingCity; + TextEditingController _txtBillingPostalCode; + TextEditingController _txtBillingEmailAddress; + String _strBillingCountry; + + var valRememberDetails = true; + + @override + void initState() { + super.initState(); + + _txtBillingFirstName = TextEditingController(); + _txtBillingLastName = TextEditingController(); + _txtBillingAddressLine = TextEditingController(); + _txtBillingCity = TextEditingController(); + _txtBillingPostalCode = TextEditingController(); + _txtBillingEmailAddress = TextEditingController(); + + if (CheckoutSession.getInstance.billingDetails.billingAddress == null) { + CheckoutSession.getInstance.billingDetails.initSession(); + CheckoutSession.getInstance.billingDetails.shippingAddress.initAddress(); + CheckoutSession.getInstance.billingDetails.billingAddress.initAddress(); + } + BillingDetails billingDetails = CheckoutSession.getInstance.billingDetails; + _txtBillingFirstName.text = billingDetails.billingAddress.firstName; + _txtBillingLastName.text = billingDetails.billingAddress.lastName; + _txtBillingAddressLine.text = billingDetails.billingAddress.addressLine; + _txtBillingCity.text = billingDetails.billingAddress.city; + _txtBillingPostalCode.text = billingDetails.billingAddress.postalCode; + _txtBillingEmailAddress.text = billingDetails.billingAddress.emailAddress; + _strBillingCountry = billingDetails.billingAddress.country; + + valRememberDetails = billingDetails.rememberDetails ?? true; + _sfCustomerAddress(); + } + + _sfCustomerAddress() async { + CustomerAddress sfCustomerAddress = + await CheckoutSession.getInstance.getBillingAddress(); + if (sfCustomerAddress != null) { + CustomerAddress customerAddress = sfCustomerAddress; + _txtBillingFirstName.text = customerAddress.firstName; + _txtBillingLastName.text = customerAddress.lastName; + _txtBillingAddressLine.text = customerAddress.addressLine; + _txtBillingCity.text = customerAddress.city; + _txtBillingPostalCode.text = customerAddress.postalCode; + _txtBillingEmailAddress.text = customerAddress.emailAddress; + _strBillingCountry = customerAddress.country; + } + } + + _showSelectCountryModal() { + wsModalBottom(context, + title: trans(context, "Select a country"), + bodyWidget: Expanded( + child: ListView.builder( + itemCount: appCountryOptions.length, + itemBuilder: (BuildContext context, int index) { + Map strName = appCountryOptions[index]; + + return InkWell( + child: Container( + child: Text(strName["name"], + style: Theme.of(context).primaryTextTheme.body2), + padding: EdgeInsets.only(top: 25, bottom: 25), + ), + splashColor: Colors.grey, + highlightColor: Colors.black12, + onTap: () { + setState(() { + _strBillingCountry = strName["name"]; + Navigator.of(context).pop(); + }); + }, + ); + }), + )); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: Colors.transparent, + title: Text(trans(context, "Billing & Shipping Details"), + style: Theme.of(context).primaryTextTheme.subhead), + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: GestureDetector( + onTap: () { + FocusScope.of(context).requestFocus(new FocusNode()); + }, + child: LayoutBuilder( + builder: (context, constraints) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Row( + children: [ + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "First Name"), + controller: _txtBillingFirstName, + shouldAutoFocus: true), + ), + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "Last Name"), + controller: _txtBillingLastName), + ), + ], + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + ), + wsTextEditingRow(context, + heading: trans(context, "Address Line"), + controller: _txtBillingAddressLine), + Row(children: [ + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "City"), + controller: _txtBillingCity), + ), + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "Postal code"), + controller: _txtBillingPostalCode), + ), + ]), + Row( + children: [ + Flexible( + child: wsTextEditingRow(context, + heading: trans(context, "Email address"), + keyboardType: TextInputType.emailAddress, + controller: _txtBillingEmailAddress), + ), + Flexible( + child: Padding( + child: wsSecondaryButton(context, + title: (_strBillingCountry != null && + _strBillingCountry.isNotEmpty + ? trans(context, "Selected") + + "\n" + + _strBillingCountry + : trans(context, "Select country")), + action: _showSelectCountryModal), + padding: EdgeInsets.all(8), + )) + ], + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + ) + ], + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: HexColor("#e8e8e8"), + blurRadius: 15.0, + // has the effect of softening the shadow + spreadRadius: 0, + offset: Offset( + 0, + 0, + ), + ) + ], + ), + padding: EdgeInsets.all(8), + ), + height: (constraints.maxHeight - constraints.minHeight) * 0.6, + ), + Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Text(trans(context, "Remember my details"), + style: Theme.of(context).primaryTextTheme.body2), + Checkbox( + value: valRememberDetails, + onChanged: (bool value) { + setState(() { + valRememberDetails = value; + }); + }, + ) + ], + ), + wsPrimaryButton(context, + title: trans(context, "USE SHIPPING ADDRESS"), + action: () { + CustomerAddress customerAddress = new CustomerAddress(); + customerAddress.firstName = _txtBillingFirstName.text; + customerAddress.lastName = _txtBillingLastName.text; + customerAddress.addressLine = _txtBillingAddressLine.text; + customerAddress.city = _txtBillingCity.text; + customerAddress.postalCode = _txtBillingPostalCode.text; + customerAddress.country = _strBillingCountry; + customerAddress.emailAddress = + _txtBillingEmailAddress.text; + + CheckoutSession.getInstance.billingDetails + .shippingAddress = customerAddress; + CheckoutSession.getInstance.billingDetails + .billingAddress = customerAddress; + + CheckoutSession.getInstance.billingDetails + .rememberDetails = valRememberDetails; + + if (valRememberDetails == true) { + CheckoutSession.getInstance.saveBillingAddress(); + } else { + CheckoutSession.getInstance.clearBillingAddress(); + } + + Navigator.pop(context); + }), + ], + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/pages/checkout_payment_type.dart b/LabelStoreMax/lib/pages/checkout_payment_type.dart new file mode 100644 index 0000000..5ae4d4e --- /dev/null +++ b/LabelStoreMax/lib/pages/checkout_payment_type.dart @@ -0,0 +1,117 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; + +class CheckoutPaymentTypePage extends StatefulWidget { + CheckoutPaymentTypePage(); + + @override + _CheckoutPaymentTypePageState createState() => + _CheckoutPaymentTypePageState(); +} + +class _CheckoutPaymentTypePageState extends State { + _CheckoutPaymentTypePageState(); + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: Colors.transparent, + title: Text(trans(context, "Payment Method"), + style: Theme.of(context).primaryTextTheme.subhead), + automaticallyImplyLeading: false, + centerTitle: true, + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: GestureDetector( + onTap: () { + FocusScope.of(context).requestFocus(new FocusNode()); + }, + child: LayoutBuilder( + builder: (context, constraints) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + child: Center( + child: Image( + image: AssetImage("assets/images/credit_cards.png"), + fit: BoxFit.fitHeight, + height: 100), + ), + padding: EdgeInsets.only(top: 20), + ), + SizedBox( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Expanded( + child: ListView.builder( + itemCount: getPaymentTypes().length, + itemBuilder: (BuildContext context, int index) { + return ListTile( + contentPadding: EdgeInsets.only( + top: 10, bottom: 10, left: 8, right: 8), + leading: Image( + image: AssetImage("assets/images/" + + getPaymentTypes()[index].assetImage), + width: 60, + fit: BoxFit.fitHeight, + alignment: Alignment.center), + title: Text(getPaymentTypes()[index].name, + style: Theme.of(context) + .primaryTextTheme + .subhead), + selected: true, + trailing: Icon(Icons.check), + onTap: () { + CheckoutSession.getInstance.paymentType = + getPaymentTypes()[index]; + Navigator.pop(context); + }, + ); + }), + ), + wsLinkButton(context, title: trans(context, "CANCEL"), + action: () { + Navigator.pop(context); + }), + ], + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: wsBoxShadow(), + ), + padding: EdgeInsets.all(8), + ), + height: (constraints.maxHeight - constraints.minHeight) * 0.5, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/pages/checkout_shipping_type.dart b/LabelStoreMax/lib/pages/checkout_shipping_type.dart new file mode 100644 index 0000000..06be3c6 --- /dev/null +++ b/LabelStoreMax/lib/pages/checkout_shipping_type.dart @@ -0,0 +1,298 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/tools.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 { + CheckoutShippingTypePage(); + + @override + _CheckoutShippingTypePageState createState() => + _CheckoutShippingTypePageState(); +} + +class _CheckoutShippingTypePageState extends State { + _CheckoutShippingTypePageState(); + + bool _isShippingSupported; + bool _isLoading; + List> _wsShippingOptions; + WSShipping _shipping; + + @override + void initState() { + super.initState(); + + _isShippingSupported = true; + _wsShippingOptions = []; + + _isLoading = true; + _getShippingMethods(); + } + + _getShippingMethods() async { + WooSignal wooSignal = await WooSignal.getInstance(config: wsConfig); + List wsShipping = await wooSignal.getShippingMethods(); + CustomerAddress customerAddress = + CheckoutSession.getInstance.billingDetails.shippingAddress; + String postalCode = customerAddress.postalCode; + String country = customerAddress.country; + String countryCode = appCountryOptions + .firstWhere((c) => c['name'] == country, orElse: () => null)["code"]; + + for (final shipping in wsShipping) { + Locations location = shipping.locations + .firstWhere((ws) => (ws.code == postalCode || ws.code == countryCode), + orElse: () { + return null; + }); + + if (location != null) { + _shipping = shipping; + break; + } + } + + if (_shipping != null) { + if (_shipping.methods.flatRate != null) { + _shipping.methods.flatRate.forEach((flatRate) { + Map tmpShippingOption = {}; + tmpShippingOption = { + "id": flatRate.id, + "title": flatRate.title, + "method_id": "flat_rate", + "cost": flatRate.cost, + "object": flatRate + }; + _wsShippingOptions.add(tmpShippingOption); + }); + } + + if (_shipping.methods.localPickup != null) { + _shipping.methods.localPickup.forEach((localPickup) { + Map tmpShippingOption = {}; + tmpShippingOption = { + "id": localPickup.id, + "method_id": "local_pickup", + "title": localPickup.title, + "cost": localPickup.cost, + "object": localPickup + }; + _wsShippingOptions.add(tmpShippingOption); + }); + } + + if (_shipping.methods.freeShipping != null) { + _shipping.methods.freeShipping.forEach((freeShipping) { + Map tmpShippingOption = {}; + tmpShippingOption = { + "id": freeShipping.id, + "method_id": "free_shipping", + "title": freeShipping.title, + "cost": freeShipping.cost, + "object": freeShipping + }; + _wsShippingOptions.add(tmpShippingOption); + }); + } + } + + if (_wsShippingOptions.length == 0) { + _isShippingSupported = false; + } + + setState(() { + _isLoading = false; + }); + } + + Future _getShippingPrice(int index) async { + double total = 0; + List cartLineItem = await Cart.getInstance.getCart(); + switch (_wsShippingOptions[index]['method_id']) { + case "flat_rate": + FlatRate flatRate = (_wsShippingOptions[index]['object'] as FlatRate); + cartLineItem.forEach((c) { + ShippingClasses shippingClasses = flatRate.shippingClasses + .firstWhere((s) => s.id == c.shippingClassId, orElse: () => null); + if (shippingClasses != null) { + total = total + double.parse(shippingClasses.cost); + } + }); + break; + default: + break; + } + return (total + double.parse(_wsShippingOptions[index]['cost'])).toString(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomPadding: false, + appBar: AppBar( + backgroundColor: Colors.transparent, + title: Text(trans(context, "Shipping Methods"), + style: Theme.of(context).primaryTextTheme.subhead), + automaticallyImplyLeading: false, + centerTitle: true, + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: GestureDetector( + onTap: () { + FocusScope.of(context).requestFocus(new FocusNode()); + }, + child: LayoutBuilder( + builder: (context, constraints) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + child: Center( + child: Image( + image: AssetImage("assets/images/shipping_icon.png"), + height: 100, + fit: BoxFit.fitHeight), + ), + padding: EdgeInsets.only(top: 20), + ), + SizedBox( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + (_isLoading + ? Expanded(child: showAppLoader()) + : (_isShippingSupported + ? Expanded( + child: ListView.separated( + itemCount: _wsShippingOptions.length, + separatorBuilder: (context, index) => + Divider( + color: Colors.black12, + ), + itemBuilder: + (BuildContext context, int index) { + return ListTile( + contentPadding: EdgeInsets.only( + left: 16, right: 16), + title: Text( + _wsShippingOptions[index] + ['title'], + style: Theme.of(context) + .primaryTextTheme + .subhead), + selected: true, + subtitle: FutureBuilder( + future: _getShippingPrice(index), + builder: (BuildContext context, + AsyncSnapshot + snapshot) { + switch ( + snapshot.connectionState) { + case ConnectionState.none: + return Text(''); + case ConnectionState.active: + case ConnectionState.waiting: + return Text(''); + case ConnectionState.done: + if (snapshot.hasError) + return Text(''); + return Text(trans( + context, "Price") + + ": " + + formatStringCurrency( + total: + snapshot.data)); + } + return null; // unreachable + }, + ), + trailing: (CheckoutSession + .getInstance + .shippingType != + null && + CheckoutSession + .getInstance + .shippingType + .object == + _wsShippingOptions[ + index]["object"] + ? Icon(Icons.check) + : null), + onTap: () async { + ShippingType shippingType = + ShippingType(); + shippingType.object = + _wsShippingOptions[index] + ['object']; + shippingType.methodId = + _wsShippingOptions[index] + ['method_id']; + shippingType.cost = + await _getShippingPrice( + index); + + CheckoutSession.getInstance + .shippingType = shippingType; + + Navigator.pop(context); + }, + ); + }), + ) + : Text( + trans(context, + "Shipping is not supported for your country, sorry"), + style: Theme.of(context) + .primaryTextTheme + .title, + textAlign: TextAlign.center))), + wsLinkButton(context, title: trans(context, "CANCEL"), + action: () { + Navigator.pop(context); + }), + ], + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: [ + BoxShadow( + color: HexColor("#e8e8e8"), + blurRadius: 15.0, + // has the effect of softening the shadow + spreadRadius: 0, + offset: Offset( + 0, + 0, + ), + ) + ], + ), + padding: EdgeInsets.all(8), + ), + height: (constraints.maxHeight - constraints.minHeight) * 0.5, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/pages/checkout_status.dart b/LabelStoreMax/lib/pages/checkout_status.dart new file mode 100644 index 0000000..4f426c8 --- /dev/null +++ b/LabelStoreMax/lib/pages/checkout_status.dart @@ -0,0 +1,175 @@ +// 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. + +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; + +class CheckoutStatusPage extends StatefulWidget { + CheckoutStatusPage(); + + @override + _CheckoutStatusState createState() => _CheckoutStatusState(); +} + +class _CheckoutStatusState extends State { + _CheckoutStatusState(); + + WS.Order _order; + + @override + void initState() { + 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), + automaticallyImplyLeading: false, + centerTitle: true, + ), + body: SafeArea( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + child: Column( + children: [ + Padding( + child: Text( + trans(context, "Order Status"), + style: Theme.of(context).primaryTextTheme.subhead, + ), + padding: EdgeInsets.only(bottom: 15), + ), + Text( + trans(context, "Thank You!"), + style: Theme.of(context).primaryTextTheme.title, + textAlign: TextAlign.left, + ), + Text( + trans(context, "Your transaction details"), + style: Theme.of(context).primaryTextTheme.body1, + textAlign: TextAlign.left, + ), + Text( + trans(context, "Order Ref") + + ". #" + + _order.id.toString(), + style: Theme.of(context).primaryTextTheme.body2, + textAlign: TextAlign.left, + ), + ], + ), + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: Border( + bottom: + BorderSide(color: Colors.black12, width: 1.0)), + ), + padding: EdgeInsets.only(bottom: 20), + ), + Container( + child: Image( + image: new AssetImage("assets/images/camion.gif"), + height: 170), + color: Colors.white, + width: double.infinity), + ], + ), + Align( + child: Padding( + child: Text( + trans(context, "Items"), + style: Theme.of(context).primaryTextTheme.subhead, + textAlign: TextAlign.left, + ), + padding: EdgeInsets.all(8), + ), + alignment: Alignment.center, + ), + Expanded( + child: new ListView.builder( + itemCount: _order.lineItems.length, + itemBuilder: (BuildContext context, int index) { + WS.LineItems lineItem = _order.lineItems[index]; + return Container( + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + Text(lineItem.name, + style: Theme.of(context) + .primaryTextTheme + .body2, + softWrap: false, + maxLines: 2, + overflow: TextOverflow.ellipsis), + Text("x" + lineItem.quantity.toString(), + style: Theme.of(context) + .primaryTextTheme + .body1), + ], + ), + ), + Text( + formatStringCurrency( + total: lineItem.total.toString()), + style: Theme.of(context).primaryTextTheme.body2) + ], + ), + decoration: BoxDecoration(color: Colors.white), + padding: EdgeInsets.all(16), + margin: EdgeInsets.all(8), + ); + }), + ), + Align( + child: MaterialButton( + child: Text(trans(context, "Back to Home")), + onPressed: () { + Navigator.pushNamed(context, "/home"); + }, + ), + alignment: Alignment.bottomCenter, + ), + ], + ), + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/pages/home.dart b/LabelStoreMax/lib/pages/home.dart new file mode 100644 index 0000000..16fe5e3 --- /dev/null +++ b/LabelStoreMax/lib/pages/home.dart @@ -0,0 +1,223 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/tools.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 { + HomePage(); + + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + _HomePageState(); + + List _products = []; + List _categories = []; + + var _productsController = ScrollController(); + + int _page; + bool _shouldStopRequests; + bool waitForNextRequest; + bool _isLoading; + + @override + void initState() { + super.initState(); + + _isLoading = true; + + _page = 1; + _shouldStopRequests = false; + waitForNextRequest = false; + + _productsController.addListener(() { + double maxScroll = _productsController.position.maxScrollExtent; + double currentScroll = _productsController.position.pixels; + double delta = 50.0; + if (maxScroll - currentScroll <= delta) { + if (_shouldStopRequests) { + return; + } + if (waitForNextRequest) { + return; + } + WooSignal.getInstance(config: wsConfig).then((wcStore) { + waitForNextRequest = true; + _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(() {}); + }); + }); + } + }); + + 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(() {}); + }); + }); + } + + void _modalBottomSheetMenu() { + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + builder: (builder) { + return new Container( + height: double.infinity, + width: double.infinity - 10, + color: Colors.transparent, + child: new Container( + padding: EdgeInsets.only(top: 25, left: 18, right: 18), + decoration: new BoxDecoration( + color: Colors.white, + borderRadius: new BorderRadius.only( + topLeft: const Radius.circular(10.0), + topRight: const Radius.circular(10.0))), + child: Column( + children: [ + Text(trans(context, "Categories"), + style: Theme.of(context).primaryTextTheme.display1, + textAlign: TextAlign.left), + Expanded( + child: new ListView.builder( + itemCount: _categories.length, + itemBuilder: (BuildContext context, int index) { + return InkWell( + child: Container( + child: Text(_categories[index].name), + padding: EdgeInsets.all(15), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: HexColor("#f2f2f2"), + width: 2))), + ), + onTap: () { + Navigator.pushNamed(context, "/browse-category", + arguments: _categories[index]); + }, + ); + })) + ], + ), + ), + ); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + leading: Container( + child: IconButton( + icon: Icon(Icons.menu), + onPressed: () { + Navigator.pushNamed(context, "/home-menu"); + }, + ), + margin: EdgeInsets.only(left: 0), + ), + title: storeLogo(height: 50), + centerTitle: true, + actions: [ + IconButton( + alignment: Alignment.centerLeft, + icon: Icon( + Icons.search, + color: Colors.black, + size: 35, + ), + onPressed: () { + Navigator.pushNamed(context, "/home-search"); + }, + ), + wsCartIcon(context) + ], + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text(trans(context, "Shop") + " / ", + style: Theme.of(context).primaryTextTheme.subhead), + Text( + trans(context, "Newest"), + style: Theme.of(context).primaryTextTheme.body1, + ) + ], + ), + MaterialButton( + minWidth: 100, + height: 60, + child: Text( + trans(context, "Browse categories"), + style: Theme.of(context).primaryTextTheme.body2, + ), + onPressed: () { + _modalBottomSheetMenu(); + }, + ) + ], + ), + (_isLoading + ? Expanded(child: showAppLoader()) + : Expanded( + child: GridView.count( + controller: _productsController, + crossAxisCount: 2, + children: List.generate(_products.length, (index) { + return wsCardProductItem(context, + index: index, product: _products[index]); + })), + flex: 1, + )), + ], + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/pages/home_menu.dart b/LabelStoreMax/lib/pages/home_menu.dart new file mode 100644 index 0000000..865cc91 --- /dev/null +++ b/LabelStoreMax/lib/pages/home_menu.dart @@ -0,0 +1,83 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/labelconfig.dart'; +import 'package:label_storemax/widgets/woosignal_ui.dart'; +import 'package:label_storemax/helpers/tools.dart'; + +class HomeMenuPage extends StatefulWidget { + HomeMenuPage(); + + @override + _HomeMenuPageState createState() => _HomeMenuPageState(); +} + +class _HomeMenuPageState extends State { + _HomeMenuPageState(); + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + elevation: 0.0, + title: Text(trans(context, "Menu"), + style: Theme.of(context).primaryTextTheme.subhead), + leading: IconButton( + icon: Icon(Icons.close), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + centerTitle: true, + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Image.network(app_logo_url, height: 100), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + wsMenuItem(context, + title: trans(context, "Cart"), + leading: Icon(Icons.shopping_cart), + action: _actionCart), + wsMenuItem(context, + title: trans(context, "About Us"), + leading: Icon(Icons.account_balance), + action: _actionAboutUs), + ], + ), + ), + ], + ), + ), + ); + } + + void _actionCart() { + Navigator.pushNamed(context, "/cart"); + } + + void _actionAboutUs() { + Navigator.pushNamed(context, "/about"); + } +} diff --git a/LabelStoreMax/lib/pages/home_search.dart b/LabelStoreMax/lib/pages/home_search.dart new file mode 100644 index 0000000..ee73298 --- /dev/null +++ b/LabelStoreMax/lib/pages/home_search.dart @@ -0,0 +1,76 @@ +// 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. + +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'; + +class HomeSearchPage extends StatefulWidget { + HomeSearchPage(); + + @override + _HomeSearchPageState createState() => _HomeSearchPageState(); +} + +class _HomeSearchPageState extends State { + _HomeSearchPageState(); + + TextEditingController _txtSearchController; + + @override + void initState() { + super.initState(); + + _txtSearchController = TextEditingController(); + } + + _actionSearch() { + Navigator.pushNamed(context, "/product-search", + arguments: _txtSearchController.text) + .then((search) { + Navigator.pop(context); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + title: Image.network(app_logo_url, + height: 60, alignment: Alignment.center), + centerTitle: true, + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + child: Icon(Icons.search, size: 36), + margin: EdgeInsets.only(bottom: 20), + ), + TextField( + controller: _txtSearchController, + style: Theme.of(context).primaryTextTheme.display2, + keyboardType: TextInputType.text, + autocorrect: false, + autofocus: true, + textCapitalization: TextCapitalization.sentences), + wsPrimaryButton(context, + title: trans(context, "Search"), action: _actionSearch) + ], + ), + ), + ); + } +} diff --git a/LabelStoreMax/lib/pages/product_detail.dart b/LabelStoreMax/lib/pages/product_detail.dart new file mode 100644 index 0000000..a0361e6 --- /dev/null +++ b/LabelStoreMax/lib/pages/product_detail.dart @@ -0,0 +1,423 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:label_storemax/labelconfig.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 _ProductDetailState extends State { + _ProductDetailState(); + + bool _isLoading; + WS.Product _product; + List _productVariations = []; + + @override + void initState() { + super.initState(); + + _isLoading = true; + } + + Map _tmpAttributeObj = {}; + + WS.ProductVariation findProductVariation() { + WS.ProductVariation tmpProductVariation; + + Map tmpSelectedObj = {}; + (_tmpAttributeObj.values).forEach((attributeObj) { + tmpSelectedObj[attributeObj["name"]] = attributeObj["value"]; + }); + + _productVariations.forEach((productVariation) { + Map tmpVariations = {}; + + productVariation.attributes.forEach((attr) { + tmpVariations[attr.name] = attr.option; + }); + + if (tmpVariations.toString() == tmpSelectedObj.toString()) { + tmpProductVariation = productVariation; + } + }); + + return tmpProductVariation; + } + + void _modalBottomSheetOptionsForAttribute(int attributeIndex) { + wsModalBottom(context, + title: trans(context, "Select a") + + " " + + _product.attributes[attributeIndex].name, + bodyWidget: Expanded( + child: ListView.separated( + itemCount: _product.attributes[attributeIndex].options.length, + separatorBuilder: (BuildContext context, int index) => Divider(), + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text(_product.attributes[attributeIndex].options[index], + style: Theme.of(context).primaryTextTheme.subhead), + trailing: (_tmpAttributeObj.isNotEmpty && + _tmpAttributeObj.containsKey(attributeIndex) && + _tmpAttributeObj[attributeIndex]["value"] == + _product.attributes[attributeIndex].options[index]) + ? Icon(Icons.check, color: Colors.blueAccent) + : null, + onTap: () { + _tmpAttributeObj[attributeIndex] = { + "name": _product.attributes[attributeIndex].name, + "value": _product.attributes[attributeIndex].options[index] + }; + Navigator.pop(context, () {}); + Navigator.pop(context); + _modalBottomSheetAttributes(); + }, + ); + }, + ), + flex: 1, + )); + } + + _itemAddToCart({CartLineItem cartLineItem}) { + Cart.getInstance.addToCart(cartLineItem: cartLineItem); + showToastWith(message: trans(context, "Added to cart"), statusType: ""); + setState(() {}); + } + + void _modalBottomSheetAttributes() { + wsModalBottom(context, + title: trans(context, "Options"), + bodyWidget: Expanded( + child: ListView.separated( + itemCount: _product.attributes.length, + separatorBuilder: (BuildContext context, int index) => Divider( + color: Colors.black12, + thickness: 1, + ), + itemBuilder: (BuildContext context, int index) { + return ListTile( + title: Text(_product.attributes[index].name, + style: Theme.of(context).primaryTextTheme.subhead), + subtitle: (_tmpAttributeObj.isNotEmpty && + _tmpAttributeObj.containsKey(index)) + ? Text(_tmpAttributeObj[index]["value"], + style: Theme.of(context).primaryTextTheme.body2) + : Text(trans(context, "Select a") + + " " + + _product.attributes[index].name), + trailing: (_tmpAttributeObj.isNotEmpty && + _tmpAttributeObj.containsKey(index)) + ? Icon(Icons.check, color: Colors.blueAccent) + : null, + onTap: () { + _modalBottomSheetOptionsForAttribute(index); + }, + ); + }, + )), + extraWidget: Container( + decoration: BoxDecoration( + border: Border(top: BorderSide(color: Colors.black12, width: 1))), + padding: EdgeInsets.only(top: 10), + child: Column( + children: [ + Text( + (findProductVariation() != null + ? trans(context, "Price") + + ": " + + formatStringCurrency( + total: findProductVariation().price) + : (((_product.attributes.length == + _tmpAttributeObj.values.length) && + findProductVariation() == null) + ? trans(context, "This variation is unavailable") + : trans(context, "Choose your options"))), + style: Theme.of(context).primaryTextTheme.subhead), + Text( + (findProductVariation() != null + ? findProductVariation().stockStatus != "instock" + ? trans(context, "Out of stock") + : "" + : ""), + style: Theme.of(context).primaryTextTheme.subhead, + ), + wsPrimaryButton(context, title: trans(context, "Add to cart"), + action: () { + if (_product.attributes.length != + _tmpAttributeObj.values.length) { + showEdgeAlertWith(context, + title: trans(context, "Oops"), + desc: trans(context, "Please select valid options first"), + style: EdgeAlertStyle.WARNING); + return; + } + + if (findProductVariation() == null) { + showEdgeAlertWith(context, + title: trans(context, "Oops"), + desc: trans(context, "Product variation does not exist"), + style: EdgeAlertStyle.WARNING); + return; + } + + if (findProductVariation() != null) { + if (findProductVariation().stockStatus != "instock") { + showEdgeAlertWith(context, + title: trans(context, "Sorry"), + desc: trans(context, "This item is not in stock"), + style: EdgeAlertStyle.WARNING); + return; + } + } + + List options = []; + _tmpAttributeObj.forEach((k, v) { + options.add(v["name"] + ": " + v["value"]); + }); + + CartLineItem cartLineItem = CartLineItem( + name: _product.name, + productId: _product.id, + variationId: findProductVariation().id, + quantity: 1, + taxStatus: findProductVariation().taxStatus, + shippingClassId: + findProductVariation().shippingClassId.toString(), + subtotal: findProductVariation().price, + stockQuantity: findProductVariation().stockQuantity, + isManagedStock: findProductVariation().manageStock, + taxClass: findProductVariation().taxClass, + imageSrc: (findProductVariation().image != null + ? findProductVariation().image.src + : _product.images.first.src), + shippingIsTaxable: _product.shippingTaxable, + variationOptions: options.join(", "), + total: findProductVariation().price); + + _itemAddToCart(cartLineItem: cartLineItem); + Navigator.of(context).pop(); + }), + ], + ), + margin: EdgeInsets.only(bottom: 10), + )); + } + + void _modalBottomSheetMenu() { + 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 + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.transparent, + actions: [wsCartIcon(context)], + title: storeLogo(height: 50), + centerTitle: true, + ), + body: SafeArea( + minimum: safeAreaDefault(), + child: _isLoading + ? showAppLoader() + : Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + flex: 3, + child: SizedBox( + child: new Swiper( + itemBuilder: (BuildContext context, int index) { + return CachedNetworkImage( + imageUrl: _product.images[index].src, + placeholder: (context, url) => + new CircularProgressIndicator( + strokeWidth: 2, + backgroundColor: Colors.black12), + errorWidget: (context, url, error) => + new Icon(Icons.error), + fit: BoxFit.contain); + }, + itemCount: _product.images.length, + viewportFraction: 0.8, + scale: 0.9, + onTap: (i) { + setState(() {}); + }, + ), + ), + ), + Padding( + padding: EdgeInsets.only(top: 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + _product.name, + style: Theme.of(context).primaryTextTheme.body2, + textAlign: TextAlign.left, + ), + flex: 4, + ), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + formatStringCurrency(total: _product.price), + style: + Theme.of(context).primaryTextTheme.subhead, + textAlign: TextAlign.right, + ), + Text( + ((_product.stockStatus != "instock" + ? trans(context, "Out of stock") + : trans(context, "In Stock"))), + style: Theme.of(context).primaryTextTheme.body1, + textAlign: TextAlign.right, + ), + ], + ), + flex: 2, + ) + ], + ), + ), + Divider( + color: Colors.black12, + thickness: 1, + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + trans(context, "Description"), + style: Theme.of(context).primaryTextTheme.body1, + textAlign: TextAlign.left, + ), + MaterialButton( + child: Text( + trans(context, "Full description"), + style: + Theme.of(context).primaryTextTheme.caption, + textAlign: TextAlign.right, + ), + height: 50, + minWidth: 60, + onPressed: () { + _modalBottomSheetMenu(); + }, + ), + ], + ), + Flexible( + child: Text( + (_product.shortDescription != null && + _product.shortDescription != "" + ? parseHtmlString(_product.shortDescription) + : parseHtmlString(_product.description)), + ), + flex: 3, + ), + ], + ), + flex: 1, + ), + wsPrimaryButton( + context, + title: trans(context, "ADD TO CART"), + action: () { + CartLineItem cartLineItem = CartLineItem( + name: _product.name, + productId: _product.id, + quantity: 1, + taxStatus: _product.taxStatus, + shippingClassId: _product.shippingClassId.toString(), + subtotal: _product.price, + taxClass: _product.taxClass, + isManagedStock: _product.manageStock, + stockQuantity: _product.stockQuantity, + shippingIsTaxable: _product.shippingTaxable, + imageSrc: _product.images.first.src, + total: _product.price); + + if (_product.type != "simple") { + _modalBottomSheetAttributes(); + return; + } + if (_product.stockStatus == "instock") { + _itemAddToCart(cartLineItem: cartLineItem); + } else { + showEdgeAlertWith(context, + title: trans(context, "Sorry"), + desc: trans(context, "This item is out of stock"), + style: EdgeAlertStyle.WARNING, + icon: Icons.local_shipping); + } + }, + ), + ], + ), + ), + ); + } +} + +class ProductDetailPage extends StatefulWidget { + ProductDetailPage(); + + @override + _ProductDetailState createState() => _ProductDetailState(); +} diff --git a/LabelStoreMax/lib/widgets/woosignal_ui.dart b/LabelStoreMax/lib/widgets/woosignal_ui.dart new file mode 100644 index 0000000..ac47a0b --- /dev/null +++ b/LabelStoreMax/lib/widgets/woosignal_ui.dart @@ -0,0 +1,593 @@ +// 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. + +import 'package:flutter/material.dart'; +import 'package:label_storemax/labelconfig.dart'; +import 'package:woosignal/models/response/products.dart'; +import 'package:label_storemax/helpers/tools.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:woosignal/models/response/tax_rate.dart'; + +const appFontFamily = "Overpass"; + +Widget wsCartIcon(BuildContext context) { + return IconButton( + icon: Stack( + children: [ + 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>( + future: Cart.getInstance.getCart(), + builder: (BuildContext context, + AsyncSnapshot> 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: [ + 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, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Container( + child: Text(text1, style: Theme.of(context).textTheme.title), + ), + flex: 3, + ), + Flexible( + child: Container( + child: Text(text2, style: Theme.of(context).primaryTextTheme.body2), + ), + flex: 3, + ) + ], + ); +} + +Widget wsNoResults(BuildContext context) { + return Column( + children: [ + Text(trans(context, "No results"), + style: Theme.of(context).primaryTextTheme.body1), + ], + ); +} + +Widget wsCheckoutRow(BuildContext context, + {heading: String, + Widget leadImage, + String leadTitle, + void Function() action, + bool showBorderBottom}) { + return Flexible( + child: InkWell( + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + child: Text(heading, + style: Theme.of(context).primaryTextTheme.body1), + padding: EdgeInsets.only(bottom: 8), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + leadImage, + Container( + child: Text(leadTitle, + style: Theme.of(context).primaryTextTheme.subhead, + maxLines: 2, + overflow: TextOverflow.ellipsis, + softWrap: false), + padding: EdgeInsets.only(left: 15), + ) + ], + ), + Icon(Icons.arrow_forward_ios) + ], + ) + ], + ), + padding: EdgeInsets.all(8), + decoration: showBorderBottom == true + ? BoxDecoration( + border: Border( + bottom: BorderSide(color: Colors.black12, width: 1))) + : BoxDecoration()), + onTap: action, + borderRadius: BorderRadius.circular(8), + ), + flex: 3, + ); +} + +Widget wsTextEditingRow(BuildContext context, + {heading: String, + TextEditingController controller, + bool shouldAutoFocus, + TextInputType keyboardType}) { + return Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + child: Text(heading, style: Theme.of(context).primaryTextTheme.body2), + padding: EdgeInsets.only(bottom: 2), + ), + TextField( + controller: controller, + style: Theme.of(context).primaryTextTheme.subhead, + keyboardType: keyboardType ?? TextInputType.text, + autocorrect: false, + autofocus: shouldAutoFocus ?? false, + textCapitalization: TextCapitalization.sentences) + ], + ), + padding: EdgeInsets.all(2), + height: 78, + ); +} + +Widget widgetCheckoutMeta(BuildContext context, {String title, String amount}) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Container( + child: Text(title, style: Theme.of(context).primaryTextTheme.body1), + ), + flex: 3, + ), + Flexible( + child: Container( + child: Text(amount, style: Theme.of(context).primaryTextTheme.body2), + ), + flex: 3, + ) + ], + ); +} + +List wsBoxShadow({double blurRadius}) { + return [ + BoxShadow( + color: HexColor("#e8e8e8"), + blurRadius: blurRadius ?? 15.0, + spreadRadius: 0, + offset: Offset( + 0, + 0, + ), + ) + ]; +} + +Widget wsCardProductItem(BuildContext context, {int index, Product product}) { + return InkWell( + child: Container( + padding: EdgeInsets.all(10), + margin: EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, borderRadius: BorderRadius.circular(5)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Flexible( + child: CachedNetworkImage( + imageUrl: (product.images.length > 0 + ? product.images.first.src + : ""), + placeholder: (context, url) => + new CircularProgressIndicator(), + errorWidget: (context, url, error) => new Icon(Icons.error), + fit: BoxFit.fitWidth), + flex: 4, + ), + Flexible( + child: Text( + formatStringCurrency(total: product.price), + style: Theme.of(context).textTheme.body2, + textAlign: TextAlign.left, + ), + flex: 1, + ), + Expanded( + child: Text( + product.name, + style: Theme.of(context).textTheme.body1, + ), + flex: 1, + ) + ], + )), + onTap: () { + Navigator.pushNamed(context, "/product-detail", arguments: product); + }, + ); +} + +void wsModalBottom(BuildContext context, + {String title, Widget bodyWidget, Widget extraWidget}) { + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + builder: (builder) { + return SafeArea( + child: Container( + height: double.infinity, + width: double.infinity - 10, + color: Colors.transparent, + child: new Container( + padding: EdgeInsets.only(top: 25, left: 18, right: 18), + decoration: new BoxDecoration( + color: Colors.white, + borderRadius: new BorderRadius.only( + topLeft: const Radius.circular(10.0), + topRight: const Radius.circular(10.0))), + child: Column( + children: [ + Text(title, + style: Theme.of(context).primaryTextTheme.display1, + textAlign: TextAlign.left), + bodyWidget, + extraWidget ?? Container() + ], + )), + ), + ); + }); +} + +FutureBuilder getTotalWidget() { + return FutureBuilder( + future: Cart.getInstance.getTotal(withFormat: true), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.waiting: + return showAppLoader(); + default: + if (snapshot.hasError) + return Text(""); + else + return new Padding( + child: wsRow2Text(context, + text1: trans(context, "Total"), text2: snapshot.data), + padding: EdgeInsets.only(bottom: 15, top: 15), + ); + } + }, + ); +} + +FutureBuilder wsCheckoutTotalWidgetFB({String title, TaxRate taxRate}) { + return FutureBuilder( + future: + CheckoutSession.getInstance.total(withFormat: true, taxRate: taxRate), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.waiting: + return showAppLoader(); + default: + if (snapshot.hasError) + return Text(""); + else + return new Padding( + child: widgetCheckoutMeta(context, + title: title, amount: snapshot.data), + padding: EdgeInsets.only(bottom: 0, top: 15), + ); + } + }, + ); +} + +FutureBuilder wsCheckoutTaxAmountWidgetFB({TaxRate taxRate}) { + return FutureBuilder( + future: Cart.getInstance.taxAmount(taxRate), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.waiting: + return showAppLoader(); + default: + if (snapshot.hasError) + return Text(""); + else + return (snapshot.data == "0" + ? Container() + : Padding( + child: widgetCheckoutMeta( + context, + title: trans(context, "Tax"), + amount: formatStringCurrency(total: snapshot.data), + ), + padding: EdgeInsets.only(bottom: 0, top: 0), + )); + } + }, + ); +} + +FutureBuilder wsCheckoutSubtotalWidgetFB({String title}) { + return FutureBuilder( + future: Cart.getInstance.getSubtotal(withFormat: true), + builder: (BuildContext context, AsyncSnapshot snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.waiting: + return showAppLoader(); + default: + if (snapshot.hasError) + return Text(""); + else + return new Padding( + child: widgetCheckoutMeta(context, + title: title, amount: snapshot.data), + padding: EdgeInsets.only(bottom: 0, top: 0), + ); + } + }, + ); +} + +FutureBuilder wsWidgetCartItemsFB( + {void Function() actionIncrementQuantity, + void Function() actionDecrementQuantity, + void Function() actionRemoveItem}) { + return FutureBuilder>( + future: Cart.getInstance.getCart(), + builder: + (BuildContext context, AsyncSnapshot> snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.waiting: + return showAppLoader(); + default: + if (snapshot.hasError) + return Text(""); + else + return ListView.builder( + padding: const EdgeInsets.all(8), + itemCount: snapshot.data.length, + itemBuilder: (BuildContext context, int index) { + CartLineItem cartLineItem = snapshot.data[index]; + return wsCardCartItem(context, + cartLineItem: cartLineItem, + actionIncrementQuantity: actionIncrementQuantity, + actionDecrementQuantity: actionDecrementQuantity, + actionRemoveItem: actionRemoveItem); + }); + } + }, + ); +} + +Widget wsCardCartItem(BuildContext context, + {CartLineItem cartLineItem, + void Function() actionIncrementQuantity, + void Function() actionDecrementQuantity, + void Function() actionRemoveItem}) { + return Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.black12, + width: 1, + ))), + padding: EdgeInsets.all(8), + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: CachedNetworkImage( + imageUrl: cartLineItem.imageSrc, + width: 100, + height: 100, + fit: BoxFit.contain, + ), + flex: 2, + ), + Flexible( + child: Padding( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(cartLineItem.name, + style: Theme.of(context).primaryTextTheme.subhead), + (cartLineItem.variationOptions != null + ? Text(cartLineItem.variationOptions, + style: Theme.of(context).primaryTextTheme.body2) + : Container()), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + (cartLineItem.stockStatus == "outofstock" + ? trans(context, "Out of stock") + : trans(context, "In Stock")), + style: (cartLineItem.stockStatus == "outofstock" + ? Theme.of(context).textTheme.caption + : Theme.of(context).primaryTextTheme.body1)), + Text( + formatDoubleCurrency( + total: double.parse(cartLineItem.total)), + style: Theme.of(context).primaryTextTheme.subhead, + textAlign: TextAlign.center) + ], + ), + ], + ), + padding: EdgeInsets.only(left: 8), + ), + flex: 5, + ) + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + icon: Icon(Icons.add_circle_outline), + onPressed: actionIncrementQuantity, + highlightColor: Colors.transparent, + ), + Text(cartLineItem.quantity.toString(), + style: Theme.of(context).primaryTextTheme.title), + IconButton( + icon: Icon(Icons.remove_circle_outline), + onPressed: actionDecrementQuantity, + highlightColor: Colors.transparent, + ), + ], + ), + IconButton( + alignment: Alignment.centerRight, + icon: Icon(Icons.delete_outline, + color: Colors.deepOrangeAccent, size: 20), + onPressed: actionRemoveItem, + highlightColor: Colors.transparent, + ), + ], + ) + ], + )); +} + +Widget storeLogo({double height}) { + return cachedImage(app_logo_url, + height: height, placeholder: Container(height: height, width: height)); +} + +Widget cachedImage(image, {double height, Widget placeholder, BoxFit fit}) { + return CachedNetworkImage( + imageUrl: image, + placeholder: (context, url) => + placeholder ?? new CircularProgressIndicator(), + errorWidget: (context, url, error) => new Icon(Icons.error), + height: height ?? null, + width: null, + alignment: Alignment.center, + fit: fit); +} diff --git a/LabelStoreMax/pubspec.lock b/LabelStoreMax/pubspec.lock new file mode 100644 index 0000000..26758c6 --- /dev/null +++ b/LabelStoreMax/pubspec.lock @@ -0,0 +1,425 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.10" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.2" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + 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: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" + device_info: + dependency: transitive + description: + name: device_info + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.1+1" + dio: + dependency: "direct main" + description: + name: dio + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.4" + edge_alert: + dependency: "direct main" + description: + name: edge_alert + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + flutter_launcher_icons: + dependency: "direct main" + description: + name: flutter_launcher_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.3" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_money_formatter: + dependency: "direct main" + description: + name: flutter_money_formatter + url: "https://pub.dartlang.org" + source: hosted + version: "0.8.3" + flutter_page_indicator: + dependency: transitive + description: + name: flutter_page_indicator + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.3" + flutter_spinkit: + dependency: "direct main" + description: + name: flutter_spinkit + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + flutter_swiper: + dependency: "direct main" + description: + name: flutter_swiper + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_browser: + dependency: "direct main" + description: + name: flutter_web_browser + url: "https://pub.dartlang.org" + source: hosted + version: "0.11.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.3" + html: + dependency: "direct main" + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.14.0+3" + http: + dependency: transitive + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.0+2" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.3" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" + intl: + dependency: transitive + 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" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.7" + package_info: + dependency: "direct main" + description: + name: package_info + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.0+6" + page_transition: + dependency: "direct main" + description: + name: page_transition + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.4" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.4" + path_provider: + dependency: transitive + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + pedantic: + dependency: transitive + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.0+1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" + platform: + dependency: transitive + description: + name: platform + 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: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.4+3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.5" + sqflite: + dependency: transitive + description: + name: sqflite + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6+5" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.9.3" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0+1" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.5" + transformer_page_view: + dependency: transitive + description: + name: transformer_page_view + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.6" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.6" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + woosignal: + dependency: "direct main" + description: + name: woosignal + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" + woosignal_stripe: + dependency: "direct main" + description: + name: woosignal_stripe + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.2" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "3.5.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" +sdks: + dart: ">2.4.0 <3.0.0" + flutter: ">=1.6.7 <2.0.0" diff --git a/LabelStoreMax/pubspec.yaml b/LabelStoreMax/pubspec.yaml new file mode 100644 index 0000000..dca9736 --- /dev/null +++ b/LabelStoreMax/pubspec.yaml @@ -0,0 +1,89 @@ +# Label StoreMax +# Version 1.0 +#authors: - "Anthony Gordon" +#documentation: https://woosignal.com/docs/app/ios/label-storemax +#homepage: https://woosignal.com/ + +### App Config +# 1 Open: "lib/labelconfig.dart" + +### Change App Icon +# 1 Open: assets/icon/appicon.png (line 53) replace icon (1024px1024px icon size) +# 2 Run this command from Terminal: flutter pub run flutter_launcher_icons:main + +### Submitting the IOS/Android app +# 1 Open our online documentation: https://woosignal.com/docs/app/ios/label-storemax + +name: label_storemax +description: LabelStoreMAX + +version: 1.0.0+1 + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + woosignal: ^1.0.2 + woosignal_stripe: ^0.0.2 + connectivity: ^0.4.4 + shared_preferences: ^0.5.3+4 + cached_network_image: ^1.1.1 + page_transition: ^1.1.4 + package_info: ^0.4.0+6 + flutter_money_formatter: ^0.8.2 + flutter_web_browser: ^0.11.0 + dio: ^3.0.2 + 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 + html: ^0.14.0+3 + flutter: + sdk: flutter + + flutter_localizations: + sdk: flutter + + cupertino_icons: ^0.1.2 + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter_icons: + android: "launcher_icon" + ios: true + image_path: "assets/icon/appicon.png" + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + - assets/images/camion.gif + - assets/images/credit_cards.png + - assets/images/shipping_icon.png + - assets/images/dark_powered_by_stripe.png + - assets/images/cart_empty.png + - lang/en.json + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + fonts: + - family: Overpass + fonts: + - asset: assets/fonts/Overpass/Overpass-Regular.ttf diff --git a/LabelStoreMax/test/widget_test.dart b/LabelStoreMax/test/widget_test.dart new file mode 100644 index 0000000..355d110 --- /dev/null +++ b/LabelStoreMax/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:label_storemax/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MaterialApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..054e8fc --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +

+ Woosignal logo +

+ +# Woocommerce App: Label StoreMax +### Label StoreMax - v1.0 + +![alt text](https://woosignal.com/images/woosignal_labelstoremax_main_banner_flutter.png "WooCommerce app WooSignal Flutter logo") + +### About Label StoreMax + +Label StoreMax is a WooCommerce Flutter App template, built exclusively for online shopping and it offers a great variety of options to customise the look and feel of the App. Label StoreMax supports product views, multi-variation products, category searches + more. + +1. Supports the latest WooCommerce (3.0+) +2. [Documentation available](https://woosignal.com/docs/app/ios/label-storemax) + +![alt text](https://woosignal.com/images/label_storemax_demo.gif "Flutter WooCommerce App") + +## Some featured integrated + +1. Stripe +2. App Store Ready +3. One config file + +## Security Vulnerabilities +If you discover a security vulnerability within WooSignal, please send an e-mail support@woosignal.com + +## Licence +The Label StoreMax framework is open-sourced software licensed under the MIT license.