├── .flutter-plugins-dependencies
├── .gitignore
├── .metadata
├── README.md
├── android
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── shahanaj
│ │ │ │ └── woocommerce_app
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable
│ │ │ ├── launch_background.xml
│ │ │ └── woocom_icon.jpg
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── key.properties
├── settings.gradle
└── woocommerce.jks
├── images
├── cover_photo.jpg
└── woocom_icon.jpg
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ └── contents.xcworkspacedata
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── bloc
│ ├── cart_page_bloc.dart
│ ├── customer_add_bloc.dart
│ ├── customer_list_bloc.dart
│ ├── home_page_bloc.dart
│ ├── order_list_bloc.dart
│ └── place_order_bloc.dart
├── helper
│ ├── const.dart
│ ├── hex_color.dart
│ ├── query_string.dart
│ ├── ui_helper.dart
│ ├── util.dart
│ └── woocommerce_api.dart
├── main.dart
├── model
│ └── ordered_product.dart
└── screen
│ ├── cart_page.dart
│ ├── customer_add.dart
│ ├── cutomer_list_page.dart
│ ├── home_page.dart
│ ├── my_profile_page.dart
│ ├── order_list_page.dart
│ ├── place_order_page.dart
│ └── splash_screen_page.dart
├── pubspec.lock
├── pubspec.yaml
└── test
└── widget_test.dart
/.flutter-plugins-dependencies:
--------------------------------------------------------------------------------
1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"fluttertoast","path":"C:\\\\Users\\\\Asus\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\fluttertoast-3.1.3\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"fluttertoast","path":"C:\\\\Users\\\\Asus\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\fluttertoast-3.1.3\\\\","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"fluttertoast","dependencies":[]}],"date_created":"2023-07-31 22:50:40.426469","version":"3.3.4"}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | .dart_tool/
26 | .flutter-plugins
27 | .packages
28 | .pub-cache/
29 | .pub/
30 | /build/
31 |
32 | # Android related
33 | **/android/**/gradle-wrapper.jar
34 | **/android/.gradle
35 | **/android/captures/
36 | **/android/gradlew
37 | **/android/gradlew.bat
38 | **/android/local.properties
39 | **/android/**/GeneratedPluginRegistrant.java
40 |
41 | # iOS/XCode related
42 | **/ios/**/*.mode1v3
43 | **/ios/**/*.mode2v3
44 | **/ios/**/*.moved-aside
45 | **/ios/**/*.pbxuser
46 | **/ios/**/*.perspectivev3
47 | **/ios/**/*sync/
48 | **/ios/**/.sconsign.dblite
49 | **/ios/**/.tags*
50 | **/ios/**/.vagrant/
51 | **/ios/**/DerivedData/
52 | **/ios/**/Icon?
53 | **/ios/**/Pods/
54 | **/ios/**/.symlinks/
55 | **/ios/**/profile
56 | **/ios/**/xcuserdata
57 | **/ios/.generated/
58 | **/ios/Flutter/App.framework
59 | **/ios/Flutter/Flutter.framework
60 | **/ios/Flutter/Generated.xcconfig
61 | **/ios/Flutter/app.flx
62 | **/ios/Flutter/app.zip
63 | **/ios/Flutter/flutter_assets/
64 | **/ios/Flutter/flutter_export_environment.sh
65 | **/ios/ServiceDefinitions.json
66 | **/ios/Runner/GeneratedPluginRegistrant.*
67 |
68 | # Exceptions to above rules.
69 | !**/ios/**/default.mode1v3
70 | !**/ios/**/default.mode2v3
71 | !**/ios/**/default.pbxuser
72 | !**/ios/**/default.perspectivev3
73 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
74 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 2d2a1ffec95cc70a3218872a2cd3f8de4933c42f
8 | channel: beta
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | WooCommerce Flutter App
4 |
5 |
6 |
7 | Flutter WooCommerce App: A sleek e-commerce mobile app integrated with WooCommerce API. Built on Flutter using Bloc pattern for state management, it enables seamless browsing of products, viewing details, and smooth checkout. Delivering a modern shopping experience, it empowers users to shop effortlessly on your WooCommerce store.
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Overview
18 |
19 |
20 | This app demonstrates how to build a cross-platform mobile application using Flutter to interact with the WooCommerce API and manage state with the Bloc pattern. It allows users to browse products, add them to the cart, and make purchases through the WooCommerce online store.
21 |
22 |
23 | Features
24 |
25 |
26 | - Product listing: Display a list of products fetched from the WooCommerce API.
27 | - Product details: Show detailed information about a selected product.
28 | - Add to cart: Allow users to add products to their shopping cart.
29 | - Cart management: Users can view and modify the contents of their shopping cart.
30 | - Checkout: Provide a seamless checkout experience using the WooCommerce API.
31 |
32 |
33 | Installation
34 |
35 |
36 | Follow these steps to set up the project:
37 |
38 |
39 |
40 | - Clone the repository to your local machine.
41 |
42 | git clone https://github.com/your-username/woocommerce-flutter-app.git
43 |
44 | - Open the project in your preferred Flutter development environment (Android Studio, VS Code, etc.).
45 |
46 | - Install the dependencies by running:
47 |
48 | flutter pub get
49 |
50 | - Create a new file named
config.dart
in the lib
folder to store your WooCommerce API credentials:
51 |
52 | // lib/config.dart
53 |
54 | const String baseUrl = 'https://your-woocommerce-store-url.com/wp-json/wc/v3/';
55 | const String consumerKey = 'YOUR_CONSUMER_KEY';
56 | const String consumerSecret = 'YOUR_CONSUMER_SECRET';
57 |
58 | Replace YOUR_CONSUMER_KEY
and YOUR_CONSUMER_SECRET
with your actual WooCommerce API credentials. You can obtain these credentials from your WooCommerce store's admin panel.
59 |
60 |
61 | How to Use
62 |
63 |
64 | This app follows the Bloc pattern for state management, which separates the business logic from the UI. The app's main components are organized as follows:
65 |
66 |
67 |
68 | - Models: Contains the data models used in the app, such as
Product
, CartItem
, etc.
69 | - Providers: Contains the
ProductProvider
and CartProvider
classes responsible for handling API calls and managing state related to products and the shopping cart.
70 | - Blocs: Contains the
ProductBloc
and CartBloc
classes that handle the business logic and interact with the providers.
71 | - Screens: Contains the different screens of the app, such as the product listing screen, product details screen, and cart screen.
72 | - Widgets: Contains various reusable widgets used throughout the app.
73 |
74 |
75 |
76 | Please refer to the code and documentation in each file to understand how the different components work together.
77 |
78 |
79 | Contributing
80 |
81 |
82 | Contributions to this project are welcome! Feel free to open issues for bugs or feature requests. If you'd like to contribute code, please fork the repository and create a pull request.
83 |
84 |
85 | License
86 |
87 |
88 | This project is licensed under the MIT License.
89 |
90 |
91 | Acknowledgments
92 |
93 |
94 | Thanks to the WooCommerce team for providing a powerful API to build e-commerce applications.
95 | The architecture and patterns used in this app are inspired by various open-source projects and online resources.
96 |
97 |
98 | Contact
99 |
100 |
101 | If you have any questions or need assistance, feel free to contact the project owner at your-email@example.com.
102 |
103 |
104 |
105 |

106 |
107 |
108 | Screenshots
109 |
110 |
111 |

112 |

113 |
114 |
115 |
116 | Tech Stack
117 |
118 |
119 | - Flutter
120 | - REST API
121 | - Bloc pattern
122 |
123 |
124 | Resources
125 |
126 |
127 | Here are some useful resources to get started with Flutter, REST API, and Bloc:
128 |
129 |
130 |
135 |
136 | How to Contribute
137 |
138 |
139 | We welcome contributions from the community! If you'd like to contribute to this project, please follow these steps:
140 |
141 |
142 |
143 | - Fork the repository on GitHub.
144 | - Create a new branch from the
main
branch.
145 | - Make your changes and commit them.
146 | - Push your changes to your forked repository.
147 | - Submit a pull request to the
main
branch of this repository.
148 |
149 |
150 | License
151 |
152 |
153 | This project is licensed under the MIT License - see the LICENSE file for details.
154 |
155 |
156 | Contact
157 |
158 |
159 | For any inquiries or questions, you can reach us at putulcse9@example.com.
160 |
161 |
162 |
163 |
Powered by Flutter
164 |
Made with ❤️ by [Your Name]
165 |
166 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 |
29 | def keystoreProperties = new Properties()
30 | def keystorePropertiesFile = rootProject.file('key.properties')
31 | if (keystorePropertiesFile.exists()) {
32 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
33 | }
34 |
35 | android {
36 | compileSdkVersion 28
37 |
38 | sourceSets {
39 | main.java.srcDirs += 'src/main/kotlin'
40 | }
41 |
42 | lintOptions {
43 | disable 'InvalidPackage'
44 | }
45 |
46 | defaultConfig {
47 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
48 | applicationId "com.shahanaj.woocommerce_app"
49 | minSdkVersion 16
50 | targetSdkVersion 28
51 | versionCode flutterVersionCode.toInteger()
52 | versionName flutterVersionName
53 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
54 | }
55 |
56 |
57 | signingConfigs {
58 | release {
59 | keyAlias keystoreProperties['keyAlias']
60 | keyPassword keystoreProperties['keyPassword']
61 | storeFile file(keystoreProperties['storeFile'])
62 | storePassword keystoreProperties['storePassword']
63 | }
64 | }
65 | buildTypes {
66 | release {
67 | signingConfig signingConfigs.release
68 | //minifyEnabled false
69 | //useProguard true
70 |
71 | // proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
72 | }
73 | }
74 |
75 | /* buildTypes {
76 | release {
77 | // TODO: Add your own signing config for the release build.
78 | // Signing with the debug keys for now, so `flutter run --release` works.
79 | signingConfig signingConfigs.debug
80 | }
81 | }*/
82 | }
83 |
84 | flutter {
85 | source '../..'
86 | }
87 |
88 | dependencies {
89 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
90 | testImplementation 'junit:junit:4.12'
91 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
92 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
93 | }
94 |
95 |
96 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
11 |
15 |
22 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/shahanaj/woocommerce_app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.shahanaj.woocommerce_app
2 |
3 | import android.os.Bundle
4 |
5 | import io.flutter.app.FlutterActivity
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity: FlutterActivity() {
9 | override fun onCreate(savedInstanceState: Bundle?) {
10 | super.onCreate(savedInstanceState)
11 | GeneratedPluginRegistrant.registerWith(this)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/woocom_icon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/android/app/src/main/res/drawable/woocom_icon.jpg
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.2.71'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.2.1'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
5 |
6 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
7 |
--------------------------------------------------------------------------------
/android/key.properties:
--------------------------------------------------------------------------------
1 | storePassword=putulputul
2 | keyPassword=putulputul
3 | keyAlias=woocommerce
4 | storeFile=/Users/prismerp/Documents/code/FlutterApp/woocommerce_app/android/woocommerce.jks
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/android/woocommerce.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/android/woocommerce.jks
--------------------------------------------------------------------------------
/images/cover_photo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/images/cover_photo.jpg
--------------------------------------------------------------------------------
/images/woocom_icon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/images/woocom_icon.jpg
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # 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.
2 | # source 'https://cdn.cocoapods.org/'
3 |
4 | # Uncomment this line to define a global platform for your project
5 | # platform :ios, '9.0'
6 |
7 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
8 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
9 |
10 | project 'Runner', {
11 | 'Debug' => :debug,
12 | 'Profile' => :release,
13 | 'Release' => :release,
14 | }
15 |
16 | def parse_KV_file(file, separator='=')
17 | file_abs_path = File.expand_path(file)
18 | if !File.exists? file_abs_path
19 | return [];
20 | end
21 | pods_ary = []
22 | skip_line_start_symbols = ["#", "/"]
23 | File.foreach(file_abs_path) { |line|
24 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
25 | plugin = line.split(pattern=separator)
26 | if plugin.length == 2
27 | podname = plugin[0].strip()
28 | path = plugin[1].strip()
29 | podpath = File.expand_path("#{path}", file_abs_path)
30 | pods_ary.push({:name => podname, :path => podpath});
31 | else
32 | puts "Invalid plugin specification: #{line}"
33 | end
34 | }
35 | return pods_ary
36 | end
37 |
38 | target 'Runner' do
39 | use_frameworks!
40 |
41 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
42 | # referring to absolute paths on developers' machines.
43 | system('rm -rf .symlinks')
44 | system('mkdir -p .symlinks/plugins')
45 |
46 | # Flutter Pods
47 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
48 | if generated_xcode_build_settings.empty?
49 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first."
50 | end
51 | generated_xcode_build_settings.map { |p|
52 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
53 | symlink = File.join('.symlinks', 'flutter')
54 | File.symlink(File.dirname(p[:path]), symlink)
55 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
56 | end
57 | }
58 |
59 | # Plugin Pods
60 | plugin_pods = parse_KV_file('../.flutter-plugins')
61 | plugin_pods.map { |p|
62 | symlink = File.join('.symlinks', 'plugins', p[:name])
63 | File.symlink(p[:path], symlink)
64 | pod p[:name], :path => File.join(symlink, 'ios')
65 | }
66 | end
67 |
68 | # Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
69 | install! 'cocoapods', :disable_input_output_paths => true
70 |
71 | post_install do |installer|
72 | installer.pods_project.targets.each do |target|
73 | target.build_configurations.each do |config|
74 | config.build_settings['ENABLE_BITCODE'] = 'NO'
75 | end
76 | end
77 | end
78 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
14 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
15 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
16 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
17 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
18 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
19 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
20 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
21 | /* End PBXBuildFile section */
22 |
23 | /* Begin PBXCopyFilesBuildPhase section */
24 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
25 | isa = PBXCopyFilesBuildPhase;
26 | buildActionMask = 2147483647;
27 | dstPath = "";
28 | dstSubfolderSpec = 10;
29 | files = (
30 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
31 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
32 | );
33 | name = "Embed Frameworks";
34 | runOnlyForDeploymentPostprocessing = 0;
35 | };
36 | /* End PBXCopyFilesBuildPhase section */
37 |
38 | /* Begin PBXFileReference section */
39 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
40 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
41 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
42 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; };
43 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
44 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
45 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
46 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
47 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
48 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; };
49 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
50 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
51 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
52 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
53 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
54 | /* End PBXFileReference section */
55 |
56 | /* Begin PBXFrameworksBuildPhase section */
57 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
58 | isa = PBXFrameworksBuildPhase;
59 | buildActionMask = 2147483647;
60 | files = (
61 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
62 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
63 | );
64 | runOnlyForDeploymentPostprocessing = 0;
65 | };
66 | /* End PBXFrameworksBuildPhase section */
67 |
68 | /* Begin PBXGroup section */
69 | 9740EEB11CF90186004384FC /* Flutter */ = {
70 | isa = PBXGroup;
71 | children = (
72 | 3B80C3931E831B6300D905FE /* App.framework */,
73 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
74 | 9740EEBA1CF902C7004384FC /* Flutter.framework */,
75 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
76 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
77 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
78 | );
79 | name = Flutter;
80 | sourceTree = "";
81 | };
82 | 97C146E51CF9000F007C117D = {
83 | isa = PBXGroup;
84 | children = (
85 | 9740EEB11CF90186004384FC /* Flutter */,
86 | 97C146F01CF9000F007C117D /* Runner */,
87 | 97C146EF1CF9000F007C117D /* Products */,
88 | );
89 | sourceTree = "";
90 | };
91 | 97C146EF1CF9000F007C117D /* Products */ = {
92 | isa = PBXGroup;
93 | children = (
94 | 97C146EE1CF9000F007C117D /* Runner.app */,
95 | );
96 | name = Products;
97 | sourceTree = "";
98 | };
99 | 97C146F01CF9000F007C117D /* Runner */ = {
100 | isa = PBXGroup;
101 | children = (
102 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
103 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
104 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
105 | 97C147021CF9000F007C117D /* Info.plist */,
106 | 97C146F11CF9000F007C117D /* Supporting Files */,
107 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
108 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
109 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
110 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
111 | );
112 | path = Runner;
113 | sourceTree = "";
114 | };
115 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
116 | isa = PBXGroup;
117 | children = (
118 | );
119 | name = "Supporting Files";
120 | sourceTree = "";
121 | };
122 | /* End PBXGroup section */
123 |
124 | /* Begin PBXNativeTarget section */
125 | 97C146ED1CF9000F007C117D /* Runner */ = {
126 | isa = PBXNativeTarget;
127 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
128 | buildPhases = (
129 | 9740EEB61CF901F6004384FC /* Run Script */,
130 | 97C146EA1CF9000F007C117D /* Sources */,
131 | 97C146EB1CF9000F007C117D /* Frameworks */,
132 | 97C146EC1CF9000F007C117D /* Resources */,
133 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
134 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
135 | );
136 | buildRules = (
137 | );
138 | dependencies = (
139 | );
140 | name = Runner;
141 | productName = Runner;
142 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
143 | productType = "com.apple.product-type.application";
144 | };
145 | /* End PBXNativeTarget section */
146 |
147 | /* Begin PBXProject section */
148 | 97C146E61CF9000F007C117D /* Project object */ = {
149 | isa = PBXProject;
150 | attributes = {
151 | LastUpgradeCheck = 1020;
152 | ORGANIZATIONNAME = "The Chromium Authors";
153 | TargetAttributes = {
154 | 97C146ED1CF9000F007C117D = {
155 | CreatedOnToolsVersion = 7.3.1;
156 | LastSwiftMigration = 0910;
157 | };
158 | };
159 | };
160 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
161 | compatibilityVersion = "Xcode 3.2";
162 | developmentRegion = en;
163 | hasScannedForEncodings = 0;
164 | knownRegions = (
165 | en,
166 | Base,
167 | );
168 | mainGroup = 97C146E51CF9000F007C117D;
169 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
170 | projectDirPath = "";
171 | projectRoot = "";
172 | targets = (
173 | 97C146ED1CF9000F007C117D /* Runner */,
174 | );
175 | };
176 | /* End PBXProject section */
177 |
178 | /* Begin PBXResourcesBuildPhase section */
179 | 97C146EC1CF9000F007C117D /* Resources */ = {
180 | isa = PBXResourcesBuildPhase;
181 | buildActionMask = 2147483647;
182 | files = (
183 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
184 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
185 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
186 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
187 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
188 | );
189 | runOnlyForDeploymentPostprocessing = 0;
190 | };
191 | /* End PBXResourcesBuildPhase section */
192 |
193 | /* Begin PBXShellScriptBuildPhase section */
194 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
195 | isa = PBXShellScriptBuildPhase;
196 | buildActionMask = 2147483647;
197 | files = (
198 | );
199 | inputPaths = (
200 | );
201 | name = "Thin Binary";
202 | outputPaths = (
203 | );
204 | runOnlyForDeploymentPostprocessing = 0;
205 | shellPath = /bin/sh;
206 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
207 | };
208 | 9740EEB61CF901F6004384FC /* Run Script */ = {
209 | isa = PBXShellScriptBuildPhase;
210 | buildActionMask = 2147483647;
211 | files = (
212 | );
213 | inputPaths = (
214 | );
215 | name = "Run Script";
216 | outputPaths = (
217 | );
218 | runOnlyForDeploymentPostprocessing = 0;
219 | shellPath = /bin/sh;
220 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
221 | };
222 | /* End PBXShellScriptBuildPhase section */
223 |
224 | /* Begin PBXSourcesBuildPhase section */
225 | 97C146EA1CF9000F007C117D /* Sources */ = {
226 | isa = PBXSourcesBuildPhase;
227 | buildActionMask = 2147483647;
228 | files = (
229 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
230 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
231 | );
232 | runOnlyForDeploymentPostprocessing = 0;
233 | };
234 | /* End PBXSourcesBuildPhase section */
235 |
236 | /* Begin PBXVariantGroup section */
237 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
238 | isa = PBXVariantGroup;
239 | children = (
240 | 97C146FB1CF9000F007C117D /* Base */,
241 | );
242 | name = Main.storyboard;
243 | sourceTree = "";
244 | };
245 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
246 | isa = PBXVariantGroup;
247 | children = (
248 | 97C147001CF9000F007C117D /* Base */,
249 | );
250 | name = LaunchScreen.storyboard;
251 | sourceTree = "";
252 | };
253 | /* End PBXVariantGroup section */
254 |
255 | /* Begin XCBuildConfiguration section */
256 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
257 | isa = XCBuildConfiguration;
258 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
259 | buildSettings = {
260 | ALWAYS_SEARCH_USER_PATHS = NO;
261 | CLANG_ANALYZER_NONNULL = YES;
262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
263 | CLANG_CXX_LIBRARY = "libc++";
264 | CLANG_ENABLE_MODULES = YES;
265 | CLANG_ENABLE_OBJC_ARC = YES;
266 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
267 | CLANG_WARN_BOOL_CONVERSION = YES;
268 | CLANG_WARN_COMMA = YES;
269 | CLANG_WARN_CONSTANT_CONVERSION = YES;
270 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
272 | CLANG_WARN_EMPTY_BODY = YES;
273 | CLANG_WARN_ENUM_CONVERSION = YES;
274 | CLANG_WARN_INFINITE_RECURSION = YES;
275 | CLANG_WARN_INT_CONVERSION = YES;
276 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
277 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
278 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
279 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
280 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
281 | CLANG_WARN_STRICT_PROTOTYPES = YES;
282 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
283 | CLANG_WARN_UNREACHABLE_CODE = YES;
284 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
285 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
286 | COPY_PHASE_STRIP = NO;
287 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
288 | ENABLE_NS_ASSERTIONS = NO;
289 | ENABLE_STRICT_OBJC_MSGSEND = YES;
290 | GCC_C_LANGUAGE_STANDARD = gnu99;
291 | GCC_NO_COMMON_BLOCKS = YES;
292 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
293 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
294 | GCC_WARN_UNDECLARED_SELECTOR = YES;
295 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
296 | GCC_WARN_UNUSED_FUNCTION = YES;
297 | GCC_WARN_UNUSED_VARIABLE = YES;
298 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
299 | MTL_ENABLE_DEBUG_INFO = NO;
300 | SDKROOT = iphoneos;
301 | TARGETED_DEVICE_FAMILY = "1,2";
302 | VALIDATE_PRODUCT = YES;
303 | };
304 | name = Profile;
305 | };
306 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
307 | isa = XCBuildConfiguration;
308 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
309 | buildSettings = {
310 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
311 | CLANG_ENABLE_MODULES = YES;
312 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
313 | ENABLE_BITCODE = NO;
314 | FRAMEWORK_SEARCH_PATHS = (
315 | "$(inherited)",
316 | "$(PROJECT_DIR)/Flutter",
317 | );
318 | INFOPLIST_FILE = Runner/Info.plist;
319 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
320 | LIBRARY_SEARCH_PATHS = (
321 | "$(inherited)",
322 | "$(PROJECT_DIR)/Flutter",
323 | );
324 | PRODUCT_BUNDLE_IDENTIFIER = com.shahanaj.woocommerceApp;
325 | PRODUCT_NAME = "$(TARGET_NAME)";
326 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
327 | SWIFT_VERSION = 4.0;
328 | VERSIONING_SYSTEM = "apple-generic";
329 | };
330 | name = Profile;
331 | };
332 | 97C147031CF9000F007C117D /* Debug */ = {
333 | isa = XCBuildConfiguration;
334 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
335 | buildSettings = {
336 | ALWAYS_SEARCH_USER_PATHS = NO;
337 | CLANG_ANALYZER_NONNULL = YES;
338 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
339 | CLANG_CXX_LIBRARY = "libc++";
340 | CLANG_ENABLE_MODULES = YES;
341 | CLANG_ENABLE_OBJC_ARC = YES;
342 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
343 | CLANG_WARN_BOOL_CONVERSION = YES;
344 | CLANG_WARN_COMMA = YES;
345 | CLANG_WARN_CONSTANT_CONVERSION = YES;
346 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
347 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
348 | CLANG_WARN_EMPTY_BODY = YES;
349 | CLANG_WARN_ENUM_CONVERSION = YES;
350 | CLANG_WARN_INFINITE_RECURSION = YES;
351 | CLANG_WARN_INT_CONVERSION = YES;
352 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
353 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
354 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
355 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
356 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
357 | CLANG_WARN_STRICT_PROTOTYPES = YES;
358 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
359 | CLANG_WARN_UNREACHABLE_CODE = YES;
360 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
361 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
362 | COPY_PHASE_STRIP = NO;
363 | DEBUG_INFORMATION_FORMAT = dwarf;
364 | ENABLE_STRICT_OBJC_MSGSEND = YES;
365 | ENABLE_TESTABILITY = YES;
366 | GCC_C_LANGUAGE_STANDARD = gnu99;
367 | GCC_DYNAMIC_NO_PIC = NO;
368 | GCC_NO_COMMON_BLOCKS = YES;
369 | GCC_OPTIMIZATION_LEVEL = 0;
370 | GCC_PREPROCESSOR_DEFINITIONS = (
371 | "DEBUG=1",
372 | "$(inherited)",
373 | );
374 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
375 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
376 | GCC_WARN_UNDECLARED_SELECTOR = YES;
377 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
378 | GCC_WARN_UNUSED_FUNCTION = YES;
379 | GCC_WARN_UNUSED_VARIABLE = YES;
380 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
381 | MTL_ENABLE_DEBUG_INFO = YES;
382 | ONLY_ACTIVE_ARCH = YES;
383 | SDKROOT = iphoneos;
384 | TARGETED_DEVICE_FAMILY = "1,2";
385 | };
386 | name = Debug;
387 | };
388 | 97C147041CF9000F007C117D /* Release */ = {
389 | isa = XCBuildConfiguration;
390 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
391 | buildSettings = {
392 | ALWAYS_SEARCH_USER_PATHS = NO;
393 | CLANG_ANALYZER_NONNULL = YES;
394 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
395 | CLANG_CXX_LIBRARY = "libc++";
396 | CLANG_ENABLE_MODULES = YES;
397 | CLANG_ENABLE_OBJC_ARC = YES;
398 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
399 | CLANG_WARN_BOOL_CONVERSION = YES;
400 | CLANG_WARN_COMMA = YES;
401 | CLANG_WARN_CONSTANT_CONVERSION = YES;
402 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
403 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
404 | CLANG_WARN_EMPTY_BODY = YES;
405 | CLANG_WARN_ENUM_CONVERSION = YES;
406 | CLANG_WARN_INFINITE_RECURSION = YES;
407 | CLANG_WARN_INT_CONVERSION = YES;
408 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
409 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
410 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
411 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
412 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
413 | CLANG_WARN_STRICT_PROTOTYPES = YES;
414 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
415 | CLANG_WARN_UNREACHABLE_CODE = YES;
416 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
417 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
418 | COPY_PHASE_STRIP = NO;
419 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
420 | ENABLE_NS_ASSERTIONS = NO;
421 | ENABLE_STRICT_OBJC_MSGSEND = YES;
422 | GCC_C_LANGUAGE_STANDARD = gnu99;
423 | GCC_NO_COMMON_BLOCKS = YES;
424 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
425 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
426 | GCC_WARN_UNDECLARED_SELECTOR = YES;
427 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
428 | GCC_WARN_UNUSED_FUNCTION = YES;
429 | GCC_WARN_UNUSED_VARIABLE = YES;
430 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
431 | MTL_ENABLE_DEBUG_INFO = NO;
432 | SDKROOT = iphoneos;
433 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
434 | TARGETED_DEVICE_FAMILY = "1,2";
435 | VALIDATE_PRODUCT = YES;
436 | };
437 | name = Release;
438 | };
439 | 97C147061CF9000F007C117D /* Debug */ = {
440 | isa = XCBuildConfiguration;
441 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
442 | buildSettings = {
443 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
444 | CLANG_ENABLE_MODULES = YES;
445 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
446 | ENABLE_BITCODE = NO;
447 | FRAMEWORK_SEARCH_PATHS = (
448 | "$(inherited)",
449 | "$(PROJECT_DIR)/Flutter",
450 | );
451 | INFOPLIST_FILE = Runner/Info.plist;
452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
453 | LIBRARY_SEARCH_PATHS = (
454 | "$(inherited)",
455 | "$(PROJECT_DIR)/Flutter",
456 | );
457 | PRODUCT_BUNDLE_IDENTIFIER = com.shahanaj.woocommerceApp;
458 | PRODUCT_NAME = "$(TARGET_NAME)";
459 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
460 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
461 | SWIFT_VERSION = 4.0;
462 | VERSIONING_SYSTEM = "apple-generic";
463 | };
464 | name = Debug;
465 | };
466 | 97C147071CF9000F007C117D /* Release */ = {
467 | isa = XCBuildConfiguration;
468 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
469 | buildSettings = {
470 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
471 | CLANG_ENABLE_MODULES = YES;
472 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
473 | ENABLE_BITCODE = NO;
474 | FRAMEWORK_SEARCH_PATHS = (
475 | "$(inherited)",
476 | "$(PROJECT_DIR)/Flutter",
477 | );
478 | INFOPLIST_FILE = Runner/Info.plist;
479 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
480 | LIBRARY_SEARCH_PATHS = (
481 | "$(inherited)",
482 | "$(PROJECT_DIR)/Flutter",
483 | );
484 | PRODUCT_BUNDLE_IDENTIFIER = com.shahanaj.woocommerceApp;
485 | PRODUCT_NAME = "$(TARGET_NAME)";
486 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
487 | SWIFT_VERSION = 4.0;
488 | VERSIONING_SYSTEM = "apple-generic";
489 | };
490 | name = Release;
491 | };
492 | /* End XCBuildConfiguration section */
493 |
494 | /* Begin XCConfigurationList section */
495 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
496 | isa = XCConfigurationList;
497 | buildConfigurations = (
498 | 97C147031CF9000F007C117D /* Debug */,
499 | 97C147041CF9000F007C117D /* Release */,
500 | 249021D3217E4FDB00AE95B9 /* Profile */,
501 | );
502 | defaultConfigurationIsVisible = 0;
503 | defaultConfigurationName = Release;
504 | };
505 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
506 | isa = XCConfigurationList;
507 | buildConfigurations = (
508 | 97C147061CF9000F007C117D /* Debug */,
509 | 97C147071CF9000F007C117D /* Release */,
510 | 249021D4217E4FDB00AE95B9 /* Profile */,
511 | );
512 | defaultConfigurationIsVisible = 0;
513 | defaultConfigurationName = Release;
514 | };
515 | /* End XCConfigurationList section */
516 |
517 | };
518 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
519 | }
520 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shahanajparvin/woocommerce_app_flutter/95c207598620dd5fa49af79e7963702ad32925ba/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | 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.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | woocommerce_app
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/lib/bloc/cart_page_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:woocommerce_app/helper/const.dart';
6 | import 'package:rxdart/rxdart.dart';
7 | import 'package:woocommerce_app/model/ordered_product.dart';
8 | import 'package:woocommerce_app/screen/customer_add.dart';
9 | import 'package:woocommerce_app/helper/ui_helper.dart';
10 |
11 | class CartListBloc {
12 | List cartProductList = new List();
13 |
14 | Map customer = new Map();
15 |
16 | final _cartProductListFetcher = BehaviorSubject();
17 |
18 | final customerFetcher = BehaviorSubject();
19 |
20 | final totalCreditValueFetcher = BehaviorSubject();
21 |
22 | Observable get allCartProducts => _cartProductListFetcher.stream;
23 |
24 | CartListBloc(dynamic value, var customer) {
25 | this.cartProductList = value;
26 | this.customer = customer;
27 | }
28 |
29 | fetchCustomer() {
30 | customerFetcher.sink.add(customer);
31 | }
32 |
33 | /*
34 | * This function calculate total credit value from order items
35 | * Sink the the value
36 | */
37 |
38 | fetchTotalCreditValue() {
39 | double totalCreditValue = 0.0;
40 | for (int i = 0; i < cartProductList.length; i++) {
41 | if (cartProductList[i].totalCreditValue != null)
42 | totalCreditValue =
43 | totalCreditValue + cartProductList[i].totalCreditValue;
44 | }
45 | totalCreditValueFetcher.sink.add(totalCreditValue);
46 | }
47 |
48 | fetchOrderedProducts() async {
49 | _cartProductListFetcher.sink.add(cartProductList);
50 | }
51 |
52 | Future createOrder(final _scaffoldKey, BuildContext context, Map paymentInfo) async {
53 |
54 |
55 | if (cartProductList.length > 0) { // Check the cart list empty or not
56 |
57 | if (customer != null) { // Before place order check customer is available or not
58 |
59 | UIHelper.showProcessingDialog(context); // Show a progress dialog during Place order http request
60 |
61 | List orderedProductList = new List(); // Prepare a product list which will be added in place order list
62 |
63 | for (int i = 0; i < cartProductList.length; i++) {
64 | Map addcartProductList = new Map();
65 | addcartProductList.putIfAbsent(
66 | 'product_id', () => int.parse(cartProductList[i].id));
67 | addcartProductList.putIfAbsent(
68 | 'quantity', () => cartProductList[i].orderCount);
69 | orderedProductList.add(addcartProductList);
70 | }
71 |
72 | try {
73 | var response = await Const.wc_api.postAsync("orders", {
74 | "payment_method": paymentInfo['payment_method'],
75 | "payment_method_title": paymentInfo['payment_method_title'],
76 | "set_paid": true,
77 | "billing": customer['billing'],
78 | "shipping": customer['shipping'],
79 | "line_items": orderedProductList,
80 | });
81 |
82 | Navigator.of(context).pop(); // Processing dialog close after getting the response
83 |
84 | if (response.containsKey('message')) //if response contains message key that means customer not created and return the reason in message key
85 | {
86 | showDefaultSnackbar(_scaffoldKey, context, response['message']);
87 | }
88 | else if (response.toString().contains('id')) // if response contains id that customer created
89 | {
90 | showDefaultSnackbar(_scaffoldKey, context,
91 | 'Congratulation ! Successfully place your order');
92 | }
93 | else
94 | {
95 | showDefaultSnackbar(_scaffoldKey, context, response.toString());
96 | }
97 |
98 | } catch (e) {
99 |
100 | }
101 | }
102 | else
103 | {
104 | showDefaultSnackbar(_scaffoldKey, context, 'Please ! add a customer');
105 | }
106 | }
107 | else
108 | {
109 | showDefaultSnackbar(
110 | _scaffoldKey, context, 'Please ! at least add one order');
111 | }
112 | }
113 |
114 | /*
115 | * This function add product count in cart by productId
116 | * Update the cart product list by sink to cartProductList
117 | * Also calculate cart product credit value
118 | */
119 |
120 | orderAdd(String productId) {
121 | for (int i = 0; i < cartProductList.length; i++) {
122 | if (productId == cartProductList[i].id) {
123 | int count = cartProductList[i].orderCount + 1;
124 | cartProductList[i].orderCount = count;
125 | if (cartProductList[i].mrp != null)
126 | cartProductList[i].totalCreditValue =
127 | double.parse(cartProductList[i].mrp) * count;
128 | break;
129 | }
130 | }
131 | _cartProductListFetcher.sink.add(cartProductList);
132 | fetchTotalCreditValue();
133 | }
134 |
135 | /*
136 | * This function remove product count in cart by productId
137 | * Update the cart product list by sink to cartProductList
138 | * Also calculate cart product credit value
139 | */
140 |
141 | orderRemove(String id) {
142 | for (int i = 0; i < cartProductList.length; i++) {
143 | if (id == cartProductList[i].id) {
144 | if (cartProductList[i].orderCount > 0) {
145 | int count = cartProductList[i].orderCount - 1;
146 | cartProductList[i].orderCount = count;
147 | if (cartProductList[i].mrp != null)
148 | cartProductList[i].totalCreditValue =
149 | double.parse(cartProductList[i].mrp) * count;
150 |
151 | break;
152 | }
153 | }
154 | }
155 |
156 | _cartProductListFetcher.sink.add(cartProductList);
157 | fetchTotalCreditValue();
158 | }
159 |
160 | /*
161 | * Function Remove product by productId from cart
162 | */
163 |
164 | orderDelete(String productId) {
165 | for (int i = 0; i < cartProductList.length; i++) {
166 | cartProductList.removeAt(i);
167 | }
168 |
169 | _cartProductListFetcher.sink.add(cartProductList);
170 | fetchTotalCreditValue();
171 | }
172 |
173 | /*
174 | Function Route to new customer page if customer not available during place order
175 | */
176 |
177 | routeToCustomerAddPage(BuildContext context) {
178 | Navigator.push(
179 | context, MaterialPageRoute(builder: (context) => CustomerAddPage()))
180 | .then((onValue) {
181 | if (onValue != null) {
182 | this.customer = onValue;
183 | fetchCustomer();
184 | }
185 | });
186 | }
187 |
188 | dispose() {
189 | _cartProductListFetcher.close();
190 | }
191 |
192 |
193 | /*
194 | Function Display proper message to user after requesting to create a order
195 | */
196 |
197 | void showDefaultSnackbar(
198 | final _scaffoldKey, BuildContext context, String message) {
199 | _scaffoldKey.currentState.showSnackBar(
200 | SnackBar(
201 | duration: Duration(minutes: 5),
202 | content: Text(message),
203 | action: SnackBarAction(
204 | textColor: Colors.white,
205 | label: 'Ok',
206 | onPressed: () {
207 | if (!message.contains('customer'))
208 | Navigator.of(context).pop(customer); // Back to customer list page
209 | },
210 | ),
211 | ),
212 | );
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/lib/bloc/customer_add_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'package:flutter/material.dart';
3 | import 'package:woocommerce_app/helper/const.dart';
4 | import 'package:woocommerce_app/helper/ui_helper.dart';
5 |
6 | class CustomerAddBloc {
7 |
8 |
9 | Future createCustomer(Map customerBasicInfo, Map customerAddressInfo, final _scaffoldKey, BuildContext context) async {
10 |
11 | UIHelper.showProcessingDialog(context); // Show a progress dialog during network request
12 |
13 | try {
14 | var response = await Const.wc_api.postAsync("customers", {
15 | "email": customerBasicInfo['email'],
16 | "first_name": customerBasicInfo['firstName'],
17 | "username": customerBasicInfo['userName'],
18 | "billing": customerAddressInfo,
19 | "shipping": customerAddressInfo
20 | });
21 |
22 |
23 | Navigator.of(context).pop(); // Processing dialog close after getting the response
24 |
25 | if (response.containsKey('message')) // if response contains message key that means customer not created and return the reason in message key
26 | {
27 |
28 | showSnackbarWithProperMessage(
29 | _scaffoldKey, context, response['message']);
30 |
31 | } else if (response.toString().contains('id')) // if response contains id that customer created
32 | {
33 |
34 | showSnackbarWithProperMessage(_scaffoldKey, context,
35 | 'Congratulation ! Successfully place your order');
36 |
37 |
38 | Navigator.of(context).pop(response); // Back to customer list page
39 |
40 | } else
41 | {
42 | showSnackbarWithProperMessage(_scaffoldKey, context,
43 | response.toString()); // JSON Object with response
44 |
45 | }
46 |
47 | } catch (e) {
48 | }
49 | }
50 |
51 | /*
52 | Function Display proper message to user after requesting to create a customer
53 | */
54 |
55 | void showSnackbarWithProperMessage(final _scaffoldKey, BuildContext context, String disPlayMessage) {
56 |
57 | _scaffoldKey.currentState.showSnackBar(
58 | SnackBar(
59 | duration: Duration(minutes: 5),
60 | content: Text(disPlayMessage),
61 | ),
62 | );
63 |
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/lib/bloc/customer_list_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:woocommerce_app/helper/const.dart';
4 | import 'package:rxdart/rxdart.dart';
5 | import 'package:woocommerce_app/screen/customer_add.dart';
6 | import 'package:woocommerce_app/screen/place_order_page.dart';
7 |
8 | class CustomerListBloc {
9 | final _customerListFetcher = BehaviorSubject();
10 |
11 | Observable get allCustomers => _customerListFetcher.stream;
12 |
13 | /*
14 | * Fetch the customer list filtering by search text
15 | */
16 |
17 | onSearchTextChanged(String searchText) async {
18 |
19 | fetchCustomers(searchText);
20 |
21 | }
22 |
23 | fetchCustomers(String search) async {
24 |
25 | var response = await Const.wc_api.getAsync("customers?search=" + search);
26 | _customerListFetcher.sink.add(response);
27 |
28 | }
29 |
30 | routeToPlaceOrderPage(BuildContext context, var customer) {
31 |
32 | Navigator.push(context,
33 | MaterialPageRoute(builder: (context) => PlaceOrderPage(customer)));
34 |
35 | }
36 |
37 | routeToCustomerAddPage(BuildContext context) {
38 |
39 | Navigator.push(
40 | context, MaterialPageRoute(builder: (context) => CustomerAddPage()))
41 | .then((onValue) {
42 |
43 | // After return the page refresh the customer list by http request to add the new order in list
44 |
45 | if (onValue != null) {
46 | fetchCustomers('');
47 | }
48 |
49 | });
50 | }
51 |
52 | dispose() {
53 |
54 | _customerListFetcher.close();
55 |
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/bloc/home_page_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:rxdart/rxdart.dart';
2 | import 'package:woocommerce_app/helper/const.dart';
3 |
4 | class HomePageBloc {
5 |
6 |
7 | final customerCountFetcher = BehaviorSubject();
8 |
9 | final productCountFetcher = BehaviorSubject();
10 |
11 | final orderCountFetcher = BehaviorSubject();
12 |
13 | final averageSalesValueFetcher = BehaviorSubject();
14 |
15 | final netSalesValueFetcher = BehaviorSubject();
16 |
17 | final totalSalesValueFetcher = BehaviorSubject();
18 |
19 |
20 | fetchSalesReports() async {
21 |
22 | var response= await Const.wc_api.getAsync('reports/sales?date_min=2016-05-03&date_max=2020-05-04');
23 | var totalSales = response[0];
24 | averageSalesValueFetcher.sink.add(totalSales['average_sales']);
25 | netSalesValueFetcher.sink.add(totalSales['net_sales']);
26 | totalSalesValueFetcher.sink.add(totalSales['total_sales']);
27 | }
28 |
29 | fetchPerModuleCount(String value) async {
30 |
31 | var p = await Const.wc_api.getCountAsync(value);
32 | if (value == 'customers') {
33 | customerCountFetcher.sink.add(p['count']);
34 | } else if (value == 'products') {
35 | productCountFetcher.sink.add(p['count']);
36 | } else if (value == 'orders') {
37 | orderCountFetcher.sink.add(p['count']);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/lib/bloc/order_list_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:woocommerce_app/helper/const.dart';
4 | import 'package:rxdart/rxdart.dart';
5 | import 'package:woocommerce_app/screen/place_order_page.dart';
6 |
7 | class OrderListBloc {
8 |
9 |
10 | final _OrderListFetcher = BehaviorSubject();
11 |
12 | Observable get allOrders => _OrderListFetcher.stream;
13 |
14 | /*
15 | * Fetch the Orders list filtering by search text
16 | */
17 |
18 | onSearchTextChanged(String text) async {
19 | fetchOrders(text);
20 | }
21 |
22 | fetchOrders(String search) async {
23 | var response = await Const.wc_api.getAsync("orders?search=" + search);
24 | _OrderListFetcher.sink.add(response);
25 | }
26 |
27 | routeToNewOrderPage(BuildContext context) {
28 | Navigator.push(context,
29 | MaterialPageRoute(builder: (context) => PlaceOrderPage(null)))
30 | .then((onValue) {
31 | fetchOrders('');
32 | });
33 | }
34 |
35 | dispose() {
36 | _OrderListFetcher.close();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/lib/bloc/place_order_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:woocommerce_app/helper/const.dart';
4 | import 'package:woocommerce_app/model/ordered_product.dart';
5 | import 'package:woocommerce_app/screen/cart_page.dart';
6 | import 'package:rxdart/rxdart.dart';
7 |
8 | class PlaceOrderBloc {
9 |
10 | List productList = new List();
11 |
12 | Map orderCount = new Map();
13 |
14 | Map categories = new Map();
15 |
16 | var customer;
17 |
18 | final _productListFetcher = BehaviorSubject();
19 |
20 | Observable get allProducts => _productListFetcher.stream;
21 |
22 | final totalCountProductItemInCartFetcher = BehaviorSubject();
23 |
24 | final totalCreditValueFetcher = BehaviorSubject();
25 |
26 | final categoriesFetcher = BehaviorSubject();
27 |
28 | List categoriesKeys = new List();
29 |
30 | PlaceOrderBloc(var customer) {
31 | this.customer = customer;
32 | }
33 |
34 | /*
35 | * Fetch the customer list filtering by search text
36 | */
37 | onSearchTextChanged(String text) async {
38 | fetchProducts(text, '');
39 | }
40 |
41 | /*
42 | * This function calculate total credit value from order items
43 | * Sink the the value
44 | */
45 |
46 | fetchTotalProductsCreditValue() {
47 | double totalCreditValue = 0.0;
48 | for (int i = 0; i < productList.length; i++) {
49 | if (productList[i].totalCreditValue != null)
50 | totalCreditValue = totalCreditValue + productList[i].totalCreditValue;
51 | }
52 | totalCreditValueFetcher.sink.add(totalCreditValue);
53 | }
54 |
55 | fetchCategories() async {
56 |
57 | var response = await Const.wc_api.getAsync("products/categories");
58 |
59 | categories = new Map();
60 |
61 | categories['Select a category'] = '';
62 |
63 | for (int i = 0; i < response.length; i++) {
64 | print(response[i]['id']);
65 | categories.putIfAbsent(response[i]['name'], () => response[i]['id'].toString());
66 | }
67 |
68 | categoriesKeys = new List();
69 | for (String value in categories.keys) {
70 | categoriesKeys.add(value);
71 | }
72 |
73 | if (categoriesKeys.length > 0) {
74 | Map> category = new Map>();
75 |
76 | category[categoriesKeys[0]] = categoriesKeys;
77 |
78 | categoriesFetcher.sink.add(category);
79 | }
80 | }
81 |
82 | /*
83 | * Function return products list
84 | * Search and Filtering by product name and product category
85 | */
86 |
87 | fetchProducts(String search, String categoryId) async {
88 | var response = await Const.wc_api
89 | .getAsync("products?search=" + search + "&category=" + categoryId);
90 |
91 | productList = new List();
92 |
93 |
94 | // This loops keep track add to cart item after refresh the product list
95 |
96 | for (int i = 0; i < response.length; i++) {
97 | bool isTrue = true;
98 |
99 | orderCount.forEach((key, value) {
100 | if (key == response[i]['id'].toString()) {
101 | productList.add(new OrderProducts.fromJson(response[i], value.orderCount));
102 | isTrue = false;
103 | return;
104 | }
105 | });
106 |
107 | if (isTrue) {
108 | productList.add(new OrderProducts.fromJson(response[i], 0));
109 | }
110 | }
111 |
112 | _productListFetcher.sink.add(productList);
113 | }
114 |
115 | /*
116 | * This function add product count in cart by productId
117 | * Update the cart product list by sink to cartProductList
118 | * Also calculate cart product credit value
119 | */
120 |
121 | orderAdd(String id) {
122 | for (int i = 0; i < productList.length; i++) {
123 | if (id == productList[i].id) {
124 | int count = productList[i].orderCount + 1;
125 | productList[i].orderCount = count;
126 | if (productList[i].mrp != null)
127 | productList[i].totalCreditValue =
128 | double.parse(productList[i].mrp) * count;
129 | orderCount[id] = productList[i];
130 | break;
131 | }
132 | }
133 |
134 | _productListFetcher.sink.add(productList);
135 | fetchTotalProductsCreditValue();
136 | totalCountProductItemInCart();
137 | }
138 |
139 | /*
140 | * This function remove product count in cart by productId
141 | * Update the cart product list by sink to cartProductList
142 | * Also calculate cart product credit value
143 | */
144 |
145 | orderRemove(String id) {
146 | for (int i = 0; i < productList.length; i++) {
147 | if (id == productList[i].id) {
148 | if (productList[i].orderCount > 0) {
149 | int count = productList[i].orderCount - 1;
150 | productList[i].orderCount = count;
151 | if (productList[i].mrp != null)
152 | productList[i].totalCreditValue =
153 | double.parse(productList[i].mrp) * count;
154 | orderCount[id] = productList[i];
155 |
156 | break;
157 | }
158 | }
159 | }
160 |
161 | _productListFetcher.sink.add(productList);
162 | fetchTotalProductsCreditValue();
163 | totalCountProductItemInCart();
164 | }
165 |
166 | searchByCategories(String value) {
167 |
168 | if (categoriesKeys.length > 0) {
169 | Map> category = new Map>();
170 |
171 | category[value] = categoriesKeys;
172 |
173 | categoriesFetcher.sink.add(category);
174 | }
175 |
176 | fetchProducts('', categories[value].toString());
177 | }
178 |
179 | routeToCartPage(BuildContext context, final _scaffoldKey) {
180 |
181 | List productsList = new List();
182 |
183 | orderCount.forEach((k, v) {
184 | if (v.orderCount > 0) {
185 | productsList.add(v);
186 | }
187 | });
188 |
189 | if (productsList.length > 0) {
190 | Navigator.push(
191 | context,
192 | MaterialPageRoute(
193 | builder: (context) =>
194 | CartListPage(productsList, this.customer))).then((onValue) {
195 |
196 | if (onValue != null) {
197 | this.customer = onValue;
198 | orderCount = new Map();
199 | fetchProducts('', '');
200 | totalCountProductItemInCartFetcher.sink.add(0);
201 | totalCreditValueFetcher.sink.add(0.00);
202 | }
203 | });
204 | } else {
205 | showDefaultSnackbar(_scaffoldKey);
206 | }
207 | }
208 |
209 | dispose() {
210 | _productListFetcher.close();
211 | }
212 |
213 | totalCountProductItemInCart() {
214 | List productsList = new List();
215 | orderCount.forEach((k, v) {
216 | if (v.orderCount > 0) {
217 | productsList.add(v);
218 | }
219 | });
220 |
221 | totalCountProductItemInCartFetcher.sink.add(productsList.length);
222 | }
223 |
224 | /*
225 | Function Display proper message to user
226 | */
227 | void showDefaultSnackbar(final _scaffoldKey) {
228 | _scaffoldKey.currentState.showSnackBar(
229 | SnackBar(
230 | duration: Duration(seconds: 5),
231 | content: Text('Please ! At least add one order'),
232 | ),
233 | );
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/lib/helper/const.dart:
--------------------------------------------------------------------------------
1 | import 'package:woocommerce_app/helper/woocommerce_api.dart';
2 |
3 | class Const {
4 | static WooCommerceAPI wc_api = new WooCommerceAPI(
5 | "your_host_name", "your_consumer_key", "your_secret_key");
6 | }
7 |
--------------------------------------------------------------------------------
/lib/helper/hex_color.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | class HexColor extends Color {
4 | static int _getColorFromHex(String hexColor) {
5 | hexColor = hexColor.toUpperCase().replaceAll("#", "");
6 | if (hexColor.length == 6) {
7 | hexColor = "FF" + hexColor;
8 | }
9 | return int.parse(hexColor, radix: 16);
10 | }
11 |
12 | HexColor(final String hexColor) : super(_getColorFromHex(hexColor));
13 | }
--------------------------------------------------------------------------------
/lib/helper/query_string.dart:
--------------------------------------------------------------------------------
1 | class QueryString {
2 | /**
3 | * Parses the given query string into a Map.
4 | */
5 | static Map parse(String query) {
6 | var search = new RegExp('([^&=]+)=?([^&]*)');
7 | var result = new Map();
8 |
9 | // Get rid off the beginning ? in query strings.
10 | if (query.startsWith('?')) query = query.substring(1);
11 |
12 | // A custom decoder.
13 | decode(String s) => Uri.decodeComponent(s.replaceAll('+', ' '));
14 |
15 | // Go through all the matches and build the result map.
16 | for (Match match in search.allMatches(query)) {
17 | result[decode(match.group(1))] = decode(match.group(2));
18 | }
19 |
20 | return result;
21 | }
22 | }
--------------------------------------------------------------------------------
/lib/helper/ui_helper.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:fluttertoast/fluttertoast.dart';
5 | import 'package:progress_hud/progress_hud.dart';
6 |
7 |
8 | class UIHelper{
9 |
10 |
11 | static const bool isFill = true;
12 |
13 | static const double margin = 15;
14 |
15 | static double navigateIconSize = 35;
16 |
17 | static const double detailsMargin = 10;
18 |
19 | static Color addFormContainerBodyColor = Color.fromRGBO(240,240,240,100);
20 | static Color themeColor = Colors.red;
21 |
22 |
23 | static showToast(String msg) {
24 | return Fluttertoast.showToast(
25 | msg: msg,
26 | toastLength: Toast.LENGTH_SHORT,
27 | gravity: ToastGravity.BOTTOM,
28 | timeInSecForIos: 1,
29 | backgroundColor: Colors.red,
30 | textColor: Colors.white,
31 | fontSize: 16.0);
32 | }
33 |
34 | static UnderlineInputBorder borderWeight()
35 | {
36 |
37 | UnderlineInputBorder(
38 | borderSide: BorderSide(width: 0.5),
39 | );
40 | }
41 |
42 |
43 |
44 | static TextStyle getTextStyleForHomeScreenItem()
45 | {
46 |
47 | return new TextStyle(
48 | color: Colors.black,
49 | fontWeight: FontWeight.w400,
50 | fontSize: 12
51 | );
52 |
53 | }
54 |
55 |
56 | static showProcessingDialog(BuildContext _context) {
57 |
58 | ProgressHUD _progressHUD = new ProgressHUD(
59 | backgroundColor: Colors.transparent,
60 | color: Colors.white,
61 | containerColor: UIHelper.themeColor,
62 | borderRadius: 5.0,
63 | text: 'Processing...',
64 | );
65 | showDialog(
66 | context: _context,
67 | builder: (_context) {
68 | // return object of type Dialog
69 | return _progressHUD;
70 | },
71 | );
72 | }
73 |
74 |
75 |
76 |
77 | }
--------------------------------------------------------------------------------
/lib/helper/util.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class CustomColors {
4 | static const Color GreyBackground = Color.fromRGBO(249, 252, 255, 1);
5 | static const Color GreyBorder = Color.fromRGBO(207, 207, 207, 1);
6 |
7 | static const Color GreenLight = Color.fromRGBO(93, 230, 26, 1);
8 | static const Color GreenDark = Color.fromRGBO(57, 170, 2, 1);
9 | static const Color GreenIcon = Color.fromRGBO(30, 209, 2, 1);
10 | static const Color GreenAccent = Color.fromRGBO(30, 209, 2, 1);
11 | static const Color GreenShadow = Color.fromRGBO(30, 209, 2, 0.24); // 24%
12 | static const Color GreenBackground = Color.fromRGBO(181, 255, 155, 0.36); // 36%
13 |
14 | static const Color OrangeIcon = Color.fromRGBO(236, 108, 11, 1);
15 | static const Color OrangeBackground = Color.fromRGBO(255, 208, 155, 0.36); // 36%
16 |
17 | static const Color PurpleLight = Color.fromRGBO(248, 87, 195, 1);
18 | static const Color PurpleDark = Color.fromRGBO(224, 19, 156, 1);
19 | static const Color PurpleIcon = Color.fromRGBO(209, 2, 99, 1);
20 | static const Color PurpleAccent = Color.fromRGBO(209, 2, 99, 1);
21 | static const Color PurpleShadow = Color.fromRGBO(209, 2, 99, 0.27); // 27%
22 | static const Color PurpleBackground = Color.fromRGBO(255, 155, 205, 0.36); // 36%
23 |
24 | static const Color DeeppurlpleIcon = Color.fromRGBO(191, 0, 128, 1);
25 | static const Color DeeppurlpleBackground = Color.fromRGBO(245, 155, 255, 0.36); // 36%
26 |
27 | static const Color BlueLight = Color.fromRGBO(126, 182, 255, 1);
28 | static const Color BlueDark = Color.fromRGBO(95, 135, 231, 1);
29 | static const Color BlueIcon = Color.fromRGBO(9, 172, 206, 1);
30 | static const Color BlueBackground = Color.fromRGBO(155, 255, 248, 0.36); // 36%
31 | static const Color BlueShadow = Color.fromRGBO(104, 148, 238, 1);
32 |
33 | static const Color HeaderBlueLight = Color.fromRGBO(129, 199, 245, 1);
34 | static const Color HeaderBlueDark = Color.fromRGBO(56, 103, 213, 1);
35 | static const Color HeaderGreyLight = Color.fromRGBO(225, 255, 255, 0.31); // 31%
36 |
37 | static const Color YellowIcon = Color.fromRGBO(249, 194, 41, 1);
38 | static const Color YellowBell = Color.fromRGBO(225, 220, 0, 1);
39 | static const Color YellowAccent = Color.fromRGBO(255, 213, 6, 1);
40 | static const Color YellowShadow = Color.fromRGBO(243, 230, 37, 0.27); // 27%
41 | static const Color YellowBackground = Color.fromRGBO(255, 238, 155, 0.36); // 36%
42 |
43 | static const Color BellGrey = Color.fromRGBO(217, 217, 217, 1);
44 | static const Color BellYellow = Color.fromRGBO(255, 220, 0, 1);
45 |
46 | static const Color TrashRed = Color.fromRGBO(251, 54, 54, 1);
47 | static const Color TrashRedBackground = Color.fromRGBO(255, 207, 207, 1);
48 |
49 | static const Color TextHeader = Color.fromRGBO(85, 78, 143, 1);
50 | static const Color TextHeaderGrey = Color.fromRGBO(104, 104, 104, 1);
51 | static const Color TextSubHeaderGrey = Color.fromRGBO(161, 161, 161, 1);
52 | static const Color TextSubHeader = Color.fromRGBO(139, 135, 179, 1);
53 | static const Color TextBody = Color.fromRGBO(130, 160, 183, 1);
54 | static const Color TextGrey = Color.fromRGBO(198, 198, 200, 1);
55 | static const Color TextWhite = Color.fromRGBO(243, 243, 243, 1);
56 | static const Color HeaderCircle = Color.fromRGBO(255, 255, 255, 0.17);
57 | }
--------------------------------------------------------------------------------
/lib/helper/woocommerce_api.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'dart:async';
3 | import "dart:collection";
4 | import 'dart:convert';
5 | import 'dart:io';
6 | import "dart:math";
7 | import "dart:core";
8 | import 'package:crypto/crypto.dart' as crypto;
9 | import 'package:http/http.dart' as http;
10 | import 'package:woocommerce_app/helper/query_string.dart';
11 |
12 | class WooCommerceAPI {
13 | String url;
14 | String consumerKey;
15 | String consumerSecret;
16 | bool isHttps;
17 |
18 | WooCommerceAPI(url, consumerKey, consumerSecret){
19 | this.url = url;
20 | this.consumerKey = consumerKey;
21 | this.consumerSecret = consumerSecret;
22 |
23 | if(this.url.startsWith("https")){
24 | this.isHttps = true;
25 | } else {
26 | this.isHttps = false;
27 | }
28 |
29 | }
30 |
31 |
32 | _getOAuthURL(String request_method, String endpoint) {
33 | var consumerKey = this.consumerKey;
34 | var consumerSecret = this.consumerSecret;
35 |
36 | var token = "";
37 | var token_secret = "";
38 | var url = this.url + "/wp-json/wc/v2/" + endpoint;
39 | var containsQueryParams = url.contains("?");
40 |
41 | // If website is HTTPS based, no need for OAuth, just return the URL with CS and CK as query params
42 | if(this.isHttps == true){
43 | return url + (containsQueryParams == true ? "&consumer_key=" + this.consumerKey + "&consumer_secret=" + this.consumerSecret : "?consumer_key=" + this.consumerKey + "&consumer_secret=" + this.consumerSecret);
44 | }
45 |
46 | var rand = new Random();
47 | var codeUnits = new List.generate(10, (index) {
48 | return rand.nextInt(26) + 97;
49 | });
50 |
51 | var nonce = new String.fromCharCodes(codeUnits);
52 | int timestamp = (new DateTime.now().millisecondsSinceEpoch / 1000).toInt();
53 |
54 | //print(timestamp);
55 | //print(nonce);
56 |
57 | var method = request_method;
58 | var path = url.split("?")[0];
59 | var parameters = "oauth_consumer_key=" +
60 | consumerKey +
61 | "&oauth_nonce=" +
62 | nonce +
63 | "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" +
64 | timestamp.toString() +
65 | "&oauth_token=" +
66 | token +
67 | "&oauth_version=1.0&";
68 |
69 | if (containsQueryParams == true) {
70 | parameters = parameters + url.split("?")[1];
71 | } else {
72 | parameters = parameters.substring(0, parameters.length - 1);
73 | }
74 |
75 | Map params = QueryString.parse(parameters);
76 | Map treeMap = new SplayTreeMap();
77 | treeMap.addAll(params);
78 |
79 | String parameterString = "";
80 |
81 | for (var key in treeMap.keys) {
82 | parameterString = parameterString +
83 | Uri.encodeQueryComponent(key) +
84 | "=" +
85 | treeMap[key] +
86 | "&";
87 | }
88 |
89 | parameterString = parameterString.substring(0, parameterString.length - 1);
90 |
91 | var baseString = method +
92 | "&" +
93 | Uri.encodeQueryComponent(
94 | containsQueryParams == true ? url.split("?")[0] : url) +
95 | "&" +
96 | Uri.encodeQueryComponent(parameterString);
97 |
98 | //print(baseString);
99 |
100 | var signingKey = consumerSecret + "&" + token;
101 | //print(signingKey);
102 | //print(UTF8.encode(signingKey));
103 | var hmacSha1 =
104 | new crypto.Hmac(crypto.sha1, utf8.encode(signingKey)); // HMAC-SHA1
105 | var signature = hmacSha1.convert(utf8.encode(baseString));
106 |
107 | //print(signature);
108 |
109 | var finalSignature = base64Encode(signature.bytes);
110 | //print(finalSignature);
111 |
112 | var requestUrl = "";
113 |
114 | if (containsQueryParams == true) {
115 | //print(url.split("?")[0] + "?" + parameterString + "&oauth_signature=" + Uri.encodeQueryComponent(finalSignature));
116 | requestUrl = url.split("?")[0] +
117 | "?" +
118 | parameterString +
119 | "&oauth_signature=" +
120 | Uri.encodeQueryComponent(finalSignature);
121 | } else {
122 | //print(url + "?" + parameterString + "&oauth_signature=" + Uri.encodeQueryComponent(finalSignature));
123 | requestUrl = url +
124 | "?" +
125 | parameterString +
126 | "&oauth_signature=" +
127 | Uri.encodeQueryComponent(finalSignature);
128 | }
129 |
130 | return requestUrl;
131 | }
132 |
133 |
134 | _getOAuthURLForCount(String request_method, String endpoint) {
135 | var consumerKey = this.consumerKey;
136 | var consumerSecret = this.consumerSecret;
137 |
138 | var token = "";
139 | var token_secret = "";
140 | var url = this.url + "/wc-api/v3/" + endpoint +"/count";
141 | var containsQueryParams = url.contains("?");
142 |
143 | // If website is HTTPS based, no need for OAuth, just return the URL with CS and CK as query params
144 | if(this.isHttps == true){
145 | return url + (containsQueryParams == true ? "&consumer_key=" + this.consumerKey + "&consumer_secret=" + this.consumerSecret : "?consumer_key=" + this.consumerKey + "&consumer_secret=" + this.consumerSecret);
146 | }
147 |
148 | var rand = new Random();
149 | var codeUnits = new List.generate(10, (index) {
150 | return rand.nextInt(26) + 97;
151 | });
152 |
153 | var nonce = new String.fromCharCodes(codeUnits);
154 | int timestamp = (new DateTime.now().millisecondsSinceEpoch / 1000).toInt();
155 |
156 | //print(timestamp);
157 | //print(nonce);
158 |
159 | var method = request_method;
160 | var path = url.split("?")[0];
161 | var parameters = "oauth_consumer_key=" +
162 | consumerKey +
163 | "&oauth_nonce=" +
164 | nonce +
165 | "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" +
166 | timestamp.toString() +
167 | "&oauth_token=" +
168 | token +
169 | "&oauth_version=1.0&";
170 |
171 | if (containsQueryParams == true) {
172 | parameters = parameters + url.split("?")[1];
173 | } else {
174 | parameters = parameters.substring(0, parameters.length - 1);
175 | }
176 |
177 | Map params = QueryString.parse(parameters);
178 | Map treeMap = new SplayTreeMap();
179 | treeMap.addAll(params);
180 |
181 | String parameterString = "";
182 |
183 | for (var key in treeMap.keys) {
184 | parameterString = parameterString +
185 | Uri.encodeQueryComponent(key) +
186 | "=" +
187 | treeMap[key] +
188 | "&";
189 | }
190 |
191 | parameterString = parameterString.substring(0, parameterString.length - 1);
192 |
193 | var baseString = method +
194 | "&" +
195 | Uri.encodeQueryComponent(
196 | containsQueryParams == true ? url.split("?")[0] : url) +
197 | "&" +
198 | Uri.encodeQueryComponent(parameterString);
199 |
200 | //print(baseString);
201 |
202 | var signingKey = consumerSecret + "&" + token;
203 | //print(signingKey);
204 | //print(UTF8.encode(signingKey));
205 | var hmacSha1 =
206 | new crypto.Hmac(crypto.sha1, utf8.encode(signingKey)); // HMAC-SHA1
207 | var signature = hmacSha1.convert(utf8.encode(baseString));
208 |
209 | //print(signature);
210 |
211 | var finalSignature = base64Encode(signature.bytes);
212 | //print(finalSignature);
213 |
214 | var requestUrl = "";
215 |
216 | if (containsQueryParams == true) {
217 | //print(url.split("?")[0] + "?" + parameterString + "&oauth_signature=" + Uri.encodeQueryComponent(finalSignature));
218 | requestUrl = url.split("?")[0] +
219 | "?" +
220 | parameterString +
221 | "&oauth_signature=" +
222 | Uri.encodeQueryComponent(finalSignature);
223 | } else {
224 | //print(url + "?" + parameterString + "&oauth_signature=" + Uri.encodeQueryComponent(finalSignature));
225 | requestUrl = url +
226 | "?" +
227 | parameterString +
228 | "&oauth_signature=" +
229 | Uri.encodeQueryComponent(finalSignature);
230 | }
231 |
232 | return requestUrl;
233 | }
234 |
235 | Future getAsync(String endPoint) async {
236 | var url = this._getOAuthURL("GET", endPoint);
237 |
238 | final response = await http.get(url);
239 |
240 | return json.decode(response.body);
241 | }
242 |
243 | Future getCountAsync(String endPoint) async {
244 | var url = this._getOAuthURLForCount("GET", endPoint);
245 |
246 | final response = await http.get(url);
247 |
248 | return json.decode(response.body);
249 | }
250 |
251 | Future postAsync(String endPoint, Map data) async {
252 | var url = this._getOAuthURL("POST", endPoint);
253 | var client = new http.Client();
254 | var request = new http.Request('POST', Uri.parse(url));
255 | request.headers[HttpHeaders.contentTypeHeader] =
256 | 'application/json; charset=utf-8';
257 | request.headers[HttpHeaders.cacheControlHeader] = "no-cache";
258 | request.body = json.encode(data);
259 | var response =
260 | await client.send(request).then((res) => res.stream.bytesToString());
261 | var dataResponse = await json.decode(response);
262 | return dataResponse;
263 | }
264 | }
265 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:woocommerce_app/screen/splash_screen_page.dart';
3 |
4 |
5 | void main() => runApp(new MyApp());
6 |
7 | class MyApp extends StatelessWidget {
8 | @override
9 | Widget build(BuildContext context) {
10 | return new MaterialApp(
11 | debugShowCheckedModeBanner: false,
12 | title: 'Woocom Admin',
13 | theme: new ThemeData(
14 | primarySwatch: Colors.red,
15 | ),
16 | home: SplashScreen(),
17 | );
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/lib/model/ordered_product.dart:
--------------------------------------------------------------------------------
1 | class OrderProducts {
2 |
3 | OrderProducts(
4 | { this.id,
5 | this.name,
6 | this.imageUrl,
7 | this.mrp,
8 | this.stock,
9 | this.totalCreditValue,
10 | this.orderCount});
11 |
12 | String id;
13 | String name;
14 | String imageUrl;
15 | String mrp;
16 | int stock;
17 | double totalCreditValue;
18 | int orderCount = 0;
19 |
20 |
21 | factory OrderProducts.fromJson(Map json,int count) {
22 | return OrderProducts(
23 | orderCount:count,
24 | totalCreditValue:0.0,
25 | id: json['id'].toString() as String,
26 | name: json['name'] as String,
27 | imageUrl: json["images"][0]["src"] as String,
28 | mrp: json['price'].toString() as String,
29 | stock: json['stock_quantity'] as int,
30 |
31 | );
32 | }
33 |
34 |
35 | }
--------------------------------------------------------------------------------
/lib/screen/cart_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:woocommerce_app/bloc/cart_page_bloc.dart';
4 | import 'package:woocommerce_app/helper/hex_color.dart';
5 | import 'package:woocommerce_app/helper/ui_helper.dart';
6 | import 'package:woocommerce_app/model/ordered_product.dart';
7 |
8 | class CartListPage extends StatefulWidget {
9 | List productList = new List();
10 |
11 | Map customer = new Map();
12 |
13 | CartListPage(this.productList, this.customer);
14 |
15 | @override
16 | CartListPageState createState() => new CartListPageState(this);
17 | }
18 |
19 | class CartListPageState extends State {
20 | Widget _mainFormWidget;
21 |
22 | BuildContext _context;
23 |
24 | var bloc;
25 |
26 | final _scaffoldKey = GlobalKey();
27 |
28 | CartListPage parent;
29 |
30 | CartListPageState(this.parent);
31 |
32 | TextEditingController paymentMethodTitle = new TextEditingController();
33 |
34 | TextEditingController paymentMethod = new TextEditingController();
35 |
36 | Map payMethodInformation = new Map();
37 |
38 | @override
39 | void initState() {
40 | super.initState();
41 | bloc = CartListBloc(parent.productList, parent.customer);
42 | }
43 |
44 | @override
45 | Widget build(BuildContext context) {
46 | _context = context;
47 | if (_mainFormWidget == null) {
48 | _mainFormWidget = mainBody();
49 | }
50 | return _mainFormWidget; // Show the form in the application
51 | }
52 |
53 | Widget mainBody() {
54 | return new Scaffold(
55 | key: _scaffoldKey,
56 | resizeToAvoidBottomInset: true,
57 | bottomNavigationBar: new Container(
58 | height: 45,
59 | child: Row(
60 | children: [
61 | Expanded(
62 | flex: 5,
63 | child: Center(
64 | child: totalCreditWidget(),
65 | ),
66 | ),
67 | Expanded(
68 | flex: 5,
69 | child: InkWell(
70 | onTap: () {
71 | payMethodInformation['payment_method'] =
72 | paymentMethod.text;
73 | payMethodInformation['payment_method_title'] =
74 | paymentMethodTitle.text;
75 | bloc.createOrder(
76 | _scaffoldKey, _context, payMethodInformation);
77 | },
78 | child: Container(
79 | color: UIHelper.themeColor,
80 | child: Center(
81 | child: Text('Place Order',
82 | style: TextStyle(
83 | fontWeight: FontWeight.w600,
84 | fontSize: 18,
85 | color: Colors.white)),
86 | ))))
87 | ],
88 | ),
89 | ),
90 | appBar: new AppBar(
91 | iconTheme: IconThemeData(
92 | color: Colors.white, //change your color here
93 | ),
94 | title: new Text("Cart", style: TextStyle(color: Colors.white)),
95 | ),
96 | body: body());
97 | }
98 |
99 | Widget body() {
100 | return new Column(children: [
101 | //UIHelper.searchBox(bloc,()=>searchForm()),
102 |
103 | headerDivWidget("Customer"),
104 |
105 | customerDetail(),
106 |
107 | Container(
108 | height: 0.5,
109 | width: MediaQuery.of(context).size.width * 1.0,
110 | color: Colors.grey,
111 | ),
112 |
113 | headerDivWidget("Item Details"),
114 |
115 | OrderedProductListBuild(),
116 |
117 | Container(
118 | height: 0.5,
119 | width: MediaQuery.of(context).size.width * 1.0,
120 | color: Colors.grey,
121 | ),
122 |
123 |
124 | Align(
125 | alignment: Alignment.bottomLeft,
126 | child: new Column(
127 | mainAxisAlignment: MainAxisAlignment.end,
128 | children: [
129 | headerDivWidget("Payment Method"),
130 | Container(
131 | margin: EdgeInsets.all(5.0),
132 | padding: EdgeInsets.all(5.0),
133 | child: TextField(
134 | controller: paymentMethod,
135 | decoration: new InputDecoration(
136 | hintText: 'Please type payment method',
137 | enabledBorder: UIHelper.borderWeight(),
138 | contentPadding: EdgeInsets.all(15),
139 | ),
140 | ))
141 | ],
142 | ))
143 | ]);
144 | }
145 |
146 | Widget headerDivWidget(String name) {
147 | return Container(
148 | width: MediaQuery.of(context).size.width * 1.0,
149 | //height: 40,
150 | padding: EdgeInsets.all(15),
151 | child: Row(
152 | mainAxisAlignment: MainAxisAlignment.start,
153 | children: [
154 | Text(
155 | name,
156 | style: TextStyle(color: Colors.grey),
157 | ),
158 | new Container(
159 | width: MediaQuery.of(context).size.width * 0.6,
160 | ),
161 |
162 |
163 | name.contains('Customer')
164 | ? addCustomer()
165 | : new Container()
166 | ],
167 | ),
168 |
169 | decoration: BoxDecoration(
170 | border: Border(
171 | bottom: BorderSide(width: 0.5, color: Colors.grey),
172 | ),
173 | color: HexColor("#FFF8F8"),
174 | ),
175 | );
176 | }
177 |
178 | /*
179 | * If customer not available during the place order this widget to available to add customer functionality
180 | * */
181 |
182 | Widget addCustomer() {
183 | return InkWell(
184 | onTap: () {
185 | bloc.routeToCustomerAddPage(_context);
186 | },
187 | child: Icon(Icons.add_circle, color: Colors.green),
188 | );
189 | }
190 |
191 | /*
192 | * Function request to the bloc for total ordered product credit and return a widget with total credit value
193 | */
194 |
195 | Widget totalCreditWidget() {
196 | bloc.fetchTotalCreditValue();
197 | return StreamBuilder(
198 | stream: bloc.totalCreditValueFetcher.stream,
199 | builder: (context, AsyncSnapshot snapshot) {
200 | return snapshot.hasData
201 | ? Text(
202 | '\$ ' + snapshot.data.toString(),
203 | style: TextStyle(
204 | fontWeight: FontWeight.w600,
205 | fontSize: 18,
206 | color: UIHelper.themeColor),
207 | )
208 | : Center(child: CircularProgressIndicator());
209 | },
210 | );
211 | }
212 |
213 | /*
214 | * Function check customer is available or not for place a order
215 | * If available return a widget with customer information
216 | * If not available return a widget with waring message
217 | */
218 |
219 | Widget customerDetail() {
220 | bloc.fetchCustomer();
221 | return StreamBuilder(
222 | stream: bloc.customerFetcher.stream,
223 | builder: (context, AsyncSnapshot snapshot) {
224 | // print(' ttt '+ snapshot.data.toString());
225 | return snapshot.hasData
226 | ? customerDetailsView(snapshot)
227 | : Center(
228 | child: Card(
229 | child: Container(
230 | padding: EdgeInsets.all(20),
231 | child: Center(
232 | child: Text('Please add a customer!'),
233 | ))));
234 | },
235 | );
236 | }
237 |
238 | /*
239 | * Return a widget with customer details information
240 | */
241 |
242 | Widget customerDetailsView(AsyncSnapshot s) {
243 | return ListTile(
244 | leading: new Container(
245 | child: new Center(
246 | child: Text(
247 | s.data["email"].substring(0, 1),
248 | style:
249 | TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
250 | ),
251 | ),
252 | width: 40.0,
253 | height: 40.0,
254 | decoration:
255 | new BoxDecoration(shape: BoxShape.circle, color: Colors.red)),
256 | title: Text(s.data["email"]),
257 | subtitle: Text(s.data["shipping"]["address_1"].toString()),
258 | );
259 | }
260 |
261 | /*
262 | * Function request ordered product list using BLoc
263 | * Return a list widget using Stream builder
264 | */
265 |
266 | Widget OrderedProductListBuild() {
267 | bloc.fetchOrderedProducts();
268 | return StreamBuilder(
269 | stream: bloc.allCartProducts,
270 | builder: (context, AsyncSnapshot snapshot) {
271 | // print(' ttt '+ snapshot.data.toString());
272 | return snapshot.hasData
273 | ? orderedProductListViewWidget(snapshot)
274 | : Center(child: CircularProgressIndicator());
275 | },
276 | );
277 | }
278 |
279 | /*
280 | * Function takes AsyncSnapshot data for build a ListView
281 | * Function return a ListView widget
282 | */
283 |
284 | Widget orderedProductListViewWidget(AsyncSnapshot s) {
285 | return new Expanded(
286 | child: ListView.builder(
287 | itemCount: s.data.length,
288 | itemBuilder: (_, index) {
289 | OrderProducts product = s.data[index];
290 |
291 | String productImageUrl = product.imageUrl;
292 |
293 | if (productImageUrl != null &&
294 | !productImageUrl.contains('woocommerce-placeholder')) {
295 | productImageUrl = product.imageUrl;
296 | } else {
297 | productImageUrl = null;
298 | }
299 |
300 | return Container(
301 | margin: EdgeInsets.all(6),
302 | child: Card(
303 | child: Column(
304 | children: [
305 | ListTile(
306 | leading: new Container(
307 | child: productImageUrl != null
308 | ? new Container()
309 | : new Center(
310 | child: Text(
311 | product.name.substring(0, 1),
312 | style: TextStyle(
313 | color: Colors.white,
314 | fontWeight: FontWeight.w600),
315 | ),
316 | ),
317 | width: 40.0,
318 | height: 40.0,
319 | decoration: productImageUrl != null
320 | ? new BoxDecoration(
321 | shape: BoxShape.circle,
322 | image: new DecorationImage(
323 | fit: BoxFit.fill,
324 | image:
325 | new NetworkImage(product.imageUrl)))
326 | : new BoxDecoration(
327 | shape: BoxShape.circle,
328 | color: UIHelper.themeColor)),
329 | title: Text(product.name),
330 | subtitle: Text("MRP : " +
331 | product.mrp.toString() +
332 | " | " +
333 | "Stock : " +
334 | product.stock.toString()),
335 | ),
336 | SizedBox(
337 | height: 15,
338 | ),
339 | new Row(
340 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
341 | children: [
342 | SizedBox(
343 | width: 30,
344 | ),
345 | IconButton(
346 | onPressed: () {
347 | bloc.orderDelete(product.id.toString());
348 | },
349 | icon: Icon(
350 | Icons.delete_outline,
351 | color: Colors.red,
352 | ),
353 | ),
354 | SizedBox(
355 | width: 30,
356 | ),
357 | new Flexible(
358 | child: Container(
359 | width: 60,
360 | child: new Text(
361 | '\$ ' + product.totalCreditValue.toString()),
362 | )),
363 | Spacer(),
364 | Container(
365 | decoration: BoxDecoration(
366 | borderRadius: BorderRadius.circular(5.0),
367 | border: Border.all(
368 | color: UIHelper.themeColor, width: 2)),
369 | width: 122,
370 | height: 40,
371 | child: new Row(
372 | children: [
373 | Container(
374 | width: 39,
375 | child: Center(
376 | child: IconButton(
377 | icon: Icon(Icons.remove,
378 | color: UIHelper.themeColor),
379 | onPressed: () {
380 | bloc.orderRemove(product.id);
381 | })),
382 | ),
383 | Container(
384 | width: 40,
385 | height: 40,
386 | child: Center(
387 | child: Text(
388 | product.orderCount.toString(),
389 | style:
390 | TextStyle(color: UIHelper.themeColor),
391 | )),
392 | decoration: BoxDecoration(
393 | border: Border(
394 | right: BorderSide(
395 | width: 1.0,
396 | color: UIHelper.themeColor),
397 | left: BorderSide(
398 | width: 1.0,
399 | color: UIHelper.themeColor),
400 | ),
401 | color: Colors.white,
402 | ),
403 | ),
404 | Container(
405 | width: 39,
406 | child: Center(
407 | child: IconButton(
408 | icon: Icon(Icons.add,
409 | color: UIHelper.themeColor),
410 | onPressed: () {
411 | bloc.orderAdd(product.id);
412 | })),
413 | ),
414 | ],
415 | ),
416 | ),
417 | SizedBox(
418 | width: 10,
419 | ),
420 | ],
421 | ),
422 | SizedBox(
423 | height: 20,
424 | )
425 | ],
426 | )));
427 | }));
428 | }
429 | }
430 |
--------------------------------------------------------------------------------
/lib/screen/customer_add.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:woocommerce_app/bloc/customer_add_bloc.dart';
3 | import 'package:woocommerce_app/helper/hex_color.dart';
4 |
5 | class CustomerAddPage extends StatefulWidget {
6 | @override
7 | _CustomerAddPageState createState() => _CustomerAddPageState();
8 | }
9 |
10 | class _CustomerAddPageState extends State {
11 | // _formKey and _autoValidate
12 | final GlobalKey _formKey = GlobalKey();
13 |
14 | final _scaffoldKey = GlobalKey();
15 |
16 | bool _autoValidate = false;
17 |
18 | Map customerBasicInformation = new Map();
19 |
20 | Map customerAddressInformation = new Map();
21 |
22 | var bloc;
23 |
24 | @override
25 | void initState() {
26 | super.initState();
27 | bloc = CustomerAddBloc();
28 | }
29 |
30 | @override
31 | Widget build(BuildContext context) {
32 | return new Scaffold(
33 | key: _scaffoldKey,
34 | appBar: new AppBar(
35 | title: new Text('New Customer'),
36 | actions: [
37 | IconButton(
38 | icon: Icon(
39 | Icons.check,
40 | color: Colors.white,
41 | size: 36,
42 | ),
43 | onPressed: () {
44 | _validateInputs();
45 | },
46 | )
47 | ],
48 | ),
49 | body: new SingleChildScrollView(
50 | child: new Container(
51 | margin: new EdgeInsets.all(0.0),
52 | child: body(),
53 | ),
54 | ),
55 | );
56 | }
57 |
58 | Widget body() {
59 | return new Form(
60 | key: _formKey,
61 | autovalidateMode: AutovalidateMode.onUserInteraction,
62 | child: Column(children: [
63 | headerDivWidget('Basic Information'),
64 | new Container(
65 | padding: EdgeInsets.all(20.0),
66 | child: customerBasicInformationUI()),
67 | headerDivWidget('Address Information'),
68 | Container(
69 | padding: EdgeInsets.all(20.0),
70 | child: customerAddressInformationUI()),
71 | ]));
72 | }
73 |
74 | Widget headerDivWidget(String heaterText) {
75 | return Container(
76 | width: MediaQuery.of(context).size.width * 1.0,
77 | //height: 40,
78 | padding: EdgeInsets.all(15),
79 | child: Text(
80 | heaterText,
81 | style: TextStyle(color: Colors.black, fontWeight: FontWeight.w600),
82 | ),
83 | decoration: BoxDecoration(
84 | border: Border(
85 | bottom: BorderSide(width: 0.5, color: Colors.grey),
86 | ),
87 | color: HexColor("#FFF8F8"),
88 | ),
89 | );
90 | }
91 |
92 | // Here is our Form UI
93 | Widget customerBasicInformationUI() {
94 | return new Column(
95 | children: [
96 | new TextFormField(
97 | decoration: const InputDecoration(labelText: 'Firstname'),
98 | keyboardType: TextInputType.text,
99 | validator: validateName,
100 | onSaved: (String val) {
101 | if (val != null)
102 | customerBasicInformation['firstName'] = val;
103 | else
104 | customerBasicInformation['firstName'] = '';
105 | },
106 | ),
107 | new TextFormField(
108 | decoration: const InputDecoration(labelText: 'Lastname'),
109 | keyboardType: TextInputType.text,
110 | onSaved: (String val) {
111 | if (val != null)
112 | customerBasicInformation['lastName'] = val;
113 | else
114 | customerBasicInformation['lastName'] = '';
115 | },
116 | ),
117 | new TextFormField(
118 | decoration: const InputDecoration(labelText: 'Username'),
119 | keyboardType: TextInputType.text,
120 | onSaved: (String val) {
121 | if (val != null)
122 | customerBasicInformation['userName'] = val;
123 | else
124 | customerBasicInformation['userName'] = '';
125 | },
126 | ),
127 | new TextFormField(
128 | decoration: const InputDecoration(labelText: 'Email'),
129 | keyboardType: TextInputType.emailAddress,
130 | validator: validateEmail,
131 | onSaved: (String val) {
132 | if (val != null) {
133 | customerBasicInformation['email'] = val;
134 | customerAddressInformation['email'] = val;
135 | }
136 | },
137 | ),
138 | new SizedBox(
139 | height: 10.0,
140 | ),
141 | ],
142 | );
143 | }
144 |
145 | Widget customerAddressInformationUI() {
146 | return new Column(
147 | children: [
148 | new TextFormField(
149 | decoration: const InputDecoration(labelText: 'Firstname'),
150 | keyboardType: TextInputType.text,
151 | validator: validateName,
152 | onSaved: (String val) {
153 | if (val != null)
154 | customerAddressInformation['first_name'] = val;
155 | else
156 | customerAddressInformation['first_name'] = '';
157 | },
158 | ),
159 | new TextFormField(
160 | decoration: const InputDecoration(labelText: 'Lastname'),
161 | keyboardType: TextInputType.text,
162 | onSaved: (String val) {
163 | if (val != null)
164 | customerAddressInformation['last_name'] = val;
165 | else
166 | customerAddressInformation['last_name'] = '';
167 | },
168 | ),
169 | new TextFormField(
170 | decoration: const InputDecoration(labelText: 'Phone'),
171 | keyboardType: TextInputType.phone,
172 | onSaved: (String val) {
173 | if (val != null)
174 | customerBasicInformation['phone'] = val;
175 | else
176 | customerBasicInformation['phone'] = '';
177 | },
178 | ),
179 | new TextFormField(
180 | decoration: const InputDecoration(labelText: 'Company'),
181 | keyboardType: TextInputType.text,
182 | onSaved: (String val) {
183 | if (val != null)
184 | customerAddressInformation['Company'] = val;
185 | else
186 | customerAddressInformation['Company'] = '';
187 | },
188 | ),
189 | new TextFormField(
190 | decoration: const InputDecoration(labelText: 'Address Line'),
191 | keyboardType: TextInputType.text,
192 | validator: validateName,
193 | onSaved: (String val) {
194 | if (val != null)
195 | customerAddressInformation['address_1'] = val;
196 | else
197 | customerAddressInformation['address_1'] = '';
198 | },
199 | ),
200 | new TextFormField(
201 | decoration: const InputDecoration(labelText: 'City'),
202 | keyboardType: TextInputType.text,
203 | onSaved: (String val) {
204 | if (val != null)
205 | customerAddressInformation['city'] = val;
206 | else
207 | customerAddressInformation['city'] = '';
208 | },
209 | ),
210 | new TextFormField(
211 | decoration: const InputDecoration(labelText: 'State'),
212 | keyboardType: TextInputType.text,
213 | onSaved: (String val) {
214 | if (val != null)
215 | customerAddressInformation['state'] = val;
216 | else
217 | customerAddressInformation['state'] = '';
218 | },
219 | ),
220 | new TextFormField(
221 | decoration: const InputDecoration(labelText: 'Postcode'),
222 | keyboardType: TextInputType.text,
223 | onSaved: (String val) {
224 | if (val != null)
225 | customerAddressInformation['postcode'] = val;
226 | else
227 | customerAddressInformation['postcode'] = '';
228 | },
229 | ),
230 | new TextFormField(
231 | decoration: const InputDecoration(labelText: 'Country'),
232 | keyboardType: TextInputType.text,
233 | onSaved: (String val) {
234 | if (val != null)
235 | customerAddressInformation['country'] = val;
236 | else
237 | customerAddressInformation['country'] = '';
238 | },
239 | ),
240 | new SizedBox(
241 | height: 10.0,
242 | ),
243 | ],
244 | );
245 | }
246 |
247 | String validateName(String value) {
248 | if (value.length < 1)
249 | return 'Field can not be empty';
250 | else if (value.length < 3)
251 | return 'Enter a valid value';
252 | else
253 | return null;
254 | }
255 |
256 | String validateEmail(String value) {
257 | Pattern pattern =
258 | 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,}))$';
259 | RegExp regex = new RegExp(pattern);
260 | if (!regex.hasMatch(value))
261 | return 'Enter Valid Email';
262 | else
263 | return null;
264 | }
265 |
266 | void _validateInputs() {
267 | if (_formKey.currentState.validate()) {
268 | //If all data are correct then save data to out variables
269 | _formKey.currentState.save();
270 |
271 | // After save data to variable a http request to create a new customer
272 | bloc.createCustomer(customerBasicInformation, customerAddressInformation,
273 | _scaffoldKey, context);
274 | } else {
275 | //If all data are not valid then start auto validation.
276 | setState(() {
277 | _autoValidate = true;
278 | });
279 | }
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/lib/screen/cutomer_list_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:woocommerce_app/bloc/customer_list_bloc.dart';
4 | import 'package:woocommerce_app/helper/const.dart';
5 |
6 | class CustomerListPage extends StatefulWidget {
7 | @override
8 | CustomerListPageState createState() => new CustomerListPageState();
9 | }
10 |
11 | class CustomerListPageState extends State {
12 | Widget _mainFormWidget; // Save the form
13 |
14 | var bloc; // Associate bloc
15 |
16 | BuildContext _context;
17 |
18 | @override
19 | void initState() {
20 | super.initState();
21 | bloc = CustomerListBloc();
22 | }
23 |
24 | @override
25 | Widget build(BuildContext context) {
26 | _context = context;
27 |
28 | if (_mainFormWidget == null) {
29 | _mainFormWidget = mainBody();
30 | }
31 |
32 | return _mainFormWidget; // Show the form in the application
33 | }
34 |
35 | Widget mainBody() {
36 | return new Scaffold(
37 | resizeToAvoidBottomInset: true,
38 | floatingActionButton: FloatingActionButton(
39 | onPressed: () {
40 | bloc.routeToCustomerAddPage(_context);
41 | },
42 | child: Icon(Icons.people),
43 | backgroundColor: Colors.green,
44 | ),
45 | appBar: new AppBar(
46 | iconTheme: IconThemeData(
47 | color: Colors.white, //change your color here
48 | ),
49 | title: new Text("Customers", style: TextStyle(color: Colors.white)),
50 | ),
51 | body: body());
52 | }
53 |
54 | Widget body() {
55 | return new Column(children: [
56 | // Search Box Widget
57 |
58 | Container(
59 | height: 50,
60 | child: new Card(
61 | child: new Row(
62 | children: [
63 | new Expanded(
64 | child: new TextField(
65 | decoration: new InputDecoration(
66 | contentPadding: EdgeInsets.fromLTRB(10.0, 15.0, 20.0, 15.0),
67 | prefixIcon: Icon(Icons.search),
68 | hintText: ' Search',
69 | border: InputBorder.none),
70 | onChanged: bloc.onSearchTextChanged,
71 | )),
72 | ],
73 | )),
74 | ),
75 |
76 | // Customer List Widget
77 |
78 | customerListBuild()
79 | ]);
80 | }
81 |
82 | /*
83 | * Function perform a http request using BLoc for all customer list
84 | * Return a list widget using Stream builder
85 | */
86 |
87 | Widget customerListBuild() {
88 | bloc.fetchCustomers('');
89 | return StreamBuilder(
90 | stream: bloc.allCustomers,
91 | builder: (context, AsyncSnapshot snapshot) {
92 | return snapshot.hasData
93 | ? customerListViewWidget(snapshot)
94 | : Align(
95 | alignment: Alignment.center,
96 | child: CircularProgressIndicator());
97 | },
98 | );
99 | }
100 |
101 |
102 | /*
103 | * Function takes AsyncSnapshot data for build a ListView
104 | * Function return a ListView widget
105 | */
106 |
107 | Widget customerListViewWidget(AsyncSnapshot snapshot) {
108 | return new Expanded(
109 | child: ListView.builder(
110 | itemCount: snapshot.data.length,
111 | itemBuilder: (_, index) {
112 | return InkWell(
113 | onTap: () {
114 | bloc.routeToPlaceOrderPage(_context, snapshot.data[index]);
115 | },
116 | child: Container(
117 | margin: EdgeInsets.all(6),
118 | child: Card(
119 | child: Column(
120 | children: [
121 | ListTile(
122 | trailing: IconButton(
123 | icon: Icon(
124 | Icons.arrow_forward_ios,
125 | size: 18,
126 | ),
127 | onPressed: () {
128 | bloc.routeToPlaceOrderPage(
129 | _context, snapshot.data[index]);
130 | }),
131 | leading: new Container(
132 | child: new Center(
133 | child: Text(
134 | snapshot.data[index]["email"].substring(0, 1),
135 | style: TextStyle(
136 | color: Colors.white,
137 | fontWeight: FontWeight.w600),
138 | ),
139 | ),
140 | width: 40.0,
141 | height: 40.0,
142 | decoration: new BoxDecoration(
143 | shape: BoxShape.circle, color: Colors.red)),
144 | title: Text(snapshot.data[index]["email"],
145 | style: TextStyle(
146 | fontSize: 14,
147 | fontWeight: FontWeight.w500,
148 | color: Colors.black)),
149 | subtitle: Text(
150 | snapshot.data[index]["shipping"]["address_1"]
151 | .toString(),
152 | style: TextStyle(
153 | fontSize: 12,
154 | fontWeight: FontWeight.w400,
155 | color: Colors.grey)),
156 | ),
157 | ],
158 | ))));
159 | }));
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/lib/screen/home_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:convert';
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:woocommerce_app/bloc/home_page_bloc.dart';
6 | import 'package:woocommerce_app/helper/const.dart';
7 | import 'package:woocommerce_app/helper/hex_color.dart';
8 | import 'package:woocommerce_app/screen/cutomer_list_page.dart';
9 | import 'package:http/http.dart' as http;
10 | import 'package:woocommerce_app/screen/my_profile_page.dart';
11 | import 'package:woocommerce_app/screen/order_list_page.dart';
12 | import 'package:woocommerce_app/screen/place_order_page.dart';
13 | import 'package:woocommerce_app/helper/ui_helper.dart';
14 |
15 |
16 | class HomePage extends StatefulWidget {
17 | @override
18 | HomePagePageState createState() => new HomePagePageState();
19 | }
20 |
21 | class HomePagePageState extends State {
22 |
23 | var bloc;
24 |
25 | @override
26 | void initState() {
27 | super.initState();
28 | bloc = HomePageBloc();
29 |
30 | // Function call for sales status report
31 | bloc.fetchSalesReports();
32 |
33 | }
34 |
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | return new Scaffold(
39 | floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
40 | appBar: new AppBar(
41 | iconTheme: IconThemeData(
42 | color: Colors.white, //change your color here
43 | ),
44 | title: new Text("Woocom Admin", style: TextStyle(color: Colors.white)),
45 | ),
46 | persistentFooterButtons: [
47 | Text('Version 1.0.0'),
48 | ],
49 | drawer: Drawer(
50 | child: ListView(
51 | padding: EdgeInsets.zero,
52 | children: [
53 | DrawerHeader(
54 | child: Column(
55 | mainAxisSize: MainAxisSize.min,
56 | mainAxisAlignment: MainAxisAlignment.center,
57 | children: [
58 | CircleAvatar(
59 | backgroundColor: Colors.white,
60 | radius: 40.0,
61 | child: Image.asset('images/woocom_icon.jpg'),
62 | ),
63 | SizedBox(height: 20,),
64 | Text("Welcome to Woocom Admin",
65 | style: TextStyle(color: Colors.white),),
66 | SizedBox(height: 10,),
67 | ],
68 | ),
69 | decoration: BoxDecoration(
70 | color: Colors.red,
71 | ),
72 | ),
73 |
74 | ListTile(
75 | leading: Icon(Icons.library_add),
76 | title: Text('New Order'),
77 | onTap: () {
78 |
79 | // Route to Order Add Page
80 |
81 | Navigator.push(
82 | context,
83 | MaterialPageRoute(
84 | builder: (context) =>
85 | PlaceOrderPage(null)));
86 | // Navigator.pop(context);
87 | },
88 | ),
89 |
90 | ListTile(
91 | leading: Icon(Icons.border_all),
92 | title: Text('My Order'),
93 | onTap: () {
94 |
95 | // Route to Order List Page
96 |
97 | Navigator.push(
98 | context,
99 | MaterialPageRoute(
100 | builder: (context) =>
101 | OrderListPage()));
102 |
103 | },
104 | ),
105 |
106 | ListTile(
107 | leading: Icon(Icons.account_circle),
108 | title: Text('My Profile'),
109 | onTap: () {
110 | Navigator.push(
111 | context,
112 | MaterialPageRoute(
113 | builder: (context) =>
114 | UserProfilePage()));
115 | // Navigator.pop(context);
116 | },
117 | ),
118 |
119 |
120 | ],
121 | ),
122 | ),
123 | body: new Container(
124 |
125 | color: HexColor("#FFF8F8"),
126 |
127 | child: Column(
128 |
129 | children: [
130 |
131 |
132 | Container(
133 |
134 | color: Colors.transparent,
135 |
136 | height: MediaQuery
137 | .of(context)
138 | .size
139 | .height * 0.35,
140 |
141 |
142 | child: Row(
143 |
144 |
145 | children: [
146 |
147 | Expanded(
148 |
149 | child: Container(
150 |
151 | margin: EdgeInsets.only(
152 | left: 20, top: 30, bottom: 30, right: 15),
153 |
154 |
155 | child: InkWell(
156 | onTap: () {
157 |
158 | // Route to Customer List Page
159 |
160 | Navigator.push(
161 | context,
162 | MaterialPageRoute(
163 | builder: (context) =>
164 | CustomerListPage()));
165 | },
166 | child: Card(
167 |
168 | child: Center(
169 |
170 |
171 | child: Column(
172 |
173 | mainAxisAlignment: MainAxisAlignment
174 | .center,
175 | mainAxisSize: MainAxisSize.max,
176 |
177 | children: [
178 |
179 | Icon(
180 | Icons.people,
181 | color: UIHelper.themeColor,
182 | size: 40,
183 | ),
184 |
185 | Container(height: 10,),
186 |
187 | Text('Customers',style: TextStyle(
188 | color: Colors.black,
189 | fontWeight: FontWeight.w400,
190 | fontSize: 14
191 | ))
192 |
193 | ]
194 |
195 | )
196 |
197 |
198 | ),
199 | )),
200 | )
201 |
202 |
203 | ),
204 |
205 | Expanded(
206 |
207 | child: Container(
208 |
209 | margin: EdgeInsets.only(
210 | left: 15, top: 30, bottom: 30, right: 20),
211 |
212 |
213 | child: InkWell(
214 | onTap: () {
215 |
216 | // Route to Order List Page
217 |
218 | Navigator.push(
219 | context,
220 | MaterialPageRoute(
221 | builder: (context) =>
222 | OrderListPage()));
223 | },
224 | child: Card(
225 |
226 | child: Center(
227 |
228 |
229 | child: Column(
230 |
231 | mainAxisAlignment: MainAxisAlignment
232 | .center,
233 | mainAxisSize: MainAxisSize.max,
234 |
235 | children: [
236 |
237 | Icon(
238 | Icons.assignment,
239 | color: UIHelper.themeColor,
240 | size: 40,
241 | ),
242 |
243 | Container(height: 10,),
244 |
245 | Text('Orders',style: TextStyle(
246 | color: Colors.black,
247 | fontWeight: FontWeight.w400,
248 | fontSize: 14
249 | ))
250 |
251 | ]
252 |
253 | )
254 |
255 |
256 | ),
257 | )),
258 | )
259 |
260 |
261 | )
262 |
263 |
264 | ],
265 |
266 |
267 | )
268 |
269 | ),
270 |
271 | Container(
272 |
273 |
274 | height: MediaQuery
275 | .of(context)
276 | .size
277 | .height * 0.45,
278 |
279 | child: Container(
280 |
281 |
282 | margin: EdgeInsets.all(20.0),
283 |
284 | child: Card(
285 |
286 |
287 | elevation: 2,
288 | child: ClipPath(
289 |
290 | clipper: ShapeBorderClipper(
291 | shape: RoundedRectangleBorder(
292 | borderRadius: BorderRadius.circular(3))),
293 |
294 | child: Container(
295 |
296 | decoration: BoxDecoration(
297 | border: Border(top: BorderSide(
298 | color: Colors.red, width: 5))),
299 |
300 | child: Container(
301 |
302 |
303 | margin: EdgeInsets.all(20.0),
304 |
305 | child:
306 |
307 | Column(
308 |
309 | children: [
310 |
311 |
312 | Flexible(
313 |
314 | flex: 5,
315 |
316 | child: new Row(
317 |
318 | children: [
319 |
320 |
321 | Flexible(
322 |
323 | flex: 3,
324 | child: new Center(
325 |
326 | child: Column(
327 |
328 | mainAxisAlignment: MainAxisAlignment
329 | .center,
330 | mainAxisSize: MainAxisSize
331 | .max,
332 |
333 | children: <
334 | Widget>[
335 |
336 | totalCountPerModuleWidget(
337 | 'customers'),
338 |
339 | Container(
340 | height: 5,),
341 |
342 | Text(
343 | 'Customer',
344 | style: UIHelper.getTextStyleForHomeScreenItem(),)
345 |
346 | ]
347 |
348 | )
349 |
350 | )),
351 |
352 |
353 | new Container(
354 | color: Colors.grey,
355 | width: .5, height: 40,),
356 |
357 | Flexible(
358 |
359 | flex: 3,
360 | child: new Container(
361 |
362 | child: Column(
363 |
364 | mainAxisAlignment: MainAxisAlignment
365 | .center,
366 | mainAxisSize: MainAxisSize
367 | .max,
368 |
369 | children: <
370 | Widget>[
371 |
372 | totalCountPerModuleWidget(
373 | 'products'),
374 |
375 | Container(
376 | height: 5,),
377 |
378 | Text(
379 | 'Products',
380 | style: UIHelper.getTextStyleForHomeScreenItem())
381 |
382 | ]
383 |
384 | )
385 |
386 | )),
387 |
388 | new Container(
389 | color: Colors.grey,
390 | width: .5, height: 40,),
391 | Flexible(
392 |
393 | flex: 3,
394 | child: new Container(
395 | child: Column(
396 |
397 | mainAxisAlignment: MainAxisAlignment
398 | .center,
399 | mainAxisSize: MainAxisSize
400 | .max,
401 |
402 | children: <
403 | Widget>[
404 |
405 | totalCountPerModuleWidget(
406 | 'orders'),
407 |
408 | Container(
409 | height: 5,),
410 |
411 | Text('Orders',
412 | style: UIHelper.getTextStyleForHomeScreenItem(),)
413 |
414 | ]
415 |
416 | ))),
417 |
418 |
419 | ]
420 | )),
421 |
422 |
423 | new Container(
424 | height: .5, color: Colors.grey,),
425 |
426 |
427 | Flexible(
428 |
429 | flex: 5,
430 |
431 | child: new Row(
432 |
433 | children: [
434 |
435 |
436 | Flexible(
437 |
438 | flex: 3,
439 | child: new Center(
440 |
441 | child: Column(
442 |
443 | mainAxisAlignment: MainAxisAlignment
444 | .center,
445 | mainAxisSize: MainAxisSize
446 | .max,
447 |
448 | children: <
449 | Widget>[
450 |
451 | salesValueReportBySalesType('average'),
452 |
453 | Container(
454 | height: 5,),
455 |
456 | Text(
457 | 'Avg sales',
458 | style: UIHelper.getTextStyleForHomeScreenItem())
459 |
460 | ]
461 |
462 | )
463 |
464 | )),
465 |
466 |
467 | new Container(
468 | color: Colors.grey,
469 | width: .5, height: 40,),
470 |
471 | Flexible(
472 |
473 | flex: 3,
474 | child: new Container(
475 |
476 | child: Column(
477 |
478 | mainAxisAlignment: MainAxisAlignment
479 | .center,
480 | mainAxisSize: MainAxisSize
481 | .max,
482 |
483 | children: <
484 | Widget>[
485 |
486 | salesValueReportBySalesType('net'),
487 |
488 | Container(
489 | height: 5,),
490 |
491 | Text(
492 | 'Net sales',
493 | style: UIHelper.getTextStyleForHomeScreenItem())
494 |
495 | ]
496 |
497 | )
498 |
499 | )),
500 |
501 | new Container(
502 | color: Colors.grey,
503 | width: .5, height: 40,),
504 | Flexible(
505 |
506 | flex: 3,
507 | child: new Container(
508 | child: Column(
509 |
510 | mainAxisAlignment: MainAxisAlignment
511 | .center,
512 | mainAxisSize: MainAxisSize
513 | .max,
514 |
515 | children: <
516 | Widget>[
517 |
518 | salesValueReportBySalesType('total'),
519 |
520 | Container(
521 | height: 5,),
522 |
523 | Text(
524 | 'Total sales',
525 | style: UIHelper.getTextStyleForHomeScreenItem())
526 |
527 | ]
528 |
529 | ))),
530 |
531 |
532 | ]
533 | )),
534 |
535 |
536 | ],
537 |
538 |
539 | )
540 |
541 |
542 | ))),
543 |
544 |
545 | )
546 |
547 |
548 | )
549 |
550 |
551 | )
552 | ],
553 |
554 | )
555 |
556 |
557 | )
558 | );
559 | }
560 |
561 | /*
562 | * This function takes input module name
563 | * Perform a http request
564 | * return the total count of module
565 | * Set the count value in Text Widget
566 | * return a Widget
567 | */
568 |
569 |
570 | Widget totalCountPerModuleWidget(String moduleName ) {
571 |
572 | bloc.fetchPerModuleCount(moduleName);
573 |
574 | Stream stream ;
575 |
576 | if(moduleName=='customers')
577 | {
578 | stream = bloc.customerCountFetcher.stream;
579 | }
580 | else if(moduleName=='products')
581 | {
582 | stream = bloc.productCountFetcher.stream;
583 | }
584 | else if(moduleName=='orders')
585 | {
586 | stream = bloc.orderCountFetcher.stream;
587 | }
588 |
589 |
590 | return StreamBuilder(
591 | stream: stream,
592 | builder: (context, AsyncSnapshot snapshot) {
593 | return snapshot.hasData
594 | ? new Container(
595 | child: Text(snapshot.data.toString(),style: TextStyle(color: UIHelper.themeColor,fontWeight: FontWeight.w600,fontSize: 14)))
596 | : new Container(
597 | height: 20,
598 | width: 20,
599 | child:CircularProgressIndicator(strokeWidth: 2,));
600 | },
601 | );
602 | }
603 |
604 | Widget salesValueReportBySalesType(String salesType ) {
605 |
606 | Stream stream ;
607 |
608 | if(salesType=='average')
609 | {
610 | stream = bloc.averageSalesValueFetcher.stream;
611 | }
612 | else if(salesType=='net')
613 | {
614 | stream = bloc.netSalesValueFetcher.stream;
615 | }
616 | else if(salesType=='total')
617 | {
618 | stream = bloc.totalSalesValueFetcher.stream;
619 | }
620 |
621 | return StreamBuilder(
622 | stream: stream,
623 | builder: (context, AsyncSnapshot snapshot) {
624 | return snapshot.hasData
625 | ? new Container(
626 | child: Text('\$ '+snapshot.data.toString(),style: TextStyle(color: UIHelper.themeColor)))
627 | : new Container(
628 | height: 20,
629 | width: 20,
630 | child:CircularProgressIndicator(strokeWidth: 2,));
631 | },
632 | );
633 | }
634 |
635 |
636 | }
637 |
--------------------------------------------------------------------------------
/lib/screen/my_profile_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class UserProfilePage extends StatelessWidget {
4 | final String _fullName = "Shahanaj Parvin";
5 | final String _status = "Software Developer";
6 | final String _bio =
7 | "\"Hi, I am a Freelance developer working for hourly basis. If you wants to contact me to build your product leave a message.\"";
8 | final String _followers = "173";
9 | final String _posts = "24";
10 | final String _scores = "450";
11 |
12 | Widget _buildCoverImage(Size screenSize) {
13 | return Container(
14 | height: screenSize.height / 2.6,
15 | decoration: BoxDecoration(
16 | image: DecorationImage(
17 | image: AssetImage('images/cover_photo.jpg'),
18 | fit: BoxFit.cover,
19 | ),
20 | ),
21 | );
22 | }
23 |
24 | Widget _buildProfileImage() {
25 | return Center(
26 | child: Container(
27 | width: 120.0,
28 | height: 120.0,
29 | decoration: BoxDecoration(
30 | image: DecorationImage(
31 | image: AssetImage('images/woocom_icon.jpg'),
32 | fit: BoxFit.cover,
33 | ),
34 | borderRadius: BorderRadius.circular(80.0),
35 | border: Border.all(
36 | color: Colors.white,
37 | width: 5.0,
38 | ),
39 | ),
40 | ),
41 | );
42 | }
43 |
44 | Widget _buildFullName() {
45 | TextStyle _nameTextStyle = TextStyle(
46 | fontFamily: 'Roboto',
47 | color: Colors.black,
48 | fontSize: 28.0,
49 | fontWeight: FontWeight.w700,
50 | );
51 |
52 | return Text(
53 | _fullName,
54 | style: _nameTextStyle,
55 | );
56 | }
57 |
58 | Widget _buildStatus(BuildContext context) {
59 | return Container(
60 | padding: EdgeInsets.symmetric(vertical: 4.0, horizontal: 6.0),
61 | decoration: BoxDecoration(
62 | color: Theme.of(context).scaffoldBackgroundColor,
63 | borderRadius: BorderRadius.circular(4.0),
64 | ),
65 | child: Text(
66 | _status,
67 | style: TextStyle(
68 | fontFamily: 'Spectral',
69 | color: Colors.black,
70 | fontSize: 20.0,
71 | fontWeight: FontWeight.w300,
72 | ),
73 | ),
74 | );
75 | }
76 |
77 | Widget _buildStatItem(String label, String count) {
78 | TextStyle _statLabelTextStyle = TextStyle(
79 | fontFamily: 'Roboto',
80 | color: Colors.black,
81 | fontSize: 16.0,
82 | fontWeight: FontWeight.w200,
83 | );
84 |
85 | TextStyle _statCountTextStyle = TextStyle(
86 | color: Colors.black54,
87 | fontSize: 24.0,
88 | fontWeight: FontWeight.bold,
89 | );
90 |
91 | return Column(
92 | mainAxisAlignment: MainAxisAlignment.center,
93 | children: [
94 | Text(
95 | count,
96 | style: _statCountTextStyle,
97 | ),
98 | Text(
99 | label,
100 | style: _statLabelTextStyle,
101 | ),
102 | ],
103 | );
104 | }
105 |
106 | Widget _buildStatContainer() {
107 | return Container(
108 | height: 60.0,
109 | margin: EdgeInsets.only(top: 8.0),
110 | decoration: BoxDecoration(
111 | color: Color(0xFFEFF4F7),
112 | ),
113 | child: Row(
114 | mainAxisAlignment: MainAxisAlignment.spaceAround,
115 | children: [
116 | _buildStatItem("Followers", _followers),
117 | _buildStatItem("Posts", _posts),
118 | _buildStatItem("Scores", _scores),
119 | ],
120 | ),
121 | );
122 | }
123 |
124 | Widget _buildBio(BuildContext context) {
125 | TextStyle bioTextStyle = TextStyle(
126 | fontFamily: 'Spectral',
127 | fontWeight: FontWeight.w400,//try changing weight to w500 if not thin
128 | fontStyle: FontStyle.italic,
129 | color: Color(0xFF799497),
130 | fontSize: 16.0,
131 | );
132 |
133 | return Container(
134 | color: Theme.of(context).scaffoldBackgroundColor,
135 | padding: EdgeInsets.all(8.0),
136 | child: Text(
137 | _bio,
138 | textAlign: TextAlign.center,
139 | style: bioTextStyle,
140 | ),
141 | );
142 | }
143 |
144 | Widget _buildSeparator(Size screenSize) {
145 | return Container(
146 | width: screenSize.width / 1.6,
147 | height: 2.0,
148 | color: Colors.black54,
149 | margin: EdgeInsets.only(top: 4.0),
150 | );
151 | }
152 |
153 | Widget _buildGetInTouch(BuildContext context) {
154 | return Container(
155 | color: Theme.of(context).scaffoldBackgroundColor,
156 | padding: EdgeInsets.only(top: 8.0),
157 | child: Text(
158 | "Get in Touch with ${_fullName.split(" ")[0]},",
159 | style: TextStyle(fontFamily: 'Roboto', fontSize: 16.0),
160 | ),
161 | );
162 | }
163 |
164 | Widget _buildButtons() {
165 | return Padding(
166 | padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
167 | child: Row(
168 | children: [
169 | Expanded(
170 | child: InkWell(
171 | onTap: () => print("followed"),
172 | child: Container(
173 | height: 40.0,
174 | decoration: BoxDecoration(
175 | border: Border.all(),
176 | color: Color(0xFF404A5C),
177 | ),
178 | child: Center(
179 | child: Text(
180 | "FOLLOW",
181 | style: TextStyle(
182 | color: Colors.white,
183 | fontWeight: FontWeight.w600,
184 | ),
185 | ),
186 | ),
187 | ),
188 | ),
189 | ),
190 | SizedBox(width: 10.0),
191 | Expanded(
192 | child: InkWell(
193 | onTap: () => print("Message"),
194 | child: Container(
195 | height: 40.0,
196 | decoration: BoxDecoration(
197 | border: Border.all(),
198 | ),
199 | child: Center(
200 | child: Padding(
201 | padding: EdgeInsets.all(10.0),
202 | child: Text(
203 | "MESSAGE",
204 | style: TextStyle(fontWeight: FontWeight.w600),
205 | ),
206 | ),
207 | ),
208 | ),
209 | ),
210 | ),
211 | ],
212 | ),
213 | );
214 | }
215 |
216 | @override
217 | Widget build(BuildContext context) {
218 | Size screenSize = MediaQuery.of(context).size;
219 | return Scaffold(
220 | body: Stack(
221 | children: [
222 | _buildCoverImage(screenSize),
223 | SafeArea(
224 | child: SingleChildScrollView(
225 | child: Column(
226 | children: [
227 | SizedBox(height: screenSize.height / 4),
228 | _buildProfileImage(),
229 | SizedBox(height: 20,),
230 | _buildFullName(),
231 | SizedBox(height: 10,),
232 | _buildStatus(context),
233 | SizedBox(height: 15,),
234 | _buildStatContainer(),
235 | _buildBio(context),
236 | _buildSeparator(screenSize),
237 | SizedBox(height: 10.0),
238 | _buildGetInTouch(context),
239 | SizedBox(height: 8.0),
240 | _buildButtons(),
241 | ],
242 | ),
243 | ),
244 | ),
245 | ],
246 | ),
247 | );
248 | }
249 | }
--------------------------------------------------------------------------------
/lib/screen/order_list_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:woocommerce_app/bloc/customer_list_bloc.dart';
4 | import 'package:woocommerce_app/bloc/order_list_bloc.dart';
5 | import 'package:woocommerce_app/helper/const.dart';
6 |
7 | class OrderListPage extends StatefulWidget {
8 | @override
9 | OrderListPageState createState() => new OrderListPageState();
10 | }
11 |
12 | class OrderListPageState extends State {
13 |
14 |
15 | Widget _mainFormWidget;
16 |
17 | var bloc;
18 |
19 | BuildContext _context;
20 |
21 | @override
22 | void initState() {
23 | super.initState();
24 | bloc = OrderListBloc();
25 | }
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 | _context = context;
30 |
31 | if (_mainFormWidget == null) {
32 | _mainFormWidget = mainBody();
33 | }
34 | return _mainFormWidget; // Show the form in the application
35 | }
36 |
37 | Widget mainBody() {
38 | return new Scaffold(
39 | resizeToAvoidBottomInset: true,
40 | floatingActionButton: FloatingActionButton(
41 | onPressed: () {
42 | bloc.routeToNewOrderPage(_context);
43 | },
44 | child: Icon(
45 | Icons.note_add,
46 | color: Colors.white,
47 | ),
48 | backgroundColor: Colors.green,
49 | ),
50 | appBar: new AppBar(
51 | iconTheme: IconThemeData(
52 | color: Colors.white, //change your color here
53 | ),
54 | title: new Text("Orders", style: TextStyle(color: Colors.white)),
55 | ),
56 | body: body());
57 | }
58 |
59 | Widget body() {
60 | return new Column(children: [
61 |
62 | // Search Box Widget
63 |
64 | Container(
65 | height: 50,
66 | child: new Card(
67 | child: new Row(
68 | children: [
69 | new Expanded(
70 | child: new TextField(
71 | // controller: controller,
72 | decoration: new InputDecoration(
73 | contentPadding: EdgeInsets.fromLTRB(10.0, 15.0, 20.0, 15.0),
74 | prefixIcon: Icon(Icons.search),
75 | hintText: ' Search',
76 | border: InputBorder.none),
77 | onChanged: bloc.onSearchTextChanged,
78 | )),
79 | ],
80 | )),
81 | ),
82 |
83 |
84 |
85 | ordersListBuild() // Orders List Widget
86 | ]);
87 | }
88 |
89 | /*
90 | * Function perform a http request using BLoc for all orders list
91 | * Return a list widget using Stream builder
92 | */
93 |
94 | Widget ordersListBuild() {
95 | bloc.fetchOrders('');
96 | return StreamBuilder(
97 | stream: bloc.allOrders,
98 | builder: (context, AsyncSnapshot snapshot) {
99 | return snapshot.hasData
100 | ? ordersListViewWidget(snapshot)
101 | : Align(
102 | alignment: Alignment.center,
103 | child: CircularProgressIndicator());
104 | },
105 | );
106 | }
107 |
108 | /*
109 | * Function takes AsyncSnapshot data for build a ListView
110 | * Function return a ListView widget
111 | */
112 |
113 | Widget ordersListViewWidget(AsyncSnapshot s) {
114 | return new Expanded(
115 | child: ListView.builder(
116 | itemCount: s.data.length,
117 | itemBuilder: (_, index) {
118 | return InkWell(
119 | /*onTap: () {
120 | bloc.routeToPlaceOrderPage(_context, s.data[index]);
121 | },*/
122 | child: Container(
123 | margin: EdgeInsets.all(6),
124 | child: Card(
125 | child: Column(
126 | children: [
127 | ListTile(
128 | trailing: statusBox(s.data[index]['status']),
129 | leading: new Container(
130 | child: new Center(
131 | child: Text(
132 | "#" + s.data[index]["id"].toString(),
133 | style: TextStyle(
134 | color: Colors.white,
135 | fontWeight: FontWeight.w600),
136 | ),
137 | ),
138 | width: 40.0,
139 | height: 40.0,
140 | decoration: new BoxDecoration(
141 | shape: BoxShape.circle, color: Colors.red)),
142 | title: Text(s.data[index]['billing']["email"],
143 | style: TextStyle(
144 | fontSize: 12,
145 | fontWeight: FontWeight.w400,
146 | color: Colors.grey)),
147 | subtitle: Text(
148 | s.data[index]["date_created"]
149 | .toString()
150 | .substring(0, 10) +
151 | " || " +
152 | s.data[index]["currency"].toString() +
153 | " " +
154 | s.data[index]["total"].toString(),
155 | style: TextStyle(
156 | fontSize: 14,
157 | fontWeight: FontWeight.w500,
158 | color: Colors.black)),
159 | ),
160 | ],
161 | ))));
162 | }));
163 | }
164 |
165 | /*
166 | * Function take order status input
167 | * Build a orders status and background color according to the status
168 | * */
169 |
170 | Widget statusBox(String orderStatus) {
171 | Color bgColor = Colors.blueAccent;
172 |
173 | if (orderStatus == 'processing') {
174 | bgColor = Colors.blue;
175 | } else if (orderStatus == 'completed') {
176 | bgColor = Colors.green;
177 | } else if (orderStatus == 'on-hold') {
178 | bgColor = Colors.orange;
179 | }
180 |
181 | return Container(
182 | width: 70,
183 | height: 30,
184 | child: Center(
185 | child: Text(orderStatus,
186 | style: TextStyle(
187 | fontSize: 12,
188 | fontWeight: FontWeight.w400,
189 | color: Colors.white))),
190 | decoration: BoxDecoration(
191 | color: bgColor, borderRadius: BorderRadius.circular(3)));
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/lib/screen/place_order_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:woocommerce_app/bloc/place_order_bloc.dart';
4 | import 'package:woocommerce_app/helper/ui_helper.dart';
5 | import 'package:woocommerce_app/model/ordered_product.dart';
6 |
7 | class PlaceOrderPage extends StatefulWidget {
8 |
9 | var customer; // Order place to this customer
10 |
11 | PlaceOrderPage(this.customer);
12 |
13 | @override
14 | PlaceOrderPageState createState() => new PlaceOrderPageState(this);
15 | }
16 |
17 | class PlaceOrderPageState extends State {
18 |
19 | Widget _mainFormWidget;
20 |
21 | var bloc;
22 |
23 | BuildContext _context;
24 |
25 | final _scaffoldKey = GlobalKey();
26 |
27 | PlaceOrderPage parent;
28 |
29 | PlaceOrderPageState(this.parent);
30 |
31 | @override
32 | void initState() {
33 | super.initState();
34 | bloc = PlaceOrderBloc(parent.customer);
35 |
36 | }
37 |
38 | @override
39 | Widget build(BuildContext context) {
40 | _context = context;
41 | if (_mainFormWidget == null) {
42 | _mainFormWidget = mainBody();
43 | }
44 | return _mainFormWidget; // Show the form in the application
45 | }
46 |
47 | Widget mainBody() {
48 | return new Scaffold(
49 | key: _scaffoldKey,
50 | bottomNavigationBar: new Container(
51 | height: 45,
52 | child: Row(
53 | children: [
54 | Expanded(
55 | flex: 5,
56 | child: InkWell(
57 | onTap: () {
58 | bloc.routeToCartPage(_context, _scaffoldKey);
59 | },
60 | child: Container(
61 | color: UIHelper.themeColor,
62 | child: Center(
63 | child: Text('Go Cart',
64 | style: TextStyle(
65 | fontWeight: FontWeight.w600,
66 | fontSize: 18,
67 | color: Colors.white)),
68 | )))),
69 | Expanded(
70 | flex: 5,
71 | child: Center(
72 | child: totalCreditWidget(),
73 | ),
74 | )
75 | ],
76 | ),
77 | ),
78 | resizeToAvoidBottomInset: true,
79 | appBar: new AppBar(
80 | iconTheme: IconThemeData(
81 | color: Colors.white, //change your color here
82 | ),
83 | title: new Text("New Order", style: TextStyle(color: Colors.white)),
84 | actions: [
85 | routeToCartWidget()
86 | ]),
87 | body: body());
88 | }
89 |
90 | /*
91 | * Function request to the bloc for total ordered product credit and return a widget with total credit value
92 | */
93 |
94 | Widget totalCreditWidget() {
95 | bloc.fetchTotalProductsCreditValue();
96 | return StreamBuilder(
97 | stream: bloc.totalCreditValueFetcher.stream,
98 | builder: (context, AsyncSnapshot snapshot) {
99 | return snapshot.hasData
100 | ? Text(
101 | '\$ ' + snapshot.data.toString(),
102 | style: TextStyle(
103 | fontWeight: FontWeight.w600,
104 | fontSize: 18,
105 | color: UIHelper.themeColor),
106 | )
107 | : Center(child: CircularProgressIndicator());
108 | },
109 | );
110 | }
111 |
112 | /*
113 | * Return the main widget body
114 | */
115 |
116 | Widget body() {
117 | return new Column(children: [
118 |
119 | // Product list search widget
120 | Container(
121 | height: 50,
122 | child: new Card(
123 | child: new Row(
124 | children: [
125 | new Expanded(
126 | flex: 6,
127 | child: new TextField(
128 | decoration: new InputDecoration(
129 | contentPadding:
130 | EdgeInsets.fromLTRB(10.0, 15.0, 20.0, 15.0),
131 | prefixIcon: Icon(Icons.search),
132 | hintText: ' Search',
133 | border: InputBorder.none),
134 | onChanged: bloc.onSearchTextChanged,
135 | )),
136 | new Container(
137 | width: 1,
138 | height: 50,
139 | color: Colors.grey,
140 | ),
141 | categoriesWidget()
142 | ],
143 | )),
144 | ),
145 |
146 | // Product List Build
147 | productListBuild()
148 | ]);
149 | }
150 |
151 | Widget routeToCartWidget() {
152 | bloc.totalCountProductItemInCart();
153 | return StreamBuilder(
154 | stream: bloc.totalCountProductItemInCartFetcher.stream,
155 | builder: (context, AsyncSnapshot snapshot) {
156 | return snapshot.hasData
157 | ? cartdButton(snapshot)
158 | : Center(child: Container());
159 | },
160 | );
161 | }
162 |
163 | Widget cartdButton(AsyncSnapshot s) {
164 | return new Container(
165 | child: new Stack(
166 | children: [
167 | new IconButton(
168 | padding: EdgeInsets.all(0),
169 | icon:
170 | new Icon(Icons.shopping_cart, color: Colors.white, size: 32),
171 | onPressed: () {
172 | bloc.routeToCartPage(_context, _scaffoldKey);
173 | }),
174 | new Positioned(
175 | left: 30.0,
176 | top: 5,
177 | child: Container(
178 | height: 24,
179 | width: 24,
180 | decoration: new BoxDecoration(
181 | color: Colors.green,
182 | shape: BoxShape.circle,
183 | ),
184 | child: Center(
185 | child: Text(
186 | s.data.toString(),
187 | style: TextStyle(color: Colors.white),
188 | ))),
189 | ),
190 | ],
191 | ),
192 | );
193 | }
194 |
195 | /*
196 | * Function request categories list by bloc
197 | * Return a dropdown widget by getting value
198 | */
199 |
200 | Widget categoriesWidget() {
201 | bloc.fetchCategories();
202 | return StreamBuilder(
203 | stream: bloc.categoriesFetcher.stream,
204 | builder: (context, AsyncSnapshot snapshot) {
205 | return snapshot.hasData
206 | ? categoryDropDownWidget(snapshot)
207 | : Center(child: CircularProgressIndicator());
208 | },
209 | );
210 | }
211 |
212 | /*
213 | * Function takes AsyncSnapshot data for build a dropdown widget
214 | * Function return a Dropdown widget
215 | */
216 |
217 | Widget categoryDropDownWidget(AsyncSnapshot snapshot) {
218 | String selectedValue;
219 | List categoriesList;
220 | snapshot.data.forEach((key, value) {
221 | selectedValue = key;
222 | categoriesList = value;
223 | });
224 |
225 | return new Expanded(
226 | flex: 4,
227 | child: Center(
228 | child: DropdownButtonHideUnderline(
229 | child: ButtonTheme(
230 | alignedDropdown: true,
231 | child: new DropdownButton(
232 | style: new TextStyle(
233 | inherit: false,
234 | color: Colors.black,
235 | decorationColor: Colors.white),
236 | isExpanded: true, // Not necessary for Option 1
237 | value: selectedValue,
238 | onChanged: (newValue) {
239 | bloc.searchByCategories(newValue);
240 | },
241 | items: categoriesList.map((location) {
242 | return DropdownMenuItem(
243 | child: new Text(location),
244 | value: location,
245 | );
246 | }).toList(),
247 | ),
248 | )),
249 | ));
250 | }
251 |
252 | /*
253 | * Function request product list using BLoc
254 | * Return a list widget using Stream builder
255 | */
256 |
257 | Widget productListBuild() {
258 | bloc.fetchProducts('', '');
259 | return StreamBuilder(
260 | stream: bloc.allProducts,
261 | builder: (context, AsyncSnapshot snapshot) {
262 | return snapshot.hasData
263 | ? productListViewWidget(snapshot)
264 | : Center(child: CircularProgressIndicator());
265 | },
266 | );
267 | }
268 | /*
269 | * Function takes AsyncSnapshot data for build a ListView
270 | * Function return a ListView widget
271 | */
272 |
273 | Widget productListViewWidget(AsyncSnapshot s) {
274 | return new Expanded(
275 | child: ListView.builder(
276 | itemCount: s.data.length,
277 | itemBuilder: (_, index) {
278 | OrderProducts product = s.data[index];
279 |
280 | String productImageUrl = product.imageUrl;
281 |
282 | if (productImageUrl != null &&
283 | !productImageUrl.contains('woocommerce-placeholder')) {
284 | productImageUrl = product.imageUrl;
285 | } else {
286 | productImageUrl = null;
287 | }
288 |
289 | return Container(
290 | margin: EdgeInsets.all(6),
291 | child: Card(
292 | child: Column(
293 | children: [
294 | ListTile(
295 | leading: new Container(
296 | child: productImageUrl != null
297 | ? new Container()
298 | : new Center(
299 | child: Text(
300 | product.name.substring(0, 1),
301 | style: TextStyle(
302 | color: Colors.white,
303 | fontWeight: FontWeight.w600),
304 | ),
305 | ),
306 | width: 40.0,
307 | height: 40.0,
308 | decoration: productImageUrl != null
309 | ? new BoxDecoration(
310 | shape: BoxShape.circle,
311 | image: new DecorationImage(
312 | fit: BoxFit.fill,
313 | image:
314 | new NetworkImage(product.imageUrl)))
315 | : new BoxDecoration(
316 | shape: BoxShape.circle,
317 | color: UIHelper.themeColor)),
318 | title: Text(product.name),
319 | subtitle: Text("MRP : " +
320 | product.mrp.toString() +
321 | " | " +
322 | "Stock : " +
323 | product.stock.toString()),
324 | ),
325 | SizedBox(
326 | height: 15,
327 | ),
328 | new Row(
329 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
330 | children: [
331 | SizedBox(
332 | width: 70,
333 | ),
334 | new Flexible(
335 | child: Container(
336 | width: 80,
337 | child: new Text(
338 | '\$ ' + product.totalCreditValue.toString()),
339 | )),
340 | Spacer(),
341 | Container(
342 | decoration: BoxDecoration(
343 | borderRadius: BorderRadius.circular(5.0),
344 | border: Border.all(
345 | color: UIHelper.themeColor, width: 2)),
346 | width: 122,
347 | height: 40,
348 | child: new Row(
349 | children: [
350 | Container(
351 | width: 39,
352 | child: Center(
353 | child: IconButton(
354 | icon: Icon(Icons.remove,
355 | color: UIHelper.themeColor),
356 | onPressed: () {
357 | bloc.orderRemove(product.id);
358 | })),
359 | ),
360 | Container(
361 | width: 40,
362 | height: 40,
363 | child: Center(
364 | child: Text(
365 | product.orderCount.toString(),
366 | style:
367 | TextStyle(color: UIHelper.themeColor),
368 | )),
369 | decoration: BoxDecoration(
370 | border: Border(
371 | right: BorderSide(
372 | width: 1.0,
373 | color: UIHelper.themeColor),
374 | left: BorderSide(
375 | width: 1.0,
376 | color: UIHelper.themeColor),
377 | ),
378 | color: Colors.white,
379 | ),
380 | ),
381 | Container(
382 | width: 39,
383 | child: Center(
384 | child: IconButton(
385 | icon: Icon(Icons.add,
386 | color: UIHelper.themeColor),
387 | onPressed: () {
388 | bloc.orderAdd(product.id);
389 | })),
390 | ),
391 | ],
392 | ),
393 | ),
394 | SizedBox(
395 | width: 10,
396 | ),
397 | ],
398 | ),
399 | SizedBox(
400 | height: 20,
401 | )
402 | ],
403 | )));
404 | }));
405 | }
406 | }
407 |
--------------------------------------------------------------------------------
/lib/screen/splash_screen_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'package:flutter/material.dart';
3 | import 'home_page.dart';
4 |
5 |
6 | class SplashScreen extends StatefulWidget {
7 | @override
8 | _SplashScreenState createState() => _SplashScreenState();
9 | }
10 |
11 | class _SplashScreenState extends State {
12 | @override
13 | void initState() {
14 | super.initState();
15 | Timer(Duration(seconds: 2), () {
16 | Navigator.pushReplacement(
17 | context,
18 | MaterialPageRoute(builder: (context) => HomePage()),
19 | );
20 | });
21 | }
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | return Scaffold(
26 | body: Stack(
27 | fit: StackFit.expand,
28 | children: [
29 | Container(
30 | decoration: BoxDecoration(color: Colors.red),
31 | ),
32 | Column(
33 | mainAxisAlignment: MainAxisAlignment.start,
34 | children: [
35 | Expanded(
36 | flex: 2,
37 | child: Container(
38 | child: Column(
39 | mainAxisAlignment: MainAxisAlignment.center,
40 | children: [
41 | CircleAvatar(
42 | backgroundColor: Colors.white,
43 | radius: 60.0,
44 | child: Image.asset('images/woocom_icon.jpg'),
45 | ),
46 | Padding(
47 | padding: EdgeInsets.all(10.0),
48 | ),
49 | Text(
50 | 'WooCom Admin',
51 | style: TextStyle(
52 | color: Colors.white,
53 | fontWeight: FontWeight.bold,
54 | fontSize: 24.0),
55 | )
56 | ],
57 | ),
58 | ),
59 | ),
60 | Expanded(
61 | flex: 1,
62 | child: Column(
63 | mainAxisAlignment: MainAxisAlignment.center,
64 | children: [
65 | CircularProgressIndicator(backgroundColor: Colors.white,),
66 | Padding(
67 | padding: EdgeInsets.only(top: 20.0),
68 | ),
69 | Text(
70 | "Manage Customers,Orders,\n and Track Sales with Real time",
71 | softWrap: true,
72 | textAlign: TextAlign.center,
73 | style: TextStyle(
74 | fontWeight: FontWeight.bold,
75 | fontSize: 18.0,
76 | color: Colors.white),
77 | )
78 | ],
79 | ),
80 | )
81 | ],
82 | )
83 | ],
84 | ),
85 | );
86 | }
87 | }
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.9.0"
11 | boolean_selector:
12 | dependency: transitive
13 | description:
14 | name: boolean_selector
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "2.1.0"
18 | characters:
19 | dependency: transitive
20 | description:
21 | name: characters
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "1.2.1"
25 | charcode:
26 | dependency: transitive
27 | description:
28 | name: charcode
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.1.2"
32 | clock:
33 | dependency: transitive
34 | description:
35 | name: clock
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.1"
39 | collection:
40 | dependency: transitive
41 | description:
42 | name: collection
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.16.0"
46 | convert:
47 | dependency: transitive
48 | description:
49 | name: convert
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "2.1.1"
53 | crypto:
54 | dependency: transitive
55 | description:
56 | name: crypto
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "2.1.3"
60 | cupertino_icons:
61 | dependency: "direct main"
62 | description:
63 | name: cupertino_icons
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "0.1.2"
67 | fake_async:
68 | dependency: transitive
69 | description:
70 | name: fake_async
71 | url: "https://pub.dartlang.org"
72 | source: hosted
73 | version: "1.3.1"
74 | flutter:
75 | dependency: "direct main"
76 | description: flutter
77 | source: sdk
78 | version: "0.0.0"
79 | flutter_test:
80 | dependency: "direct dev"
81 | description: flutter
82 | source: sdk
83 | version: "0.0.0"
84 | fluttertoast:
85 | dependency: "direct main"
86 | description:
87 | name: fluttertoast
88 | url: "https://pub.dartlang.org"
89 | source: hosted
90 | version: "3.1.3"
91 | http:
92 | dependency: transitive
93 | description:
94 | name: http
95 | url: "https://pub.dartlang.org"
96 | source: hosted
97 | version: "0.11.3+17"
98 | http_parser:
99 | dependency: transitive
100 | description:
101 | name: http_parser
102 | url: "https://pub.dartlang.org"
103 | source: hosted
104 | version: "3.1.3"
105 | matcher:
106 | dependency: transitive
107 | description:
108 | name: matcher
109 | url: "https://pub.dartlang.org"
110 | source: hosted
111 | version: "0.12.12"
112 | material_color_utilities:
113 | dependency: transitive
114 | description:
115 | name: material_color_utilities
116 | url: "https://pub.dartlang.org"
117 | source: hosted
118 | version: "0.1.5"
119 | meta:
120 | dependency: transitive
121 | description:
122 | name: meta
123 | url: "https://pub.dartlang.org"
124 | source: hosted
125 | version: "1.8.0"
126 | path:
127 | dependency: transitive
128 | description:
129 | name: path
130 | url: "https://pub.dartlang.org"
131 | source: hosted
132 | version: "1.8.2"
133 | progress_hud:
134 | dependency: "direct main"
135 | description:
136 | name: progress_hud
137 | url: "https://pub.dartlang.org"
138 | source: hosted
139 | version: "1.1.0"
140 | rxdart:
141 | dependency: "direct main"
142 | description:
143 | name: rxdart
144 | url: "https://pub.dartlang.org"
145 | source: hosted
146 | version: "0.18.1"
147 | sky_engine:
148 | dependency: transitive
149 | description: flutter
150 | source: sdk
151 | version: "0.0.99"
152 | source_span:
153 | dependency: transitive
154 | description:
155 | name: source_span
156 | url: "https://pub.dartlang.org"
157 | source: hosted
158 | version: "1.9.0"
159 | stack_trace:
160 | dependency: transitive
161 | description:
162 | name: stack_trace
163 | url: "https://pub.dartlang.org"
164 | source: hosted
165 | version: "1.10.0"
166 | stream_channel:
167 | dependency: transitive
168 | description:
169 | name: stream_channel
170 | url: "https://pub.dartlang.org"
171 | source: hosted
172 | version: "2.1.0"
173 | string_scanner:
174 | dependency: transitive
175 | description:
176 | name: string_scanner
177 | url: "https://pub.dartlang.org"
178 | source: hosted
179 | version: "1.1.1"
180 | term_glyph:
181 | dependency: transitive
182 | description:
183 | name: term_glyph
184 | url: "https://pub.dartlang.org"
185 | source: hosted
186 | version: "1.2.1"
187 | test_api:
188 | dependency: transitive
189 | description:
190 | name: test_api
191 | url: "https://pub.dartlang.org"
192 | source: hosted
193 | version: "0.4.12"
194 | typed_data:
195 | dependency: transitive
196 | description:
197 | name: typed_data
198 | url: "https://pub.dartlang.org"
199 | source: hosted
200 | version: "1.1.6"
201 | vector_math:
202 | dependency: transitive
203 | description:
204 | name: vector_math
205 | url: "https://pub.dartlang.org"
206 | source: hosted
207 | version: "2.1.2"
208 | woocommerce_api:
209 | dependency: "direct main"
210 | description:
211 | name: woocommerce_api
212 | url: "https://pub.dartlang.org"
213 | source: hosted
214 | version: "0.0.8"
215 | sdks:
216 | dart: ">=2.17.0-0 <3.0.0"
217 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: woocommerce_app
2 | description: A new Flutter application.
3 |
4 | # The following defines the version and build number for your application.
5 | # A version number is three numbers separated by dots, like 1.2.43
6 | # followed by an optional build number separated by a +.
7 | # Both the version and the builder number may be overridden in flutter
8 | # build by specifying --build-name and --build-number, respectively.
9 | # In Android, build-name is used as versionName while build-number used as versionCode.
10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
12 | # Read more about iOS versioning at
13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
14 | version: 1.0.0+1
15 |
16 | environment:
17 | sdk: ">=2.1.0 <3.0.0"
18 |
19 | dependencies:
20 | flutter:
21 | sdk: flutter
22 |
23 | # The following adds the Cupertino Icons font to your application.
24 | # Use with the CupertinoIcons class for iOS style icons.
25 | cupertino_icons: ^0.1.2
26 | woocommerce_api: ^0.0.8
27 | rxdart: ^0.18.0
28 | fluttertoast: ^3.0.1
29 | progress_hud: ^1.1.0
30 |
31 | dev_dependencies:
32 | flutter_test:
33 | sdk: flutter
34 |
35 |
36 | # For information on the generic Dart part of this file, see the
37 | # following page: https://dart.dev/tools/pub/pubspec
38 |
39 | # The following section is specific to Flutter.
40 | flutter:
41 |
42 | # The following line ensures that the Material Icons font is
43 | # included with your application, so that you can use the icons in
44 | # the material Icons class.
45 | uses-material-design: true
46 |
47 | # To add assets to your application, add an assets section, like this:
48 | assets:
49 | - images/cover_photo.jpg
50 | - images/woocom_icon.jpg
51 |
52 | # An image asset can refer to one or more resolution-specific "variants", see
53 | # https://flutter.dev/assets-and-images/#resolution-aware.
54 |
55 | # For details regarding adding assets from package dependencies, see
56 | # https://flutter.dev/assets-and-images/#from-packages
57 |
58 | # To add custom fonts to your application, add a fonts section here,
59 | # in this "flutter" section. Each entry in this list should have a
60 | # "family" key with the font family name, and a "fonts" key with a
61 | # list giving the asset and other descriptors for the font. For
62 | # example:
63 | # fonts:
64 | # - family: Schyler
65 | # fonts:
66 | # - asset: fonts/Schyler-Regular.ttf
67 | # - asset: fonts/Schyler-Italic.ttf
68 | # style: italic
69 | # - family: Trajan Pro
70 | # fonts:
71 | # - asset: fonts/TrajanPro.ttf
72 | # - asset: fonts/TrajanPro_Bold.ttf
73 | # weight: 700
74 | #
75 | # For details regarding fonts from package dependencies,
76 | # see https://flutter.dev/custom-fonts/#from-packages
77 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:woocommerce_app/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------