├── .flutter-plugins-dependencies
├── .gitignore
├── .metadata
├── README.md
├── android
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── appshmapp
│ │ │ │ └── cool_store
│ │ │ │ └── MainActivity.java
│ │ └── res
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── 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
└── settings.gradle
├── assets
├── category_image_default.jpg
├── colors.csv
├── empty.svg
├── empty_cart.png
├── list.svg
├── no_result.svg
├── shoppint_cart_empty.svg
└── wishlist.png
├── fonts
├── Raleway-Black.ttf
├── Raleway-BlackItalic.ttf
├── Raleway-Bold.ttf
├── Raleway-BoldItalic.ttf
├── Raleway-ExtraBold.ttf
├── Raleway-ExtraBoldItalic.ttf
├── Raleway-ExtraLight.ttf
├── Raleway-ExtraLightItalic.ttf
├── Raleway-Italic.ttf
├── Raleway-Light.ttf
├── Raleway-LightItalic.ttf
├── Raleway-Medium.ttf
├── Raleway-MediumItalic.ttf
├── Raleway-Regular.ttf
├── Raleway-SemiBold.ttf
├── Raleway-SemiBoldItalic.ttf
├── Raleway-Thin.ttf
└── Raleway-ThinItalic.ttf
├── ios
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ ├── Flutter.podspec
│ ├── Release.xcconfig
│ └── flutter_export_environment.sh
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── 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
│ └── main.m
├── lib
├── app.dart
├── main.dart
├── models
│ ├── category.dart
│ ├── order.dart
│ ├── payment.dart
│ ├── product.dart
│ ├── shipping_methods.dart
│ └── user.dart
├── screens
│ ├── cart_screen.dart
│ ├── category_screen.dart
│ ├── checkout_screen.dart
│ ├── detail_screen.dart
│ ├── home_screen.dart
│ ├── order_review_screen.dart
│ ├── order_summary_screen.dart
│ ├── product_list_screen.dart
│ ├── search_screen.dart
│ ├── setting_screen.dart
│ ├── shipping_address_screen.dart
│ ├── shipping_methods_screen.dart
│ └── wishlist_screen.dart
├── services
│ ├── base_services.dart
│ ├── woocommerce.dart
│ └── woocommerce_api.dart
├── states
│ ├── app_state.dart
│ ├── cart_state.dart
│ ├── category_state.dart
│ ├── checkout_state.dart
│ ├── detail_state.dart
│ ├── home_state.dart
│ ├── product_list_state.dart
│ ├── search_state.dart
│ └── settings_state.dart
├── utils
│ ├── color.dart
│ └── constants.dart
└── widgets
│ ├── Badge.dart
│ ├── CartItem.dart
│ ├── ColorChooser.dart
│ ├── DefaultChooser.dart
│ ├── GalleryView.dart
│ ├── ImageView.dart
│ ├── InfoView.dart
│ ├── OffersBanner.dart
│ ├── ProductCard.dart
│ ├── ProductDescription.dart
│ ├── ProductTitle.dart
│ ├── QuantityChooser.dart
│ ├── RelatedProducts.dart
│ ├── ShimmerGrid.dart
│ ├── ShimmerList.dart
│ ├── VariantChooser.dart
│ ├── VariationsView.dart
│ └── category_banner.dart
├── pubspec.lock
└── pubspec.yaml
/.flutter-plugins-dependencies:
--------------------------------------------------------------------------------
1 | {"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"connectivity","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]}]}
--------------------------------------------------------------------------------
/.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 | # Visual Studio Code related
19 | .vscode/
20 |
21 | # Flutter/Dart/Pub related
22 | **/doc/api/
23 | .dart_tool/
24 | .flutter-plugins
25 | .packages
26 | .pub-cache/
27 | .pub/
28 | /build/
29 |
30 | # Android related
31 | **/android/**/gradle-wrapper.jar
32 | **/android/.gradle
33 | **/android/captures/
34 | **/android/gradlew
35 | **/android/gradlew.bat
36 | **/android/local.properties
37 | **/android/**/GeneratedPluginRegistrant.java
38 |
39 | # iOS/XCode related
40 | **/ios/**/*.mode1v3
41 | **/ios/**/*.mode2v3
42 | **/ios/**/*.moved-aside
43 | **/ios/**/*.pbxuser
44 | **/ios/**/*.perspectivev3
45 | **/ios/**/*sync/
46 | **/ios/**/.sconsign.dblite
47 | **/ios/**/.tags*
48 | **/ios/**/.vagrant/
49 | **/ios/**/DerivedData/
50 | **/ios/**/Icon?
51 | **/ios/**/Pods/
52 | **/ios/**/.symlinks/
53 | **/ios/**/profile
54 | **/ios/**/xcuserdata
55 | **/ios/.generated/
56 | **/ios/Flutter/App.framework
57 | **/ios/Flutter/Flutter.framework
58 | **/ios/Flutter/Generated.xcconfig
59 | **/ios/Flutter/app.flx
60 | **/ios/Flutter/app.zip
61 | **/ios/Flutter/flutter_assets/
62 | **/ios/ServiceDefinitions.json
63 | **/ios/Runner/GeneratedPluginRegistrant.*
64 |
65 | # Exceptions to above rules.
66 | !**/ios/**/default.mode1v3
67 | !**/ios/**/default.mode2v3
68 | !**/ios/**/default.pbxuser
69 | !**/ios/**/default.perspectivev3
70 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
71 |
--------------------------------------------------------------------------------
/.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: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # COOL STORE (CROSS-PLATFORM E-Commerce application)
2 |
3 | A E-Commerce Flutter Application for woocommerce stores
4 |
5 | Show some ❤️ and star the repo to support the project
6 |
7 |
8 | ## Features
9 | - Supports Dynamic themes (Light/Dark)
10 | - Built with Provider achitecture
11 | - Woocommerce Backend
12 |
13 | ## Created & Maintained by
14 | [Mithlesh Parmar](https://github.com/mithilesh-parmar) ([linkedin](https://www.linkedin.com/in/mithilesh-parmar-97395712b/))
15 |
16 | ## Screen recording of the app
17 | [YouTube](https://www.youtube.com/watch?v=TGCEG3YHbWQ)
18 |
19 | # License
20 | >MIT License
21 | >
22 | >Copyright (c) [2019] [Mithilesh Parmar]
23 | >
24 | >Permission is hereby granted, free of charge, to any person obtaining a copy
25 | >of this software and associated documentation files (the "Software"), to deal
26 | >in the Software without restriction, including without limitation the rights
27 | >to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28 | >copies of the Software, and to permit persons to whom the Software is
29 | >furnished to do so, subject to the following conditions:
30 | >
31 | >The above copyright notice and this permission notice shall be included in all
32 | >copies or substantial portions of the Software.
33 | >
34 | >THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 | >IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 | >FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37 | >AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38 | >LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39 | >OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40 | >SOFTWARE.
41 |
--------------------------------------------------------------------------------
/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 from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26 |
27 | android {
28 | compileSdkVersion 28
29 |
30 | lintOptions {
31 | disable 'InvalidPackage'
32 | }
33 |
34 | defaultConfig {
35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
36 | applicationId "com.appshmapp.cool_store"
37 | minSdkVersion 16
38 | targetSdkVersion 28
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
42 | }
43 |
44 | buildTypes {
45 | release {
46 | // TODO: Add your own signing config for the release build.
47 | // Signing with the debug keys for now, so `flutter run --release` works.
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 | }
52 |
53 | flutter {
54 | source '../..'
55 | }
56 |
57 | dependencies {
58 | testImplementation 'junit:junit:4.12'
59 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
60 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
61 | }
62 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
15 |
19 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/appshmapp/cool_store/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.appshmapp.cool_store;
2 |
3 | import android.os.Bundle;
4 | import io.flutter.app.FlutterActivity;
5 | import io.flutter.plugins.GeneratedPluginRegistrant;
6 |
7 | public class MainActivity extends FlutterActivity {
8 | @Override
9 | protected void onCreate(Bundle savedInstanceState) {
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/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.5.0'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | jcenter()
16 | }
17 | }
18 |
19 | rootProject.buildDir = '../build'
20 | subprojects {
21 | project.buildDir = "${rootProject.buildDir}/${project.name}"
22 | }
23 | subprojects {
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Sep 08 20:21:20 IST 2019
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-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/assets/category_image_default.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/assets/category_image_default.jpg
--------------------------------------------------------------------------------
/assets/empty.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/empty_cart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/assets/empty_cart.png
--------------------------------------------------------------------------------
/assets/list.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/shoppint_cart_empty.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
51 |
--------------------------------------------------------------------------------
/assets/wishlist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/assets/wishlist.png
--------------------------------------------------------------------------------
/fonts/Raleway-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-Black.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-BlackItalic.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-Bold.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-BoldItalic.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-ExtraBold.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-ExtraBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-ExtraBoldItalic.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-ExtraLight.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-ExtraLight.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-ExtraLightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-ExtraLightItalic.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-Italic.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-Light.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-LightItalic.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-Medium.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-MediumItalic.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-Regular.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-SemiBold.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-Thin.ttf
--------------------------------------------------------------------------------
/fonts/Raleway-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/fonts/Raleway-ThinItalic.ttf
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
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/Flutter.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # NOTE: This podspec is NOT to be published. It is only used as a local source!
3 | #
4 |
5 | Pod::Spec.new do |s|
6 | s.name = 'Flutter'
7 | s.version = '1.0.0'
8 | s.summary = 'High-performance, high-fidelity mobile apps.'
9 | s.description = <<-DESC
10 | Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
11 | DESC
12 | s.homepage = 'https://flutter.io'
13 | s.license = { :type => 'MIT' }
14 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
15 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
16 | s.ios.deployment_target = '8.0'
17 | s.vendored_frameworks = 'Flutter.framework'
18 | end
19 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/flutter_export_environment.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is a generated file; do not edit or check into version control.
3 | export "FLUTTER_ROOT=/Users/mithileshparmar/Development/flutter"
4 | export "FLUTTER_APPLICATION_PATH=/Users/mithileshparmar/Development/Android_Projects/Flutter-store"
5 | export "FLUTTER_TARGET=/Users/mithileshparmar/Development/Android_Projects/Flutter-store/lib/main.dart"
6 | export "FLUTTER_BUILD_DIR=build"
7 | export "SYMROOT=${SOURCE_ROOT}/../build/ios"
8 | export "FLUTTER_FRAMEWORK_DIR=/Users/mithileshparmar/Development/flutter/bin/cache/artifacts/engine/ios"
9 | export "FLUTTER_BUILD_NAME=1.0.0"
10 | export "FLUTTER_BUILD_NUMBER=1"
11 | export "TRACK_WIDGET_CREATION=true"
12 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def parse_KV_file(file, separator='=')
14 | file_abs_path = File.expand_path(file)
15 | if !File.exists? file_abs_path
16 | return [];
17 | end
18 | pods_ary = []
19 | skip_line_start_symbols = ["#", "/"]
20 | File.foreach(file_abs_path) { |line|
21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22 | plugin = line.split(pattern=separator)
23 | if plugin.length == 2
24 | podname = plugin[0].strip()
25 | path = plugin[1].strip()
26 | podpath = File.expand_path("#{path}", file_abs_path)
27 | pods_ary.push({:name => podname, :path => podpath});
28 | else
29 | puts "Invalid plugin specification: #{line}"
30 | end
31 | }
32 | return pods_ary
33 | end
34 |
35 | target 'Runner' do
36 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
37 | # referring to absolute paths on developers' machines.
38 | system('rm -rf .symlinks')
39 | system('mkdir -p .symlinks/plugins')
40 |
41 | # Flutter Pods
42 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
43 | if generated_xcode_build_settings.empty?
44 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
45 | end
46 | generated_xcode_build_settings.map { |p|
47 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
48 | symlink = File.join('.symlinks', 'flutter')
49 | File.symlink(File.dirname(p[:path]), symlink)
50 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
51 | end
52 | }
53 |
54 | # Plugin Pods
55 | plugin_pods = parse_KV_file('../.flutter-plugins')
56 | plugin_pods.map { |p|
57 | symlink = File.join('.symlinks', 'plugins', p[:name])
58 | File.symlink(p[:path], symlink)
59 | pod p[:name], :path => File.join(symlink, 'ios')
60 | }
61 | end
62 |
63 | post_install do |installer|
64 | installer.pods_project.targets.each do |target|
65 | target.build_configurations.each do |config|
66 | config.build_settings['ENABLE_BITCODE'] = 'NO'
67 | end
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - connectivity (0.0.1):
3 | - Flutter
4 | - Reachability
5 | - Flutter (1.0.0)
6 | - path_provider (0.0.1):
7 | - Flutter
8 | - Reachability (3.2)
9 | - shared_preferences (0.0.1):
10 | - Flutter
11 | - shared_preferences_macos (0.0.1):
12 | - Flutter
13 | - shared_preferences_web (0.0.1):
14 | - Flutter
15 |
16 | DEPENDENCIES:
17 | - connectivity (from `.symlinks/plugins/connectivity/ios`)
18 | - Flutter (from `.symlinks/flutter/ios`)
19 | - path_provider (from `.symlinks/plugins/path_provider/ios`)
20 | - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
21 | - shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`)
22 | - shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`)
23 |
24 | SPEC REPOS:
25 | trunk:
26 | - Reachability
27 |
28 | EXTERNAL SOURCES:
29 | connectivity:
30 | :path: ".symlinks/plugins/connectivity/ios"
31 | Flutter:
32 | :path: ".symlinks/flutter/ios"
33 | path_provider:
34 | :path: ".symlinks/plugins/path_provider/ios"
35 | shared_preferences:
36 | :path: ".symlinks/plugins/shared_preferences/ios"
37 | shared_preferences_macos:
38 | :path: ".symlinks/plugins/shared_preferences_macos/ios"
39 | shared_preferences_web:
40 | :path: ".symlinks/plugins/shared_preferences_web/ios"
41 |
42 | SPEC CHECKSUMS:
43 | connectivity: 6e94255659cc86dcbef1d452ad3e0491bb1b3e75
44 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
45 | path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d
46 | Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
47 | shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01
48 | shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087
49 | shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9
50 |
51 | PODFILE CHECKSUM: aff02bfeed411c636180d6812254b2daeea14d09
52 |
53 | COCOAPODS: 1.8.4
54 |
--------------------------------------------------------------------------------
/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 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Original
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mithilesh-parmar/Flutter-store/eed653978fdd1b9e453f083c687ec1607b5a7368/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 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | cool_store
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/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/app.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/screens/cart_screen.dart';
2 | import 'package:cool_store/screens/home_screen.dart';
3 | import 'package:cool_store/screens/category_screen.dart';
4 | import 'package:cool_store/screens/setting_screen.dart';
5 | import 'package:cool_store/states/app_state.dart';
6 | import 'package:cool_store/states/cart_state.dart';
7 | import 'package:cool_store/states/home_state.dart';
8 | import 'package:cool_store/states/category_state.dart';
9 | import 'package:cool_store/states/settings_state.dart';
10 | import 'package:flutter/material.dart';
11 | import 'package:provider/provider.dart';
12 |
13 | class App extends StatelessWidget {
14 | @override
15 | Widget build(BuildContext context) {
16 | return MultiProvider(
17 | providers: [
18 | ChangeNotifierProvider(
19 | builder: (_) => AppState(initialScreen: HomeScreen(), screens: [
20 | HomeScreen(),
21 | CategoryScreen(),
22 | CartScreen(),
23 | SettingScreen()
24 | ]),
25 | ),
26 | ChangeNotifierProvider(
27 | builder: (_) => HomeState(),
28 | ),
29 | ChangeNotifierProvider(
30 | builder: (_) => CartState(),
31 | ),
32 | ChangeNotifierProvider(
33 | builder: (_) => CategoryState(),
34 | ),
35 | ChangeNotifierProvider(
36 | builder: (_) => SettingState(),
37 | ),
38 | ],
39 | child: Consumer(
40 | builder: (context, state, child) => MaterialApp(
41 | debugShowCheckedModeBanner: false,
42 | theme: state.getTheme(),
43 | home: Scaffold(
44 | body: state.selectedScreen,
45 | bottomNavigationBar: BottomNavigationBar(
46 | type: BottomNavigationBarType.fixed,
47 | onTap: (pos) => state.setScreenIndex(pos),
48 | currentIndex: state.selectedScreenIndex,
49 | selectedItemColor: state.getTheme().accentColor,
50 | items: [
51 | BottomNavigationBarItem(
52 | icon: Icon(Icons.home), title: Text('Home')),
53 | BottomNavigationBarItem(
54 | icon: Icon(Icons.search), title: Text('Search')),
55 | BottomNavigationBarItem(
56 | icon: Icon(Icons.add_shopping_cart), title: Text('Cart')),
57 | BottomNavigationBarItem(
58 | icon: Icon(Icons.settings), title: Text('Setting')),
59 | ],
60 | ),
61 | ),
62 | ),
63 | ),
64 | );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/app.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:cool_store/utils/color.dart';
4 |
5 | void main() => runApp(App());
6 |
--------------------------------------------------------------------------------
/lib/models/category.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class Category {
4 | int id;
5 | String name;
6 | String image;
7 | int parent;
8 | int totalProduct;
9 |
10 | Category.fromJson(Map parsedJson) {
11 | if (parsedJson["slug"] == 'uncategorized') {
12 | return;
13 | }
14 |
15 | id = parsedJson["id"];
16 | name = parsedJson["name"];
17 | parent = parsedJson["parent"];
18 | totalProduct = parsedJson["count"];
19 |
20 | final image = parsedJson["image"];
21 | if (image != null) {
22 | this.image = image["src"];
23 | } else {
24 | this.image = 'category_image_default.jpg';
25 | }
26 | }
27 |
28 | @override
29 | String toString() => 'Category { id: $id name: $name}';
30 | }
31 |
--------------------------------------------------------------------------------
/lib/models/order.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/payment.dart';
2 | import 'package:cool_store/models/product.dart';
3 | import 'package:cool_store/models/user.dart';
4 | import 'package:cool_store/states/cart_state.dart';
5 |
6 | class ProductItem {
7 | int productId;
8 | String name;
9 | int quantity;
10 | String total;
11 |
12 | ProductItem.fromJson(Map parsedJson) {
13 | productId = parsedJson["product_id"];
14 | name = parsedJson["name"];
15 | quantity = parsedJson["quantity"];
16 | total = parsedJson["total"];
17 | }
18 | }
19 |
20 | class Order {
21 | int id;
22 | String number;
23 | String status;
24 | DateTime createdAt;
25 | double total;
26 | String paymentMethodTitle;
27 | String shippingMethodTitle;
28 | List lineItems = [];
29 | Address billing;
30 |
31 | Order({this.id, this.number, this.status, this.createdAt, this.total});
32 |
33 | Order.fromJson(Map parsedJson) {
34 | id = parsedJson["id"];
35 | number = parsedJson["number"];
36 | status = parsedJson["status"];
37 | createdAt = parsedJson["date_created"] != null
38 | ? DateTime.parse(parsedJson["date_created"])
39 | : DateTime.now();
40 | total =
41 | parsedJson["total"] != null ? double.parse(parsedJson["total"]) : 0.0;
42 | paymentMethodTitle = parsedJson["payment_method_title"];
43 |
44 | parsedJson["line_items"].forEach((item) {
45 | lineItems.add(ProductItem.fromJson(item));
46 | });
47 |
48 | billing = Address.fromJson(parsedJson["billing"]);
49 | shippingMethodTitle = parsedJson["shipping_lines"][0]["method_title"];
50 | }
51 |
52 | Map toJson(
53 | Map productsInCart,
54 | Map productVariationsInCart,
55 | Address address,
56 | PaymentMethod paymentMethod,
57 | [userId = 1]) {
58 | var lineItems = productsInCart.keys.map((key) {
59 | var productId = int.parse(key);
60 | var item = {"product_id": productId, "quantity": productsInCart[key]};
61 | if (productVariationsInCart[key] != null) {
62 | item['variation_id'] = productVariationsInCart[key].id;
63 | }
64 |
65 | return item;
66 | }).toList();
67 |
68 | return {
69 | "payment_method": paymentMethod.id,
70 | "payment_method_title": paymentMethod.title,
71 | "set_paid": false,
72 | "billing": address.toJson(),
73 | "shipping": address.toJson(),
74 | "line_items": lineItems,
75 | "customer_id": userId,
76 | "shipping_lines": [
77 | {"method_id": 'flat_rate', "method_title": 'Flat Rate'}
78 | ]
79 | };
80 | }
81 |
82 | @override
83 | String toString() => 'Order { id: $id number: $number}';
84 | }
85 |
--------------------------------------------------------------------------------
/lib/models/payment.dart:
--------------------------------------------------------------------------------
1 | class PaymentMethod {
2 | String id;
3 | String title;
4 | String description;
5 | bool enabled;
6 |
7 | PaymentMethod({this.id, this.title, this.description, this.enabled});
8 |
9 | PaymentMethod.fromJson(Map parsedJson) {
10 | id = parsedJson["id"];
11 | title = parsedJson["title"];
12 | description = parsedJson["description"];
13 | enabled = parsedJson["enabled"];
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lib/models/product.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 |
3 | class Product {
4 | int id;
5 | String sku;
6 | String name;
7 | String description;
8 | String permalink;
9 | String price;
10 | String regularPrice;
11 | String salePrice;
12 | bool onSale;
13 | bool inStock;
14 | double averageRating;
15 | double ratingCount;
16 | List images;
17 | String featuredImage;
18 | List attributes;
19 | int categoryId;
20 |
21 | Product.empty(int id) {
22 | this.id = id;
23 | name = 'Loading...';
24 | price = '0.0';
25 | featuredImage = '';
26 | }
27 |
28 | bool isEmptyProduct() {
29 | return name == 'Loading...' && price == '0.0' && featuredImage == '';
30 | }
31 |
32 | Product.fromJson(Map parsedJson) {
33 | id = parsedJson["id"];
34 | name = parsedJson["name"];
35 | description = parsedJson["description"];
36 | permalink = parsedJson["permalink"];
37 | price = parsedJson["price"] == 0 ? 10 : parsedJson["price"];
38 |
39 | regularPrice = parsedJson["regular_price"];
40 | salePrice = parsedJson["sale_price"];
41 | onSale = parsedJson["on_sale"];
42 | inStock = parsedJson["in_stock"];
43 |
44 | averageRating = double.parse(parsedJson["average_rating"]);
45 | ratingCount = double.parse(parsedJson["rating_count"].toString());
46 | categoryId =
47 | parsedJson["categories"] != null && parsedJson["categories"].length > 0
48 | ? parsedJson["categories"][0]["id"]
49 | : 0;
50 |
51 | List attributeList = [];
52 | parsedJson["attributes"].forEach((item) {
53 | attributeList.add(ProductAttribute.fromJson(item));
54 | });
55 | attributes = attributeList;
56 |
57 | List list = [];
58 | for (var item in parsedJson["images"]) {
59 | list.add(item["src"]);
60 | }
61 | images = list;
62 | featuredImage = images[0];
63 | }
64 |
65 | Map toJson() {
66 | return {
67 | "id": id,
68 | "sku": sku,
69 | "name": name,
70 | "description": description,
71 | "permalink": permalink,
72 | "price": price,
73 | "regularPrice": regularPrice,
74 | "salePrice": salePrice,
75 | "onSale": onSale,
76 | "inStock": inStock,
77 | "averageRating": averageRating,
78 | "ratingCount": ratingCount,
79 | "images": images,
80 | "imageFeature": featuredImage,
81 | "attributes": attributes,
82 | "categoryId": categoryId
83 | };
84 | }
85 |
86 | Product.fromLocalJson(Map json) {
87 | try {
88 | id = json['id'];
89 | sku = json['sku'];
90 | name = json['name'];
91 | description = json['description'];
92 | permalink = json['permalink'];
93 | price = json['price'];
94 | regularPrice = json['regularPrice'];
95 | salePrice = json['salePrice'];
96 | onSale = json['onSale'];
97 | inStock = json['inStock'];
98 | averageRating = json['averageRating'];
99 | ratingCount = json['ratingCount'];
100 | List imgs = [];
101 | for (var item in json['images']) {
102 | imgs.add(item);
103 | }
104 | images = imgs;
105 | featuredImage = json['imageFeature'];
106 | List attrs = [];
107 | for (var item in json['attributes']) {
108 | attrs.add(ProductAttribute.fromLocalJson(item));
109 | }
110 | attributes = attrs;
111 | categoryId = json['categoryId'];
112 | } catch (e) {
113 | print(e.toString());
114 | }
115 | }
116 |
117 | @override
118 | String toString() => 'Product { id: $id name: $name }';
119 | }
120 |
121 | class ProductAttribute {
122 | int id;
123 | String name;
124 | List options;
125 |
126 | ProductAttribute.fromJson(Map parsedJson) {
127 | id = parsedJson["id"];
128 | name = parsedJson["name"];
129 | options = parsedJson["options"];
130 | }
131 |
132 | Map toJson() {
133 | return {"id": id, "name": name, "options": options};
134 | }
135 |
136 | @override
137 | String toString() {
138 | return 'id: $id name: $name options: $options';
139 | }
140 |
141 | ProductAttribute.fromLocalJson(Map json) {
142 | try {
143 | id = json['id'];
144 | name = json['name'];
145 | options = json['options'];
146 | } catch (e) {
147 | print(e.toString());
148 | }
149 | }
150 | }
151 |
152 | class Attribute {
153 | int id;
154 | String name;
155 | String option;
156 |
157 | Attribute();
158 |
159 | Map toJson() {
160 | return {'id': id, 'name': name, 'option': option};
161 | }
162 |
163 | Attribute.fromJson(Map parsedJson) {
164 | id = parsedJson["id"];
165 | name = parsedJson["name"];
166 | option = parsedJson["option"];
167 | }
168 |
169 | @override
170 | String toString() {
171 | // TODO: implement toString
172 | return '$name: $option';
173 | }
174 | }
175 |
176 | class ProductVariation {
177 | int id;
178 | String price;
179 | String regularPrice;
180 | String salePrice;
181 | bool onSale;
182 | bool inStock;
183 | String imageFeature;
184 | List attributes = [];
185 |
186 | ProductVariation();
187 |
188 | Map toJson() {
189 | return {
190 | 'id': id,
191 | 'price': price,
192 | 'regularPrice': regularPrice,
193 | 'salePrice': salePrice,
194 | 'onSale': onSale,
195 | 'inStock': inStock,
196 | 'imageFeature': imageFeature,
197 | 'attributes': attributes
198 | };
199 | }
200 |
201 | ProductVariation.fromJson(Map parsedJson) {
202 | id = parsedJson["id"];
203 | price = parsedJson["price"];
204 | regularPrice = parsedJson["regular_price"];
205 | salePrice = parsedJson["sale_price"];
206 | onSale = parsedJson["on_sale"];
207 | inStock = parsedJson["in_stock"];
208 | imageFeature = parsedJson["imageFeature"];
209 |
210 | List attributeList = [];
211 | parsedJson["attributes"].forEach((item) {
212 | attributeList.add(Attribute.fromJson(item));
213 | });
214 | attributes = attributeList;
215 | }
216 |
217 | @override
218 | String toString() {
219 | String value = '';
220 | attributes.forEach((attribute) {
221 | value += '${attribute.name}: ${attribute.option}, ';
222 | });
223 | value = value.substring(0, value.length - 3);
224 | return value;
225 | }
226 | }
227 |
228 | class Review {
229 | int id, productId;
230 | String reviewer, reviewerEmail, review;
231 | int rating;
232 |
233 | Review(
234 | {this.id,
235 | this.productId,
236 | this.reviewer,
237 | this.reviewerEmail,
238 | this.review,
239 | this.rating});
240 |
241 | Map toJson() {
242 | return {
243 | 'product_id': productId,
244 | 'reviewer': reviewer,
245 | 'reviewer_email': reviewerEmail,
246 | 'review': review,
247 | 'rating': rating
248 | };
249 | }
250 |
251 | Review.fromJson(Map parsedJson) {
252 | id = parsedJson['id'];
253 | productId = parsedJson['product_id'];
254 | reviewer = parsedJson['reviewer'];
255 | reviewerEmail = parsedJson['reviewer_email'];
256 | review = parsedJson['review'];
257 | rating = parsedJson['rating'];
258 | }
259 | }
260 |
--------------------------------------------------------------------------------
/lib/models/shipping_methods.dart:
--------------------------------------------------------------------------------
1 | class ShippingMethods {
2 | String id;
3 | String title;
4 | String description;
5 |
6 | ShippingMethods({this.id, this.title, this.description});
7 |
8 | toJson() {
9 | return {
10 | 'method_id': id,
11 | 'method_title': title,
12 | };
13 | }
14 |
15 | ShippingMethods.fromJson(Map parsedjson) {
16 | id = parsedjson['id'];
17 | title = parsedjson['title'];
18 | description = parsedjson['description'];
19 | }
20 |
21 | bool isEqual(ShippingMethods item) {
22 | return id == item.id &&
23 | title == item.title &&
24 | description == item.description;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/models/user.dart:
--------------------------------------------------------------------------------
1 | class Address {
2 | String firstName;
3 | String lastName;
4 | String email;
5 | String street;
6 | String city;
7 | String state;
8 | String country;
9 | String phoneNumber;
10 | String zipCode;
11 |
12 | Address(
13 | {this.firstName,
14 | this.lastName,
15 | this.email,
16 | this.street,
17 | this.city,
18 | this.state,
19 | this.country,
20 | this.phoneNumber,
21 | this.zipCode});
22 |
23 | Address.fromJson(Map parsedJson) {
24 | firstName = parsedJson["first_name"];
25 | lastName = parsedJson["last_name"];
26 | street = parsedJson["address_1"];
27 | city = parsedJson["city"];
28 | state = parsedJson["state"];
29 | country = parsedJson["country"];
30 | email = parsedJson["email"];
31 | phoneNumber = parsedJson["phone"];
32 | zipCode = parsedJson["postcode"];
33 | }
34 |
35 | Map toJson() {
36 | return {
37 | "first_name": firstName,
38 | "last_name": lastName,
39 | "address_1": street,
40 | "address_2": '',
41 | "city": city,
42 | "state": state,
43 | "country": country,
44 | "email": email,
45 | "phone": phoneNumber,
46 | "postcode": zipCode
47 | };
48 | }
49 |
50 | Address.fromLocalJson(Map json) {
51 | try {
52 | firstName = json['first_name'];
53 | lastName = json['last_name'];
54 | street = json['address_1'];
55 | city = json['city'];
56 | state = json['state'];
57 | country = json['country'];
58 | email = json['email'];
59 | phoneNumber = json['phone'];
60 | zipCode = json['postcode'];
61 | } catch (e) {
62 | print(e.toString());
63 | }
64 | }
65 |
66 | bool isValid() {
67 | return firstName.isNotEmpty &&
68 | lastName.isNotEmpty &&
69 | email.isNotEmpty &&
70 | street.isNotEmpty &&
71 | city.isNotEmpty &&
72 | state.isNotEmpty &&
73 | country.isNotEmpty &&
74 | phoneNumber.isNotEmpty;
75 | }
76 |
77 | @override
78 | String toString() {
79 | return '\nFirst Name:$firstName\nLastName:$lastName\nemail:$email\nstreet:$street\ncity:$city\nState:$state\ncountry:$country\nPhoneNumber:$phoneNumber';
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/screens/category_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/screens/product_list_screen.dart';
2 | import 'package:cool_store/screens/search_screen.dart';
3 | import 'package:cool_store/states/product_list_state.dart';
4 | import 'package:cool_store/states/category_state.dart';
5 | import 'package:cool_store/states/search_state.dart';
6 | import 'package:cool_store/utils/constants.dart';
7 | import 'package:cool_store/widgets/GalleryView.dart';
8 | import 'package:cool_store/widgets/ShimmerList.dart';
9 | import 'package:cool_store/widgets/category_banner.dart';
10 | import 'package:flutter/material.dart';
11 | import 'package:provider/provider.dart';
12 |
13 | class CategoryScreen extends StatelessWidget {
14 | @override
15 | Widget build(BuildContext context) {
16 | final CategoryState state = Provider.of(context);
17 | return Scaffold(
18 | body: CustomScrollView(
19 | slivers: [
20 | SliverAppBar(
21 | floating: true,
22 | snap: true,
23 | centerTitle: false,
24 | bottom: PreferredSize(
25 | preferredSize: Size(100, 100),
26 | child: GestureDetector(
27 | onTap: () {
28 | Navigator.of(context).push(MaterialPageRoute(
29 | fullscreenDialog: true,
30 | builder: (_) => ChangeNotifierProvider(
31 | child: SearchScreen(),
32 | builder: (_) => SearchState(),
33 | )));
34 | },
35 | child: Column(
36 | mainAxisAlignment: MainAxisAlignment.start,
37 | crossAxisAlignment: CrossAxisAlignment.start,
38 | children: [
39 | Container(
40 | child: Text(
41 | 'Search',
42 | style: TextStyle(
43 | fontWeight: FontWeight.bold,
44 | fontFamily: 'Raleway',
45 | fontSize: 40),
46 | ),
47 | padding:
48 | EdgeInsets.symmetric(horizontal: 17, vertical: 8),
49 | ),
50 | Container(
51 | height: Constants.screenAwareSize(40, context),
52 | width: MediaQuery.of(context).size.width,
53 | child: Row(
54 | children: [
55 | Align(
56 | child: Padding(
57 | padding:
58 | const EdgeInsets.symmetric(horizontal: 8.0),
59 | child: Text(
60 | 'SEARCH FOR BRAND, PRODUCTS, CATEGORY',
61 | style: TextStyle(
62 | fontFamily: 'Raleway',
63 | fontWeight: FontWeight.w200,
64 | fontSize: 12),
65 | ),
66 | ),
67 | alignment: Alignment.centerLeft,
68 | ),
69 | Spacer(),
70 | Padding(
71 | padding:
72 | const EdgeInsets.symmetric(horizontal: 8.0),
73 | child: Icon(Icons.search),
74 | )
75 | ],
76 | ),
77 | margin: EdgeInsets.only(left: 18, right: 18),
78 | decoration: BoxDecoration(
79 | border: Border.all(color: Colors.grey[600]),
80 | ),
81 | ),
82 | ],
83 | ),
84 | ),
85 | ),
86 | ),
87 | SliverList(
88 | delegate: SliverChildListDelegate([
89 | state.isLoading
90 | ? ShimmerList()
91 | : ListView.builder(
92 | shrinkWrap: true,
93 | physics: NeverScrollableScrollPhysics(),
94 | itemCount: state.categories.length,
95 | itemBuilder: (context, pos) {
96 | return CategoryBanner(state.categories[pos], () {
97 | Navigator.push(context,
98 | MaterialPageRoute(builder: (BuildContext context) {
99 | final item = state.categories[pos];
100 | return ProductListScreen(category: item);
101 | }));
102 | });
103 | })
104 | ]))
105 | ],
106 | ),
107 | );
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/lib/screens/checkout_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/screens/order_review_screen.dart';
3 | import 'package:cool_store/screens/order_summary_screen.dart';
4 | import 'package:cool_store/screens/shipping_address_screen.dart';
5 | import 'package:cool_store/screens/shipping_methods_screen.dart';
6 | import 'package:flutter/material.dart';
7 |
8 | // Todo add layout for address input and search for shipping
9 | class Checkout extends StatefulWidget {
10 | final Map productsInCart;
11 | final Map productVariationsInCart;
12 |
13 | Checkout({this.productsInCart, this.productVariationsInCart});
14 |
15 | @override
16 | _CheckoutState createState() => _CheckoutState();
17 | }
18 |
19 | class _CheckoutState extends State {
20 | int _currentPage = 0;
21 | PageController _pageController = PageController(initialPage: 0);
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | return Scaffold(
26 | appBar: AppBar(
27 | title: Text('CHECKOUT'),
28 | ),
29 | body: SafeArea(
30 | child: Padding(
31 | padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 18),
32 | child: PageView.builder(
33 | itemCount: 4,
34 | controller: _pageController,
35 | physics: NeverScrollableScrollPhysics(),
36 | itemBuilder: (BuildContext context, int index) {
37 | switch (index) {
38 | case 0:
39 | return ShippingAddressScreen(
40 | function: nextPage,
41 | );
42 | case 1:
43 | return ShippingMethodsScreen(
44 | onNextPressed: nextPage,
45 | onBackPressed: previousPage,
46 | );
47 | case 2:
48 | return OrderReview(
49 | onButtonClicked: nextPage,
50 | );
51 | case 3:
52 | return OrderSummary();
53 | }
54 | return Container();
55 | },
56 | ),
57 | )),
58 | );
59 | }
60 |
61 | nextPage() {
62 | print('Next page $_currentPage');
63 | if (_currentPage == 3) return;
64 | setState(() {
65 | _currentPage++;
66 | _pageController.animateToPage(_currentPage,
67 | duration: Duration(milliseconds: 400), curve: Curves.ease);
68 | });
69 | }
70 |
71 | previousPage() {
72 | print('prev page $_currentPage');
73 | if (_currentPage == 0) return;
74 | setState(() {
75 | _currentPage--;
76 | _pageController.animateToPage(_currentPage,
77 | duration: Duration(milliseconds: 400), curve: Curves.ease);
78 | });
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/screens/detail_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/states/detail_state.dart';
3 | import 'package:cool_store/widgets/ShimmerList.dart';
4 | import 'package:cool_store/widgets/ImageView.dart';
5 | import 'package:cool_store/widgets/ProductCard.dart';
6 | import 'package:cool_store/widgets/ProductDescription.dart';
7 | import 'package:cool_store/widgets/ProductTitle.dart';
8 | import 'package:cool_store/widgets/QuantityChooser.dart';
9 | import 'package:cool_store/widgets/VariationsView.dart';
10 | import 'package:flutter/material.dart';
11 | import 'package:flutter/widgets.dart';
12 | import 'package:provider/provider.dart';
13 |
14 | class DetailScreen extends StatefulWidget {
15 | final Product _product;
16 |
17 | DetailScreen(this._product);
18 |
19 | @override
20 | _DetailScreenState createState() => _DetailScreenState();
21 | }
22 |
23 | class _DetailScreenState extends State {
24 | @override
25 | Widget build(BuildContext context) {
26 | return ChangeNotifierProvider(
27 | builder: (_) => DetailState(widget._product.id),
28 | child: Scaffold(
29 | body: SafeArea(
30 | child: CustomScrollView(
31 | slivers: [
32 | SliverAppBar(
33 | backgroundColor: Theme.of(context).primaryColor,
34 | elevation: 0,
35 | title: Text(
36 | widget._product.name,
37 | style: TextStyle(
38 | fontFamily: 'Raleway', fontWeight: FontWeight.w500),
39 | ),
40 | centerTitle: false,
41 | pinned: true,
42 | floating: false,
43 | ),
44 | SliverList(
45 | delegate: SliverChildListDelegate([
46 | ImageView(),
47 | Padding(
48 | padding:
49 | const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
50 | child: Column(
51 | children: [
52 | ProductTitle(widget._product),
53 | VariationsView(widget._product),
54 | Row(
55 | children: [
56 | Expanded(
57 | flex: 4,
58 | child: Consumer(
59 | builder: (context, state, child) {
60 | return FlatButton.icon(
61 | onPressed: () {
62 | try {
63 | state.addToCart(context);
64 | _showSnackbar(context, 'ADDED TO CART');
65 | } catch (e) {
66 | _showSnackbar(context, e.toString());
67 | }
68 | },
69 | textColor: Colors.white,
70 | color: Theme.of(context).accentColor,
71 | icon: Icon(
72 | Icons.add_shopping_cart,
73 | color: Colors.white,
74 | ),
75 | label: Text(
76 | 'ADD TO CART',
77 | ));
78 | }),
79 | ),
80 | Expanded(
81 | child: QuantityChooser(),
82 | )
83 | ],
84 | ),
85 | ProductDescription(widget._product),
86 | Column(
87 | crossAxisAlignment: CrossAxisAlignment.start,
88 | mainAxisAlignment: MainAxisAlignment.start,
89 | children: [
90 | Padding(
91 | padding:
92 | const EdgeInsets.symmetric(vertical: 16.0),
93 | child: Text(
94 | 'YOU MIGHT LIKE',
95 | style: TextStyle(
96 | fontSize: 17, fontFamily: 'Raleway'),
97 | ),
98 | ),
99 | Consumer(
100 | builder: (context, state, child) {
101 | return Container(
102 | height:
103 | MediaQuery.of(context).size.height / 2.7,
104 | child: state.isRelatedProductsLoading
105 | ? ShimmerList(
106 | direction: Axis.horizontal,
107 | )
108 | : ListView.builder(
109 | shrinkWrap: true,
110 | itemCount: state.relatedProducts.length,
111 | scrollDirection: Axis.horizontal,
112 | itemBuilder: (context, pos) {
113 | return ProductDisplayCard(
114 | onPressed: () {
115 | Navigator.push(
116 | context,
117 | MaterialPageRoute(
118 | fullscreenDialog: true,
119 | builder: (context) =>
120 | DetailScreen(state
121 | .relatedProducts[
122 | pos])));
123 | },
124 | product: state.relatedProducts[pos],
125 | margin: 2,
126 | );
127 | }),
128 | );
129 | })
130 | ],
131 | )
132 | ],
133 | ),
134 | ),
135 | ]))
136 | ],
137 | ),
138 | ),
139 | ));
140 | }
141 |
142 | _showSnackbar(BuildContext context, String text) {
143 | Scaffold.of(context).showSnackBar(
144 | SnackBar(duration: Duration(seconds: 1), content: Text(text)));
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/lib/screens/home_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/screens/detail_screen.dart';
2 | import 'package:cool_store/states/home_state.dart';
3 | import 'package:cool_store/utils/constants.dart';
4 | import 'package:cool_store/widgets/OffersBanner.dart';
5 | import 'package:cool_store/widgets/ProductCard.dart';
6 | import 'package:cool_store/widgets/ShimmerGrid.dart';
7 | import 'package:flutter/material.dart';
8 | import 'package:provider/provider.dart';
9 |
10 | class HomeScreen extends StatelessWidget {
11 | @override
12 | Widget build(BuildContext context) {
13 | final HomeState state = Provider.of(context);
14 | return SafeArea(
15 | child: CustomScrollView(
16 | slivers: [
17 | SliverAppBar(
18 | expandedHeight: Constants.screenAwareSize(300, context),
19 | flexibleSpace: FlexibleSpaceBar(
20 | background: Container(
21 | child: Column(
22 | crossAxisAlignment: CrossAxisAlignment.start,
23 | mainAxisAlignment: MainAxisAlignment.start,
24 | children: [
25 | Padding(
26 | padding: const EdgeInsets.only(
27 | left: 18.0, right: 18, top: 18, bottom: 20),
28 | child: Text(
29 | 'COOL STORE',
30 | style: TextStyle(
31 | fontWeight: FontWeight.bold,
32 | fontFamily: 'Raleway',
33 | fontSize: 40),
34 | ),
35 | ),
36 | Container(
37 | height: Constants.screenAwareSize(200, context),
38 | width: MediaQuery.of(context).size.width,
39 | child: OffersBanner(),
40 | )
41 | ],
42 | ),
43 | )),
44 | ),
45 | SliverList(
46 | delegate: SliverChildListDelegate([
47 | Padding(
48 | padding: EdgeInsets.all(18),
49 | child: Row(
50 | children: [
51 | Text(
52 | 'BEST SELLERS',
53 | style: TextStyle(
54 | fontFamily: 'Raleway', fontWeight: FontWeight.bold),
55 | ),
56 | Spacer(),
57 | FlatButton(
58 | onPressed: () {},
59 | child: Text('SEE ALL',
60 | style: TextStyle(fontFamily: 'Raleway', fontSize: 12)),
61 | )
62 | ],
63 | ),
64 | ),
65 | state.isLoading
66 | ? ShimmerGrid()
67 | : GridView.builder(
68 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
69 | childAspectRatio: .6,
70 | crossAxisCount: 2,
71 | crossAxisSpacing: 1,
72 | mainAxisSpacing: 1),
73 | itemBuilder: (context, pos) => ProductDisplayCard(
74 | onPressed: () {
75 | Navigator.push(
76 | context,
77 | MaterialPageRoute(
78 | builder: (_) =>
79 | DetailScreen(state.products[pos]),
80 | fullscreenDialog: true));
81 | },
82 | product: state.products[pos],
83 | ),
84 | physics: NeverScrollableScrollPhysics(),
85 | shrinkWrap: true,
86 | itemCount: state.products.length,
87 | ),
88 | ]))
89 | ],
90 | ),
91 | );
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/lib/screens/order_review_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/states/cart_state.dart';
3 | import 'package:cool_store/utils/constants.dart';
4 | import 'package:cool_store/widgets/CartItem.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:provider/provider.dart';
7 | import 'detail_screen.dart';
8 |
9 | class OrderReview extends StatelessWidget {
10 | final Function onButtonClicked;
11 |
12 | OrderReview({this.onButtonClicked});
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | final state = Provider.of(context);
17 | return SingleChildScrollView(
18 | child: Column(
19 | crossAxisAlignment: CrossAxisAlignment.start,
20 | children: [
21 | Container(
22 | child: Text(
23 | 'Total items ${state.cartProducts.length}',
24 | style: TextStyle(
25 | fontWeight: FontWeight.w300,
26 | fontFamily: 'Raleway',
27 | ),
28 | ),
29 | padding: EdgeInsets.symmetric(horizontal: 17, vertical: 2),
30 | ),
31 | buildCartListView(state),
32 | Container(
33 | child: Column(
34 | mainAxisSize: MainAxisSize.max,
35 | mainAxisAlignment: MainAxisAlignment.end,
36 | crossAxisAlignment: CrossAxisAlignment.center,
37 | children: [
38 | // coupon view
39 | buildCouponView(context, state),
40 |
41 | Padding(
42 | padding: const EdgeInsets.only(top: 18.0),
43 | child: ListTile(
44 | leading: Text('SUB TOTAL'),
45 | trailing: Text('...'),
46 | ),
47 | ),
48 |
49 | RawMaterialButton(
50 | onPressed: onButtonClicked,
51 | fillColor: Theme.of(context).accentColor,
52 | constraints: BoxConstraints(
53 | minWidth: MediaQuery.of(context).size.width,
54 | minHeight: 45),
55 | elevation: 0,
56 | child: Text(
57 | 'PLACE ORDER',
58 | style:
59 | TextStyle(fontFamily: 'Raleway', color: Colors.white),
60 | ),
61 | ),
62 | ],
63 | ),
64 | ),
65 | ],
66 | ),
67 | );
68 | }
69 |
70 | ListView buildCartListView(CartState state) {
71 | return ListView.builder(
72 | shrinkWrap: true,
73 | physics: NeverScrollableScrollPhysics(),
74 | itemCount: state.cartProducts.length,
75 | itemBuilder: (context, pos) {
76 | final item = state.cartProducts[pos];
77 | Product testProduct = state.cartProducts[pos].product;
78 | ProductVariation testProductVariation =
79 | state.cartProducts[pos].productVariation;
80 | int quantity = state.cartProducts[pos].quantity;
81 |
82 | return CartItem(
83 | product: testProduct,
84 | variation: testProductVariation,
85 | quantity: quantity,
86 | onPrimaryButtonPressed: () {
87 | state.addProductToWishList(item);
88 | },
89 | onRemovePressed: () {
90 | state.removeProductFromCart(item);
91 | },
92 | onTap: () {
93 | Navigator.of(context).push(MaterialPageRoute(
94 | builder: (context) => DetailScreen(testProduct),
95 | fullscreenDialog: true));
96 | },
97 | );
98 | });
99 | }
100 |
101 | Container buildCouponView(BuildContext context, CartState state) {
102 | return Container(
103 | height: Constants.screenAwareSize(35, context),
104 | decoration: BoxDecoration(border: Border.all(color: Colors.grey[600])),
105 | margin: EdgeInsets.symmetric(horizontal: 12),
106 | padding: EdgeInsets.symmetric(horizontal: 8),
107 | child: Row(
108 | mainAxisAlignment: MainAxisAlignment.center,
109 | crossAxisAlignment: CrossAxisAlignment.center,
110 | mainAxisSize: MainAxisSize.max,
111 | children: [
112 | Expanded(
113 | flex: 2,
114 | child: TextField(
115 | onChanged: (value) {
116 | // state.setCouponCode(value);
117 | },
118 | onSubmitted: (value) {
119 | // TODO check for code
120 | state.setCouponCode(value);
121 | },
122 | decoration: InputDecoration(
123 | hintText: 'Coupon Code',
124 | hintStyle: TextStyle(
125 | fontFamily: 'Raleway',
126 | color: Theme.of(context).textTheme.subhead.color),
127 | focusedBorder: InputBorder.none,
128 | disabledBorder: InputBorder.none,
129 | enabledBorder: InputBorder.none,
130 | errorBorder: InputBorder.none,
131 | focusedErrorBorder: InputBorder.none),
132 | ),
133 | ),
134 | Expanded(
135 | child: FlatButton.icon(
136 | onPressed: () {},
137 | icon: Icon(Icons.local_offer),
138 | label: Text('Apply')),
139 | )
140 | ],
141 | ),
142 | );
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/lib/screens/order_summary_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/cart_state.dart';
2 | import 'package:cool_store/states/checkout_state.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:provider/provider.dart';
5 |
6 | class OrderSummary extends StatelessWidget {
7 | @override
8 | Widget build(BuildContext context) {
9 | final state = Provider.of(context);
10 | return SingleChildScrollView(
11 | child: Column(
12 | mainAxisAlignment: MainAxisAlignment.center,
13 | mainAxisSize: MainAxisSize.max,
14 | crossAxisAlignment: CrossAxisAlignment.center,
15 | children: [
16 | Text('Order placed',
17 | style: TextStyle(
18 | color: Theme.of(context).accentColor,
19 | fontFamily: 'Raleway',
20 | fontSize: 40)),
21 | SizedBox(
22 | height: 40,
23 | ),
24 | RawMaterialButton(
25 | onPressed: () {
26 | state.clearCart();
27 | Navigator.pop(context);
28 | },
29 | fillColor: Theme.of(context).accentColor,
30 | constraints: BoxConstraints(
31 | minWidth: MediaQuery.of(context).size.width, minHeight: 45),
32 | elevation: 0,
33 | child: Text(
34 | 'Continue Shopping',
35 | style: TextStyle(fontFamily: 'Raleway', color: Colors.white),
36 | ),
37 | ),
38 | ],
39 | ),
40 | );
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/screens/product_list_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/category.dart';
2 | import 'package:cool_store/screens/detail_screen.dart';
3 | import 'package:cool_store/states/product_list_state.dart';
4 | import 'package:cool_store/utils/constants.dart';
5 | import 'package:cool_store/widgets/ProductCard.dart';
6 | import 'package:cool_store/widgets/ShimmerGrid.dart';
7 | import 'package:flutter/material.dart';
8 | import 'package:provider/provider.dart';
9 |
10 | class ProductListScreen extends StatelessWidget {
11 | final Category category;
12 |
13 | ProductListScreen({this.category});
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Scaffold(
18 | body: ChangeNotifierProvider(
19 | builder: (_) => ProductListState(category.id),
20 | child: Consumer(
21 | builder: (context, state, child) {
22 | return SafeArea(
23 | child: CustomScrollView(
24 | slivers: [
25 | SliverAppBar(
26 | title: Text('COOL STORE'),
27 | bottom: buildPreferenceView(context, state),
28 | ),
29 | SliverList(
30 | delegate: SliverChildListDelegate([
31 | state.isLoading
32 | ? ShimmerGrid()
33 | : Column(
34 | children: [
35 | buildDecorationView(context),
36 | buildCategoryProductsView(state)
37 | ],
38 | )
39 | ]))
40 | ],
41 | ),
42 | );
43 | },
44 | )),
45 | );
46 | }
47 |
48 | GridView buildCategoryProductsView(ProductListState state) {
49 | return GridView.builder(
50 | itemCount: state.products.length,
51 | physics: NeverScrollableScrollPhysics(),
52 | shrinkWrap: true,
53 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
54 | crossAxisCount: 2,
55 | childAspectRatio: .6,
56 | mainAxisSpacing: 2,
57 | crossAxisSpacing: 2),
58 | itemBuilder: (context, pos) {
59 | return ProductDisplayCard(
60 | onPressed: () {
61 | Navigator.push(
62 | context,
63 | MaterialPageRoute(
64 | builder: (_) => DetailScreen(state.products[pos]),
65 | fullscreenDialog: true));
66 | },
67 | product: state.products[pos],
68 | );
69 | });
70 | }
71 |
72 | Container buildDecorationView(BuildContext context) {
73 | return Container(
74 | padding: EdgeInsets.all(17),
75 | child: Column(
76 | children: [
77 | RichText(
78 | text: TextSpan(
79 | children: [
80 | TextSpan(
81 | text: ' NEW ARRIVALS - ${category.name}',
82 | style: DefaultTextStyle.of(context).style.copyWith(
83 | fontFamily: 'Raleway', fontWeight: FontWeight.bold)),
84 | TextSpan(
85 | text: ' ( ${category.totalProduct} )',
86 | style: DefaultTextStyle.of(context)
87 | .style
88 | .copyWith(fontWeight: FontWeight.w100))
89 | ],
90 | ),
91 | ),
92 | Container(
93 | margin: EdgeInsets.all(4),
94 | height: 2,
95 | width: MediaQuery.of(context).size.width / 4,
96 | color: Theme.of(context).accentColor,
97 | )
98 | ],
99 | ),
100 | );
101 | }
102 |
103 | PreferredSize buildPreferenceView(
104 | BuildContext context, ProductListState state) {
105 | return PreferredSize(
106 | child: Container(
107 | child: Row(
108 | children: [
109 | Expanded(
110 | child: FlatButton.icon(
111 | onPressed: () {
112 | _showOptions(context, [
113 | // 'SORT BY',
114 | 'POPULAR',
115 | 'NEW',
116 | 'PRICE: LOW TO HIGH',
117 | 'PRICE: HIGH TO LOW'
118 | ]);
119 | },
120 | icon: Icon(Icons.sort),
121 | label: Text('SORT BY'),
122 | )),
123 | Container(
124 | width: 1,
125 | height: 15,
126 | color: Colors.black,
127 | ),
128 | Expanded(
129 | child: FlatButton.icon(
130 | onPressed: () {},
131 | label: Text('FILTER'),
132 | icon: Icon(Icons.tune),
133 | ))
134 | ],
135 | ),
136 | ),
137 | preferredSize: Size(100, Constants.screenAwareSize(40, context)));
138 | }
139 |
140 | _showOptions(context, List options) {
141 | return showModalBottomSheet(
142 | context: context,
143 | builder: (context) {
144 | return SafeArea(
145 | child: Column(
146 | mainAxisSize: MainAxisSize.min,
147 | children: options
148 | .map((value) => ListTile(
149 | onTap: () {
150 | Navigator.of(context).pop(value);
151 | },
152 | title: Center(
153 | child: Text(
154 | value,
155 | style: TextStyle(fontFamily: 'Raleway', fontSize: 14),
156 | )),
157 | ))
158 | .toList(),
159 | ),
160 | );
161 | });
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/lib/screens/search_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/app_state.dart';
2 | import 'package:cool_store/states/search_state.dart';
3 | import 'package:cool_store/widgets/InfoView.dart';
4 | import 'package:cool_store/widgets/ProductCard.dart';
5 | import 'package:cool_store/widgets/ShimmerGrid.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:flutter_svg/svg.dart';
8 | import 'package:provider/provider.dart';
9 |
10 | class SearchScreen extends StatefulWidget {
11 | @override
12 | _SearchScreenState createState() => _SearchScreenState();
13 | }
14 |
15 | class _SearchScreenState extends State {
16 | final TextEditingController _searchController = TextEditingController();
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | final state = Provider.of(context);
21 | return Scaffold(
22 | appBar: AppBar(
23 | leading: IconButton(
24 | icon: Icon(Icons.close),
25 | onPressed: () async {
26 | state.addKeywordsToStorage();
27 | Navigator.of(context).pop();
28 | }),
29 | ),
30 | body: SafeArea(
31 | child: CustomScrollView(
32 | slivers: [
33 | SliverList(
34 | delegate: SliverChildListDelegate([
35 | Container(
36 | margin: EdgeInsets.all(8),
37 | padding: EdgeInsets.symmetric(horizontal: 8),
38 | decoration: BoxDecoration(
39 | border: Border.all(color: Colors.grey[600])),
40 | child: Row(
41 | mainAxisSize: MainAxisSize.max,
42 | mainAxisAlignment: MainAxisAlignment.center,
43 | crossAxisAlignment: CrossAxisAlignment.center,
44 | children: [
45 | Expanded(
46 | child: TextField(
47 | controller: _searchController,
48 | onChanged: (value) {
49 | state.clearResult();
50 | },
51 | onSubmitted: (value) {
52 | state.setKeyword(value);
53 | },
54 | decoration: InputDecoration(
55 | focusedErrorBorder: InputBorder.none,
56 | hintText: 'Search for products',
57 | errorBorder: InputBorder.none,
58 | enabledBorder: InputBorder.none,
59 | disabledBorder: InputBorder.none,
60 | focusedBorder: InputBorder.none,
61 | ),
62 | )),
63 | IconButton(
64 | icon: Icon(Icons.clear_all),
65 | onPressed: () {
66 | state.clearResult();
67 | _searchController.clear();
68 | })
69 | ],
70 | ),
71 | ),
72 | state.showKeywords
73 | ? buildKeywords(state)
74 | : state.isResultLoading
75 | ? ShimmerGrid()
76 | : state.searchResult.length > 0
77 | ? buildResultView(state)
78 | : InfoView(
79 | primaryText:
80 | 'We couldn\'t find any matches for ${state.searchKeyword} ',
81 | secondaryText:
82 | 'Maybe your search was too specific, please try searching with another term',
83 | )
84 | ]))
85 | ],
86 | ),
87 | ));
88 | }
89 |
90 | GridView buildResultView(SearchState state) {
91 | return GridView.builder(
92 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
93 | crossAxisCount: 2,
94 | mainAxisSpacing: 2,
95 | crossAxisSpacing: 2,
96 | childAspectRatio: .6),
97 | itemCount: state.searchResult.length,
98 | shrinkWrap: true,
99 | physics: NeverScrollableScrollPhysics(),
100 | itemBuilder: (context, pos) {
101 | return ProductDisplayCard(
102 | onPressed: () {},
103 | product: state.searchResult[pos],
104 | );
105 | });
106 | }
107 |
108 | ListView buildKeywords(SearchState state) {
109 | return ListView.separated(
110 | physics: NeverScrollableScrollPhysics(),
111 | shrinkWrap: true,
112 | itemCount: state.keyWords.length,
113 | itemBuilder: (context, pos) {
114 | return ListTile(
115 | onTap: () {
116 | _searchController.text = state.keyWords[pos];
117 | state.setKeyword(state.keyWords[pos]);
118 | },
119 | onLongPress: () {
120 | state.removeKeyword(state.keyWords[pos]);
121 | },
122 | title: Text('${state.keyWords[pos]}'),
123 | leading: Icon(Icons.search),
124 | trailing: Icon(Icons.chevron_right),
125 | );
126 | },
127 | separatorBuilder: (BuildContext context, int index) => Divider(),
128 | );
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/lib/screens/setting_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/app_state.dart';
2 | import 'package:cool_store/utils/constants.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:provider/provider.dart';
5 |
6 | class SettingScreen extends StatelessWidget {
7 | @override
8 | Widget build(BuildContext context) {
9 | final AppState appState = Provider.of(context);
10 | return SafeArea(
11 | child: CustomScrollView(
12 | slivers: [
13 | SliverAppBar(
14 | expandedHeight: Constants.screenAwareSize(80, context),
15 | flexibleSpace: FlexibleSpaceBar(
16 | background: Column(
17 | crossAxisAlignment: CrossAxisAlignment.start,
18 | children: [
19 | Container(
20 | child: Text(
21 | 'Setting',
22 | style: TextStyle(
23 | fontWeight: FontWeight.bold,
24 | fontFamily: 'Raleway',
25 | fontSize: 40),
26 | ),
27 | padding: EdgeInsets.symmetric(horizontal: 17, vertical: 8),
28 | ),
29 | ],
30 | ),
31 | ),
32 | ),
33 | SliverList(
34 | delegate: SliverChildListDelegate([
35 | ListTile(
36 | onTap: () {
37 | appState.isDark
38 | ? appState.setLightTheme()
39 | : appState.setDarkTheme();
40 | },
41 | leading: Icon(Icons.lightbulb_outline),
42 | title: Text('Change Theme'),
43 | )
44 | ]))
45 | ],
46 | ));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/lib/screens/shipping_methods_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/checkout_state.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:provider/provider.dart';
4 |
5 | class ShippingMethodsScreen extends StatelessWidget {
6 | final Function onNextPressed;
7 | final Function onBackPressed;
8 |
9 | ShippingMethodsScreen(
10 | {@required this.onNextPressed, @required this.onBackPressed});
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | final state = Provider.of(context);
15 |
16 | return SingleChildScrollView(
17 | child: Column(
18 | children: [
19 | Padding(
20 | padding: const EdgeInsets.all(8.0),
21 | child: Text(
22 | 'Choose Shipping Method',
23 | textAlign: TextAlign.start,
24 | style: TextStyle(fontFamily: 'Raleway-bold', fontSize: 28),
25 | ),
26 | ),
27 | state.isShippingMethodsLoading
28 | ? Center(
29 | child: CircularProgressIndicator(),
30 | )
31 | : ListView.separated(
32 | shrinkWrap: true,
33 | itemCount: state.shippingMethods.length,
34 | physics: NeverScrollableScrollPhysics(),
35 | itemBuilder: (_, pos) {
36 | final item = state.shippingMethods[pos];
37 | return ListTile(
38 | isThreeLine: true,
39 | leading: state.selectedShippingMethod.isEqual(item)
40 | ? Icon(
41 | Icons.check,
42 | color: Theme.of(context).accentColor,
43 | )
44 | : Icon(Icons.radio_button_unchecked),
45 | title: Text(
46 | '${item.title}',
47 | style: TextStyle(
48 | fontFamily: "Raleway",
49 | color: state.selectedShippingMethod.isEqual(item)
50 | ? Theme.of(context).accentColor
51 | : Theme.of(context).textTheme.title.color),
52 | ),
53 | subtitle: Text(
54 | '${item.description}',
55 | style: TextStyle(fontFamily: "Raleway"),
56 | ),
57 | onTap: () {
58 | state.setShippingMethod(item);
59 | },
60 | );
61 | },
62 | separatorBuilder: (__, _) => Divider(),
63 | ),
64 | SizedBox(
65 | height: 30,
66 | ),
67 | RawMaterialButton(
68 | onPressed: onNextPressed,
69 | constraints: BoxConstraints(
70 | minWidth: MediaQuery.of(context).size.width, minHeight: 45),
71 | fillColor: Theme.of(context).accentColor,
72 | elevation: 0,
73 | child: Text(
74 | 'REVIEW ORDER',
75 | style: TextStyle(fontFamily: 'Raleway', color: Colors.white),
76 | ),
77 | ),
78 | RawMaterialButton(
79 | onPressed: onBackPressed,
80 | constraints: BoxConstraints(
81 | minWidth: MediaQuery.of(context).size.width, minHeight: 25),
82 | elevation: 0,
83 | child: Text(
84 | 'EDIT ADDRESS',
85 | style: TextStyle(
86 | fontFamily: 'Raleway', color: Theme.of(context).accentColor),
87 | ),
88 | ),
89 | ],
90 | ),
91 | );
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/lib/screens/wishlist_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/app_state.dart';
2 | import 'package:cool_store/states/cart_state.dart';
3 | import 'package:cool_store/widgets/CartItem.dart';
4 | import 'package:cool_store/widgets/InfoView.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:provider/provider.dart';
7 |
8 | class WishListScreen extends StatelessWidget {
9 | @override
10 | Widget build(BuildContext context) {
11 | final state = Provider.of(context);
12 | final theme = Theme.of(context);
13 | return Scaffold(
14 | body: CustomScrollView(
15 | slivers: [
16 | SliverAppBar(),
17 | SliverList(
18 | delegate: SliverChildListDelegate([
19 | state.wishListCartProducts.length > 0
20 | ? ListView.builder(
21 | physics: NeverScrollableScrollPhysics(),
22 | shrinkWrap: true,
23 | itemCount: state.wishListCartProducts.length,
24 | itemBuilder: (context, pos) {
25 | // Product product =
26 | // state.wishListProducts.keys.elementAt(pos);
27 | // ProductVariation variation =
28 | // state.wishListProducts.values.elementAt(pos);
29 | final item = state.wishListCartProducts[pos];
30 | final product = item.product;
31 | final variation = item.productVariation;
32 | return CartItem(
33 | product: product,
34 | variation: variation,
35 | primaryTitle: 'Move to cart',
36 | onRemovePressed: () {
37 | state.removeProductFromWishList(item);
38 | },
39 | onPrimaryButtonPressed: () {
40 | state.removeProductAndAddToCart(item);
41 | },
42 | );
43 | })
44 | : buildEmptyView(theme, context)
45 | ]))
46 | ],
47 | ),
48 | );
49 | }
50 |
51 | Column buildEmptyView(ThemeData theme, BuildContext context) {
52 | return Column(
53 | mainAxisAlignment: MainAxisAlignment.center,
54 | crossAxisAlignment: CrossAxisAlignment.center,
55 | mainAxisSize: MainAxisSize.max,
56 | children: [
57 | InfoView(
58 | path: 'assets/list.svg',
59 | iconColor: theme.iconTheme.color.withOpacity(.8),
60 | primaryText: 'Empty wishlist',
61 | ),
62 | Padding(
63 | padding: const EdgeInsets.all(8.0),
64 | child: FlatButton(
65 | color: theme.accentColor,
66 | onPressed: () {
67 | Navigator.pop(context);
68 | Provider.of(context).navigateToHome();
69 | },
70 | child: Text(
71 | 'START SHOPPING',
72 | style: TextStyle(color: Colors.white, fontFamily: 'Raleway'),
73 | )),
74 | )
75 | ],
76 | );
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/lib/services/woocommerce_api.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import "dart:collection";
3 | import 'dart:convert';
4 | import "dart:core";
5 | import 'dart:io';
6 | import "dart:math";
7 | import 'package:crypto/crypto.dart' as crypto;
8 | import 'package:flutter/cupertino.dart';
9 | import 'package:http/http.dart' as http;
10 |
11 | class QueryString {
12 | static Map parse(String query) {
13 | var search = new RegExp('([^&=]+)=?([^&]*)');
14 | var result = new Map();
15 |
16 | // Get rid off the beginning ? in query strings.
17 | if (query.startsWith('?')) query = query.substring(1);
18 | // A custom decoder.
19 | decode(String s) => Uri.decodeComponent(s.replaceAll('+', ' '));
20 |
21 | // Go through all the matches and build the result map.
22 | for (Match match in search.allMatches(query)) {
23 | result[decode(match.group(1))] = decode(match.group(2));
24 | }
25 | return result;
26 | }
27 | }
28 |
29 | class WooCommerceAPI {
30 | String url;
31 | String consumerKey;
32 | String consumerSecret;
33 | bool isHttps;
34 |
35 | WooCommerceAPI({this.url, this.consumerKey, this.consumerSecret}) {
36 | if (this.url.startsWith("https")) {
37 | this.isHttps = true;
38 | } else {
39 | this.isHttps = false;
40 | }
41 | }
42 |
43 | _getOAuthURL(String requestMethod, String endpoint) {
44 | var consumerKey = this.consumerKey;
45 | var consumerSecret = this.consumerSecret;
46 |
47 | var token = "";
48 | var url = this.url + "/wp-json/wc/v3/" + endpoint;
49 | var containsQueryParams = url.contains("?");
50 |
51 | // If website is HTTPS based, no need for OAuth, just return the URL with CS and CK as query params
52 | if (this.isHttps == true) {
53 | return url +
54 | (containsQueryParams == true
55 | ? "&consumer_key=" +
56 | this.consumerKey +
57 | "&consumer_secret=" +
58 | this.consumerSecret
59 | : "?consumer_key=" +
60 | this.consumerKey +
61 | "&consumer_secret=" +
62 | this.consumerSecret);
63 | }
64 |
65 | var rand = new Random();
66 | var codeUnits = new List.generate(10, (index) {
67 | return rand.nextInt(26) + 97;
68 | });
69 |
70 | var nonce = new String.fromCharCodes(codeUnits);
71 | int timestamp = (new DateTime.now().millisecondsSinceEpoch ~/ 1000).toInt();
72 |
73 | var method = requestMethod;
74 | var parameters = "oauth_consumer_key=" +
75 | consumerKey +
76 | "&oauth_nonce=" +
77 | nonce +
78 | "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" +
79 | timestamp.toString() +
80 | "&oauth_token=" +
81 | token +
82 | "&oauth_version=1.0&";
83 |
84 | if (containsQueryParams == true) {
85 | parameters = parameters + url.split("?")[1];
86 | } else {
87 | parameters = parameters.substring(0, parameters.length - 1);
88 | }
89 |
90 | Map params = QueryString.parse(parameters);
91 | Map treeMap = new SplayTreeMap();
92 | treeMap.addAll(params);
93 |
94 | String parameterString = "";
95 |
96 | for (var key in treeMap.keys) {
97 | parameterString = parameterString +
98 | Uri.encodeQueryComponent(key) +
99 | "=" +
100 | treeMap[key] +
101 | "&";
102 | }
103 |
104 | parameterString = parameterString.substring(0, parameterString.length - 1);
105 |
106 | var baseString = method +
107 | "&" +
108 | Uri.encodeQueryComponent(
109 | containsQueryParams == true ? url.split("?")[0] : url) +
110 | "&" +
111 | Uri.encodeQueryComponent(parameterString);
112 |
113 | var signingKey = consumerSecret + "&" + token;
114 |
115 | var hmacSha1 =
116 | new crypto.Hmac(crypto.sha1, utf8.encode(signingKey)); // HMAC-SHA1
117 | var signature = hmacSha1.convert(utf8.encode(baseString));
118 |
119 | var finalSignature = base64Encode(signature.bytes);
120 |
121 | var requestUrl = "";
122 |
123 | if (containsQueryParams == true) {
124 | requestUrl = url.split("?")[0] +
125 | "?" +
126 | parameterString +
127 | "&oauth_signature=" +
128 | Uri.encodeQueryComponent(finalSignature);
129 | } else {
130 | requestUrl = url +
131 | "?" +
132 | parameterString +
133 | "&oauth_signature=" +
134 | Uri.encodeQueryComponent(finalSignature);
135 | }
136 |
137 | // print('network: $requestUrl');
138 |
139 | return requestUrl;
140 | }
141 |
142 | Future getAsync(String endPoint, {Map data}) async {
143 | // debugPrint('int woocommerceAPI getAsync method');
144 | var url = this._getOAuthURL("GET", endPoint);
145 |
146 | //// print('$url');
147 | // if (data != null) {
148 | // var client = new http.Client();
149 | // Map headers = HashMap();
150 | // headers.update(HttpHeaders.contentTypeHeader,
151 | // (_) => 'application/json; charset=utf-8',
152 | // ifAbsent: () => 'application/json; charset=utf-8');
153 | // headers.update(HttpHeaders.cacheControlHeader, (_) => 'no-cache',
154 | // ifAbsent: () => 'no-cache');
155 | // print('${Uri.parse(url)} body: ${json.encode(data)}');
156 | // var response = await client.post(Uri.parse(url),
157 | // headers: headers, body: json.encode(data));
158 | // print('response ${response.body}');
159 | // return json.decode(response.body);
160 | // } else {
161 | // print('$url');
162 | final response = await http.get(url);
163 |
164 | return json.decode(response.body);
165 | // }
166 | }
167 |
168 | Future postAsync(String endPoint, Map data) async {
169 | var url = this._getOAuthURL("POST", endPoint);
170 |
171 | var client = new http.Client();
172 | // var request = new http.Request('POST', Uri.parse(url));
173 | // request.headers[HttpHeaders.contentTypeHeader] =
174 | // 'application/json; charset=utf-8';
175 | // request.headers[HttpHeaders.cacheControlHeader] = "no-cache";
176 | // request.body = json.encode(data);
177 | //
178 | // var response =
179 | // await client.send(request).then((res) => res.stream.bytesToString());
180 | // var dataResponse = await json.decode(response);
181 | // return dataResponse;
182 | Map headers = HashMap();
183 | headers.update(
184 | HttpHeaders.contentTypeHeader, (_) => 'application/json; charset=utf-8',
185 | ifAbsent: () => 'application/json; charset=utf-8');
186 | headers.update(HttpHeaders.cacheControlHeader, (_) => 'no-cache',
187 | ifAbsent: () => 'no-cache');
188 | var response = await client.post(Uri.parse(url),
189 | headers: headers, body: json.encode(data));
190 | print('response ${response.body}');
191 | return json.decode(response.body);
192 | }
193 |
194 | Future putAsync(String endPoint, Map data) async {
195 | var url = this._getOAuthURL("PUT", endPoint);
196 |
197 | print('url: $url');
198 | var client = new http.Client();
199 | // var request = new http.Request('PUT', Uri.parse(url));
200 | // request.headers[HttpHeaders.contentTypeHeader] =
201 | // 'application/json; charset=utf-8';
202 | // request.headers[HttpHeaders.cacheControlHeader] = "no-cache";
203 | // request.body = json.encode(data);
204 |
205 | // print(
206 | // 'request : $request body ${request.body} headers: ${request.headers}');
207 | // var response =
208 | // await client.send(request).then((res) => res.stream.bytesToString());
209 | // var dataResponse = await json.decode(response);
210 | // print('data response: $dataResponse');
211 | Map headers = HashMap();
212 | headers.update(
213 | HttpHeaders.contentTypeHeader, (_) => 'application/json; charset=utf-8',
214 | ifAbsent: () => 'application/json; charset=utf-8');
215 | headers.update(HttpHeaders.cacheControlHeader, (_) => 'no-cache',
216 | ifAbsent: () => 'no-cache');
217 | var response = await client.put(Uri.parse(url),
218 | headers: headers, body: json.encode(data));
219 | print('response ${response.body}');
220 | return json.decode(response.body);
221 | }
222 |
223 | void dispose() {}
224 | }
225 |
--------------------------------------------------------------------------------
/lib/states/app_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/utils/constants.dart';
2 | import 'package:extended_image/extended_image.dart';
3 | import 'package:flutter/foundation.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:shared_preferences/shared_preferences.dart';
6 |
7 | class AppState extends ChangeNotifier {
8 | ThemeData _themeData = Constants.lightTheme;
9 | bool isDark = false;
10 | int _selectedScreenIndex = 0;
11 | Widget _selectedScreen;
12 | List _screens;
13 |
14 | AppState({@required initialScreen, @required screens}) {
15 | _selectedScreen = initialScreen;
16 | _screens = screens;
17 | _reteriveThemePreference();
18 | }
19 |
20 | Widget get selectedScreen => _selectedScreen;
21 |
22 | List get screens => _screens;
23 |
24 | ThemeData getTheme() => _themeData;
25 |
26 | _setTheme(ThemeData themeData) {
27 | _themeData = themeData;
28 | notifyListeners();
29 | _saveThemePreference();
30 | }
31 |
32 | int get selectedScreenIndex => _selectedScreenIndex;
33 |
34 | setScreenIndex(int pos) {
35 | _selectedScreenIndex = pos;
36 | _selectedScreen = _screens[pos];
37 | notifyListeners();
38 | }
39 |
40 | changeScreenTo(Widget widget) {
41 | _selectedScreenIndex = _screens.indexOf(widget);
42 | _selectedScreen = _screens[_selectedScreenIndex];
43 | notifyListeners();
44 | }
45 |
46 | setDarkTheme() {
47 | isDark = true;
48 | _setTheme(Constants.darkTheme);
49 | }
50 |
51 | setLightTheme() {
52 | isDark = false;
53 | _setTheme(Constants.lightTheme);
54 | }
55 |
56 | _saveThemePreference() async {
57 | SharedPreferences preferences = await SharedPreferences.getInstance();
58 | preferences.setBool(Constants.kLocalKey['isDarkTheme'], isDark);
59 | }
60 |
61 | _reteriveThemePreference() async {
62 | SharedPreferences preferences = await SharedPreferences.getInstance();
63 | if (preferences.containsKey(Constants.kLocalKey['isDarkTheme'])) {
64 | isDark = preferences.getBool(Constants.kLocalKey['isDarkTheme']);
65 | isDark ? setDarkTheme() : setLightTheme();
66 | }
67 | }
68 |
69 | void navigateToHome() {
70 | setScreenIndex(0);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/states/cart_state.dart:
--------------------------------------------------------------------------------
1 | import 'dart:collection';
2 | import 'dart:convert';
3 |
4 | import 'package:cool_store/models/payment.dart';
5 | import 'package:cool_store/models/product.dart';
6 | import 'package:cool_store/models/user.dart';
7 | import 'package:cool_store/utils/constants.dart';
8 | import 'package:flutter/foundation.dart';
9 | import 'package:localstorage/localstorage.dart';
10 |
11 | class CartState extends ChangeNotifier {
12 | // product and id
13 | Map _products;
14 |
15 | // product id and the quantity
16 | Map _productsInCart;
17 |
18 | Map get productsInCart =>
19 | _productsInCart; // products list in cart
20 |
21 | //product id and variations
22 | Map _productVariationsInCart;
23 |
24 | Map get productVariationsInCart =>
25 | _productVariationsInCart;
26 |
27 | double totalCartAmount = 0;
28 |
29 | Map get products => _products; // addProduct(
30 |
31 | Map _wishListProducts = HashMap();
32 |
33 | Map get wishListProducts => _wishListProducts;
34 |
35 | // product id and quantity selected
36 | Map _productQuantityInCart;
37 |
38 | Map get productQuantityInCart => _productQuantityInCart;
39 |
40 | //TODO update according to shipping methods
41 | double totalCartExtraCharge = 200;
42 | double totalCartPayableAmount = 0;
43 |
44 | Address address;
45 | PaymentMethod paymentMethod;
46 |
47 | String couponCode;
48 |
49 | List cartProducts = List();
50 | List wishListCartProducts = List();
51 |
52 | CartState() {
53 | _products = HashMap();
54 | _productsInCart = HashMap();
55 | _productVariationsInCart = HashMap();
56 | _productQuantityInCart = HashMap();
57 | address = Address(
58 | zipCode: '343905',
59 | firstName: 'mithilesh',
60 | lastName: 'parmar',
61 | email: 'test@cool.com',
62 | street: 'vit road',
63 | city: 'jaipur',
64 | state: 'Rajasthan',
65 | country: 'in',
66 | phoneNumber: '19863921631');
67 | paymentMethod = PaymentMethod(
68 | id: '1', title: 'cod', description: 'cash on delivery', enabled: true);
69 | _loadFromLocalStorage();
70 | calculateTotalCartAmount();
71 | }
72 |
73 | addProductToCart(
74 | Product product,
75 | ProductVariation variation,
76 | int quantity,
77 | ) {
78 | cartProducts.add(CartProduct(
79 | productVariation: variation, product: product, quantity: quantity));
80 | // _productsInCart.update(product.id.toString(), (_) => quantity,
81 | // ifAbsent: () => quantity);
82 | // _products.update(product.id.toString(), (_) => product,
83 | // ifAbsent: () => product);
84 | // _productVariationsInCart.update(product.id.toString(), (_) => variation,
85 | // ifAbsent: () => variation);
86 | totalCartAmount += double.parse(variation.price);
87 | notifyListeners();
88 | _saveProductsToLocalStorage();
89 | }
90 |
91 | // Save products to local storage
92 | _saveProductsToLocalStorage() async {
93 | final LocalStorage _localStorage = LocalStorage(
94 | Constants.APP_FOLDER,
95 | );
96 |
97 | try {
98 | final ready = await _localStorage.ready;
99 | if (ready) {
100 | await _localStorage.setItem(
101 | Constants.kLocalKey['productsInCart'], json.encode(cartProducts));
102 | }
103 | } catch (e) {
104 | throw e;
105 | }
106 | }
107 |
108 | _loadFromLocalStorage() async {
109 | final LocalStorage _localStorage = LocalStorage(Constants.APP_FOLDER);
110 | try {
111 | final ready = await _localStorage.ready;
112 | if (ready) {
113 | if (await _localStorage
114 | .getItem(Constants.kLocalKey['productsInCart']) !=
115 | null) {
116 | final localJson = jsonDecode(await _localStorage
117 | .getItem(Constants.kLocalKey['productsInCart']));
118 | localJson.forEach((value) {
119 | final item = CartProduct.fromJson(value);
120 | cartProducts.add(item);
121 |
122 | // _productsInCart.update(
123 | // item.product.id.toString(), (_) => item.quantity,
124 | // ifAbsent: () => item.quantity);
125 | // _products.update(item.product.id.toString(), (_) => item.product,
126 | // ifAbsent: () => item.product);
127 | // _productVariationsInCart.update(
128 | // item.product.id.toString(), (_) => item.productVariation,
129 | // ifAbsent: () => item.productVariation);
130 | notifyListeners();
131 | });
132 | }
133 | }
134 | } catch (e) {
135 | throw e;
136 | }
137 | }
138 |
139 | // addProductToWishList(Product product, ProductVariation variation) {
140 | // _wishListProducts.update(product, (_) => variation,
141 | // ifAbsent: () => variation);
142 | // removeProduct(product.id);
143 | // notifyListeners();
144 | // }
145 |
146 | addProductToWishList(CartProduct product) {
147 | wishListCartProducts.add(product);
148 | removeProductFromCart(product);
149 | // totalCartAmount -= double.parse(product.productVariation.price);
150 | notifyListeners();
151 | }
152 |
153 | removeProductAndAddToCart(CartProduct item) {
154 | wishListCartProducts.remove(item);
155 | cartProducts.add(item);
156 | // totalCartAmount += double.parse(item.productVariation.price);
157 | notifyListeners();
158 | }
159 |
160 | // removeProduct(int id) {
161 | // _productsInCart.remove(id.toString());
162 | // _products.remove(id);
163 | // _productVariationsInCart.remove(id);
164 | //
165 | // notifyListeners();
166 | //
167 | // _saveProductsToLocalStorage();
168 | // }
169 |
170 | removeProductFromCart(item) {
171 | cartProducts.remove(item);
172 | // totalCartAmount -= double.parse(item.productVariation.price);
173 | notifyListeners();
174 | _saveProductsToLocalStorage();
175 | }
176 |
177 | removeProductFromWishList(item) {
178 | wishListCartProducts.remove(item);
179 | notifyListeners();
180 | }
181 |
182 | setCouponCode(String value) {
183 | couponCode = value;
184 | }
185 |
186 | calculateTotalCartAmount() {
187 | cartProducts
188 | .forEach((item) => totalCartAmount += double.parse(item.product.price));
189 | }
190 |
191 | clearCart() {
192 | cartProducts.clear();
193 | notifyListeners();
194 | _saveProductsToLocalStorage();
195 | }
196 |
197 | updateTotalPayableAmount() =>
198 | totalCartPayableAmount = totalCartAmount + totalCartExtraCharge;
199 | }
200 |
201 | // class used to save and reterive product from local storage
202 | class CartProduct {
203 | Product product;
204 | ProductVariation productVariation;
205 | int quantity;
206 |
207 | CartProduct({this.product, this.productVariation, this.quantity});
208 |
209 | Map toJson() {
210 | return {
211 | 'product': product,
212 | 'productVariation': productVariation,
213 | 'quantity': quantity
214 | };
215 | }
216 |
217 | CartProduct.fromJson(Map parsedJson) {
218 | product = Product.fromLocalJson(parsedJson['product']);
219 | productVariation =
220 | ProductVariation.fromJson(parsedJson['productVariation']);
221 | quantity = parsedJson['quantity'];
222 | }
223 |
224 | @override
225 | String toString() {
226 | // TODO: implement toString
227 | return '\n$product\n$productVariation\n$quantity';
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/lib/states/category_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/category.dart' as Product;
2 | import 'package:cool_store/services/base_services.dart';
3 | import 'package:flutter/foundation.dart';
4 | import 'package:cool_store/models/product.dart' as Woocommerce;
5 |
6 | class CategoryState extends ChangeNotifier {
7 | Services _services;
8 | bool isLoading;
9 | bool isSearchResultLoading;
10 | Map _categoryList;
11 | String errorMessage;
12 | List categories;
13 | List _searchResult;
14 |
15 | CategoryState() {
16 | isLoading = true;
17 | isSearchResultLoading = true;
18 | categories = List();
19 | _categoryList = {};
20 | _services = Services();
21 | initCategories();
22 | }
23 |
24 | List get searchResult => _searchResult;
25 |
26 | performSearch(String query) async {
27 | _searchResult = List();
28 | _searchResult = await _services.searchProducts(name: query, page: 1);
29 | isSearchResultLoading = false;
30 | notifyListeners();
31 | }
32 |
33 | initCategories() async {
34 | try {
35 | categories = await _services.getCategories();
36 | isLoading = false;
37 | for (var cat in categories) {
38 | _categoryList[cat.id] = cat;
39 | }
40 | notifyListeners();
41 | } catch (err) {
42 | isLoading = false;
43 | errorMessage = err.toString();
44 | notifyListeners();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/states/checkout_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/payment.dart';
2 | import 'package:cool_store/models/product.dart';
3 | import 'package:cool_store/models/shipping_methods.dart';
4 |
5 | import 'package:cool_store/models/user.dart';
6 | import 'package:cool_store/services/base_services.dart';
7 | import 'package:cool_store/states/cart_state.dart';
8 |
9 | import 'package:flutter/foundation.dart';
10 |
11 | class CheckoutState extends ChangeNotifier {
12 | bool isLoading = true;
13 | String response = '';
14 | Services _service = Services();
15 | List _shippingMethods = List();
16 | bool isShippingMethodsLoading = true;
17 | ShippingMethods selectedShippingMethod;
18 | List cartProducts = List();
19 | double subTotal = 0.0;
20 |
21 | Services get service => _service;
22 |
23 | CheckoutState() {
24 | getShippingMethods();
25 |
26 | calculateSubTotal();
27 | }
28 |
29 |
30 |
31 | createOrder(
32 | Map productsInCart,
33 | Map productVariationsInCart,
34 | Address address,
35 | PaymentMethod paymentMethod) {
36 | _service.createOrder(
37 | productsInCart, productVariationsInCart, address, paymentMethod);
38 | }
39 |
40 | getShippingMethods() async {
41 | _shippingMethods = await _service.getShippingMethods();
42 | setShippingMethod(_shippingMethods[0]);
43 | isShippingMethodsLoading = false;
44 | notifyListeners();
45 | }
46 |
47 | List get shippingMethods => _shippingMethods;
48 |
49 | setShippingMethod(item) {
50 | selectedShippingMethod = item;
51 | notifyListeners();
52 | }
53 |
54 | calculateSubTotal() {
55 | cartProducts.forEach((item) {
56 | subTotal += double.parse(item.productVariation.price);
57 | });
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/states/detail_state.dart:
--------------------------------------------------------------------------------
1 | import 'dart:collection';
2 |
3 | import 'package:cool_store/models/product.dart';
4 | import 'package:cool_store/services/base_services.dart';
5 | import 'package:cool_store/states/cart_state.dart';
6 | import 'package:flutter/foundation.dart';
7 | import 'package:provider/provider.dart';
8 |
9 | enum Errors { variationNotSelected, productNotLoaded }
10 |
11 | class DetailState extends ChangeNotifier {
12 | bool isLoading,
13 | isRelatedProductsLoading,
14 | isVariantsLoading,
15 | isReviewsLoading,
16 | doesContainReviews;
17 | String _quantity;
18 | Services _services;
19 | ProductVariation _currentVariation;
20 | Product _product;
21 | List relatedProducts;
22 | List _productVariations;
23 | List _reviews;
24 |
25 | String _productId;
26 | int _categoryId;
27 |
28 | // contains id of variation and variation itself
29 | Map variationMap = HashMap();
30 |
31 | // container attribute name and value
32 | Map attributesMap = HashMap();
33 |
34 | DetailState(id) {
35 | this._productId = id.toString();
36 | _quantity = '1';
37 | isLoading = true;
38 | isVariantsLoading = true;
39 | isRelatedProductsLoading = true;
40 | isReviewsLoading = true;
41 | doesContainReviews = false;
42 | relatedProducts = List();
43 | _productVariations = List();
44 | _reviews = List();
45 | _services = Services();
46 | initProduct();
47 | }
48 |
49 | String get quantity => _quantity;
50 |
51 | Product get product => _product;
52 |
53 | initProduct() async {
54 | try {
55 | _product = await _services.getProduct(_productId);
56 | _categoryId = _product.categoryId;
57 | isLoading = false;
58 | notifyListeners();
59 | initRelatedProducts();
60 | initProductVariations();
61 | initReviews();
62 | } catch (e) {
63 | print('$e');
64 | // throw Exception('No INTERNET CONNECTION');
65 | }
66 | }
67 |
68 | changeAttributesTo(String attribute, String value) {
69 | if (value == null) print('no value for $attribute selected');
70 | attributesMap.update(attribute, (_) => value, ifAbsent: () => value);
71 | changeProductVariation(variationMap[attributesMap.toString()]);
72 | }
73 |
74 | void changeProductVariation(ProductVariation variation) {
75 | _currentVariation = variation;
76 | notifyListeners();
77 | }
78 |
79 | ProductVariation get currentVariation => _currentVariation;
80 |
81 | initRelatedProducts() async {
82 | relatedProducts = await _services.fetchProductsByCategory(
83 | categoryId: _categoryId, page: 1);
84 | isRelatedProductsLoading = false;
85 | notifyListeners();
86 | }
87 |
88 | initReviews() async {
89 | _reviews = await _services.getReviews(_product.id);
90 | if (_reviews.length > 0) doesContainReviews = true;
91 | isReviewsLoading = false;
92 | notifyListeners();
93 | }
94 |
95 | List getTopReviews() {
96 | List topReviews =
97 | _reviews.length > 5 ? _reviews.sublist(0, 5) : _reviews;
98 | return topReviews;
99 | }
100 |
101 | initProductVariations() async {
102 | _productVariations = await _services.getProductVariations(_product);
103 |
104 | isVariantsLoading = false;
105 | notifyListeners();
106 |
107 | _productVariations.forEach((variant) {
108 | Map map = HashMap();
109 | variant.attributes.forEach((value) {
110 | map.update(value.name, (_) => value.option,
111 | ifAbsent: () => value.option);
112 | });
113 | variationMap.update(map.toString(), (_) => variant,
114 | ifAbsent: () => variant);
115 | });
116 | }
117 |
118 | List get productVariations => _productVariations;
119 |
120 | setQuantity(String value) {
121 | _quantity = value;
122 | notifyListeners();
123 | }
124 |
125 | addToCart(context) {
126 | if (_currentVariation == null) throw 'Please select variation';
127 | if (_product == null) throw 'product not loaded';
128 | Provider.of(context)
129 | .addProductToCart(_product, _currentVariation, int.parse(quantity));
130 | }
131 |
132 | @override
133 | void dispose() {
134 | // TODO: implement dispose
135 | super.dispose();
136 | _services.dispose();
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/lib/states/home_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/services/base_services.dart';
3 | import 'package:cool_store/utils/constants.dart';
4 | import 'package:flutter/foundation.dart';
5 | import 'package:localstorage/localstorage.dart';
6 |
7 | class HomeState extends ChangeNotifier {
8 | Services _services;
9 | bool isLoading;
10 | List products;
11 | String errorMessage;
12 | bool errorOccured = false;
13 |
14 | HomeState() {
15 | isLoading = true;
16 | _services = Services();
17 | products = List();
18 | getProducts();
19 | }
20 |
21 | getProducts() async {
22 | try {
23 | products = await _services.getProducts();
24 | isLoading = false;
25 | notifyListeners();
26 | cacheProducts();
27 | } catch (e) {
28 | errorOccured = true;
29 | errorMessage = e.toString();
30 | loadProductsFromCache();
31 | }
32 | }
33 |
34 | // cached products to local storage
35 | cacheProducts() async {
36 | final LocalStorage _localStorage = LocalStorage(
37 | Constants.APP_FOLDER,
38 | );
39 |
40 | try {
41 | final ready = await _localStorage.ready;
42 | if (ready) {
43 | await _localStorage.setItem(Constants.kLocalKey["home"], products);
44 | }
45 | } catch (e) {
46 | throw e;
47 | }
48 | }
49 |
50 | // called if there is a connection problem to load last cached products from local storage
51 | loadProductsFromCache() async {
52 | isLoading = true;
53 | final LocalStorage storage = new LocalStorage(Constants.APP_FOLDER);
54 | try {
55 | final ready = await storage.ready;
56 | if (ready) {
57 | final json = storage.getItem(Constants.kLocalKey["home"]);
58 | if (json != null) {
59 | List list = [];
60 | for (var item in json) {
61 | list.add(Product.fromLocalJson(item));
62 | }
63 | products = list;
64 | }
65 | }
66 | } catch (err) {
67 | print(err);
68 | }
69 | isLoading = false;
70 | notifyListeners();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/states/product_list_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/services/base_services.dart';
3 | import 'package:flutter/foundation.dart';
4 |
5 | class ProductListState extends ChangeNotifier {
6 | bool isLoading;
7 | Services _services;
8 | List _products;
9 | int _categoryId;
10 |
11 | List get products => _products;
12 |
13 | ProductListState(categoryID) {
14 | isLoading = true;
15 | this._categoryId = categoryID;
16 | _products = List();
17 | _services = Services();
18 | initProducts();
19 | }
20 |
21 | initProducts() async {
22 | _products = await _services.fetchProductsByCategory(
23 | categoryId: _categoryId, page: 1);
24 | isLoading = false;
25 | notifyListeners();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/states/search_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/services/base_services.dart';
3 | import 'package:cool_store/utils/constants.dart';
4 | import 'package:flutter/foundation.dart';
5 | import 'package:shared_preferences/shared_preferences.dart';
6 |
7 | class SearchState extends ChangeNotifier {
8 | bool isResultLoading = true;
9 | bool showKeywords = true;
10 |
11 | String searchKeyword;
12 | List keyWords = List();
13 | List searchResult = List();
14 | int currentPage = 1;
15 | Services _services = Services();
16 |
17 | SearchState() {
18 | _getRecentSearchList();
19 | }
20 |
21 | setKeyword(String value) {
22 | isResultLoading = true;
23 | showKeywords = false;
24 | notifyListeners();
25 | searchKeyword = value;
26 | if (!keyWords.contains(value)) keyWords.add(value);
27 | _performSearch();
28 | }
29 |
30 | _performSearch() async {
31 | searchResult =
32 | await _services.searchProducts(name: searchKeyword, page: currentPage);
33 | isResultLoading = false;
34 | notifyListeners();
35 | }
36 |
37 | addKeywordsToStorage() async {
38 | try {
39 | SharedPreferences _pref = await SharedPreferences.getInstance();
40 | await _pref.setStringList(
41 | Constants.kLocalKey['recentSearches'], keyWords);
42 | } catch (e) {
43 | print(e);
44 | }
45 | }
46 |
47 | clearResult() {
48 | showKeywords = true;
49 | searchResult.clear();
50 | notifyListeners();
51 | }
52 |
53 | _getRecentSearchList() async {
54 | try {
55 | SharedPreferences _pref = await SharedPreferences.getInstance();
56 | final list = _pref.getStringList(Constants.kLocalKey['recentSearches']);
57 | if (list != null && list.length > 0) keyWords = list;
58 | } catch (e) {
59 | print(e);
60 | }
61 | notifyListeners();
62 | }
63 |
64 | removeKeyword(String value) {
65 | keyWords.remove(value);
66 | notifyListeners();
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/states/settings_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 |
3 | class SettingState extends ChangeNotifier {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/lib/utils/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 | }
14 |
15 | final colors = {
16 | "aliceblue": "#f0f8ff",
17 | "antiquewhite": "#faebd7",
18 | "aqua": "#00ffff",
19 | "aquamarine": "#7fffd4",
20 | "azure": "#f0ffff",
21 | "beige": "#f5f5dc",
22 | "bisque": "#ffe4c4",
23 | "black": "#000000",
24 | "blanchedalmond": "#ffebcd",
25 | "blue": "#0000ff",
26 | "blueviolet": "#8a2be2",
27 | "brown": "#a52a2a",
28 | "burlywood": "#deb887",
29 | "cadetblue": "#5f9ea0",
30 | "chartreuse": "#7fff00",
31 | "chocolate": "#d2691e",
32 | "coral": "#ff7f50",
33 | "cornflowerblue": "#6495ed",
34 | "cornsilk": "#fff8dc",
35 | "crimson": "#dc143c",
36 | "cyan": "#00ffff",
37 | "darkblue": "#00008b",
38 | "darkcyan": "#008b8b",
39 | "darkgoldenrod": "#b8860b",
40 | "darkgray": "#a9a9a9",
41 | "darkgreen": "#006400",
42 | "darkgrey": "#a9a9a9",
43 | "darkkhaki": "#bdb76b",
44 | "darkmagenta": "#8b008b",
45 | "darkolivegreen": "#556b2f",
46 | "darkorange": "#ff8c00",
47 | "darkorchid": "#9932cc",
48 | "darkred": "#8b0000",
49 | "darksalmon": "#e9967a",
50 | "darkseagreen": "#8fbc8f",
51 | "darkslateblue": "#483d8b",
52 | "darkslategray": "#2f4f4f",
53 | "darkslategrey": "#2f4f4f",
54 | "darkturquoise": "#00ced1",
55 | "darkviolet": "#9400d3",
56 | "deeppink": "#ff1493",
57 | "deepskyblue": "#00bfff",
58 | "dimgray": "#696969",
59 | "dimgrey": "#696969",
60 | "dodgerblue": "#1e90ff",
61 | "firebrick": "#b22222",
62 | "floralwhite": "#fffaf0",
63 | "forestgreen": "#228b22",
64 | "fuchsia": "#ff00ff",
65 | "gainsboro": "#dcdcdc",
66 | "ghostwhite": "#f8f8ff",
67 | "goldenrod": "#daa520",
68 | "gold": "#ffd700",
69 | "gray": "#808080",
70 | "green": "#008000",
71 | "greenyellow": "#adff2f",
72 | "grey": "#808080",
73 | "honeydew": "#f0fff0",
74 | "hotpink": "#ff69b4",
75 | "indianred": "#cd5c5c",
76 | "indigo": "#4b0082",
77 | "ivory": "#fffff0",
78 | "khaki": "#f0e68c",
79 | "lavenderblush": "#fff0f5",
80 | "lavender": "#e6e6fa",
81 | "lawngreen": "#7cfc00",
82 | "lemonchiffon": "#fffacd",
83 | "lightblue": "#add8e6",
84 | "lightcoral": "#f08080",
85 | "lightcyan": "#e0ffff",
86 | "lightgoldenrodyellow": "#fafad2",
87 | "lightgray": "#d3d3d3",
88 | "lightgreen": "#90ee90",
89 | "lightgrey": "#d3d3d3",
90 | "lightpink": "#ffb6c1",
91 | "lightsalmon": "#ffa07a",
92 | "lightseagreen": "#20b2aa",
93 | "lightskyblue": "#87cefa",
94 | "lightslategray": "#778899",
95 | "lightslategrey": "#778899",
96 | "lightsteelblue": "#b0c4de",
97 | "lightyellow": "#ffffe0",
98 | "lime": "#00ff00",
99 | "limegreen": "#32cd32",
100 | "linen": "#faf0e6",
101 | "magenta": "#ff00ff",
102 | "maroon": "#800000",
103 | "mediumaquamarine": "#66cdaa",
104 | "mediumblue": "#0000cd",
105 | "mediumorchid": "#ba55d3",
106 | "mediumpurple": "#9370db",
107 | "mediumseagreen": "#3cb371",
108 | "mediumslateblue": "#7b68ee",
109 | "mediumspringgreen": "#00fa9a",
110 | "mediumturquoise": "#48d1cc",
111 | "mediumvioletred": "#c71585",
112 | "midnightblue": "#191970",
113 | "mintcream": "#f5fffa",
114 | "mistyrose": "#ffe4e1",
115 | "moccasin": "#ffe4b5",
116 | "navajowhite": "#ffdead",
117 | "navy": "#000080",
118 | "oldlace": "#fdf5e6",
119 | "olive": "#808000",
120 | "olivedrab": "#6b8e23",
121 | "orange": "#ffa500",
122 | "orangered": "#ff4500",
123 | "orchid": "#da70d6",
124 | "palegoldenrod": "#eee8aa",
125 | "palegreen": "#98fb98",
126 | "paleturquoise": "#afeeee",
127 | "palevioletred": "#db7093",
128 | "papayawhip": "#ffefd5",
129 | "peachpuff": "#ffdab9",
130 | "peru": "#cd853f",
131 | "pink": "#ffc0cb",
132 | "plum": "#dda0dd",
133 | "powderblue": "#b0e0e6",
134 | "purple": "#800080",
135 | "rebeccapurple": "#663399",
136 | "red": "#ff0000",
137 | "rosybrown": "#bc8f8f",
138 | "royalblue": "#4169e1",
139 | "saddlebrown": "#8b4513",
140 | "salmon": "#fa8072",
141 | "sandybrown": "#f4a460",
142 | "seagreen": "#2e8b57",
143 | "seashell": "#fff5ee",
144 | "sienna": "#a0522d",
145 | "silver": "#c0c0c0",
146 | "skyblue": "#87ceeb",
147 | "slateblue": "#6a5acd",
148 | "slategray": "#708090",
149 | "slategrey": "#708090",
150 | "snow": "#fffafa",
151 | "springgreen": "#00ff7f",
152 | "steelblue": "#4682b4",
153 | "tan": "#d2b48c",
154 | "teal": "#008080",
155 | "thistle": "#d8bfd8",
156 | "tomato": "#ff6347",
157 | "turquoise": "#40e0d0",
158 | "violet": "#ee82ee",
159 | "wheat": "#f5deb3",
160 | "white": "#ffffff",
161 | "whitesmoke": "#f5f5f5",
162 | "yellow": "#ffff00",
163 | "yellowgreen": "#9acd32"
164 | };
165 |
--------------------------------------------------------------------------------
/lib/utils/constants.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class Constants {
4 | static final CONSUMER_KEY_CLOUD =
5 | 'ck_fc75eb207e9e48ecc852fbfdd9461f112ef9d860';
6 | static final CONSUMER_SECRET_CLOUD =
7 | 'cs_998324c7091df9dd256117dcf6105865f155de78';
8 |
9 | static final URL_CLOUD = 'https://mastigophoran-miner.000webhostapp.com';
10 |
11 | static final APP_FOLDER = 'COOL_STORE';
12 |
13 | // keys for localstorage
14 | static final kLocalKey = {
15 | "userInfo": "userInfo",
16 | "shippingAddress": "shippingAddress",
17 | "recentSearches": "recentSearches",
18 | "wishlist": "wishlist",
19 | "home": "home",
20 | 'isDarkTheme': 'isDarkTheme',
21 | 'productsInCart': 'productsInCart',
22 | 'cartproducts': 'products',
23 | 'productVariationsInCart': 'productVariationsInCart'
24 | };
25 |
26 | //Colors for theme
27 | static Color lightPrimary = Color(0xfffcfcff);
28 | static Color darkPrimary = Colors.black;
29 | static Color lightAccent = Colors.orange;
30 | static Color darkAccent = Colors.orangeAccent;
31 | static Color lightBG = Color(0xfffcfcff);
32 | static Color darkBG = Colors.black;
33 |
34 | static String searchBarTag = 'searchbartag';
35 | static String searchSubtitleTag = 'searchSubtitleTag';
36 | static String searchIconTag = 'searchIconTag';
37 | static double baseHeight = 640;
38 |
39 | static double screenAwareSize(double size, BuildContext context) {
40 | return size * MediaQuery.of(context).size.height / baseHeight;
41 | }
42 |
43 | static ThemeData lightTheme = ThemeData(
44 | backgroundColor: lightBG,
45 | primaryColor: lightPrimary,
46 | accentColor: lightAccent,
47 | cursorColor: lightAccent,
48 | scaffoldBackgroundColor: lightBG,
49 | appBarTheme: AppBarTheme(
50 | elevation: 0,
51 | textTheme: TextTheme(
52 | title: TextStyle(
53 | color: darkBG,
54 | fontSize: 18.0,
55 | fontWeight: FontWeight.w800,
56 | ),
57 | ),
58 | ),
59 | );
60 |
61 | static ThemeData darkTheme = ThemeData(
62 | brightness: Brightness.dark,
63 | backgroundColor: darkBG,
64 | hintColor: darkBG,
65 | primaryColor: darkPrimary,
66 | accentColor: darkAccent,
67 | scaffoldBackgroundColor: darkBG,
68 | cursorColor: darkAccent,
69 | appBarTheme: AppBarTheme(
70 | elevation: 0,
71 | textTheme: TextTheme(
72 | title: TextStyle(
73 | color: lightBG,
74 | fontSize: 18.0,
75 | fontWeight: FontWeight.w800,
76 | ),
77 | ),
78 | ),
79 | );
80 | }
81 |
--------------------------------------------------------------------------------
/lib/widgets/Badge.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/cart_state.dart';
2 | import 'package:cool_store/utils/constants.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:provider/provider.dart';
5 |
6 | class Badge extends StatelessWidget {
7 | final String count;
8 | final IconData iconData;
9 | final TextStyle style;
10 | final Color countBackgroundColor;
11 |
12 | Badge({this.count, this.iconData, this.style, this.countBackgroundColor});
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | final length = Provider.of(context).wishListProducts.length;
17 | ThemeData themeData = Theme.of(context);
18 | return Container(
19 | decoration: BoxDecoration(
20 | shape: BoxShape.circle,
21 | ),
22 | child: Center(
23 | child: Stack(
24 | children: [
25 | Icon(
26 | iconData,
27 | size: Constants.screenAwareSize(20, context),
28 | color: themeData.iconTheme.color.withOpacity(.8),
29 | ),
30 | Positioned(
31 | bottom: 5,
32 | right: 0,
33 | child: Container(
34 | padding: EdgeInsets.all(6),
35 | decoration: BoxDecoration(
36 | shape: BoxShape.circle,
37 | color: length > 0
38 | ? countBackgroundColor ??
39 | Colors.redAccent.withOpacity(.7)
40 | : Colors.transparent),
41 | child: Text(
42 | '${length > 0 ? length : ''}',
43 | style: style ??
44 | TextStyle(color: Colors.white),
45 | ),
46 | ))
47 | ],
48 | ),
49 | ),
50 | );
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lib/widgets/CartItem.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/utils/constants.dart';
3 | import 'package:extended_image/extended_image.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class CartItem extends StatelessWidget {
7 | final Function onTap, onRemovePressed, onPrimaryButtonPressed;
8 |
9 | final String primaryTitle;
10 | final Product product;
11 | final ProductVariation variation;
12 | final int quantity;
13 |
14 | CartItem(
15 | {this.onTap,
16 | this.onRemovePressed,
17 | this.onPrimaryButtonPressed,
18 | this.variation,
19 | this.product,
20 | this.primaryTitle = 'Add to wishlist',
21 | this.quantity = 1});
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | return Column(
26 | children: [
27 | ListTile(
28 | onTap: onTap,
29 | leading: ExtendedImage.network(
30 | product.featuredImage,
31 | cache: true,
32 | fit: BoxFit.contain,
33 | constraints: BoxConstraints(
34 | maxHeight: Constants.screenAwareSize(60, context),
35 | maxWidth: Constants.screenAwareSize(60, context)
36 | ),
37 | ),
38 | subtitle: Column(
39 | mainAxisAlignment: MainAxisAlignment.start,
40 | crossAxisAlignment: CrossAxisAlignment.start,
41 | children: [Text('$variation'), Text('Qty: $quantity')],
42 | ),
43 | title: Text(
44 | product.name,
45 | style: TextStyle(
46 | fontFamily: 'Rlaleway',
47 | fontWeight: FontWeight.w400,
48 | ),
49 | ),
50 | trailing: Column(
51 | mainAxisAlignment: MainAxisAlignment.end,
52 | children: [
53 | Text(
54 | 'Rs ${product.price}',
55 | style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14),
56 | )
57 | ],
58 | ),
59 | isThreeLine: true,
60 | ),
61 | Padding(
62 | padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 2),
63 | child: Row(
64 | children: [
65 | Expanded(
66 | child: RawMaterialButton(
67 | onPressed: onRemovePressed,
68 | child: Text('REMOVE'),
69 | ),
70 | ),
71 | Expanded(
72 | child: RawMaterialButton(
73 | onPressed: onPrimaryButtonPressed,
74 | fillColor: Theme.of(context).accentColor,
75 | child: Text('$primaryTitle'),
76 | textStyle: TextStyle(color: Colors.white),
77 | elevation: 0,
78 | ),
79 | ),
80 | ],
81 | ),
82 | ),
83 | SizedBox(
84 | height: Constants.screenAwareSize(15, context),
85 | )
86 | ],
87 | );
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/lib/widgets/ColorChooser.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/detail_state.dart';
2 | import 'package:cool_store/utils/color.dart';
3 | import 'package:cool_store/utils/constants.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:provider/provider.dart';
6 | import 'package:shimmer/shimmer.dart';
7 |
8 | class ColorChooser extends StatefulWidget {
9 | final String title;
10 | final List options;
11 |
12 | ColorChooser({this.title, this.options});
13 |
14 | @override
15 | _ColorChooserState createState() => _ColorChooserState();
16 | }
17 |
18 | class _ColorChooserState extends State {
19 | int selectedIndex = -1;
20 | int time = 1000;
21 | int offset = 50;
22 | bool isSafe = true;
23 |
24 | Color baseColor, highlightColor, borderColor, accentColor;
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | widget.options.forEach((value) {
29 | value = value.replaceAll(' ', '').toLowerCase();
30 | if (colors.containsKey(value) == false) {
31 | setState(() {
32 | isSafe = false;
33 | });
34 | }
35 | });
36 | final state = Provider.of(context);
37 | final theme = Theme.of(context);
38 | baseColor = theme.iconTheme.color;
39 | highlightColor = theme.primaryColor;
40 | accentColor = theme.accentColor.withOpacity(.85);
41 | borderColor = theme.textTheme.title.color.withOpacity(.7);
42 |
43 | return Container(
44 | height: Constants.screenAwareSize(40, context),
45 | child: Row(
46 | crossAxisAlignment: CrossAxisAlignment.center,
47 | mainAxisAlignment: MainAxisAlignment.center,
48 | children: [
49 | Expanded(
50 | flex: 1,
51 | child: Padding(
52 | padding: const EdgeInsets.all(8.0),
53 | child: Text(widget.title),
54 | )),
55 | Expanded(
56 | flex: 4,
57 | child: ListView.builder(
58 | itemCount: widget.options.length,
59 | shrinkWrap: true,
60 | scrollDirection: Axis.horizontal,
61 | itemBuilder: (_, pos) {
62 | offset += 80;
63 | time += offset;
64 | return state.isVariantsLoading
65 | ? buildLoadingContainers(pos, time)
66 | : buildVariantContainer(state, pos);
67 | }),
68 | )
69 | ],
70 | ),
71 | );
72 | }
73 |
74 | Widget buildLoadingContainers(pos, time) {
75 | return Shimmer.fromColors(
76 | child: Container(
77 | padding: EdgeInsets.all(8),
78 | constraints: BoxConstraints(
79 | minWidth: Constants.screenAwareSize(30, context),
80 | minHeight: Constants.screenAwareSize(35, context)),
81 | margin: EdgeInsets.all(8),
82 | decoration: BoxDecoration(
83 | border: Border.all(color: borderColor),
84 | borderRadius: BorderRadius.circular(2)),
85 | child: Center(
86 | child: Text(
87 | '${widget.options[pos]}',
88 | )),
89 | ),
90 | period: Duration(milliseconds: time),
91 | highlightColor: highlightColor,
92 | baseColor: baseColor,
93 | );
94 | }
95 |
96 | Widget buildVariantContainer(state, pos) {
97 | return GestureDetector(
98 | onTap: () {
99 | state.changeAttributesTo(widget.title, widget.options[pos]);
100 | selectedIndex = pos;
101 | setState(() {});
102 | },
103 | child: Container(
104 | padding: EdgeInsets.all(8),
105 | constraints: BoxConstraints(
106 | minWidth: Constants.screenAwareSize(30, context),
107 | minHeight: Constants.screenAwareSize(35, context)),
108 | margin: EdgeInsets.all(8),
109 | decoration: BoxDecoration(
110 | color: isSafe
111 | ? HexColor(colors[widget.options[pos].toLowerCase()])
112 | .withOpacity(.6)
113 | : Colors.transparent,
114 | borderRadius: BorderRadius.circular(2),
115 | border: Border.all(
116 | color: selectedIndex == pos ? accentColor : borderColor)),
117 | child: Center(
118 | child: Text(
119 | '${isSafe ? '' : widget.options[pos]}',
120 | )),
121 | ),
122 | );
123 | }
124 | }
125 |
126 | class SemiClipper extends CustomClipper {
127 | @override
128 | Path getClip(Size size) {
129 | final path = Path();
130 | //path.lineTo(size.width, 0.0);
131 | // path.lineTo(size.width / 2, size.height);
132 | path.close();
133 | return path;
134 | }
135 |
136 | @override
137 | bool shouldReclip(CustomClipper oldClipper) {
138 | // TODO: implement shouldReclip
139 | return false;
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/lib/widgets/DefaultChooser.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/detail_state.dart';
2 | import 'package:cool_store/utils/constants.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:provider/provider.dart';
5 |
6 | class DefaultChooser extends StatefulWidget {
7 | final String title;
8 | final List options;
9 |
10 | DefaultChooser({this.title, this.options});
11 |
12 | @override
13 | _DefaultChooserState createState() => _DefaultChooserState();
14 | }
15 |
16 | class _DefaultChooserState extends State {
17 | int index = 0;
18 | String value = 'SELECT';
19 |
20 | _DefaultChooserState();
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | final DetailState state = Provider.of(context);
25 | return GestureDetector(
26 | onTap: () async {
27 | if (state.isVariantsLoading) return;
28 | var result = await _showOptions(widget.options, state);
29 | if (result != null) {
30 | value = result;
31 | state.changeAttributesTo(widget.title, value);
32 | setState(() {});
33 | }
34 | },
35 | child: Container(
36 | padding: EdgeInsets.symmetric(vertical: 4),
37 | child: Row(
38 | crossAxisAlignment: CrossAxisAlignment.center,
39 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
40 | children: [
41 | Container(
42 | width: Constants.screenAwareSize(50, context),
43 | height: Constants.screenAwareSize(25, context),
44 | child: Center(
45 | child: Text(
46 | widget.title,
47 | softWrap: true,
48 | overflow: TextOverflow.fade,
49 | textAlign: TextAlign.end,
50 | style: TextStyle(fontFamily: 'Raleway', fontSize: 16),
51 | ),
52 | ),
53 | ),
54 | SizedBox(
55 | width: 10,
56 | ),
57 | Container(
58 | height: Constants.screenAwareSize(25, context),
59 | width: Constants.screenAwareSize(50, context),
60 | decoration:
61 | BoxDecoration(border: Border.all(color: Colors.grey[600])),
62 | child: Center(
63 | child: Text(value,
64 | softWrap: true,
65 | overflow: TextOverflow.fade,
66 | style: TextStyle(
67 | fontWeight: FontWeight.w600,
68 | decorationColor:
69 | Theme.of(context).textTheme.title.color,
70 | decoration: state.isVariantsLoading
71 | ? TextDecoration.lineThrough
72 | : TextDecoration.none))),
73 | )
74 | ],
75 | ),
76 | ),
77 | );
78 | }
79 |
80 | _showOptions(List options, DetailState state) {
81 | return showModalBottomSheet(
82 | context: context,
83 | builder: (context) {
84 | return SafeArea(
85 | child: Column(
86 | mainAxisSize: MainAxisSize.min,
87 | children: options
88 | .map((value) => ListTile(
89 | onTap: () {
90 | Navigator.of(context).pop(value);
91 | },
92 | title: Center(
93 | child: Text(
94 | value,
95 | style: TextStyle(fontFamily: 'Raleway'),
96 | )),
97 | ))
98 | .toList(),
99 | ),
100 | );
101 | });
102 | }
103 | }
104 |
105 |
106 |
--------------------------------------------------------------------------------
/lib/widgets/GalleryView.dart:
--------------------------------------------------------------------------------
1 | import 'package:carousel_slider/carousel_slider.dart';
2 | import 'package:cool_store/app.dart';
3 | import 'package:cool_store/models/product.dart';
4 | import 'package:cool_store/states/detail_state.dart';
5 | import 'package:extended_image/extended_image.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:provider/provider.dart';
8 | import 'package:shimmer/shimmer.dart';
9 |
10 | class GalleryView extends StatefulWidget {
11 | final Product product;
12 |
13 | GalleryView({this.product});
14 |
15 | @override
16 | _GalleryViewState createState() => _GalleryViewState();
17 | }
18 |
19 | class _GalleryViewState extends State {
20 | int currentIndex = 0;
21 |
22 | PageController controller = PageController();
23 |
24 | ScrollController scrollController = ScrollController();
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | return Scaffold(
29 | backgroundColor: Theme.of(context).primaryColor,
30 | appBar: AppBar(),
31 | body: SafeArea(
32 | child: Column(
33 | children: [
34 | Expanded(
35 | child: ExtendedImageGesturePageView.builder(
36 | itemBuilder: (BuildContext context, int index) {
37 | var item = widget.product.images[index];
38 | Widget image = ExtendedImage.network(item,
39 | fit: BoxFit.contain, initGestureConfigHandler: (state) {
40 | return GestureConfig(
41 | minScale: 0.9,
42 | animationMinScale: 0.7,
43 | maxScale: 3.0,
44 | animationMaxScale: 3.5,
45 | speed: 1.0,
46 | inertialSpeed: 100.0,
47 | initialScale: 1.0,
48 | inPageView: true);
49 | });
50 | image = Container(
51 | child: image,
52 | padding: EdgeInsets.all(5.0),
53 | );
54 | if (index == currentIndex) {
55 | return Hero(
56 | tag: item + index.toString(),
57 | child: image,
58 | );
59 | } else {
60 | return image;
61 | }
62 | },
63 | itemCount: widget.product.images.length,
64 | onPageChanged: (int index) {
65 | currentIndex = index;
66 | setState(() {});
67 | },
68 | controller: controller,
69 | scrollDirection: Axis.horizontal,
70 | ),
71 | ),
72 | Container(
73 | height: 10,
74 | margin: EdgeInsets.symmetric(horizontal: 18, vertical: 8),
75 | child: ListView.builder(
76 | itemCount: widget.product.images.length,
77 | scrollDirection: Axis.horizontal,
78 | itemBuilder: (_, pos) {
79 | return Container(
80 | width: 20,
81 | margin: EdgeInsets.all(8),
82 | decoration: BoxDecoration(
83 | border: Border.all(
84 | color: currentIndex == pos
85 | ? Theme.of(context).accentColor
86 | : Colors.grey[600])),
87 | );
88 | }),
89 | )
90 | ],
91 | ),
92 | ),
93 | );
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/lib/widgets/ImageView.dart:
--------------------------------------------------------------------------------
1 | import 'package:carousel_slider/carousel_slider.dart';
2 | import 'package:cool_store/states/detail_state.dart';
3 | import 'package:cool_store/utils/constants.dart';
4 | import 'package:cool_store/widgets/GalleryView.dart';
5 | import 'package:extended_image/extended_image.dart';
6 | import 'package:flutter/cupertino.dart';
7 | import 'package:flutter/material.dart';
8 | import 'package:provider/provider.dart';
9 | import 'package:shimmer/shimmer.dart';
10 |
11 | class ImageView extends StatelessWidget {
12 | @override
13 | Widget build(BuildContext context) {
14 | final DetailState state = Provider.of(context);
15 |
16 | return GestureDetector(
17 | onTap: () {
18 | if (!state.isLoading)
19 | Navigator.push(
20 | context,
21 | MaterialPageRoute(
22 | fullscreenDialog: true,
23 | builder: (context) => GalleryView(product: state.product)));
24 | },
25 | child: state.isLoading
26 | ? Container(
27 | height: Constants.screenAwareSize(300, context),
28 | color: Colors.grey[300],
29 | )
30 | : CarouselSlider(
31 | viewportFraction: 0.9,
32 | aspectRatio: 1,
33 | enlargeCenterPage: true,
34 | height: Constants.screenAwareSize(280, context),
35 | items: state.product.images.map((url) {
36 | return Builder(
37 | builder: (BuildContext context) {
38 | return Container(
39 | width: MediaQuery.of(context).size.width,
40 | margin:
41 | EdgeInsets.symmetric(horizontal: 8.0, vertical: 17),
42 | decoration: BoxDecoration(
43 | color: Colors.grey[300],
44 | boxShadow: [
45 | BoxShadow(
46 | color: Colors.blueGrey,
47 | offset: Offset(0, 10),
48 | blurRadius: 10,
49 | )
50 | ],
51 | borderRadius: BorderRadius.all(Radius.circular(8)),
52 | // image: DecorationImage(
53 | // fit: BoxFit.cover, image: NetworkImage(url))
54 | ),
55 | child: ExtendedImage.network(
56 | url,
57 | cache: true,
58 | // ignore: missing_return
59 | loadStateChanged: (ExtendedImageState imagestate) {
60 | switch (imagestate.extendedImageLoadState) {
61 | case LoadState.loading:
62 | //TODO add loading graphic
63 | return Shimmer(
64 | child: Center(child: Text('Loading')),
65 | gradient: LinearGradient(
66 | colors: [Colors.black, Colors.white]));
67 | break;
68 |
69 | case LoadState.failed:
70 | return GestureDetector(
71 | child: Stack(
72 | fit: StackFit.expand,
73 | children: [
74 | Icon(Icons.error),
75 | Positioned(
76 | bottom: 0.0,
77 | left: 0.0,
78 | right: 0.0,
79 | child: Text(
80 | "load image failed, click to reload",
81 | textAlign: TextAlign.center,
82 | ),
83 | )
84 | ],
85 | ),
86 | onTap: () {
87 | imagestate.reLoadImage();
88 | },
89 | );
90 | break;
91 | case LoadState.completed:
92 | // TODO: Handle this case.
93 | break;
94 | }
95 | },
96 | ),
97 | );
98 | },
99 | );
100 | }).toList(),
101 | ),
102 | );
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/lib/widgets/InfoView.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_svg/svg.dart';
3 |
4 | class InfoView extends StatelessWidget {
5 | final String primaryText, secondaryText, path;
6 | final Color iconColor;
7 |
8 | InfoView(
9 | {this.primaryText,
10 | this.secondaryText,
11 | this.iconColor,
12 | this.path = 'assets/no_result.svg'});
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return Column(
17 | mainAxisAlignment: MainAxisAlignment.center,
18 | crossAxisAlignment: CrossAxisAlignment.center,
19 | mainAxisSize: MainAxisSize.max,
20 | children: [
21 | Padding(
22 | padding: const EdgeInsets.all(50.0),
23 | child: SvgPicture.asset(
24 | path,
25 | height: MediaQuery.of(context).size.height / 4,
26 | color: iconColor,
27 | ),
28 | ),
29 | Padding(
30 | padding: const EdgeInsets.all(18.0),
31 | child: Text(
32 | primaryText,
33 | textAlign: TextAlign.center,
34 | style: TextStyle(
35 | fontFamily: 'Raleway',
36 | fontSize: 35,
37 | fontWeight: FontWeight.w200),
38 | ),
39 | ),
40 | if (secondaryText != null)
41 | Padding(
42 | padding: const EdgeInsets.all(18.0),
43 | child: Text(
44 | secondaryText,
45 | textAlign: TextAlign.center,
46 | style: TextStyle(
47 | fontFamily: 'Raleway',
48 | fontSize: 16,
49 | fontWeight: FontWeight.w200),
50 | ),
51 | ),
52 | ],
53 | );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/widgets/OffersBanner.dart:
--------------------------------------------------------------------------------
1 | import 'package:carousel_slider/carousel_slider.dart';
2 | import 'package:extended_image/extended_image.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | class OffersBanner extends StatelessWidget {
6 | final imageList = [
7 | 'https://assets.myntassets.com/w_980,c_limit,fl_progressive,dpr_2.0/assets/images/banners/2019/8/2/1f55b32d-a54f-4130-8de6-142167685e941564742794212-desktop.jpg',
8 | 'https://assets.myntassets.com/w_980,c_limit,fl_progressive,dpr_2.0/assets/images/banners/2019/8/3/8e251762-1833-4490-9612-67c11877b2d61564848407937-Gerua_Desk_Banner.jpg',
9 | 'https://assets.myntassets.com/w_980,c_limit,fl_progressive,dpr_2.0/assets/images/banners/2019/8/3/8fe43105-e031-4271-b66a-017abefd25ba1564848407967-Highlander_Desk_Banner.jpg',
10 | 'https://assets.myntassets.com/w_980,c_limit,fl_progressive,dpr_2.0/assets/images/banners/2019/8/3/c0232ddd-5017-4dbe-8cf8-108e4a111b0a1564848407994-Jockey_Desk_Banner.jpg',
11 | 'https://assets.myntassets.com/w_980,c_limit,fl_progressive,dpr_2.0/assets/images/banners/2019/8/3/71cbabc8-2fdf-42b9-8179-4cd136aa5f5b1564848408043-Only_Desk_Banner.jpg',
12 | 'https://assets.myntassets.com/w_980,c_limit,fl_progressive,dpr_2.0/assets/images/banners/2019/8/3/c27bc5ae-17dc-4326-b44c-f761da6e48fe1564848408020-Portico_Desk_Banner.jpg',
13 | ];
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return CarouselSlider(
18 | autoPlay: true,
19 | pauseAutoPlayOnTouch: Duration(seconds: 1),
20 | viewportFraction: 0.9,
21 | aspectRatio: 1,
22 | enlargeCenterPage: true,
23 | items: imageList.map((url) {
24 | return Builder(
25 | builder: (BuildContext context) {
26 | return Container(
27 | width: MediaQuery.of(context).size.width,
28 | margin: EdgeInsets.symmetric(horizontal: 4.0),
29 | decoration: BoxDecoration(
30 | image: DecorationImage(
31 | fit: BoxFit.cover,
32 | image: ExtendedNetworkImageProvider(
33 | url,
34 | cache: true,
35 | ))),
36 | );
37 | },
38 | );
39 | }).toList(),
40 | );
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/widgets/ProductCard.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/utils/constants.dart';
3 | import 'package:extended_image/extended_image.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class ProductDisplayCard extends StatelessWidget {
7 | final Function onPressed;
8 | final Product product;
9 | final double margin;
10 |
11 | ProductDisplayCard({@required this.onPressed, this.product, this.margin = 0});
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return InkWell(
16 | onTap: onPressed,
17 | child: Container(
18 | margin: EdgeInsets.only(right: margin),
19 | decoration: BoxDecoration(
20 | gradient: LinearGradient(
21 | colors: [Colors.transparent, Constants.lightBG.withOpacity(.1)],
22 | begin: Alignment.topCenter,
23 | end: Alignment.bottomCenter),
24 | ),
25 | child: Column(
26 | crossAxisAlignment: CrossAxisAlignment.start,
27 | children: [
28 | Expanded(
29 | child: Container(
30 | width: MediaQuery.of(context).size.width / 2,
31 | margin: EdgeInsets.all(margin),
32 | decoration: BoxDecoration(
33 | image: DecorationImage(
34 | fit: BoxFit.cover,
35 | image: ExtendedNetworkImageProvider(
36 | product.featuredImage,
37 | cache: true))),
38 | ),
39 | ),
40 | SizedBox(
41 | height: Constants.screenAwareSize(8, context),
42 | ),
43 | Padding(
44 | padding: const EdgeInsets.only(left: 8.0),
45 | child: Text(
46 | '${product.name}',
47 | style: TextStyle(
48 | fontFamily: 'Raleway',
49 | fontSize: Constants.screenAwareSize(12, context),
50 | fontWeight: FontWeight.w400),
51 | ),
52 | ),
53 | Padding(
54 | padding: const EdgeInsets.only(left: 8.0),
55 | child: Text(
56 | 'Rs. ${product.price}',
57 | style: TextStyle(
58 | fontWeight: FontWeight.bold,
59 | fontSize: Constants.screenAwareSize(10, context)),
60 | ),
61 | ),
62 | SizedBox(
63 | height: Constants.screenAwareSize(10, context),
64 | )
65 | ],
66 | ),
67 | ),
68 | );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/lib/widgets/ProductDescription.dart:
--------------------------------------------------------------------------------
1 | import 'package:configurable_expansion_tile/configurable_expansion_tile.dart';
2 | import 'package:cool_store/models/product.dart';
3 | import 'package:cool_store/states/detail_state.dart';
4 | import 'package:cool_store/utils/constants.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
7 | import 'package:provider/provider.dart';
8 | import 'package:smooth_star_rating/smooth_star_rating.dart';
9 |
10 | class ProductDescription extends StatelessWidget {
11 | final Product product;
12 | final textStyle = TextStyle(fontFamily: 'Raleway');
13 |
14 | ProductDescription(this.product);
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | final state = Provider.of(context);
19 | bool enableReview = true;
20 |
21 | return Column(
22 | children: [
23 | SizedBox(height: 15),
24 | ExpansionInfo(
25 | title: 'DESCRIPTION',
26 | children: [
27 | Align(
28 | alignment: Alignment.topLeft,
29 | child: HtmlWidget(
30 | product.description,
31 | textStyle: textStyle,
32 | ),
33 | ),
34 | ],
35 | expand: true),
36 | if (enableReview)
37 | Container(
38 | height: 1, decoration: BoxDecoration(color: Colors.grey[200])),
39 | if (enableReview)
40 | ExpansionInfo(
41 | title: 'REVIEWS',
42 | children: state.isReviewsLoading
43 | ? [CircularProgressIndicator()]
44 | : state.doesContainReviews
45 | ? state
46 | .getTopReviews()
47 | .map((Review review) => ListTile(
48 | title: Row(
49 | mainAxisAlignment:
50 | MainAxisAlignment.spaceBetween,
51 | children: [
52 | HtmlWidget(
53 | review.reviewer,
54 | textStyle: TextStyle(
55 | fontFamily: 'Raleway',
56 | ),
57 | bodyPadding: EdgeInsets.symmetric(
58 | horizontal: 2, vertical: 2),
59 | ),
60 | SmoothStarRating(
61 | allowHalfRating: true,
62 | starCount: review.rating,
63 | rating: product.averageRating,
64 | size: Constants.screenAwareSize(
65 | 10, context),
66 | color: Theme.of(context).accentColor,
67 | borderColor:
68 | Theme.of(context).accentColor,
69 | spacing: 0.0),
70 | ],
71 | ),
72 | subtitle: HtmlWidget(
73 | review.review,
74 | textStyle: TextStyle(
75 | fontFamily: 'Raleway',
76 | ),
77 | bodyPadding: EdgeInsets.symmetric(
78 | horizontal: 2, vertical: 2),
79 | ),
80 | dense: true,
81 | ))
82 | .toList()
83 | : [
84 | ListTile(
85 | title: Text(
86 | 'No Reviews yet',
87 | style: TextStyle(
88 | fontFamily: 'Raleway', fontSize: 14),
89 | ),
90 | )
91 | ]
92 | // children: [
93 | // state.isReviewsLoading
94 | // ? CircularProgressIndicator()
95 | // : state.reviews.length > 0
96 | // ? ListView.builder(
97 | // physics: NeverScrollableScrollPhysics(),
98 | // itemBuilder: (_, pos) {
99 | // Review review = state.reviews[pos];
100 | // return ListTile(
101 | // title: HtmlWidget(review.reviewer),
102 | // subtitle: HtmlWidget(review.review),
103 | // );
104 | // },
105 | // itemCount: state.reviews.length,
106 | // )
107 | // : ListTile(
108 | // title: Text('No Reviews'),
109 | // )
110 | // ],
111 | ),
112 | Container(
113 | height: 1, decoration: BoxDecoration(color: Colors.grey[200])),
114 | ExpansionInfo(
115 | title: 'ADDITIONAL INFO',
116 | children: [
117 | Align(
118 | alignment: Alignment.topLeft,
119 | child: HtmlWidget(
120 | product.description,
121 | textStyle: textStyle,
122 | ),
123 | )
124 | ],
125 | ),
126 | ],
127 | );
128 | }
129 | }
130 |
131 | class ExpansionInfo extends StatelessWidget {
132 | final String title;
133 | final bool expand;
134 | final List children;
135 |
136 | ExpansionInfo(
137 | {@required this.title, @required this.children, this.expand = false});
138 |
139 | @override
140 | Widget build(BuildContext context) {
141 | return ConfigurableExpansionTile(
142 | initiallyExpanded: expand,
143 | headerExpanded: Flexible(
144 | child: Padding(
145 | padding: EdgeInsets.symmetric(vertical: 17.0),
146 | child: Row(
147 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
148 | children: [
149 | Text(title,
150 | style: TextStyle(fontSize: 17, fontFamily: 'Raleway')),
151 | Icon(
152 | Icons.keyboard_arrow_up,
153 | size: 20,
154 | )
155 | ])),
156 | ),
157 | header: Flexible(
158 | child: Padding(
159 | padding: EdgeInsets.symmetric(vertical: 17.0),
160 | child: Row(
161 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
162 | children: [
163 | Text(title,
164 | style: TextStyle(fontSize: 17, fontFamily: 'Raleway')),
165 | Icon(
166 | Icons.keyboard_arrow_right,
167 | size: 20,
168 | )
169 | ])),
170 | ),
171 | children: children,
172 | );
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/lib/widgets/ProductTitle.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/states/detail_state.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:provider/provider.dart';
5 | import 'package:smooth_star_rating/smooth_star_rating.dart';
6 |
7 | class ProductTitle extends StatelessWidget {
8 | final Product product;
9 |
10 | ProductTitle(this.product);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | ThemeData theme = Theme.of(context);
15 | final DetailState state = Provider.of(context);
16 | ProductVariation variation = state.currentVariation;
17 | return Column(
18 | mainAxisAlignment: MainAxisAlignment.start,
19 | children: [
20 | SizedBox(height: 10),
21 | Container(
22 | width: MediaQuery.of(context).size.width,
23 | child: Text(
24 | product.name,
25 | style: TextStyle(fontSize: 18, fontFamily: 'Raleway'),
26 | ),
27 | ),
28 | SizedBox(height: 10),
29 | Row(
30 | children: [
31 | // Text(Tools.getCurrecyFormatted(price),
32 | // style: Theme.of(context)
33 | // .textTheme
34 | // .headline
35 | // .copyWith(fontSize: 17, color: theme.accentColor)),
36 | Text(
37 | // product.price,
38 | variation == null ? product.price : variation.price,
39 | style: TextStyle(
40 | fontSize: 17,
41 | ),
42 | ),
43 | if (product.onSale)
44 | SizedBox(width: 5),
45 | if (product.onSale)
46 | Text(
47 | variation == null
48 | ? product.regularPrice
49 | : variation.regularPrice,
50 | style: TextStyle(fontSize: 16),
51 | ),
52 | // Text(Tools.getCurrecyFormatted(regularPrice),
53 | // style: Theme.of(context).textTheme.headline.copyWith(
54 | // fontSize: 16,
55 | // color: Theme.of(context).accentColor,
56 | // decoration: TextDecoration.lineThrough)),
57 | ],
58 | ),
59 | Padding(
60 | padding: EdgeInsets.symmetric(vertical: 10.0),
61 | child: Row(
62 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
63 | children: [
64 | SmoothStarRating(
65 | allowHalfRating: true,
66 | starCount: 5,
67 | rating: product.averageRating,
68 | size: 17.0,
69 | color: theme.accentColor,
70 | borderColor: theme.accentColor,
71 | spacing: 0.0),
72 | ],
73 | ),
74 | ),
75 | ],
76 | );
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/lib/widgets/QuantityChooser.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/detail_state.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:provider/provider.dart';
4 |
5 | class QuantityChooser extends StatelessWidget {
6 | @override
7 | Widget build(BuildContext context) {
8 | return Consumer(builder: (context, state, child) {
9 | return Container(
10 | margin: EdgeInsets.symmetric(horizontal: 8),
11 | child: Center(
12 | child: DropdownButton(
13 | value: state.quantity.toString(),
14 | items: [
15 | DropdownMenuItem(
16 | child: Center(child: Text('1')),
17 | value: '1',
18 | ),
19 | DropdownMenuItem(
20 | child: Center(child: Text('2')),
21 | value: '2',
22 | ),
23 | DropdownMenuItem(
24 | child: Center(child: Text('3')),
25 | value: '3',
26 | ),
27 | ],
28 | onChanged: (value) {
29 | state.setQuantity(value);
30 | },
31 | ),
32 | ),
33 | );
34 | });
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/widgets/RelatedProducts.dart:
--------------------------------------------------------------------------------
1 | import 'package:async/async.dart';
2 | import 'package:cool_store/models/product.dart';
3 | import 'package:cool_store/services/base_services.dart';
4 | import 'package:cool_store/widgets/ProductCard.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:provider/provider.dart';
7 |
8 | class RelatedProduct extends StatelessWidget {
9 | final Product product;
10 |
11 | RelatedProduct(this.product);
12 |
13 | final _memoizer = AsyncMemoizer>();
14 | final services = Services();
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | final Size screenSize = MediaQuery.of(context).size;
19 |
20 | Future> getRelativeProducts() => _memoizer.runOnce(() {
21 | return services.fetchProductsByCategory(
22 | categoryId: product.categoryId,
23 | );
24 | });
25 |
26 | return FutureBuilder>(
27 | future: getRelativeProducts(),
28 | builder: (BuildContext context, AsyncSnapshot> snapshot) {
29 | switch (snapshot.connectionState) {
30 | case ConnectionState.none:
31 | case ConnectionState.active:
32 | case ConnectionState.waiting:
33 | return Container(
34 | height: 100,
35 | child: CircularProgressIndicator(),
36 | );
37 | case ConnectionState.done:
38 | if (snapshot.hasError) {
39 | return Container(
40 | height: 100,
41 | child: Center(
42 | child: Text(
43 | 'Error: ${snapshot.error}',
44 | style: TextStyle(color: Theme.of(context).accentColor),
45 | ),
46 | ),
47 | );
48 | } else if (snapshot.data.length == 0) {
49 | return Container();
50 | } else {
51 | return Column(
52 | crossAxisAlignment: CrossAxisAlignment.start,
53 | children: [
54 | Padding(
55 | padding: const EdgeInsets.symmetric(vertical: 18.0),
56 | child: Text(
57 | 'You might like',
58 | style: TextStyle(
59 | fontSize: 17, color: Theme.of(context).accentColor),
60 | ),
61 | ),
62 | Container(
63 | height: MediaQuery.of(context).size.width * 0.7,
64 | child: ListView(
65 | shrinkWrap: true,
66 | scrollDirection: Axis.horizontal,
67 | children: [
68 | for (var item in snapshot.data)
69 | if (item.id != product.id)
70 | ProductDisplayCard(
71 | onPressed: (){},
72 | product: item,
73 | )
74 | ],
75 | ))
76 | ],
77 | );
78 | }
79 | }
80 | return Container(); // unreachable
81 | },
82 | );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/widgets/ShimmerGrid.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shimmer/shimmer.dart';
3 |
4 | class ShimmerGrid extends StatelessWidget {
5 | int time = 600;
6 | int offset = 50;
7 |
8 | @override
9 | Widget build(BuildContext context) {
10 | return SafeArea(
11 | child: GridView.builder(
12 | shrinkWrap: true,
13 | physics: NeverScrollableScrollPhysics(),
14 | itemCount: 4,
15 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
16 | childAspectRatio: .6,
17 | crossAxisCount: 2,
18 | crossAxisSpacing: 1,
19 | mainAxisSpacing: 1),
20 | itemBuilder: (context, pos) {
21 | offset += 50;
22 | time += offset;
23 | return Shimmer.fromColors(
24 | baseColor: Colors.grey[300],
25 | highlightColor: Colors.white,
26 | child: ShimmerLayout(),
27 | period: Duration(milliseconds: time),
28 | );
29 | }),
30 | );
31 | }
32 | }
33 |
34 | class ShimmerLayout extends StatelessWidget {
35 | @override
36 | Widget build(BuildContext context) {
37 | return Container(
38 | child: Column(
39 | mainAxisAlignment: MainAxisAlignment.center,
40 | crossAxisAlignment: CrossAxisAlignment.start,
41 | children: [
42 | Expanded(
43 | child: Container(
44 | color: Colors.grey,
45 | ),
46 | ),
47 | Container(
48 | margin: EdgeInsets.only(top: 4, bottom: 4, left: 4, right: 40),
49 | height: 10,
50 | color: Colors.grey,
51 | ),
52 | Container(
53 | margin: EdgeInsets.only(top: 4, bottom: 4, left: 4, right: 80),
54 | height: 10,
55 | color: Colors.grey,
56 | ),
57 | ],
58 | ),
59 | );
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/lib/widgets/ShimmerList.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:shimmer/shimmer.dart';
3 |
4 | class ShimmerList extends StatelessWidget {
5 | int time = 600;
6 | int offset = 50;
7 |
8 | final Axis direction;
9 |
10 | ShimmerList({this.direction = Axis.vertical});
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return SafeArea(
15 | child: ListView.builder(
16 | scrollDirection: direction,
17 | physics: NeverScrollableScrollPhysics(),
18 | itemCount: 4,
19 | shrinkWrap: true,
20 | itemBuilder: (context, pos) {
21 | offset += 50;
22 | time += offset;
23 | return Shimmer.fromColors(
24 | child: direction == Axis.horizontal
25 | ? ShimmerHorizontalLayout()
26 | : ShimmerLayout(),
27 | highlightColor: Colors.white,
28 | period: Duration(milliseconds: time),
29 | baseColor: Colors.grey[300],
30 | );
31 | }),
32 | );
33 | }
34 | }
35 |
36 | class ShimmerHorizontalLayout extends StatelessWidget {
37 | @override
38 | Widget build(BuildContext context) {
39 | return Container(
40 | height: MediaQuery.of(context).size.height / 3,
41 | width: MediaQuery.of(context).size.width / 2,
42 | margin: EdgeInsets.symmetric(horizontal: 8),
43 | child: Column(
44 | mainAxisAlignment: MainAxisAlignment.center,
45 | crossAxisAlignment: CrossAxisAlignment.start,
46 | children: [
47 | Expanded(
48 | child: Container(
49 | color: Colors.grey,
50 | ),
51 | ),
52 | Container(
53 | margin: EdgeInsets.only(top: 4, bottom: 4, left: 4, right: 40),
54 | height: 10,
55 | color: Colors.grey,
56 | ),
57 | Container(
58 | margin: EdgeInsets.only(top: 4, bottom: 4, left: 4, right: 80),
59 | height: 10,
60 | color: Colors.grey,
61 | ),
62 | ],
63 | ),
64 | );
65 | }
66 | }
67 |
68 | class ShimmerLayout extends StatelessWidget {
69 | @override
70 | Widget build(BuildContext context) {
71 | double height = (MediaQuery.of(context).size.height) / 2 - 150;
72 | return Container(
73 | margin: EdgeInsets.all(4),
74 | height: height,
75 | color: Colors.grey,
76 | );
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/lib/widgets/VariantChooser.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/states/detail_state.dart';
2 | import 'package:cool_store/utils/constants.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:provider/provider.dart';
5 | import 'package:shimmer/shimmer.dart';
6 |
7 | class VariantChooser extends StatefulWidget {
8 | final String title;
9 | final List options;
10 |
11 | VariantChooser({this.title, this.options});
12 |
13 | @override
14 | _VariantChooserState createState() => _VariantChooserState();
15 | }
16 |
17 | class _VariantChooserState extends State {
18 | int selectedIndex = -1;
19 | int time = 1000;
20 | int offset = 50;
21 |
22 | Color baseColor, highlightColor, borderColor, accentColor;
23 |
24 | @override
25 | Widget build(BuildContext context) {
26 | final state = Provider.of(context);
27 | final theme = Theme.of(context);
28 | baseColor = theme.iconTheme.color;
29 | highlightColor = theme.primaryColor;
30 | accentColor = theme.accentColor.withOpacity(.85);
31 | borderColor = theme.textTheme.title.color.withOpacity(.7);
32 | return Container(
33 | height: Constants.screenAwareSize(40, context),
34 | child: Row(
35 | crossAxisAlignment: CrossAxisAlignment.center,
36 | mainAxisAlignment: MainAxisAlignment.center,
37 | children: [
38 | Expanded(
39 | flex: 1,
40 | child: Padding(
41 | padding: const EdgeInsets.all(8.0),
42 | child: Text(widget.title),
43 | )),
44 | Expanded(
45 | flex: 4,
46 | child: ListView.builder(
47 | itemCount: widget.options.length,
48 | shrinkWrap: true,
49 | scrollDirection: Axis.horizontal,
50 | itemBuilder: (_, pos) {
51 | offset += 80;
52 | time += offset;
53 | return state.isVariantsLoading
54 | ? buildLoadingContainers(pos, time)
55 | : buildVariantContainer(state, pos);
56 | }),
57 | )
58 | ],
59 | ),
60 | );
61 | }
62 |
63 | Widget buildLoadingContainers(pos, time) {
64 | return Shimmer.fromColors(
65 | child: Container(
66 | padding: EdgeInsets.all(8),
67 | constraints: BoxConstraints(
68 | minWidth: Constants.screenAwareSize(30, context),
69 | minHeight: Constants.screenAwareSize(35, context)),
70 | margin: EdgeInsets.all(8),
71 | decoration: BoxDecoration(
72 | border: Border.all(color: borderColor),
73 | borderRadius: BorderRadius.circular(2)),
74 | child: Center(
75 | child: Text(
76 | '${widget.options[pos]}',
77 | )),
78 | ),
79 | period: Duration(milliseconds: time),
80 | highlightColor: highlightColor,
81 | baseColor: baseColor,
82 | );
83 | }
84 |
85 | Widget buildVariantContainer(state, pos) {
86 | return GestureDetector(
87 | onTap: () {
88 | state.changeAttributesTo(widget.title, widget.options[pos]);
89 | selectedIndex = pos;
90 | setState(() {});
91 | },
92 | child: Container(
93 | padding: EdgeInsets.all(8),
94 | constraints: BoxConstraints(
95 | minWidth: Constants.screenAwareSize(30, context),
96 | minHeight: Constants.screenAwareSize(40, context)),
97 | margin: EdgeInsets.all(8),
98 | decoration: BoxDecoration(
99 | borderRadius: BorderRadius.circular(2),
100 | border: Border.all(
101 | color: selectedIndex == pos ? accentColor : borderColor)),
102 | child: Center(
103 | child: Text(
104 | '${widget.options[pos]}',
105 | )),
106 | ),
107 | );
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/lib/widgets/VariationsView.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/product.dart';
2 | import 'package:cool_store/states/detail_state.dart';
3 | import 'package:cool_store/widgets/ColorChooser.dart';
4 | import 'package:cool_store/widgets/VariantChooser.dart';
5 | import 'package:flutter/cupertino.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:provider/provider.dart';
8 |
9 | import 'DefaultChooser.dart';
10 |
11 | class VariationsView extends StatelessWidget {
12 | final Product product;
13 |
14 | VariationsView(this.product);
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return Column(
19 | mainAxisAlignment: MainAxisAlignment.spaceAround,
20 | crossAxisAlignment: CrossAxisAlignment.center,
21 | children: product.attributes.map((value) {
22 | if (value.name == 'SIZE' || value.name == 'size')
23 | return VariantChooser(
24 | title: value.name,
25 | options: value.options,
26 | );
27 | else if (value.name == 'COLOR' ||
28 | value.name == 'color' ||
29 | value.name == 'colour' ||
30 | value.name == 'COLOUR')
31 | return ColorChooser(
32 | title: value.name,
33 | options: value.options,
34 | );
35 | return DefaultChooser(
36 | title: value.name,
37 | options: value.options,
38 | );
39 | }).toList());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/widgets/category_banner.dart:
--------------------------------------------------------------------------------
1 | import 'package:cool_store/models/category.dart';
2 | import 'package:cool_store/utils/constants.dart';
3 | import 'package:extended_image/extended_image.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class CategoryBanner extends StatelessWidget {
7 | final Category _category;
8 | final Function _onPressed;
9 |
10 | CategoryBanner(this._category, this._onPressed);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | double height = (MediaQuery.of(context).size.height) / 4.5;
15 | return InkWell(
16 | onTap: _onPressed,
17 | child: Stack(
18 | children: [
19 | Container(
20 | height: Constants.screenAwareSize(height, context),
21 | margin: EdgeInsets.all(4),
22 | decoration: BoxDecoration(
23 | image: DecorationImage(
24 | fit: BoxFit.cover,
25 | image: ExtendedNetworkImageProvider(_category.image,
26 | cache: true))),
27 | ),
28 | Container(
29 | height: Constants.screenAwareSize(height, context),
30 | margin: EdgeInsets.all(4),
31 | decoration: BoxDecoration(
32 | gradient: LinearGradient(
33 | begin: Alignment.topCenter,
34 | end: Alignment.bottomCenter,
35 | colors: [Colors.transparent, Colors.black54]),
36 | ),
37 | ),
38 | Container(
39 | height: Constants.screenAwareSize(height, context),
40 | margin: EdgeInsets.all(4),
41 | child: Center(
42 | child: Container(
43 | padding: EdgeInsets.all(8),
44 | decoration:
45 | BoxDecoration(border: Border.all(color: Colors.white)),
46 | child: Text(
47 | _category.name,
48 | style: TextStyle(
49 | fontSize: Constants.screenAwareSize(40, context),
50 | fontFamily: 'Raleway',
51 | color: Colors.white),
52 | ),
53 | )),
54 | )
55 | ],
56 | ),
57 | );
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: cool_store
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.2.2 <3.0.0"
18 |
19 | dependencies:
20 | flutter:
21 | sdk: flutter
22 | cupertino_icons: ^0.1.2
23 | crypto: ^2.1.2
24 | shimmer: ^1.0.0
25 | http: ^0.12.0+2
26 | connectivity: ^0.4.4
27 | provider: ^3.1.0
28 | carousel_slider: ^1.3.0
29 | smooth_star_rating: 1.0.3
30 | flutter_widget_from_html_core: ^0.2.2+1
31 | configurable_expansion_tile: ^1.0.0
32 | localstorage: ^2.0.0
33 | shared_preferences: ^0.5.3+4
34 | extended_image: ^0.5.6
35 | flutter_svg: ^0.14.0
36 | badges: ^1.1.0
37 | validate: ^1.7.0
38 |
39 | dev_dependencies:
40 | flutter_test:
41 | sdk: flutter
42 |
43 |
44 | # For information on the generic Dart part of this file, see the
45 | # following page: https://www.dartlang.org/tools/pub/pubspec
46 |
47 | # The following section is specific to Flutter.
48 | flutter:
49 |
50 | # The following line ensures that the Material Icons font is
51 | # included with your application, so that you can use the icons in
52 | # the material Icons class.
53 | uses-material-design: true
54 |
55 | # To add assets to your application, add an assets section, like this:
56 | assets:
57 | - category_image_default.jpg
58 | - empty_cart.png
59 | - no_result.svg
60 | - empty.svg
61 | - wishlist.png
62 | - list.svg
63 | - shoppint_cart_empty.svg
64 | - colors.csv
65 |
66 |
67 | # An image asset can refer to one or more resolution-specific "variants", see
68 | # https://flutter.dev/assets-and-images/#resolution-aware.
69 |
70 | # For details regarding adding assets from package dependencies, see
71 | # https://flutter.dev/assets-and-images/#from-packages
72 |
73 | # To add custom fonts to your application, add a fonts section here,
74 | # in this "flutter" section. Each entry in this list should have a
75 | # "family" key with the font family name, and a "fonts" key with a
76 | # list giving the asset and other descriptors for the font. For
77 | # example:
78 | fonts:
79 | - family: Raleway
80 | fonts:
81 | - asset: fonts/Raleway-Regular.ttf
82 | - asset: fonts/Raleway-Black.ttf
83 | - asset: fonts/Raleway-Bold.ttf
84 | weight: 700
85 | #
86 | # For details regarding fonts from package dependencies,
87 | # see https://flutter.dev/custom-fonts/#from-packages
88 |
--------------------------------------------------------------------------------