├── .gitignore ├── .metadata ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── personal │ │ │ │ └── clean_architecture │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── 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-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets └── image │ ├── application_logo.png │ └── user_profile.png ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── core │ ├── assets │ │ ├── assets.dart │ │ ├── icon.dart │ │ └── image.dart │ ├── constant │ │ ├── api_error.dart │ │ ├── auto_validate_mode.dart │ │ ├── constant.dart │ │ ├── enum.dart │ │ ├── global_data.dart │ │ ├── regular_expression.dart │ │ ├── session.dart │ │ ├── setting.dart │ │ ├── string.dart │ │ ├── url.dart │ │ └── validation.dart │ ├── error │ │ ├── error.dart │ │ └── failure.dart │ ├── extension │ │ └── extension.dart │ ├── extensions │ │ └── extensions.dart │ ├── language │ │ ├── en.dart │ │ └── translation.dart │ ├── route │ │ ├── route_collection.dart │ │ └── route_name.dart │ ├── theme │ │ ├── color.dart │ │ ├── style.dart │ │ └── theme.dart │ └── util │ │ ├── json_util.dart │ │ └── util.dart ├── data │ ├── datasource │ │ ├── datasource.dart │ │ ├── remote_datasource.dart │ │ └── session_datasource.dart │ ├── mapper │ │ ├── login_mapper.dart │ │ └── model.dart │ ├── model │ │ ├── login_model.dart │ │ └── model.dart │ ├── repository │ │ ├── api_provider_repository_impl.dart │ │ ├── get_storage_repository_impl.dart │ │ ├── network_info_impl.dart │ │ └── repository.dart │ └── usecases │ │ ├── dashboard_remote.dart │ │ ├── login_remote.dart │ │ ├── profile_remote.dart │ │ ├── splash_remote.dart │ │ ├── usecase.dart │ │ └── usecases.dart ├── dependency_injection.dart ├── domain │ ├── entity │ │ ├── entity.dart │ │ ├── login_entity.dart │ │ └── no_params.dart │ ├── model │ │ ├── login_model.dart │ │ ├── model.dart │ │ └── no_params.dart │ ├── repository │ │ ├── api_provider_repository.dart │ │ ├── get_storage_repository.dart │ │ ├── network_info_repository.dart │ │ └── repository.dart │ └── usecases │ │ ├── dashboard_get.dart │ │ ├── profile_get.dart │ │ ├── splash_get.dart │ │ └── usecases.dart ├── main.dart └── presentation │ ├── binding │ ├── binding.dart │ ├── dashboard_binding.dart │ ├── global_binding.dart │ ├── home_binding.dart │ ├── login_binding.dart │ ├── profile_binding.dart │ ├── splash_binding.dart │ └── visit_history_binding.dart │ ├── controller │ ├── controller.dart │ ├── dashboard_controller.dart │ ├── home_controller.dart │ ├── login_controller.dart │ ├── pickup_controller.dart │ ├── profile_controller.dart │ ├── settings_controller.dart │ ├── splash_controller.dart │ ├── total_record_controller.dart │ └── visit_history_controller.dart │ └── ui │ ├── page │ ├── dashbaord_page.dart │ ├── history_page.dart │ ├── home_page.dart │ ├── list_device_page.dart │ ├── login_mobile_page.dart │ ├── login_username_page.dart │ ├── new_device_add.dart │ ├── new_vendor_add.dart │ ├── otp_verify_page.dart │ ├── page.dart │ ├── pick_up_page.dart │ ├── profile_page.dart │ ├── qr_code_scanner_page.dart │ ├── return_page.dart │ ├── splash_page.dart │ └── vendor_visit_page.dart │ └── widget │ ├── category_list_item.dart │ ├── form_button_component.dart │ ├── form_icon_loading_component.dart │ ├── itemview │ └── customer_detail_itemview.dart │ ├── option_widget.dart │ ├── text_field_component.dart │ ├── text_field_search_component.dart │ └── widget.dart ├── pubspec.lock ├── pubspec.yaml └── test └── widget_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /.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: 5f105a6ca7a5ac7b8bc9b241f4c2d86f4188cf5c 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # clean_architecture 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | Core Layer 7 | - assets 8 | - constant 9 | - error 10 | - extensions 11 | - language 12 | - route 13 | - theme 14 | 15 | Data Layer (Domain Implement abstract method domain, gathering data) 16 | 1) Data Source: Rest API, Session, GraphQl etc. 17 | 2) Model: From json 18 | 3) UseCases: (Depend on Repository) 19 | - Convert (FromJson) model to entity Domain Layer 20 | 21 | Domain Layer (Abstract method) 22 | 1) Entity: Without FromJson use to UseCases Data Layer. 23 | 2) Repository: Rest API, Session, GraphQl etc. abstract method. 24 | 3) UseCases: Create abstract method, depend on logic of single controller (cubit event, getx controller). 25 | 26 | ## Change 13/02/2022 27 | 1) Model class name change both packages data and domain 28 | 2) Internet connection check 29 | 3) Form button animation 30 | 4) json_util (jsonEncode and jsonDecode) 31 | 5) Regular expression email 32 | 6) Add new extensions are BoolExtensions, DurationExtensions, IntExtensions 33 | 7) Add new constant package validation, api_error, auto_validate_mode, enum -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | 5 | rules: 6 | avoid_print: false 7 | prefer_single_quotes: true 8 | curly_braces_in_flow_control_structures: false 9 | avoid_function_literals_in_foreach_calls: false 10 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion flutter.compileSdkVersion 30 | 31 | compileOptions { 32 | sourceCompatibility JavaVersion.VERSION_1_8 33 | targetCompatibility JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlinOptions { 37 | jvmTarget = '1.8' 38 | } 39 | 40 | sourceSets { 41 | main.java.srcDirs += 'src/main/kotlin' 42 | } 43 | 44 | defaultConfig { 45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 46 | applicationId "com.personal.clean_architecture" 47 | minSdkVersion 20 48 | targetSdkVersion flutter.targetSdkVersion 49 | versionCode flutterVersionCode.toInteger() 50 | versionName flutterVersionName 51 | } 52 | 53 | buildTypes { 54 | release { 55 | // TODO: Add your own signing config for the release build. 56 | // Signing with the debug keys for now, so `flutter run --release` works. 57 | signingConfig signingConfigs.debug 58 | } 59 | } 60 | } 61 | 62 | flutter { 63 | source '../..' 64 | } 65 | 66 | dependencies { 67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 68 | } 69 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/personal/clean_architecture/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.personal.clean_architecture 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /assets/image/application_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/assets/image/application_logo.png -------------------------------------------------------------------------------- /assets/image/user_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/assets/image/user_profile.png -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /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 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/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/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttertutorialin/clean_architecture/c776608e277f7f615ecc3802561eba228592f175/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Clean Architecture 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | clean_architecture 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/core/assets/assets.dart: -------------------------------------------------------------------------------- 1 | export 'icon.dart'; 2 | export 'image.dart'; -------------------------------------------------------------------------------- /lib/core/assets/icon.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:line_icons/line_icons.dart'; 7 | 8 | const mapIcon = LineIcons.map; 9 | const callIcon = LineIcons.phone; 10 | const roadIcon = LineIcons.road; 11 | const arrowLefAndroidIcon = LineIcons.arrowLeft; 12 | 13 | const userCircleIcon = LineIcons.userCircle; 14 | const phoneIcon = LineIcons.phone; 15 | const themeIcon = LineIcons.code; 16 | const languageIcon = LineIcons.language; 17 | const privacyPolicyIcon = LineIcons.infoCircle; 18 | const selectIcon = LineIcons.checkCircle; 19 | const dateIcon = LineIcons.calendarCheck; 20 | const timeIcon = LineIcons.calendarCheck; 21 | const radioSelectIcon = LineIcons.checkCircle; 22 | const radioUnSelectIcon = LineIcons.timesCircleAlt; 23 | const reasonIcon = LineIcons.dotCircle; 24 | const mobileQcSelectIcon = LineIcons.dotCircle; 25 | const mobileQcUnSelectIcon = LineIcons.circle; 26 | 27 | const logoutIcon = LineIcons.lock; -------------------------------------------------------------------------------- /lib/core/assets/image.dart: -------------------------------------------------------------------------------- 1 | const String applicationLogoAsset = 'assets/image/application_logo.png'; 2 | const String profileAsset = 'assets/image/user_profile.png'; -------------------------------------------------------------------------------- /lib/core/constant/api_error.dart: -------------------------------------------------------------------------------- 1 | const int notFound = 404; 2 | 3 | const String notFoundMessage = 'There’s no Account with the info that you provided.'; 4 | -------------------------------------------------------------------------------- /lib/core/constant/auto_validate_mode.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | const AutovalidateMode autoValidateMode = AutovalidateMode.disabled; 4 | const AutovalidateMode loginFormAutoValidateMode = autoValidateMode; -------------------------------------------------------------------------------- /lib/core/constant/constant.dart: -------------------------------------------------------------------------------- 1 | export 'enum.dart'; 2 | export 'global_data.dart'; 3 | export 'session.dart'; 4 | export 'url.dart'; 5 | export 'auto_validate_mode.dart'; 6 | export 'string.dart'; 7 | export 'setting.dart'; 8 | export 'regular_expression.dart'; 9 | export 'api_error.dart'; -------------------------------------------------------------------------------- /lib/core/constant/enum.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | enum LoadingStatusEnum { initial, loading, success } 7 | enum ApiTypeEnum { get, post, delete, put } 8 | 9 | enum ListTypeEnum { pickUpMobile, returnMobile} -------------------------------------------------------------------------------- /lib/core/constant/global_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const List> themes = [ 4 | {'index': 0, 'value': ThemeMode.light, 'label': 'lightMode'}, 5 | {'index': 1, 'value': ThemeMode.dark, 'label': 'darkMode'}, 6 | {'index': 2, 'value': ThemeMode.system, 'label': 'systemMode'} 7 | ]; 8 | 9 | const List languages = [ 10 | {'value': 'en', 'label': 'English'}, 11 | {'value': 'ar', 'label': 'عربي'}, 12 | ]; -------------------------------------------------------------------------------- /lib/core/constant/regular_expression.dart: -------------------------------------------------------------------------------- 1 | class RegularExpression { 2 | static String emailRegex = r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'; 3 | } 4 | -------------------------------------------------------------------------------- /lib/core/constant/session.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | //PARAMETER 7 | const String uniqueIdSession = 'uniqueId'; 8 | const String mobileSession = 'mobile'; 9 | const String userNameSession = 'userName'; 10 | const String loginDateTimeSession = 'loginDateTime'; 11 | const String languageSession = 'language'; 12 | const String isLoginSession = 'isLogin'; -------------------------------------------------------------------------------- /lib/core/constant/setting.dart: -------------------------------------------------------------------------------- 1 | const Duration waitingToastGetSnackBar = Duration(seconds: 2); 2 | 3 | -------------------------------------------------------------------------------- /lib/core/constant/string.dart: -------------------------------------------------------------------------------- 1 | 2 | //TOAST 3 | const String loginTitleToast = 'Login'; 4 | 5 | //NETWORK CONNECTION 6 | const String networkConnectionError = 'Please check your internet connection'; 7 | -------------------------------------------------------------------------------- /lib/core/constant/url.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | //API URL 7 | const String baseUrl = ''; 8 | 9 | const String loginUrl = ''; 10 | 11 | 12 | //MUST BE ALL API CALLING USING DEFAULT HEADER PASS 13 | var defaultHeader = { 14 | '': '', 15 | }; 16 | 17 | //PARAMETER 18 | String userNameParam = 'USERNAME'; 19 | String passwordParam = 'PASSWORD'; 20 | 21 | //JSON KEY 22 | String messageJsonKey = 'MESSAGE'; 23 | String statusCodeJsonKey = 'STATUS_CODE'; 24 | String dataJsonKey = 'DATA'; 25 | String userIdJsonKey = 'USERID'; 26 | String userNameJsonKey = 'USERNAME'; 27 | String employeeIdJsonKey = 'EMPID'; 28 | -------------------------------------------------------------------------------- /lib/core/constant/validation.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | const AutovalidateMode autoValidateMode = AutovalidateMode.disabled; 4 | const AutovalidateMode loginFormAutoValidateMode = autoValidateMode; -------------------------------------------------------------------------------- /lib/core/error/error.dart: -------------------------------------------------------------------------------- 1 | export 'failure.dart'; -------------------------------------------------------------------------------- /lib/core/error/failure.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | 3 | class Failure extends Equatable { 4 | final int? code; 5 | final String? message; 6 | final String? title; 7 | 8 | const Failure({this.code, this.message, this.title}); 9 | 10 | @override 11 | List get props => [code!, message!, title!]; 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /lib/core/extension/extension.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import 'package:intl/intl.dart'; 4 | import '../theme/color.dart'; 5 | 6 | /// Use across of the application 7 | extension DynamicUtil on dynamic { 8 | toast({required String? title, required String? message}) { 9 | return GetSnackBar( 10 | titleText: Text(title!.tr, 11 | style: Get.textTheme.headline3!.copyWith(fontSize: 14, color: whiteColor)), 12 | messageText: Text(message!.tr, 13 | style: Get.textTheme.headline4!.copyWith(fontSize: 14, color: whiteColor)), 14 | snackPosition: SnackPosition.BOTTOM, 15 | margin: const EdgeInsets.all(20), 16 | backgroundColor: Get.theme.primaryColor, 17 | padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), 18 | borderRadius: 8, 19 | reverseAnimationCurve: Curves.easeInOut, 20 | dismissDirection: DismissDirection.horizontal, 21 | duration: const Duration(seconds: 3)) 22 | .show(); 23 | } 24 | } 25 | 26 | extension ContextExtensions on BuildContext {} 27 | 28 | extension InputDecorationExtensions on InputDecoration {} 29 | 30 | extension WidgetExtensions on Widget {} 31 | 32 | extension VoidExtensions on void { 33 | showProgress() {} 34 | 35 | void navigationBack() { 36 | Get.back(); 37 | } 38 | } 39 | 40 | extension StringExtensions on String { 41 | /*String unescapeConvert(String htmlString) { 42 | var unescape = HtmlUnescape(); 43 | var text = unescape.convert(htmlString); 44 | return text; 45 | }*/ 46 | 47 | String hourMinuteDateDateFormat() { 48 | return DateFormat('kk:mm a | dd - MMM') 49 | .format(DateFormat('dd-MM-yyyy HH:mm').parse(this)); 50 | } 51 | 52 | String hourMinuteDateMonthYearDateFormat() { 53 | return DateFormat('dd-MMM-yyyy | KK:mm a') 54 | .format(DateFormat('yyyy-MM-dd HH:mm').parse(this)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/core/extensions/extensions.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:get/get.dart'; 5 | import 'package:intl/intl.dart'; 6 | import '../constant/constant.dart'; 7 | import '../theme/color.dart'; 8 | 9 | /// Use across of the application 10 | extension DynamicUtil on dynamic { 11 | toast({required String? title, required String? message}) { 12 | return GetSnackBar( 13 | titleText: Text(title!.tr, 14 | style: Get.textTheme.headline3! 15 | .copyWith(fontSize: 14, color: whiteColor)), 16 | messageText: Text(message!.tr, 17 | style: Get.textTheme.headline4! 18 | .copyWith(fontSize: 14, color: whiteColor)), 19 | snackPosition: SnackPosition.BOTTOM, 20 | margin: const EdgeInsets.all(20), 21 | backgroundColor: Get.theme.primaryColor, 22 | padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), 23 | borderRadius: 8, 24 | reverseAnimationCurve: Curves.easeInOut, 25 | dismissDirection: DismissDirection.horizontal, 26 | duration: waitingToastGetSnackBar) 27 | .show(); 28 | } 29 | } 30 | 31 | extension ContextExtensions on BuildContext {} 32 | 33 | extension InputDecorationExtensions on InputDecoration {} 34 | 35 | extension WidgetExtensions on Widget {} 36 | 37 | extension VoidExtensions on void { 38 | showProgress() {} 39 | 40 | void navigationBack() { 41 | Get.back(); 42 | } 43 | } 44 | 45 | extension BoolExtensions on bool { 46 | bool _hasMatch(String pattern) { 47 | return RegExp(pattern).hasMatch(pattern); 48 | } 49 | 50 | //VALIDATION 51 | bool get isEmail => _hasMatch(RegularExpression.emailRegex); 52 | } 53 | 54 | extension DurationExtensions on Duration { 55 | Future delay([FutureOr Function()? callback]) async => Future.delayed(this, callback); 56 | } 57 | 58 | extension StringExtensions on String { 59 | //DATE 60 | String hourMinuteDateDateFormat() { 61 | return DateFormat('kk:mm a | dd - MMM') 62 | .format(DateFormat('dd-MM-yyyy HH:mm').parse(this)); 63 | } 64 | 65 | String hourMinuteDateMonthYearDateFormat() { 66 | return DateFormat('dd-MMM-yyyy | KK:mm a') 67 | .format(DateFormat('yyyy-MM-dd HH:mm').parse(this)); 68 | } 69 | } 70 | 71 | extension IntExtensions on int { 72 | Color get hexColor => Color(this); 73 | } 74 | -------------------------------------------------------------------------------- /lib/core/language/en.dart: -------------------------------------------------------------------------------- 1 | const Map en = { 2 | 'lightMode': 'Light mode', 3 | 'darkMode': 'Dark mode', 4 | 'systemMode': 'System mode', 5 | 6 | 'settings': 'Settings', 7 | 'language': 'Language', 8 | 'themeMode': 'Theme mode', 9 | 10 | 'appName': 'Maan Food', 11 | 12 | 'categories': 'Categories', 13 | 'seeAll': 'See all', 14 | }; -------------------------------------------------------------------------------- /lib/core/language/translation.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | import 'en.dart'; 3 | 4 | class Translation extends Translations { 5 | @override 6 | Map> get keys => {'en': en}; 7 | } 8 | -------------------------------------------------------------------------------- /lib/core/route/route_collection.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:get/get.dart'; 7 | import 'route_name.dart'; 8 | import '../../presentation/ui/page/dashbaord_page.dart'; 9 | import '../../presentation/binding/binding.dart'; 10 | import '../../presentation/ui/page/page.dart'; 11 | 12 | class RouteCollection { 13 | RouteCollection._(); 14 | 15 | static final routeCollection = [ 16 | GetPage( 17 | binding: SplashBinding(), 18 | name: RouteName.slashRoute, 19 | page: () => const SplashPage()), 20 | GetPage( 21 | binding: LoginBinding(), 22 | name: RouteName.loginUserNameRoute, 23 | page: () => const LoginUserNamePage()), 24 | GetPage( 25 | name: RouteName.loginMobileRoute, page: () => const LoginMobilePage()), 26 | GetPage(name: RouteName.otpVerifyRoute, page: () => OtpVerifyPage()), 27 | GetPage( 28 | binding: DashboardBinding(), 29 | name: RouteName.dashboardRoute, 30 | page: () => const DashBoardPage()), 31 | GetPage( 32 | binding: ProfileBinding(), 33 | name: RouteName.profileRoute, 34 | page: () => const ProfilePage()), 35 | GetPage( 36 | name: RouteName.listDeviceRoute, page: () => const ListDevicePage()), 37 | GetPage( 38 | name: RouteName.newDeviceAddRoute, page: () => const NewDevicePage()), 39 | GetPage( 40 | name: RouteName.newVendorAddRoute, 41 | page: () => const NewVendorAddPage()), 42 | GetPage( 43 | binding: HomeBinding(), 44 | name: RouteName.homeRoute, 45 | page: () => const HomePage()), 46 | GetPage( 47 | binding: VisitHistoryBinding(), 48 | name: RouteName.historyRoute, 49 | page: () => const HistoryPage()), 50 | GetPage( 51 | name: RouteName.qrCodeScannerRoute, 52 | page: () => const QRCodeScannerPage()), 53 | GetPage( 54 | name: RouteName.vendorVisitRoute, page: () => const VendorVisitPage()), 55 | ]; 56 | } 57 | -------------------------------------------------------------------------------- /lib/core/route/route_name.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 20-11-21 06:00 4 | */ 5 | 6 | class RouteName { 7 | static const slashRoute = '/splash'; 8 | static const otpVerifyRoute = '/otpVerify'; 9 | static const loginUserNameRoute = '/loginUserName'; 10 | static const loginMobileRoute = '/loginMobile'; 11 | static const dashboardRoute = '/dashboard'; 12 | static const homeRoute = '/home'; 13 | static const listDeviceRoute = '/listDevice'; 14 | static const newDeviceAddRoute = '/newDeviceAdd'; 15 | static const newVendorAddRoute = '/newVendorAdd'; 16 | static const themeModeRoute = '/theme'; 17 | static const profileRoute = '/profile'; 18 | static const languageRoute = '/language'; 19 | static const historyRoute = '/history'; 20 | static const qrCodeScannerRoute = '/QRCodeScanner'; 21 | static const vendorVisitRoute = '/vendorVisit'; 22 | } 23 | -------------------------------------------------------------------------------- /lib/core/theme/color.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const whiteThemeLightColor = Color(0xFFFFFFFF); 4 | const blackThemeDarkColor = Color(0xFF252525); 5 | const loadingColor = Color(0xFFEF5523); 6 | 7 | const scaffoldBackgroundThemeLightColor = Color(0xFFFFFFFF); 8 | const scaffoldBackgroundThemeDarkColor = Color(0xFF2C2C2C); 9 | 10 | 11 | const whiteColor = Color(0xFFFFFFFF); 12 | 13 | const onBoardBackgroundColor = Color(0xFFFCF1F0); 14 | const subTitle1LightColor = Color(0xFF2C2C2C); 15 | const subTitle1DarkColor = Color(0xFF2C2C2C); 16 | 17 | const bodyText2LightColor = Color(0xFF707070); 18 | 19 | const doneButtonBgColor = Colors.green; 20 | const postponeButtonBgColor = Colors.orange; 21 | const cancelButtonBgColor = Colors.red; -------------------------------------------------------------------------------- /lib/core/theme/style.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:google_fonts/google_fonts.dart'; 3 | 4 | final _googleFonts = GoogleFonts.ptSans(fontStyle: FontStyle.normal); 5 | headLine6Style(Color color) => _googleFonts.copyWith(fontSize: 15.0, fontWeight: FontWeight.w700, color: color, height: 1.3); 6 | headLine5Style(Color color) => _googleFonts.copyWith(letterSpacing: 0.8, fontSize: 16.0, fontWeight: FontWeight.w700, color: color, height: 1.3); 7 | headLine4Style(Color color) => _googleFonts.copyWith(fontSize: 18.0, fontWeight: FontWeight.w400, color: color, height: 1.3); 8 | headLine3Style(Color color) => _googleFonts.copyWith(fontSize: 20.0, fontWeight: FontWeight.w700, color: color, height: 1.3); 9 | headLine2Style(Color color) => _googleFonts.copyWith(fontSize: 22.0, fontWeight: FontWeight.w700, color: color, height: 1.3); 10 | headLine1Style(Color color) => _googleFonts.copyWith(fontSize: 24.0, fontWeight: FontWeight.w300, color: color, height: 1.3); 11 | subtitle2Style(Color color) => _googleFonts.copyWith(fontSize: 15.0, fontWeight: FontWeight.w600, color: color, height: 1.3); 12 | subtitle1Style(Color color) => _googleFonts.copyWith(fontSize: 13.0, fontWeight: FontWeight.w400, color: color, height: 1.3); 13 | bodyText2Style(Color color) => _googleFonts.copyWith(fontSize: 13.0, fontWeight: FontWeight.w600, color: color, height: 1.2); 14 | bodyText1Style(Color color) => _googleFonts.copyWith(fontSize: 12.0, fontWeight: FontWeight.w400, color: color, height: 1.3); 15 | captionStyle(Color color) => _googleFonts.copyWith(fontSize: 12.0, fontWeight: FontWeight.w300, color: color, height: 1.3); -------------------------------------------------------------------------------- /lib/core/theme/theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'color.dart'; 3 | import 'style.dart'; 4 | 5 | final ThemeData lightTheme = ThemeData.light().copyWith( 6 | textTheme: TextTheme( 7 | headline6: headLine6Style(const Color(0xFFFA4F26)), 8 | headline5: headLine5Style(const Color(0xFF08143a)), 9 | headline4: headLine4Style(const Color(0xFF08143a)), 10 | headline3: headLine3Style(const Color(0xFF08143a)), 11 | headline2: headLine2Style(const Color(0xFFFA4F26)), 12 | headline1: headLine1Style(const Color(0xFF08143a)), 13 | subtitle2: subtitle2Style(const Color(0xFF08143a)), 14 | subtitle1: subtitle1Style(const Color(0xFFFA4F26)), 15 | bodyText2: bodyText2Style(const Color(0xFF08143a)), 16 | bodyText1: bodyText1Style(const Color(0xFF08143a)), 17 | caption: captionStyle(const Color(0xFF8C9DA8))), 18 | dividerColor: const Color(0xFF8C9DA8).withOpacity(0.1), 19 | focusColor: const Color(0xFF8C9DA8), 20 | hintColor: const Color(0xFF08143a), 21 | textButtonTheme: TextButtonThemeData( 22 | style: TextButton.styleFrom(primary: const Color(0xFFEF5523))), 23 | colorScheme: const ColorScheme.light( 24 | primary: Color(0xFFEF5523), secondary: Color(0xFFEF5523)), 25 | unselectedWidgetColor: Colors.grey, 26 | selectedRowColor: const Color(0xFF2E7D32).withOpacity(0.1), 27 | brightness: Brightness.light, 28 | iconTheme: const IconThemeData(color: Color(0xFF000000)), 29 | primaryColor: const Color(0xFFEF5523), 30 | indicatorColor: const Color(0xFFFFEAD1)); 31 | 32 | final ThemeData darkTheme = ThemeData.light().copyWith( 33 | textTheme: TextTheme( 34 | headline6: headLine6Style(const Color(0xFFEF5523)), 35 | headline5: headLine5Style(const Color(0xFFCCCCDD)), 36 | headline4: headLine4Style(const Color(0xFFCCCCDD)), 37 | headline3: headLine3Style(const Color(0xFFCCCCDD)), 38 | headline2: headLine2Style(const Color(0xFFEF5523)), 39 | headline1: headLine1Style(const Color(0xFFCCCCDD)), 40 | subtitle2: subtitle2Style(const Color(0xFFCCCCDD)), 41 | subtitle1: subtitle1Style(const Color(0xFFEF5523)), 42 | bodyText2: bodyText2Style(const Color(0xFFCCCCDD)), 43 | bodyText1: bodyText1Style(const Color(0xFFCCCCDD)), 44 | caption: captionStyle(const Color(0xFF9999AA))), 45 | scaffoldBackgroundColor: scaffoldBackgroundThemeDarkColor, 46 | brightness: Brightness.dark, 47 | primaryColor: const Color(0xFF252525), 48 | iconTheme: const IconThemeData(color: Color(0xFFFFFFFF)), 49 | cardColor: const Color(0xFF252525), 50 | dividerColor: const Color(0xFF9999aa).withOpacity(0.1), 51 | focusColor: const Color(0xFF9999aa), 52 | hintColor: const Color(0xFFCCCCDD), 53 | textButtonTheme: TextButtonThemeData( 54 | style: TextButton.styleFrom(primary: const Color(0xFFEF5523))), 55 | colorScheme: const ColorScheme.dark( 56 | primary: Color(0xFFEF5523), secondary: Color(0xFFEF5523)), 57 | unselectedWidgetColor: Colors.grey, 58 | selectedRowColor: const Color(0xFF2E7D32).withOpacity(0.1), 59 | ); 60 | -------------------------------------------------------------------------------- /lib/core/util/json_util.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | /// Converts [value] to a JSON string. 4 | String jsonEncode(Object? value, {Object? Function(dynamic object)? toEncodable}) => 5 | json.encode(value, toEncodable: toEncodable); 6 | 7 | /// Parses the string and returns the resulting Json object. 8 | dynamic jsonDecode(String source, 9 | {Object? Function(Object? key, Object? value)? reviver}) => 10 | json.decode(source, reviver: reviver); -------------------------------------------------------------------------------- /lib/core/util/util.dart: -------------------------------------------------------------------------------- 1 | export 'json_util.dart'; -------------------------------------------------------------------------------- /lib/data/datasource/datasource.dart: -------------------------------------------------------------------------------- 1 | export 'remote_datasource.dart'; 2 | export 'session_datasource.dart'; -------------------------------------------------------------------------------- /lib/data/datasource/remote_datasource.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:dio_helper_flutter/dio_helper.dart'; 3 | import '../mapper/model.dart'; 4 | import '../../core/constant/constant.dart'; 5 | import '../../core/error/error.dart'; 6 | import '../repository/repository.dart'; 7 | 8 | abstract class RemoteDataSource { 9 | Future> login( 10 | {required Map parameter}); 11 | } 12 | 13 | class RemoteDataSourceImpl extends RemoteDataSource { 14 | final ApiProviderImpl _apiProviderImpl; 15 | final NetWorkInfoImpl _networkInfoImpl; 16 | 17 | RemoteDataSourceImpl(this._apiProviderImpl, this._networkInfoImpl); 18 | 19 | Future _loginApi({required Map parameter}) async { 20 | var response = await _apiProviderImpl.postApi(loginUrl, queryParameters: parameter, header: defaultHeader); 21 | return LoginMapper.fromJson(response); 22 | } 23 | 24 | @override 25 | Future> login( 26 | {required Map parameter}) async { 27 | if (await _networkInfoImpl.isConnected) { 28 | try { 29 | final response = await _loginApi(parameter: parameter); 30 | return Right(response); 31 | } catch (error) { 32 | var getError = error as DioErrorEntity; 33 | return Left(Failure( 34 | code: getError.statusCode!, 35 | title: loginTitleToast, 36 | message: getError.errorLanguageEntity?.defaultLanguage!)); 37 | } 38 | } else { 39 | return const Left( 40 | Failure(title: loginTitleToast, message: networkConnectionError)); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/data/datasource/session_datasource.dart: -------------------------------------------------------------------------------- 1 | import '../../core/constant/constant.dart'; 2 | import '../repository/repository.dart'; 3 | 4 | abstract class SessionDataSource { 5 | //USERNAME 6 | String userNameRead(); 7 | Future userNameWrite(String value); 8 | Future userNameRemove(); 9 | 10 | //LOGIN IN TIME 11 | String loginInTimeRead(); 12 | Future loginInTimeWrite(String value); 13 | Future loginInTimeRemove(); 14 | 15 | //USER IS LOGIN 16 | bool isLoginRead(); 17 | Future isLoginWrite(bool value); 18 | Future isLoginRemove(); 19 | } 20 | 21 | class SessionDataSourceImpl extends SessionDataSource { 22 | final GetStorageImpl _getStorageImpl; 23 | 24 | SessionDataSourceImpl(this._getStorageImpl); 25 | 26 | @override 27 | String userNameRead() => _getStorageImpl.read(userNameSession); 28 | 29 | @override 30 | Future userNameWrite(String value) => 31 | _getStorageImpl.write(userNameSession, value); 32 | 33 | @override 34 | Future isLoginRemove() => 35 | _getStorageImpl.remove(userNameSession); 36 | 37 | @override 38 | bool isLoginRead() => _getStorageImpl.hasData(isLoginSession); 39 | 40 | @override 41 | Future isLoginWrite(bool value) => 42 | _getStorageImpl.write(isLoginSession, value); 43 | 44 | @override 45 | Future loginInTimeRemove() => _getStorageImpl.remove(isLoginSession); 46 | 47 | @override 48 | String loginInTimeRead() => _getStorageImpl.read(loginDateTimeSession); 49 | 50 | @override 51 | Future loginInTimeWrite(String value) => 52 | _getStorageImpl.write(loginDateTimeSession, value); 53 | 54 | @override 55 | Future userNameRemove() => _getStorageImpl.remove(loginDateTimeSession); 56 | } 57 | -------------------------------------------------------------------------------- /lib/data/mapper/login_mapper.dart: -------------------------------------------------------------------------------- 1 | import '../../domain/model/model.dart'; 2 | import '../../core/constant/constant.dart'; 3 | 4 | //LOGIN (CLASS - 1) 5 | class LoginMapper extends LoginModel { 6 | final String? statusCode; 7 | final String? message; 8 | 9 | const LoginMapper({ 10 | required List? loginDetailList, 11 | this.message, 12 | this.statusCode, 13 | }) : super(loginDetailList: loginDetailList); 14 | 15 | factory LoginMapper.fromJson(Map json) => LoginMapper( 16 | loginDetailList: List.from( 17 | json[dataJsonKey].map((value) => LoginDetailMapper.fromJson(value))), 18 | message: json[messageJsonKey], 19 | statusCode: json[statusCodeJsonKey]); 20 | } 21 | 22 | //LOGIN DETAIL (CLASS - 2) GET THE USERID, USERNAME AND EMPLOYEE-ID 23 | class LoginDetailMapper extends LoginDetailModel { 24 | const LoginDetailMapper({required String? userId, userName, employeeId}) 25 | : super(userId: userId, userName: userName, employeeId: employeeId); 26 | 27 | factory LoginDetailMapper.fromJson(Map json) => 28 | LoginDetailMapper( 29 | userId: json[userIdJsonKey], 30 | userName: json[userNameJsonKey], 31 | employeeId: json[employeeIdJsonKey]); 32 | } 33 | 34 | /* 35 | final value = ListResponse.fromJson(response, (json) => LoginDetailModel.fromJson(json)); 36 | print(value.data.toString()); 37 | 38 | class BaseResponse { 39 | final String? statusCode; 40 | final String? message; 41 | 42 | BaseResponse({this.statusCode, this.message}); 43 | 44 | factory BaseResponse.fromJson(Map json) { 45 | return BaseResponse( 46 | statusCode: json[messageJsonKey], message: json[statusCodeJsonKey]); 47 | } 48 | } 49 | 50 | class ListResponse extends BaseResponse { 51 | List? data; 52 | 53 | ListResponse({ 54 | required String message, 55 | required String statusCode, 56 | this.data, 57 | }) : super(message: message, statusCode: statusCode); 58 | 59 | factory ListResponse.fromJson( 60 | Map json, Function(Map) create) { 61 | var data = []; 62 | json[dataJsonKey].forEach((v) { 63 | data.add(create(v)); 64 | }); 65 | 66 | return ListResponse( 67 | statusCode: json[messageJsonKey], 68 | message: json[statusCodeJsonKey], 69 | data: data); 70 | } 71 | } 72 | */ 73 | -------------------------------------------------------------------------------- /lib/data/mapper/model.dart: -------------------------------------------------------------------------------- 1 | export 'login_mapper.dart'; -------------------------------------------------------------------------------- /lib/data/model/login_model.dart: -------------------------------------------------------------------------------- 1 | import '../../domain/entity/entity.dart'; 2 | import '../../core/constant/constant.dart'; 3 | 4 | class LoginModel extends LoginEntity { 5 | final String? statusCode; 6 | final String? message; 7 | 8 | const LoginModel({ 9 | required List? loginDetailList, 10 | this.message, 11 | this.statusCode, 12 | }) : super(loginDetailList: loginDetailList); 13 | 14 | factory LoginModel.fromJson(Map json) => LoginModel( 15 | loginDetailList: List.from( 16 | json[dataJsonKey].map((value) => LoginDetailModel.fromJson(value))), 17 | message: json[messageJsonKey], 18 | statusCode: json[statusCodeJsonKey]); 19 | } 20 | 21 | class LoginDetailModel extends LoginDetailEntity { 22 | const LoginDetailModel({required String? userId, userName, employeeId}) 23 | : super(userId: userId, userName: userName, employeeId: employeeId); 24 | 25 | factory LoginDetailModel.fromJson(Map json) => 26 | LoginDetailModel( 27 | userId: json[userIdJsonKey], 28 | userName: json[userNameJsonKey], 29 | employeeId: json[employeeIdJsonKey]); 30 | } 31 | -------------------------------------------------------------------------------- /lib/data/model/model.dart: -------------------------------------------------------------------------------- 1 | export 'login_model.dart'; -------------------------------------------------------------------------------- /lib/data/repository/api_provider_repository_impl.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 20-11-21 3:41 4 | */ 5 | 6 | import 'dart:io'; 7 | import 'package:dio/dio.dart'; 8 | import 'package:dio_helper_flutter/dio_helper.dart'; 9 | import '../../domain/repository/repository.dart'; 10 | 11 | class ApiProviderImpl implements ApiProviderRepository { 12 | final DioHelper _dioHelper; 13 | 14 | ApiProviderImpl(this._dioHelper); 15 | 16 | @override 17 | Future getApi(String pathUrl, {Map? queryParameter}) async { 18 | return await _dioHelper.request('${APiKey.baseUrlKey}$pathUrl', 19 | queryParameter: queryParameter, dioMethod: DioMethod.get); 20 | } 21 | 22 | @override 23 | Future imageUpload(String pathUrl, {required FormData formData}) async { 24 | return await _dioHelper.request(pathUrl, data: formData); 25 | } 26 | 27 | @override 28 | Future postApi(String pathUrl, 29 | {Map? queryParameters, 30 | data, 31 | Map? header}) async { 32 | return await _dioHelper.request('${APiKey.baseUrlKey}$pathUrl', 33 | data: data, 34 | queryParameter: queryParameters, 35 | header: header, 36 | dioMethod: DioMethod.post); 37 | } 38 | 39 | @override 40 | void imageUploadMap(String pathUrl, 41 | {Map? imageUploadParameter}) { 42 | FormData formData = FormData.fromMap(imageUploadParameter!); 43 | imageUploadParameter.forEach((key, value) async { 44 | if ((value) is File) { 45 | //create multipart using filepath, string or bytes 46 | MapEntry pic = MapEntry( 47 | key, 48 | MultipartFile.fromFileSync(value.path, 49 | filename: value.path 50 | .split('/') 51 | .last)); 52 | formData.files.add(pic); 53 | } else if ((value) is List) { 54 | List> files = []; 55 | value.forEach((element) async { 56 | MapEntry pic = MapEntry( 57 | key, 58 | MultipartFile.fromFileSync( 59 | element.path, 60 | filename: element.path 61 | .split('/') 62 | .last 63 | )); 64 | files.add(pic); 65 | }); 66 | formData.files.addAll(files); 67 | } 68 | }); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/data/repository/get_storage_repository_impl.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 20-11-21 3:41 4 | */ 5 | 6 | import 'package:get_storage/get_storage.dart'; 7 | import '../../domain/repository/get_storage_repository.dart'; 8 | 9 | class GetStorageImpl implements GetStorageRepository { 10 | final GetStorage _getStorage; 11 | 12 | GetStorageImpl(this._getStorage); 13 | 14 | @override 15 | Future erase() { 16 | return _getStorage.erase(); 17 | } 18 | 19 | @override 20 | T? read(String key) { 21 | return _getStorage.read(key); 22 | } 23 | 24 | @override 25 | bool hasData(String key) { 26 | return _getStorage.hasData(key); 27 | } 28 | 29 | @override 30 | Future remove(String key) { 31 | return _getStorage.remove(key); 32 | } 33 | 34 | @override 35 | Future write(String key, value) { 36 | return _getStorage.write(key, value); 37 | } 38 | 39 | @override 40 | Future writeIfNull(String key, value) { 41 | return _getStorage.writeIfNull(key, value); 42 | } 43 | 44 | @override 45 | void writeInMemory(String key, value) { 46 | _getStorage.writeInMemory(key, value); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/data/repository/network_info_impl.dart: -------------------------------------------------------------------------------- 1 | import 'package:connectivity_plus/connectivity_plus.dart'; 2 | import 'package:vendor/domain/repository/repository.dart'; 3 | 4 | class NetWorkInfoImpl implements NetWokInfoRepository { 5 | ConnectivityResult? _connectivityResult; 6 | 7 | Future _connect() async { 8 | _connectivityResult = await Connectivity().checkConnectivity(); 9 | } 10 | 11 | @override 12 | Future get isConnected async { 13 | await _connect(); 14 | 15 | if (_connectivityResult == ConnectivityResult.mobile) { 16 | return true; 17 | } 18 | if (_connectivityResult == ConnectivityResult.wifi) { 19 | return true; 20 | } 21 | return false; 22 | } 23 | 24 | /*@override 25 | Future> isOnline() async { 26 | try { 27 | final check = await isConnected; 28 | if (check) { 29 | return const Right(unit); 30 | } 31 | return const Left(networkConnectionError); 32 | } on Failure catch (e) { 33 | return const Left(networkConnectionError); 34 | } catch (e) { 35 | return const Left(networkConnectionError); 36 | } 37 | }*/ 38 | } 39 | -------------------------------------------------------------------------------- /lib/data/repository/repository.dart: -------------------------------------------------------------------------------- 1 | export 'get_storage_repository_impl.dart'; 2 | export 'api_provider_repository_impl.dart'; 3 | export 'network_info_impl.dart'; -------------------------------------------------------------------------------- /lib/data/usecases/dashboard_remote.dart: -------------------------------------------------------------------------------- 1 | import '../datasource/datasource.dart'; 2 | import '../../domain/usecases/usecases.dart'; 3 | 4 | class DashboardRemote implements DashboardGet { 5 | final RemoteDataSource _remoteDataSource; 6 | final SessionDataSource _sessionDataSource; 7 | 8 | DashboardRemote(this._remoteDataSource, this._sessionDataSource); 9 | 10 | @override 11 | String userNameReadSession() => _sessionDataSource.userNameRead(); 12 | } 13 | 14 | -------------------------------------------------------------------------------- /lib/data/usecases/login_remote.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:equatable/equatable.dart'; 3 | import '../../domain/model/model.dart'; 4 | import 'usecase.dart'; 5 | import '../../core/error/error.dart'; 6 | import '../datasource/datasource.dart'; 7 | 8 | 9 | class LoginParameter extends Equatable { 10 | final String? userName, password; 11 | 12 | const LoginParameter({required this.userName, required this.password}); 13 | 14 | @override 15 | List get props => [userName!, password!]; 16 | 17 | //final bodyParameter = LoginParameter.fromJson(params).toJson(); //GET JSON PARAMETER 18 | Map toJson() => {'username': userName, 'password': password}; 19 | } 20 | 21 | class LoginRemote extends UseCase { 22 | final RemoteDataSource _remoteDataSource; 23 | final SessionDataSource _sessionDataSource; 24 | 25 | LoginRemote(this._remoteDataSource, this._sessionDataSource); 26 | 27 | @override 28 | Future> call(LoginParameter parameter) async => 29 | await _remoteDataSource.login(parameter: parameter.toJson()); 30 | 31 | bool isLoginReadSession() => _sessionDataSource.isLoginRead(); 32 | 33 | void isLoginWriteSession(bool value) => 34 | _sessionDataSource.isLoginWrite(value); 35 | 36 | String userNameReadSession() => _sessionDataSource.userNameRead(); 37 | 38 | void userNameWriteSession(String value) => 39 | _sessionDataSource.userNameWrite(value); 40 | 41 | void loginInTimeWriteSession(String value) => 42 | _sessionDataSource.loginInTimeWrite(value); 43 | } 44 | -------------------------------------------------------------------------------- /lib/data/usecases/profile_remote.dart: -------------------------------------------------------------------------------- 1 | import '../datasource/datasource.dart'; 2 | import '../../domain/usecases/usecases.dart'; 3 | 4 | class ProfileRemote implements ProfileGet { 5 | final RemoteDataSource _remoteDataSource; 6 | final SessionDataSource _sessionDataSource; 7 | 8 | ProfileRemote(this._remoteDataSource, this._sessionDataSource); 9 | 10 | @override 11 | String userNameReadSession() => _sessionDataSource.userNameRead(); 12 | 13 | @override 14 | String loginInTimeReadSession() => _sessionDataSource.loginInTimeRead(); 15 | 16 | @override 17 | void logout() { 18 | _sessionDataSource.isLoginRemove(); 19 | _sessionDataSource.userNameRemove(); 20 | _sessionDataSource.loginInTimeRemove(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/data/usecases/splash_remote.dart: -------------------------------------------------------------------------------- 1 | import '../datasource/datasource.dart'; 2 | import '../../domain/usecases/usecases.dart'; 3 | 4 | class SplashRemote implements SplashGet { 5 | final SessionDataSource _sessionDataSource; 6 | 7 | SplashRemote(this._sessionDataSource); 8 | 9 | @override 10 | bool isLoginReadSession() => _sessionDataSource.isLoginRead(); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /lib/data/usecases/usecase.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import '../../core/error/error.dart'; 3 | 4 | abstract class UseCase { 5 | Future?> call(Params parameter); 6 | } -------------------------------------------------------------------------------- /lib/data/usecases/usecases.dart: -------------------------------------------------------------------------------- 1 | export 'usecase.dart'; 2 | export 'splash_remote.dart'; 3 | export 'login_remote.dart'; 4 | export 'dashboard_remote.dart'; 5 | export 'profile_remote.dart'; -------------------------------------------------------------------------------- /lib/dependency_injection.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | import 'package:dio_helper_flutter/dio_helper.dart'; 3 | import 'package:get/get.dart'; 4 | import 'package:get_storage/get_storage.dart'; 5 | import 'data/datasource/datasource.dart'; 6 | import 'data/repository/repository.dart'; 7 | import 'data/usecases/usecases.dart'; 8 | import 'domain/repository/repository.dart'; 9 | import 'domain/usecases/usecases.dart'; 10 | 11 | class DependencyInjection { 12 | static void init() { 13 | //INIT BINDING 14 | Get.lazyPut(() => GetStorage(), fenix: true); 15 | Get.lazyPut(() => DioHelper(Dio()), fenix: true); 16 | 17 | //SESSION BINDING 18 | Get.lazyPut(() => GetStorageImpl(Get.find()), fenix: true); 19 | Get.lazyPut(() => GetStorageImpl(Get.find()), fenix: true); 20 | Get.lazyPut(() => SessionDataSourceImpl(Get.find()), fenix: true); 21 | 22 | //NETWORK INFO BINDING 23 | Get.lazyPut(() => NetWorkInfoImpl(), fenix: true); 24 | Get.lazyPut(() => NetWorkInfoImpl(), fenix: true); 25 | 26 | //API BINDING 27 | Get.lazyPut(() => ApiProviderImpl(Get.find()), fenix: true); 28 | Get.lazyPut(() => ApiProviderImpl(Get.find()), fenix: true); 29 | Get.lazyPut(() => RemoteDataSourceImpl(Get.find(), Get.find()), fenix: true); 30 | 31 | //CONTROLLER PASS DATA BINDING 32 | Get.lazyPut(() => LoginRemote(Get.find(), Get.find()), fenix: true); 33 | Get.lazyPut(() => SplashRemote(Get.find()), fenix: true); 34 | Get.lazyPut(() => DashboardRemote(Get.find(), Get.find()), fenix: true); 35 | Get.lazyPut(() => ProfileRemote(Get.find(), Get.find()), fenix: true); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/domain/entity/entity.dart: -------------------------------------------------------------------------------- 1 | export 'no_params.dart'; 2 | export 'login_entity.dart'; -------------------------------------------------------------------------------- /lib/domain/entity/login_entity.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | 3 | class LoginEntity extends Equatable { 4 | final List? loginDetailList; 5 | 6 | const LoginEntity({ 7 | required this.loginDetailList, 8 | }); 9 | 10 | @override 11 | List get props { 12 | return [loginDetailList]; 13 | } 14 | 15 | @override 16 | bool get stringify => true; 17 | } 18 | 19 | class LoginDetailEntity extends Equatable { 20 | final String? userId, userName, employeeId; 21 | 22 | const LoginDetailEntity({this.userId, this.userName, this.employeeId}); 23 | 24 | @override 25 | List get props => [userId!, userName!, employeeId!]; 26 | 27 | @override 28 | bool get stringify => true; 29 | } 30 | -------------------------------------------------------------------------------- /lib/domain/entity/no_params.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | 3 | class NoParams extends Equatable { 4 | @override 5 | List get props => []; 6 | } 7 | -------------------------------------------------------------------------------- /lib/domain/model/login_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | 3 | class LoginModel extends Equatable { 4 | final List? loginDetailList; 5 | 6 | const LoginModel({ 7 | required this.loginDetailList, 8 | }); 9 | 10 | @override 11 | List get props { 12 | return [loginDetailList]; 13 | } 14 | 15 | @override 16 | bool get stringify => true; 17 | } 18 | 19 | class LoginDetailModel extends Equatable { 20 | final String? userId, userName, employeeId; 21 | 22 | const LoginDetailModel({this.userId, this.userName, this.employeeId}); 23 | 24 | @override 25 | List get props => [userId!, userName!, employeeId!]; 26 | 27 | @override 28 | bool get stringify => true; 29 | } 30 | -------------------------------------------------------------------------------- /lib/domain/model/model.dart: -------------------------------------------------------------------------------- 1 | export 'no_params.dart'; 2 | export 'login_model.dart'; -------------------------------------------------------------------------------- /lib/domain/model/no_params.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | 3 | class NoParams extends Equatable { 4 | @override 5 | List get props => []; 6 | } 7 | -------------------------------------------------------------------------------- /lib/domain/repository/api_provider_repository.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Use: CREATE API API PROVIDER REPOSITORY USE FOR CALLING CALLING API 3 | Get (getApi), Post (postApi) and Image upload formData (imageUpload) 4 | */ 5 | 6 | import 'package:dio/dio.dart' as dio; 7 | 8 | abstract class ApiProviderRepository { 9 | //GET API 10 | Future getApi(String pathUrl, {Map? queryParameter}); 11 | 12 | //POST API 13 | Future postApi(String pathUrl, 14 | {Map? queryParameters, dynamic data}); 15 | 16 | //IMAGE UPLOAD POST 17 | Future imageUpload(String pathUrl, {required dio.FormData formData}); 18 | 19 | void imageUploadMap(String pathUrl, 20 | {Map? imageUploadParameter}); 21 | } 22 | -------------------------------------------------------------------------------- /lib/domain/repository/get_storage_repository.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 20-11-21 3:41 4 | Use: Create get storage method write, writeIfNull, writeInMemory, read, hasData, remove, erase 5 | */ 6 | 7 | abstract class GetStorageRepository { 8 | //WRITE DATA ON YOUR CONTAINER 9 | Future write(String key, dynamic value); 10 | 11 | //WRITE DATA ON YOUR ONLY IF DATA IS NULL 12 | Future writeIfNull(String key, dynamic value); 13 | 14 | //WRITE IN MEMORY 15 | void writeInMemory(String key, dynamic value); 16 | 17 | //READS A VALUE IN YOUR CONTAINER WITH THE GIVEN KEY 18 | T? read(String key); 19 | 20 | //SESSION CHECK THE DATA IS AVAILABLE RETURN TRUE ELSE FALSE 21 | bool hasData(String key); 22 | 23 | //REMOVE DATA FROM CONTAINER BY KEY 24 | Future remove(String key); 25 | 26 | //CLEAR ALL DATA ON YOUR CONTAINER 27 | Future erase(); 28 | } -------------------------------------------------------------------------------- /lib/domain/repository/network_info_repository.dart: -------------------------------------------------------------------------------- 1 | abstract class NetWokInfoRepository { 2 | Future get isConnected; 3 | } -------------------------------------------------------------------------------- /lib/domain/repository/repository.dart: -------------------------------------------------------------------------------- 1 | export 'api_provider_repository.dart'; 2 | export 'get_storage_repository.dart'; 3 | export 'network_info_repository.dart'; -------------------------------------------------------------------------------- /lib/domain/usecases/dashboard_get.dart: -------------------------------------------------------------------------------- 1 | abstract class DashboardGet { 2 | //API 3 | 4 | //SESSION 5 | String userNameReadSession(); 6 | } 7 | -------------------------------------------------------------------------------- /lib/domain/usecases/profile_get.dart: -------------------------------------------------------------------------------- 1 | abstract class ProfileGet { 2 | //SESSION 3 | String userNameReadSession(); 4 | String loginInTimeReadSession(); 5 | void logout(); 6 | } 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/domain/usecases/splash_get.dart: -------------------------------------------------------------------------------- 1 | abstract class SplashGet { 2 | bool isLoginReadSession(); 3 | } 4 | -------------------------------------------------------------------------------- /lib/domain/usecases/usecases.dart: -------------------------------------------------------------------------------- 1 | export 'splash_get.dart'; 2 | export 'dashboard_get.dart'; 3 | export 'profile_get.dart'; -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio_helper_flutter/dio_helper.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:get/get.dart'; 5 | import 'package:get_storage/get_storage.dart'; 6 | import 'core/constant/url.dart'; 7 | import 'core/language/translation.dart'; 8 | import 'core/route/route_collection.dart'; 9 | import 'core/route/route_name.dart'; 10 | import 'core/theme/theme.dart'; 11 | import 'dependency_injection.dart'; 12 | import 'presentation/binding/global_binding.dart'; 13 | import 'presentation/controller/controller.dart'; 14 | 15 | void main() async { 16 | await Get.putAsync(() => GetStorage.init()); 17 | DependencyInjection.init(); 18 | 19 | SystemUiOverlayStyle systemUiOverlayStyle = 20 | const SystemUiOverlayStyle(statusBarColor: Colors.transparent); 21 | SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); 22 | 23 | APiKey.baseUrlKey = baseUrl; 24 | 25 | runApp(const MyApp()); 26 | } 27 | 28 | class MyApp extends StatelessWidget { 29 | const MyApp({Key? key}) : super(key: key); 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return GetMaterialApp( 34 | debugShowCheckedModeBanner: false, 35 | locale: SettingsController().getLocale(), 36 | themeMode: SettingsController().getThemeMode(), 37 | theme: lightTheme, 38 | darkTheme: darkTheme, 39 | translations: Translation(), 40 | fallbackLocale: const Locale('en'), 41 | initialBinding: GlobalBinding(), 42 | initialRoute: RouteName.slashRoute, //FIRST TIME WHICH LAUNCH SCREEN 43 | getPages: RouteCollection.routeCollection //COLLECTION OF ROUTES 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/presentation/binding/binding.dart: -------------------------------------------------------------------------------- 1 | export 'login_binding.dart'; 2 | export 'splash_binding.dart'; 3 | export 'home_binding.dart'; 4 | export 'visit_history_binding.dart'; 5 | export 'dashboard_binding.dart'; 6 | export 'profile_binding.dart'; -------------------------------------------------------------------------------- /lib/presentation/binding/dashboard_binding.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:get/get.dart'; 7 | import '../controller/controller.dart'; 8 | 9 | class DashboardBinding extends Bindings { 10 | @override 11 | void dependencies() => Get.lazyPut(() => DashboardController(Get.find())); 12 | } 13 | -------------------------------------------------------------------------------- /lib/presentation/binding/global_binding.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | import '../controller/controller.dart'; 3 | 4 | class GlobalBinding implements Bindings { 5 | @override 6 | void dependencies() { 7 | Get.put(SettingsController()); 8 | } 9 | } -------------------------------------------------------------------------------- /lib/presentation/binding/home_binding.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:get/get.dart'; 7 | import '../controller/controller.dart'; 8 | 9 | class HomeBinding extends Bindings { 10 | @override 11 | void dependencies() { 12 | Get.lazyPut(() => HomeController(Get.find())); 13 | Get.lazyPut(() => TotalRecordController(), fenix: false); 14 | 15 | Get.lazyPut(() => PickUpController(Get.find()), fenix: false); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/presentation/binding/login_binding.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:get/get.dart'; 7 | import '../controller/controller.dart'; 8 | 9 | class LoginBinding extends Bindings { 10 | @override 11 | void dependencies() => Get.lazyPut(() => LoginController(Get.find())); 12 | } 13 | -------------------------------------------------------------------------------- /lib/presentation/binding/profile_binding.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:get/get.dart'; 7 | import '../controller/controller.dart'; 8 | 9 | class ProfileBinding extends Bindings { 10 | @override 11 | void dependencies() => Get.lazyPut(() => ProfileController(Get.find())); 12 | } 13 | -------------------------------------------------------------------------------- /lib/presentation/binding/splash_binding.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:get/get.dart'; 7 | import '../controller/controller.dart'; 8 | 9 | class SplashBinding extends Bindings { 10 | @override 11 | void dependencies() => Get.lazyPut(() => SplashController(Get.find())); 12 | } 13 | -------------------------------------------------------------------------------- /lib/presentation/binding/visit_history_binding.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:get/get.dart'; 7 | import '../controller/controller.dart'; 8 | 9 | class VisitHistoryBinding extends Bindings { 10 | @override 11 | void dependencies() => Get.lazyPut(() => VisitHistoryController()); 12 | } 13 | -------------------------------------------------------------------------------- /lib/presentation/controller/controller.dart: -------------------------------------------------------------------------------- 1 | export 'splash_controller.dart'; 2 | export 'login_controller.dart'; 3 | export 'settings_controller.dart'; 4 | export 'home_controller.dart'; 5 | export 'total_record_controller.dart'; 6 | export 'pickup_controller.dart'; 7 | export 'visit_history_controller.dart'; 8 | export 'dashboard_controller.dart'; 9 | export 'profile_controller.dart'; -------------------------------------------------------------------------------- /lib/presentation/controller/dashboard_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | import '../../domain/usecases/usecases.dart'; 3 | 4 | class DashboardController extends GetxController { 5 | //CONSTRUCTOR 6 | final DashboardGet _dashBoardGet; 7 | DashboardController(this._dashBoardGet); 8 | 9 | var userNameRx = RxString(''); 10 | get userName => userNameRx.value; 11 | 12 | @override 13 | void onInit() { 14 | super.onInit(); 15 | userNameRx.value = _dashBoardGet.userNameReadSession(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/presentation/controller/home_controller.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:get/get.dart'; 8 | import 'total_record_controller.dart'; 9 | import '../../domain/repository/get_storage_repository.dart'; 10 | 11 | class HomeController extends GetxController with GetSingleTickerProviderStateMixin{ 12 | static HomeController get to => Get.find(); 13 | 14 | //Constructor 15 | final GetStorageRepository _getStorageRepository; 16 | HomeController(this._getStorageRepository); 17 | 18 | late final TabController tabController; 19 | 20 | final RxString _selectTabNameRx = 'pickUp'.tr.obs; 21 | get selectTabName => _selectTabNameRx.value; 22 | 23 | final RxInt _selectTotalRecordRx = 0.obs; 24 | get selectTotalRecord => _selectTotalRecordRx.value; 25 | 26 | @override 27 | void onInit() { 28 | super.onInit(); 29 | tabController = TabController(length: 2, vsync: this); 30 | 31 | tabController.addListener(_tabSelection); 32 | } 33 | 34 | _tabSelection() { 35 | switch (tabController.index) { 36 | case 0: 37 | selectTotalRecordGet(0); 38 | _selectTabNameRx.value = 'pickUp'.tr; 39 | break; 40 | case 1: 41 | selectTotalRecordGet(1); 42 | _selectTabNameRx.value = 'return'.tr; 43 | break; 44 | case 2: 45 | selectTotalRecordGet(2); 46 | _selectTabNameRx.value = 'postpone'.tr; 47 | break; 48 | } 49 | } 50 | 51 | selectTotalRecordGet(int index) { 52 | _selectTotalRecordRx.value = TotalRecordController.to.selectTabTotalData[index]; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/presentation/controller/login_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import '../ui/widget/widget.dart'; 4 | import '../../core/constant/constant.dart'; 5 | import '../../core/route/route_name.dart'; 6 | import '../../data/usecases/login_remote.dart'; 7 | import '../../core/extensions/extensions.dart'; 8 | 9 | class LoginController extends GetxController { 10 | //CONSTRUCTOR 11 | final LoginRemote _loginRemote; 12 | LoginController(this._loginRemote); 13 | 14 | //FORM KEY USE FOR VALIDATION 15 | final formKey = GlobalKey(); 16 | 17 | //TEXT EDITING CONTROLLER INIT AND GET 18 | late TextEditingController passwordController = TextEditingController(); 19 | String get password => passwordController.text; 20 | 21 | late TextEditingController userNameController = TextEditingController(); 22 | String get userName => userNameController.text; 23 | 24 | final IconButtonController loginButtonController = IconButtonController(); 25 | 26 | final FocusNode userNameFocusNode = FocusNode(); 27 | final FocusNode passwordFocusNode = FocusNode(); 28 | 29 | //PASSWORD VISIBLE OR NOT 30 | final RxBool _isPasswordVisibleRx = RxBool(false); 31 | bool get isPasswordVisible => _isPasswordVisibleRx.value; 32 | 33 | Future _loginGetData() async { 34 | loginButtonController.showProgress(); 35 | 36 | final loginEither = await _loginRemote 37 | .call(LoginParameter(userName: userName, password: password)); 38 | 39 | loginEither.fold((error) { 40 | //ERROR RESPONSE 41 | loginButtonController.error(); 42 | Future.delayed(const Duration(seconds: 1), () { 43 | loginButtonController.reset(); 44 | }); 45 | 46 | passwordController.clear(); 47 | 48 | switch (error.code) { 49 | case notFound: 50 | toast(title: error.title, message: notFoundMessage); 51 | break; 52 | default: 53 | toast(title: error.title, message: error.message!); 54 | } 55 | }, (response) async { 56 | loginButtonController.success(); 57 | loginButtonController.reset(); 58 | 59 | //SUCCESS RESPONSE 60 | if (response.loginDetailList!.isNotEmpty) { 61 | var loginDetail = response.loginDetailList?.first; 62 | 63 | //SESSION STORE 64 | _loginRemote.userNameWriteSession(loginDetail!.userName!); 65 | _loginRemote.loginInTimeWriteSession('${DateTime.now()}'); 66 | _loginRemote.isLoginWriteSession(true); 67 | 68 | //LOGIN SUCCESS NAVIGATION 69 | Get.offAllNamed(RouteName.dashboardRoute); 70 | } 71 | }); 72 | } 73 | 74 | passwordVisibleChange(bool value) { 75 | _isPasswordVisibleRx.value = !value; 76 | } 77 | 78 | //VALIDATION 79 | loginValidate() { 80 | switch (formKey.currentState!.validate()) { 81 | case true: 82 | formKey.currentState!.save(); 83 | _loginGetData(); 84 | break; 85 | } 86 | } 87 | 88 | loginWithMobileNavigation() { 89 | FocusScope.of(Get.context!).requestFocus(FocusNode()); 90 | Get.toNamed(RouteName.loginMobileRoute); 91 | } 92 | 93 | @override 94 | void onClose() { 95 | userNameController.dispose(); 96 | passwordController.dispose(); 97 | super.onClose(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/presentation/controller/pickup_controller.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | 5 | UPDATE DETAIL 6 | - 24-11-21 03:41 (Lakhani kamlesh) 7 | - PICK UP CONTROLLER CREATE AND CALLING THE API. 8 | */ 9 | 10 | import 'package:get/get.dart'; 11 | import '../../domain/repository/get_storage_repository.dart'; 12 | 13 | class PickUpController extends GetxController { 14 | //Constructor 15 | final GetStorageRepository _getStorageRepository; 16 | 17 | PickUpController(this._getStorageRepository); 18 | } 19 | -------------------------------------------------------------------------------- /lib/presentation/controller/profile_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | import '../../core/route/route_name.dart'; 3 | import '../../domain/usecases/usecases.dart'; 4 | 5 | class ProfileController extends GetxController { 6 | //CONSTRUCTOR 7 | final ProfileGet _profileGet; 8 | ProfileController(this._profileGet); 9 | 10 | final _userNameRx = RxString(''); 11 | get userName => _userNameRx.value; 12 | 13 | final _loginInTimeRx = RxString(''); 14 | get loginInTime => _loginInTimeRx.value; 15 | 16 | @override 17 | void onInit() { 18 | super.onInit(); 19 | _userNameRx.value = _profileGet.userNameReadSession(); 20 | _loginInTimeRx.value = _profileGet.loginInTimeReadSession(); 21 | } 22 | 23 | logout(){ 24 | _profileGet.logout(); 25 | Get.offAllNamed(RouteName.loginUserNameRoute); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/presentation/controller/settings_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import 'package:get_storage/get_storage.dart'; 4 | import '../../core/constant/global_data.dart'; 5 | 6 | class SettingsController extends GetxController { 7 | final GetStorage _getStorage = GetStorage(); 8 | 9 | //Rx variables 10 | RxInt currentTheme = 2.obs; 11 | RxString language = 'en'.obs; 12 | 13 | //keys variables 14 | final String themeKey = 'theme'; 15 | final String languageKey = 'language'; 16 | 17 | //constrictor 18 | SettingsController() { 19 | currentTheme.value = _getStorage.read(themeKey) ?? 2; 20 | language.value = _getStorage.read(languageKey) ?? 'ar'; 21 | } 22 | 23 | //theme mode functions 24 | ThemeMode getThemeMode() => themes[_getThemeValue()]['value']; 25 | 26 | int _getThemeValue() { 27 | return _getStorage.read(themeKey) ?? 2; 28 | } 29 | 30 | changeCurrentTheme(int value, ThemeMode themeMode) { 31 | Get.changeThemeMode(themeMode); 32 | currentTheme.value = value; 33 | _getStorage.write(themeKey, value); 34 | } 35 | 36 | //language functions 37 | Locale getLocale() => Locale(_getLanguageValue()); 38 | 39 | String _getLanguageValue() { 40 | return _getStorage.read(languageKey) ?? 'en'; 41 | } 42 | 43 | changeLanguage(String value) { 44 | language.value = value; 45 | Get.updateLocale(Locale(value)); 46 | _getStorage.write(languageKey, value); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/presentation/controller/splash_controller.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 22-OCT-21 09:41 4 | 5 | UPDATE DETAIL 6 | - 04-FEB-22 11:11 (Lakhani kamlesh) 7 | Splash controller create. 8 | */ 9 | 10 | import 'package:get/get.dart'; 11 | import '../../core/route/route_name.dart'; 12 | import '../../domain/usecases/usecases.dart'; 13 | 14 | class SplashController extends GetxController { 15 | //CONSTRUCTOR 16 | final SplashGet _splashGet; 17 | SplashController(this._splashGet); 18 | 19 | late String? appName; 20 | 21 | @override 22 | void onInit() { 23 | super.onInit(); 24 | appName = 'Clean Architecture'; 25 | 26 | _splashGet.isLoginReadSession() 27 | ? _loginNavigation() 28 | : _withOutLoginNavigation(); 29 | } 30 | 31 | _withOutLoginNavigation() async => 32 | await Future.delayed(const Duration(seconds: 3)).then((value) { 33 | Get.offAllNamed(RouteName.loginUserNameRoute); 34 | }); 35 | 36 | _loginNavigation() async => 37 | await Future.delayed(const Duration(seconds: 1)).then((value) { 38 | Get.offAllNamed(RouteName.dashboardRoute); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /lib/presentation/controller/total_record_controller.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:get/get.dart'; 7 | 8 | class TotalRecordController extends GetxController { 9 | static TotalRecordController get to => Get.find(); 10 | 11 | final RxList _selectTabTotalDataRx = RxList([3]); 12 | List get selectTabTotalData => _selectTabTotalDataRx; 13 | 14 | @override 15 | void onInit() { 16 | super.onInit(); 17 | _selectTabTotalDataRx.value = [00, 00, 00]; 18 | } 19 | 20 | totalData(int index, int length) { 21 | _selectTabTotalDataRx[index] = length; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/presentation/controller/visit_history_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | import 'package:intl/intl.dart'; 3 | 4 | class VisitHistoryController extends GetxController{ 5 | String startDateTime = DateFormat('dd-MM-yyyy').format(DateTime.now()); 6 | String endDateTime = DateFormat('dd-MM-yyyy').format(DateTime.now()); 7 | 8 | } -------------------------------------------------------------------------------- /lib/presentation/ui/page/history_page.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:get/get.dart'; 8 | import '../../../core/assets/assets.dart'; 9 | import '../../controller/controller.dart'; 10 | import '../../../core/theme/color.dart'; 11 | import '../widget/form_button_component.dart'; 12 | 13 | class HistoryPage extends GetView { 14 | const HistoryPage({Key? key}) : super(key: key); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return Scaffold( 19 | appBar: AppBar( 20 | title: Text('Visit History', 21 | style: Get.textTheme.headline4!.copyWith(color: whiteColor)), 22 | backgroundColor: Get.theme.primaryColor, 23 | leading: IconButton( 24 | icon: const Icon(arrowLefAndroidIcon), onPressed: () => Get.back()), 25 | elevation: 0), 26 | body: Padding( 27 | padding: const EdgeInsets.all(10), 28 | child: 29 | Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ 30 | Card( 31 | child: ListTile( 32 | onTap: () {}, 33 | leading: const Icon(dateIcon), 34 | trailing: Icon(selectIcon, 35 | color: context.theme.colorScheme.secondary), 36 | title: Text('select start date', 37 | style: context.textTheme.headline6! 38 | .merge(const TextStyle(fontSize: 12))), 39 | subtitle: Text(controller.startDateTime, 40 | style: context.textTheme.bodyText1! 41 | .merge(const TextStyle(fontSize: 14))))), 42 | Card( 43 | child: ListTile( 44 | onTap: () {}, 45 | leading: const Icon(dateIcon), 46 | trailing: Icon(selectIcon, 47 | color: context.theme.colorScheme.secondary), 48 | title: Text('Select end date', 49 | style: context.textTheme.headline6! 50 | .merge(const TextStyle(fontSize: 12))), 51 | subtitle: Text(controller.endDateTime, 52 | style: context.textTheme.bodyText1! 53 | .merge(const TextStyle(fontSize: 14))))), 54 | FormButtonComponent( 55 | onPressed: () {}, 56 | color: Get.theme.colorScheme.secondary, 57 | text: Text('Submit', 58 | style: Get.textTheme.headline2! 59 | .copyWith(color: whiteColor, fontSize: 14)), 60 | ).paddingSymmetric(vertical: 10.0, horizontal: 0.0) 61 | ]))); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/home_page.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:get/get.dart'; 8 | import 'page.dart'; 9 | import '../../controller/controller.dart'; 10 | import '../../../core/assets/assets.dart'; 11 | 12 | class HomePage extends GetView { 13 | const HomePage({Key? key}) : super(key: key); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Scaffold( 18 | body: NestedScrollView( 19 | floatHeaderSlivers: true, 20 | headerSliverBuilder: (context, innerBoxIsScrolled) { 21 | return [ 22 | SliverOverlapAbsorber( 23 | handle: NestedScrollView.sliverOverlapAbsorberHandleFor( 24 | context), 25 | sliver: SliverSafeArea( 26 | top: false, 27 | sliver: SliverAppBar( 28 | backgroundColor: Get.theme.primaryColor, 29 | floating: true, 30 | pinned: true, 31 | snap: true, 32 | leading: IconButton( 33 | icon: const Icon(arrowLefAndroidIcon), 34 | onPressed: () => Get.back()), 35 | automaticallyImplyLeading: true, 36 | forceElevated: innerBoxIsScrolled, 37 | elevation: 0, 38 | bottom: _buildHomeTabBar()))) 39 | ]; 40 | }, 41 | body: Expanded( 42 | child: TabBarView( 43 | controller: controller.tabController, 44 | children: [PickUpPage(), ReturnPage()])))); 45 | } 46 | 47 | _buildHomeTabBar() { 48 | return TabBar( 49 | controller: controller.tabController, 50 | indicator: const UnderlineTabIndicator( 51 | insets: EdgeInsets.symmetric(horizontal: 12), 52 | borderSide: BorderSide( 53 | color: Color(0xffFFFFFF), 54 | width: 2.0, 55 | style: BorderStyle.solid)), 56 | indicatorPadding: const EdgeInsets.only(left: 1, right: 1), 57 | tabs: ['Pick up', 'Return'].map((e) => Tab(child: Text(e))).toList(), 58 | labelColor: const Color(0xffFFFFFF), 59 | unselectedLabelColor: Colors.white70, 60 | labelStyle: Get.textTheme.headline1!.copyWith(fontSize: 16)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/list_device_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:get/get.dart'; 5 | import 'package:line_icons/line_icons.dart'; 6 | import '../widget/category_list_item.dart'; 7 | import '../../../core/assets/assets.dart'; 8 | import '../../../core/route/route_name.dart'; 9 | import '../../../core/theme/color.dart'; 10 | 11 | class ListDevicePage extends StatelessWidget { 12 | const ListDevicePage({Key? key}) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return AnnotatedRegion( 17 | value: SystemUiOverlayStyle.dark, 18 | child: Scaffold( 19 | appBar: AppBar( 20 | leading: IconButton( 21 | icon: const Icon(arrowLefAndroidIcon), 22 | onPressed: () => Get.back()), 23 | actions: [ 24 | PopupMenuButton( 25 | onSelected: (result) { 26 | //RESULT IT GIVES THE VALUE WHICH IS SELECTED 27 | switch (result) { 28 | case 1: 29 | Get.toNamed(RouteName.newVendorAddRoute); 30 | break; 31 | 32 | case 2: 33 | Get.toNamed(RouteName.newDeviceAddRoute); 34 | break; 35 | 36 | case 3: 37 | Get.toNamed(RouteName.vendorVisitRoute); 38 | break; 39 | } 40 | }, 41 | itemBuilder: (context) => [ 42 | PopupMenuItem( 43 | child: Text('Add new dealer', 44 | style: context.textTheme.headline1! 45 | .copyWith(fontSize: 14)), 46 | value: 1), 47 | PopupMenuItem( 48 | child: Text('Add new device', 49 | style: context.textTheme.headline1! 50 | .copyWith(fontSize: 14)), 51 | value: 2), 52 | PopupMenuItem( 53 | child: Text('Vendor visit', 54 | style: context.textTheme.headline1! 55 | .copyWith(fontSize: 14)), 56 | value: 3) 57 | ]) 58 | ], 59 | backgroundColor: Get.theme.primaryColor, 60 | elevation: 0, 61 | title: Text('Listing', 62 | style: 63 | Get.textTheme.headline4!.copyWith(color: whiteColor))), 64 | bottomNavigationBar: Container( 65 | padding: const EdgeInsets.all(10), 66 | height: 60, 67 | color: Colors.grey.withOpacity(0.1), 68 | child: Row( 69 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 70 | children: [ 71 | Text('SELECT ALL', 72 | style: Get.textTheme.headline3! 73 | .copyWith(fontSize: 14)) 74 | .paddingAll(8), 75 | Row(children: [ 76 | InkWell( 77 | onTap: () { 78 | _soldAvailableAll(context, staus: 'sold all'); 79 | }, 80 | child: Container( 81 | width: 80, 82 | padding: const EdgeInsets.only( 83 | top: 3, bottom: 3, right: 5, left: 5), 84 | decoration: BoxDecoration( 85 | color: Colors.red.withOpacity(0.1), 86 | border: Border.all(color: Colors.red), 87 | borderRadius: const BorderRadius.all( 88 | Radius.circular(15))), 89 | child: Text('SOLD ALL', 90 | textAlign: TextAlign.center, 91 | style: Get.textTheme.headline1!.copyWith( 92 | fontSize: 12, color: Colors.red)))), 93 | const SizedBox(width: 10.0), 94 | InkWell( 95 | onTap: () { 96 | _soldAvailableAll(context, 97 | staus: 'available all'); 98 | }, 99 | child: Container( 100 | width: 110, 101 | padding: const EdgeInsets.only( 102 | top: 3, bottom: 3, right: 5, left: 5), 103 | decoration: BoxDecoration( 104 | color: Colors.green.withOpacity(0.1), 105 | border: Border.all(color: Colors.green), 106 | borderRadius: const BorderRadius.all( 107 | Radius.circular(15))), 108 | child: Text('AVAILABLE ALL', 109 | textAlign: TextAlign.center, 110 | style: Get.textTheme.bodyText1!.copyWith( 111 | fontSize: 12, color: Colors.green)))), 112 | ]) 113 | ])), 114 | body: Column(children: [ 115 | Container( 116 | padding: const EdgeInsets.all(10), 117 | decoration: BoxDecoration( 118 | borderRadius: BorderRadius.circular(16.0), 119 | boxShadow: [ 120 | BoxShadow( 121 | color: Colors.deepOrange.withOpacity(0.23), 122 | offset: const Offset(0, 10), 123 | blurRadius: 50) 124 | ]), 125 | child: Row( 126 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 127 | children: [ 128 | Row(children: [ 129 | Icon(LineIcons.user, 130 | size: 18, color: Get.theme.focusColor), 131 | const SizedBox(width: 7.0), 132 | Column( 133 | crossAxisAlignment: CrossAxisAlignment.start, 134 | children: [ 135 | Text('Select vendor', 136 | style: context.textTheme.bodyText2), 137 | Text('No select vendor', 138 | style: context.textTheme.caption) 139 | ]).paddingAll(5.0) 140 | ]), 141 | Row(children: [ 142 | InkWell( 143 | customBorder: const CircleBorder(), 144 | child: CircleAvatar( 145 | backgroundColor: Get.theme.primaryColor, 146 | radius: 15, 147 | child: const Icon(LineIcons.searchLocation, 148 | size: 18, color: whiteColor)), 149 | onTap: () {}), 150 | const SizedBox(width: 5.0) 151 | ]) 152 | ])), 153 | const SizedBox(height: 10), 154 | Container( 155 | margin: const EdgeInsets.symmetric(horizontal: 20), 156 | padding: const EdgeInsets.symmetric(horizontal: 20), 157 | alignment: Alignment.center, 158 | height: 46, 159 | decoration: BoxDecoration( 160 | color: Colors.white, 161 | borderRadius: BorderRadius.circular(16.0), 162 | boxShadow: [ 163 | BoxShadow( 164 | color: Colors.deepOrange.withOpacity(0.23), 165 | offset: const Offset(0, 10), 166 | blurRadius: 50) 167 | ]), 168 | child: Row( 169 | crossAxisAlignment: CrossAxisAlignment.center, 170 | children: [ 171 | const Icon(LineIcons.search, color: Colors.deepOrange), 172 | const SizedBox(width: 10.0), 173 | Expanded( 174 | child: TextField( 175 | onChanged: (value) {}, 176 | decoration: InputDecoration( 177 | hintText: 'Search', 178 | hintStyle: TextStyle( 179 | color: Colors.black.withOpacity(0.5), 180 | ), 181 | enabledBorder: InputBorder.none, 182 | focusedBorder: InputBorder.none))) 183 | ])), 184 | const SizedBox(height: 15), 185 | Expanded( 186 | child: ListView.builder( 187 | itemCount: 5, 188 | itemBuilder: (BuildContext context, int index) { 189 | return CategoryListItem( 190 | key: PageStorageKey('ListDevice$index'), 191 | restorationId: 'home_material_category_list', 192 | initiallyExpanded: false, 193 | onTapAvailable: () { 194 | Get.toNamed(RouteName.qrCodeScannerRoute); 195 | }, 196 | onTapSold: () {}, 197 | onTapEdit: (shouldOpenList) {}); 198 | })) 199 | ]))); 200 | } 201 | 202 | _soldAvailableAll(BuildContext context, {String? staus}) { 203 | Get.dialog(CupertinoAlertDialog( 204 | title: Text(staus!.toUpperCase(), 205 | style: Get.textTheme.headline5!.copyWith(fontSize: 12)), 206 | content: Text('Are you sure $staus mobile?', 207 | style: Get.textTheme.bodyText1!), 208 | actions: [ 209 | CupertinoDialogAction( 210 | isDefaultAction: true, 211 | onPressed: () { 212 | Get.back(); 213 | }, 214 | child: Text('CANCEL', 215 | style: Get.textTheme.headline6!.copyWith(fontSize: 14))), 216 | CupertinoDialogAction( 217 | isDefaultAction: true, 218 | onPressed: () {}, 219 | child: Text(staus.toUpperCase(), 220 | style: Get.textTheme.headline5!.copyWith(fontSize: 14))) 221 | ])); 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/login_mobile_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import 'package:vendor/core/assets/icon.dart'; 4 | import '../../../core/route/route_name.dart'; 5 | import '../../../core/theme/color.dart'; 6 | import '../widget/form_button_component.dart'; 7 | import '../widget/text_field_component.dart'; 8 | 9 | class LoginMobilePage extends StatelessWidget { 10 | const LoginMobilePage({Key? key}) : super(key: key); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Scaffold( 15 | appBar: AppBar( 16 | centerTitle: true, 17 | backgroundColor: Colors.transparent, 18 | automaticallyImplyLeading: false, 19 | leading: IconButton( 20 | icon: Icon(arrowLefAndroidIcon, color: Get.theme.hintColor), 21 | onPressed: () => Get.back()), 22 | elevation: 0), 23 | body: SingleChildScrollView( 24 | child: Column(children: [ 25 | SizedBox(height: Get.height / 10), 26 | Text('Clean Architecture', 27 | style: Get.textTheme.headline5! 28 | .copyWith(color: Get.theme.primaryColor, fontSize: 22)), 29 | const SizedBox(height: 50), 30 | Text('Please sign in continues...', 31 | style: Get.textTheme.caption!.copyWith(fontSize: 14)), 32 | const SizedBox(height: 15), 33 | const TextFieldComponent(labelText: 'Mobile'), 34 | const SizedBox(height: 5), 35 | _submitButtonWidget(), 36 | Align( 37 | alignment: Alignment.topRight, 38 | child: InkWell( 39 | child: Text('Back', 40 | style: 41 | Get.textTheme.headline3!.copyWith(fontSize: 14)) 42 | .paddingOnly(top: 5, bottom: 5, left: 3, right: 3), 43 | onTap: () { 44 | Get.back(); 45 | })) 46 | ]).paddingAll(15))); 47 | } 48 | 49 | _submitButtonWidget() => FormButtonComponent( 50 | onPressed: () { 51 | Get.toNamed(RouteName.otpVerifyRoute); 52 | }, 53 | color: Get.theme.primaryColor, 54 | text: Text('SUBMIT', 55 | style: Get.textTheme.headline2! 56 | .copyWith(color: whiteColor, fontSize: 14)), 57 | ).paddingSymmetric(vertical: 10.0); 58 | } 59 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/login_username_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import 'package:line_icons/line_icons.dart'; 4 | import '../widget/widget.dart'; 5 | import '../../controller/controller.dart'; 6 | 7 | class LoginUserNamePage extends GetView { 8 | const LoginUserNamePage({Key? key}) : super(key: key); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return Scaffold( 13 | body: SingleChildScrollView( 14 | child: Form( 15 | key: controller.formKey, 16 | child: Column(children: [ 17 | SizedBox(height: Get.height / 4), 18 | Text('Clean Architecture', 19 | style: Get.textTheme.headline5!.copyWith( 20 | color: Get.theme.primaryColor, fontSize: 22)), 21 | const SizedBox(height: 50), 22 | Text('Please sign in continues...', 23 | style: Get.textTheme.caption!.copyWith(fontSize: 14)), 24 | const SizedBox(height: 15), 25 | TextFieldComponent( 26 | labelText: 'Username', 27 | focusNode: controller.userNameFocusNode, 28 | textInputAction: TextInputAction.next, 29 | maxLength: 50, 30 | controller: controller.userNameController), 31 | const SizedBox(height: 15), 32 | Obx(() => TextFieldComponent( 33 | labelText: 'Password', 34 | focusNode: controller.passwordFocusNode, 35 | textInputAction: TextInputAction.done, 36 | obscureText: controller.isPasswordVisible, 37 | maxLength: 10, 38 | suffixIcon: IconButton( 39 | onPressed: () { 40 | controller.passwordVisibleChange( 41 | controller.isPasswordVisible); 42 | }, 43 | icon: Icon(controller.isPasswordVisible 44 | ? LineIcons.eyeSlashAlt 45 | : LineIcons.eyeAlt)), 46 | controller: controller.passwordController)), 47 | const SizedBox(height: 15), 48 | _loginButtonWidget(context), 49 | const SizedBox(height: 15), 50 | Align( 51 | alignment: Alignment.topRight, 52 | child: InkWell( 53 | child: Text('Login with mobile', 54 | style: Get.textTheme.headline3! 55 | .copyWith(fontSize: 14)) 56 | .paddingOnly( 57 | top: 5, bottom: 5, left: 3, right: 3), 58 | onTap: () { 59 | FocusScope.of(context).requestFocus(FocusNode()); 60 | controller.loginWithMobileNavigation(); 61 | })) 62 | ])).paddingAll(15))); 63 | } 64 | 65 | _loginButtonWidget(BuildContext? context) => FormIconLoadingComponent( 66 | height: 45, 67 | elevation: 0, 68 | spaceBetween: 20, 69 | color: Get.theme.primaryColor, 70 | iconColor: Colors.white, 71 | valueColor: Get.theme.primaryColor, 72 | errorColor: const Color(0xffe0333c), 73 | loaderSize: 45, 74 | successColor: Get.theme.primaryColor, 75 | child: const Text('SUBMIT'), 76 | iconData: LineIcons.lock, 77 | borderRadius: 20.0, 78 | failedIcon: LineIcons.infoCircle, 79 | onPressed: () { 80 | FocusScope.of(context!).requestFocus(FocusNode()); 81 | controller.loginValidate(); 82 | }, 83 | successIcon: LineIcons.check, 84 | controller: controller.loginButtonController, 85 | ); 86 | } 87 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/new_device_add.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:get/get.dart'; 4 | import 'package:line_icons/line_icons.dart'; 5 | import '../../../core/assets/assets.dart'; 6 | import '../../../core/route/route_name.dart'; 7 | import '../../../core/theme/color.dart'; 8 | import '../widget/form_button_component.dart'; 9 | import '../widget/text_field_search_component.dart'; 10 | 11 | class NewDevicePage extends StatelessWidget { 12 | const NewDevicePage({Key? key}) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return AnnotatedRegion( 17 | value: SystemUiOverlayStyle.dark, 18 | child: Scaffold( 19 | appBar: AppBar( 20 | leading: IconButton( 21 | icon: const Icon(arrowLefAndroidIcon), 22 | onPressed: () => Get.back()), 23 | backgroundColor: Get.theme.primaryColor, 24 | elevation: 0, 25 | title: Text('Add new device', 26 | style: 27 | Get.textTheme.headline4!.copyWith(color: whiteColor))), 28 | body: Column(children: [ 29 | Container( 30 | color: Colors.grey.withOpacity(0.1), 31 | padding: const EdgeInsets.all(15), 32 | child: Column(children: [ 33 | Row(children: [ 34 | const Expanded( 35 | child: TextFieldSearchComponent( 36 | labelText: 'Find device')), 37 | const SizedBox(width: 7.0), 38 | Container( 39 | width: 100, 40 | height: 35, 41 | padding: const EdgeInsets.only( 42 | top: 3, bottom: 3, right: 5, left: 5), 43 | decoration: const BoxDecoration( 44 | color: whiteColor, 45 | borderRadius: 46 | BorderRadius.all(Radius.circular(15))), 47 | child: Center( 48 | child: Text('FIND DEVICE', 49 | style: Get.textTheme.headline5! 50 | .copyWith(fontSize: 12)))) 51 | ]), 52 | const SizedBox(height: 15), 53 | Container( 54 | height: 35, 55 | padding: const EdgeInsets.only( 56 | top: 3, bottom: 3, right: 5, left: 5), 57 | decoration: BoxDecoration( 58 | color: Colors.grey.shade300, 59 | borderRadius: 60 | const BorderRadius.all(Radius.circular(15))), 61 | child: Center( 62 | child: Text('GET THE MOBILE DETAIL FROM CAMERA', 63 | style: Get.textTheme.headline5! 64 | .copyWith(fontSize: 12)))) 65 | ])), 66 | Expanded( 67 | child: SingleChildScrollView( 68 | child: Column(children: [ 69 | Container( 70 | decoration: BoxDecoration( 71 | border: Border.all(color: Colors.grey, width: 1.0), 72 | borderRadius: 73 | const BorderRadius.all(Radius.circular(10.0))), 74 | padding: const EdgeInsets.all(5), 75 | child: Row( 76 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 77 | children: [ 78 | Column( 79 | crossAxisAlignment: CrossAxisAlignment.start, 80 | children: [ 81 | Text('Select make', 82 | style: Get.textTheme.bodyText2), 83 | Text('No select make', 84 | style: Get.textTheme.caption) 85 | ]).paddingAll(5.0), 86 | Icon(LineIcons.angleDown, 87 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 88 | ])), 89 | const SizedBox(height: 10), 90 | Container( 91 | padding: const EdgeInsets.all(5), 92 | decoration: BoxDecoration( 93 | border: Border.all(color: Colors.grey, width: 1.0), 94 | borderRadius: 95 | const BorderRadius.all(Radius.circular(10.0))), 96 | child: Row( 97 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 98 | children: [ 99 | Column( 100 | crossAxisAlignment: CrossAxisAlignment.start, 101 | children: [ 102 | Text('Select mapper', 103 | style: Get.textTheme.bodyText2), 104 | Text('No select mapper', 105 | style: Get.textTheme.caption) 106 | ]).paddingAll(5.0), 107 | Icon(LineIcons.angleDown, 108 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 109 | ])), 110 | const SizedBox(height: 10), 111 | Container( 112 | padding: const EdgeInsets.all(5), 113 | decoration: BoxDecoration( 114 | border: Border.all(color: Colors.grey, width: 1.0), 115 | borderRadius: 116 | const BorderRadius.all(Radius.circular(10.0))), 117 | child: Row( 118 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 119 | children: [ 120 | Column( 121 | crossAxisAlignment: CrossAxisAlignment.start, 122 | children: [ 123 | Text('Select ram', 124 | style: Get.textTheme.bodyText2), 125 | Text('No select ram', 126 | style: Get.textTheme.caption) 127 | ]).paddingAll(5.0), 128 | Icon(LineIcons.angleDown, 129 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 130 | ])), 131 | const SizedBox(height: 10), 132 | Container( 133 | padding: const EdgeInsets.all(5), 134 | decoration: BoxDecoration( 135 | border: Border.all(color: Colors.grey, width: 1.0), 136 | borderRadius: 137 | const BorderRadius.all(Radius.circular(10.0))), 138 | child: Row( 139 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 140 | children: [ 141 | Column( 142 | crossAxisAlignment: CrossAxisAlignment.start, 143 | children: [ 144 | Text('Select rom', 145 | style: Get.textTheme.bodyText2), 146 | Text('No select rom', 147 | style: Get.textTheme.caption) 148 | ]).paddingAll(5.0), 149 | Icon(LineIcons.angleDown, 150 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 151 | ])), 152 | const SizedBox(height: 10), 153 | Container( 154 | padding: const EdgeInsets.all(5), 155 | decoration: BoxDecoration( 156 | border: Border.all(color: Colors.grey, width: 1.0), 157 | borderRadius: 158 | const BorderRadius.all(Radius.circular(10.0))), 159 | child: Row( 160 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 161 | children: [ 162 | Column( 163 | crossAxisAlignment: CrossAxisAlignment.start, 164 | children: [ 165 | Text('Select color', 166 | style: Get.textTheme.bodyText2), 167 | Text('No select color', 168 | style: Get.textTheme.caption) 169 | ]).paddingAll(5.0), 170 | Icon(LineIcons.angleDown, 171 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 172 | ])), 173 | const SizedBox(height: 10), 174 | Container( 175 | padding: const EdgeInsets.all(5), 176 | decoration: BoxDecoration( 177 | border: Border.all(color: Colors.grey, width: 1.0), 178 | borderRadius: 179 | const BorderRadius.all(Radius.circular(10.0))), 180 | child: Row( 181 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 182 | children: [ 183 | Column( 184 | crossAxisAlignment: CrossAxisAlignment.start, 185 | children: [ 186 | Text('Select vendor', 187 | style: Get.textTheme.bodyText2), 188 | Text('No select vendor', 189 | style: Get.textTheme.caption) 190 | ]).paddingAll(5.0), 191 | Icon(LineIcons.angleDown, 192 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 193 | ])), 194 | const SizedBox(height: 10), 195 | Container( 196 | padding: const EdgeInsets.all(5), 197 | decoration: BoxDecoration( 198 | border: Border.all(color: Colors.grey, width: 1.0), 199 | borderRadius: 200 | const BorderRadius.all(Radius.circular(10.0))), 201 | child: Row( 202 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 203 | children: [ 204 | Column( 205 | crossAxisAlignment: CrossAxisAlignment.start, 206 | children: [ 207 | Text('Select stock', 208 | style: Get.textTheme.bodyText2), 209 | Text('No select stock', 210 | style: Get.textTheme.caption) 211 | ]).paddingAll(5.0), 212 | Icon(LineIcons.angleDown, 213 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 214 | ])), 215 | const SizedBox(height: 10), 216 | Container( 217 | padding: const EdgeInsets.all(5), 218 | decoration: BoxDecoration( 219 | border: Border.all(color: Colors.grey, width: 1.0), 220 | borderRadius: 221 | const BorderRadius.all(Radius.circular(10.0))), 222 | child: Row( 223 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 224 | children: [ 225 | Column( 226 | crossAxisAlignment: CrossAxisAlignment.start, 227 | children: [ 228 | Text('rate', style: Get.textTheme.bodyText2), 229 | Text('No select rate', 230 | style: Get.textTheme.caption) 231 | ]).paddingAll(5.0), 232 | Icon(LineIcons.angleDown, 233 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 234 | ])), 235 | const SizedBox(height: 10), 236 | Container( 237 | padding: const EdgeInsets.all(5), 238 | decoration: BoxDecoration( 239 | border: Border.all(color: Colors.grey, width: 1.0), 240 | borderRadius: 241 | const BorderRadius.all(Radius.circular(10.0))), 242 | child: Row( 243 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 244 | children: [ 245 | Column( 246 | crossAxisAlignment: CrossAxisAlignment.start, 247 | children: [ 248 | Text('Vendor name', 249 | style: Get.textTheme.bodyText2), 250 | Text('No select vendor name', 251 | style: Get.textTheme.caption) 252 | ]).paddingAll(5.0), 253 | Icon(LineIcons.angleDown, 254 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 255 | ])), 256 | const SizedBox(height: 10), 257 | Container( 258 | padding: const EdgeInsets.all(5), 259 | decoration: BoxDecoration( 260 | border: Border.all(color: Colors.grey, width: 1.0), 261 | borderRadius: 262 | const BorderRadius.all(Radius.circular(10.0))), 263 | child: Row( 264 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 265 | children: [ 266 | Column( 267 | crossAxisAlignment: CrossAxisAlignment.start, 268 | children: [ 269 | Text('Invoice', style: Get.textTheme.bodyText2), 270 | Text('No select invoice', 271 | style: Get.textTheme.caption) 272 | ]).paddingAll(5.0), 273 | Icon(LineIcons.angleDown, 274 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 275 | ])), 276 | const SizedBox(height: 10), 277 | Container( 278 | padding: const EdgeInsets.all(5), 279 | decoration: BoxDecoration( 280 | border: Border.all(color: Colors.grey, width: 1.0), 281 | borderRadius: 282 | const BorderRadius.all(Radius.circular(10.0))), 283 | child: Row( 284 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 285 | children: [ 286 | Column( 287 | crossAxisAlignment: CrossAxisAlignment.start, 288 | children: [ 289 | Text('Box', style: Get.textTheme.bodyText2), 290 | Text('No select box', 291 | style: Get.textTheme.caption) 292 | ]).paddingAll(5.0), 293 | Icon(LineIcons.angleDown, 294 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 295 | ])), 296 | const SizedBox(height: 10), 297 | Container( 298 | padding: const EdgeInsets.all(5), 299 | decoration: BoxDecoration( 300 | border: Border.all(color: Colors.grey, width: 1.0), 301 | borderRadius: 302 | const BorderRadius.all(Radius.circular(10.0))), 303 | child: Row( 304 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 305 | children: [ 306 | Column( 307 | crossAxisAlignment: CrossAxisAlignment.start, 308 | children: [ 309 | Text('Charger', style: Get.textTheme.bodyText2), 310 | Text('No select charger', 311 | style: Get.textTheme.caption) 312 | ]).paddingAll(5.0), 313 | Icon(LineIcons.angleDown, 314 | size: 12, color: Get.theme.primaryColor).paddingAll(3).paddingAll(3) 315 | ])), 316 | const SizedBox(height: 10), 317 | Container( 318 | padding: const EdgeInsets.all(5), 319 | decoration: BoxDecoration( 320 | border: Border.all(color: Colors.grey, width: 1.0), 321 | borderRadius: 322 | const BorderRadius.all(Radius.circular(10.0))), 323 | child: Row( 324 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 325 | children: [ 326 | Column( 327 | crossAxisAlignment: CrossAxisAlignment.start, 328 | children: [ 329 | Text('IMEI', style: Get.textTheme.bodyText2), 330 | Text('Enter IMEI', style: Get.textTheme.caption) 331 | ]).paddingAll(5.0), 332 | Icon(LineIcons.angleDown, 333 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 334 | ])), 335 | const SizedBox(height: 10), 336 | _addButtonWidget() 337 | ]).paddingAll(15))) 338 | ]))); 339 | } 340 | 341 | _addButtonWidget() => FormButtonComponent( 342 | onPressed: () { 343 | Get.toNamed(RouteName.qrCodeScannerRoute); 344 | }, 345 | color: Get.theme.primaryColor, 346 | text: Text('SUBMIT', 347 | style: Get.textTheme.headline2! 348 | .copyWith(color: whiteColor, fontSize: 14)), 349 | ).paddingSymmetric(vertical: 10.0); 350 | } 351 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/new_vendor_add.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:get/get.dart'; 4 | import 'package:line_icons/line_icons.dart'; 5 | import '../../../core/assets/assets.dart'; 6 | import '../../../core/theme/color.dart'; 7 | import '../widget/form_button_component.dart'; 8 | import '../widget/text_field_component.dart'; 9 | 10 | class NewVendorAddPage extends StatelessWidget { 11 | const NewVendorAddPage({Key? key}) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return AnnotatedRegion( 16 | value: SystemUiOverlayStyle.dark, 17 | child: Scaffold( 18 | appBar: AppBar( 19 | leading: IconButton( 20 | icon: const Icon(arrowLefAndroidIcon), 21 | onPressed: () => Get.back()), 22 | backgroundColor: Get.theme.primaryColor, 23 | elevation: 0, 24 | title: Text('Add new dealer', 25 | style: 26 | Get.textTheme.headline4!.copyWith(color: whiteColor))), 27 | body: SingleChildScrollView( 28 | child: Column( 29 | crossAxisAlignment: CrossAxisAlignment.start, 30 | children: [ 31 | Text('Address 1', style: Get.textTheme.caption), 32 | const SizedBox(height: 3), 33 | const TextFieldComponent(labelText: 'Address 1'), 34 | const SizedBox(height: 15), 35 | Text('Address 2', style: Get.textTheme.caption), 36 | const SizedBox(height: 3), 37 | const TextFieldComponent(labelText: 'Address 2'), 38 | const SizedBox(height: 15), 39 | Text('Address 3', style: Get.textTheme.caption), 40 | const SizedBox(height: 3), 41 | const TextFieldComponent(labelText: 'Address 3'), 42 | const SizedBox(height: 15), 43 | Container( 44 | decoration: BoxDecoration( 45 | border: Border.all(color: Colors.grey, width: 1.0), 46 | borderRadius: 47 | const BorderRadius.all(Radius.circular(10.0))), 48 | padding: const EdgeInsets.all(5), 49 | child: Row( 50 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 51 | children: [ 52 | Column( 53 | crossAxisAlignment: CrossAxisAlignment.start, 54 | children: [ 55 | Text('Select area', 56 | style: Get.textTheme.bodyText2), 57 | Text('No select area', 58 | style: Get.textTheme.caption) 59 | ]).paddingAll(5.0), 60 | Icon(LineIcons.angleDown, 61 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 62 | ])), 63 | const SizedBox(height: 15), 64 | Text('Pin code', style: Get.textTheme.caption), 65 | const SizedBox(height: 3), 66 | const TextFieldComponent(labelText: 'Pin code'), 67 | const SizedBox(height: 15), 68 | Container( 69 | decoration: BoxDecoration( 70 | border: Border.all(color: Colors.grey, width: 1.0), 71 | borderRadius: 72 | const BorderRadius.all(Radius.circular(10.0))), 73 | padding: const EdgeInsets.all(5), 74 | child: Row( 75 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 76 | children: [ 77 | Column( 78 | crossAxisAlignment: CrossAxisAlignment.start, 79 | children: [ 80 | Text('Select state', 81 | style: Get.textTheme.bodyText2), 82 | Text('No select state', 83 | style: Get.textTheme.caption) 84 | ]).paddingAll(5.0), 85 | Icon(LineIcons.angleDown, 86 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 87 | ])), 88 | const SizedBox(height: 15), 89 | Text('City', style: Get.textTheme.caption), 90 | const SizedBox(height: 3), 91 | const TextFieldComponent(labelText: 'City'), 92 | const SizedBox(height: 15), 93 | Container( 94 | decoration: BoxDecoration( 95 | border: Border.all(color: Colors.grey, width: 1.0), 96 | borderRadius: 97 | const BorderRadius.all(Radius.circular(10.0))), 98 | padding: const EdgeInsets.all(5), 99 | child: Row( 100 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 101 | children: [ 102 | Column( 103 | crossAxisAlignment: CrossAxisAlignment.start, 104 | children: [ 105 | Text('Select country', 106 | style: Get.textTheme.bodyText2), 107 | Text('No select country', 108 | style: Get.textTheme.caption) 109 | ]).paddingAll(5.0), 110 | Icon(LineIcons.angleDown, 111 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 112 | ])), 113 | const SizedBox(height: 15), 114 | Text('Shop photo', style: Get.textTheme.caption), 115 | const SizedBox(height: 15), 116 | Container( 117 | decoration: BoxDecoration( 118 | border: Border.all(color: Colors.grey, width: 1.0), 119 | borderRadius: 120 | const BorderRadius.all(Radius.circular(10.0))), 121 | padding: const EdgeInsets.all(5), 122 | child: Row( 123 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 124 | children: [ 125 | Column( 126 | crossAxisAlignment: CrossAxisAlignment.start, 127 | children: [ 128 | Text('Select biker', 129 | style: Get.textTheme.bodyText2), 130 | Text('No select biker', 131 | style: Get.textTheme.caption) 132 | ]).paddingAll(5.0), 133 | Icon(LineIcons.angleDown, 134 | size: 12, color: Get.theme.primaryColor).paddingAll(3) 135 | ])), 136 | _addButtonWidget() 137 | ]).paddingAll(15)))); 138 | } 139 | 140 | _addButtonWidget() => FormButtonComponent( 141 | onPressed: () {}, 142 | color: Get.theme.primaryColor, 143 | text: Text('SUBMIT', 144 | style: Get.textTheme.headline2! 145 | .copyWith(color: whiteColor, fontSize: 14)), 146 | ).paddingSymmetric(vertical: 10.0); 147 | } 148 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/otp_verify_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import '../../../core/assets/assets.dart'; 4 | import '../../../core/theme/color.dart'; 5 | import '../widget/form_button_component.dart'; 6 | import '../widget/text_field_component.dart'; 7 | 8 | class OtpVerifyPage extends StatelessWidget { 9 | OtpVerifyPage({Key? key}) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Scaffold( 14 | appBar: AppBar( 15 | centerTitle: true, 16 | backgroundColor: Colors.transparent, 17 | automaticallyImplyLeading: false, 18 | leading: IconButton( 19 | icon: Icon(arrowLefAndroidIcon, color: Get.theme.hintColor), 20 | onPressed: () => Get.back()), 21 | elevation: 0), 22 | body: SingleChildScrollView( 23 | child: Column(children: [ 24 | SizedBox(height: Get.height / 10), 25 | Text('Verify phone', 26 | style: Get.textTheme.headline5! 27 | .copyWith(color: Get.theme.primaryColor, fontSize: 22)), 28 | const SizedBox(height: 50), 29 | Text('We have sent OTP on 7990971929 mobile number', 30 | style: Get.textTheme.caption!.copyWith(fontSize: 14)), 31 | const SizedBox(height: 15), 32 | const TextFieldComponent(labelText: 'OTP'), 33 | const SizedBox(height: 5), 34 | _optVerifyButtonWidget, 35 | Align( 36 | alignment: Alignment.topRight, 37 | child: Wrap(children: [ 38 | Text("Didn't receive code?", 39 | style: Get.textTheme.caption!.copyWith(fontSize: 14)), 40 | const SizedBox(width: 10), 41 | Text('Request again', 42 | style: Get.textTheme.headline2!.copyWith(fontSize: 14)) 43 | ])), 44 | ]).paddingAll(15))); 45 | } 46 | 47 | final _optVerifyButtonWidget = FormButtonComponent( 48 | onPressed: () {}, 49 | color: Get.theme.primaryColor, 50 | text: Text('SUBMIT', 51 | style: 52 | Get.textTheme.headline2!.copyWith(color: whiteColor, fontSize: 14)), 53 | ).paddingSymmetric(vertical: 10.0); 54 | } 55 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/page.dart: -------------------------------------------------------------------------------- 1 | export 'splash_page.dart'; 2 | export 'login_username_page.dart'; 3 | export 'login_mobile_page.dart'; 4 | export 'otp_verify_page.dart'; 5 | export 'list_device_page.dart'; 6 | export 'new_device_add.dart'; 7 | export 'new_vendor_add.dart'; 8 | export 'home_page.dart'; 9 | export 'pick_up_page.dart'; 10 | export 'return_page.dart'; 11 | export 'history_page.dart'; 12 | export 'qr_code_scanner_page.dart'; 13 | export 'vendor_visit_page.dart'; 14 | export 'profile_page.dart'; -------------------------------------------------------------------------------- /lib/presentation/ui/page/pick_up_page.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/cupertino.dart'; 7 | import 'package:flutter/material.dart'; 8 | import 'package:get/get.dart'; 9 | import '../../../core/constant/constant.dart'; 10 | import '../../../core/assets/assets.dart'; 11 | import '../../../core/theme/color.dart'; 12 | import '../widget/itemview/customer_detail_itemview.dart'; 13 | import '../widget/option_widget.dart'; 14 | import '../../controller/controller.dart'; 15 | 16 | class PickUpPage extends GetView { 17 | PickUpPage({Key? key}) : super(key: key); 18 | 19 | final refreshKey = GlobalKey(); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return RefreshIndicator( 24 | key: refreshKey, 25 | color: loadingColor, 26 | onRefresh: () async { 27 | refreshKey.currentState!.show(); 28 | }, 29 | child: SafeArea( 30 | top: false, 31 | bottom: false, 32 | child: Builder(builder: (context) { 33 | return CustomScrollView(slivers: [ 34 | SliverOverlapInjector( 35 | handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context)), 36 | SliverList( 37 | delegate: SliverChildBuilderDelegate((context, index) { 38 | return Container( 39 | margin: const EdgeInsets.only( 40 | left: 10, right: 10, top: 1, bottom: 1), 41 | child: Card( 42 | child: Container( 43 | margin: const EdgeInsets.all(8.0), 44 | child: Column( 45 | crossAxisAlignment: CrossAxisAlignment.start, 46 | children: [ 47 | const CustomerDetailItemView( 48 | dateTime: '', 49 | inquiryUniqueId: '000001', 50 | customerName: 'Lakhani kamlesh', 51 | mobileModel: 'MI', 52 | mobileBrand: 'A2', 53 | address: 54 | '4th Floor/A-WING, SHASHWAT BUSINESS PARK, Rakhial Rd, opp. SOMA TEXTILE, Ahmedabad, Gujarat 380023'), 55 | OptionWidget( 56 | mobile: '9586331823', 57 | address: 'Address', 58 | postponeButtonText: ' Postpone ', 59 | doneButtonText: ' Done ', 60 | listTypeEnum: ListTypeEnum.pickUpMobile, 61 | doneOnClick: () { 62 | _pickUpDoneDialog(context, 63 | customerName: 'Lakhani kamlesh', 64 | inquiryUniqueId: 000000001); 65 | }, 66 | postponeOnClick: () {}, 67 | cancelOnClick: () {}) 68 | ])))); 69 | }, childCount: 10)) 70 | ]); 71 | }))); 72 | } 73 | 74 | _pickUpDoneDialog(BuildContext context, 75 | {String? customerName, required int inquiryUniqueId}) { 76 | Get.dialog(CupertinoAlertDialog( 77 | title: Text(customerName!, 78 | style: Get.textTheme.headline5!.copyWith(fontSize: 12)), 79 | content: Column(children: [ 80 | Text('Are you sure pick up done?', style: Get.textTheme.bodyText1!), 81 | const SizedBox(height: 10), 82 | Row(mainAxisAlignment: MainAxisAlignment.center, children: [ 83 | GestureDetector( 84 | child: Row(children: [ 85 | const Icon(mobileQcSelectIcon), 86 | const SizedBox(width: 3), 87 | Text('QC pass', 88 | style: Get.textTheme.bodyText1!.copyWith(fontSize: 12)) 89 | ]), 90 | onTap: () {}), 91 | const SizedBox(width: 10), 92 | GestureDetector( 93 | child: Row(children: [ 94 | const Icon(mobileQcUnSelectIcon), 95 | const SizedBox(width: 3), 96 | Text('QC fail', 97 | style: Get.textTheme.bodyText1!.copyWith(fontSize: 12)) 98 | ]), 99 | onTap: () {}) 100 | ]) 101 | ]), 102 | actions: [ 103 | CupertinoDialogAction( 104 | isDefaultAction: true, 105 | onPressed: () { 106 | Get.back(); 107 | }, 108 | child: Text('CANCEL', style: Get.textTheme.headline6!.copyWith(fontSize: 14))), 109 | CupertinoDialogAction( 110 | isDefaultAction: true, 111 | onPressed: () {}, 112 | child: Text('YES', style: Get.textTheme.headline5!.copyWith(fontSize: 14))) 113 | ])); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/profile_page.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:get/get.dart'; 8 | import '../../../core/assets/assets.dart'; 9 | import '../../controller/controller.dart'; 10 | 11 | class ProfilePage extends GetView { 12 | const ProfilePage({Key? key}) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Scaffold( 17 | bottomNavigationBar: Padding( 18 | padding: const EdgeInsets.all(10.0), 19 | child: Text('${'version'} 1.0.0+1', 20 | textAlign: TextAlign.center, 21 | style: context.textTheme.headline5! 22 | .merge(const TextStyle(fontSize: 15)))), 23 | appBar: AppBar( 24 | centerTitle: true, 25 | backgroundColor: Colors.transparent, 26 | automaticallyImplyLeading: false, 27 | leading: IconButton( 28 | icon: Icon(arrowLefAndroidIcon, color: Get.theme.hintColor), 29 | onPressed: () => Get.back()), 30 | elevation: 0), 31 | body: SingleChildScrollView( 32 | child: Column(children: [ 33 | Center( 34 | child: Column(mainAxisSize: MainAxisSize.min, children: [ 35 | CircleAvatar( 36 | backgroundColor: Colors.grey.withOpacity(0.1), 37 | radius: 35, 38 | backgroundImage: const AssetImage(profileAsset)), 39 | const SizedBox(height: 10.0), 40 | ])), 41 | ListTile( 42 | leading: const Icon(userCircleIcon), 43 | title: Text('Name', 44 | style: context.textTheme.headline6! 45 | .merge(const TextStyle(fontSize: 12))), 46 | subtitle: Text(controller.userName!, 47 | style: context.textTheme.bodyText1! 48 | .merge(const TextStyle(fontSize: 14)))), 49 | const Divider(), 50 | /*ListTile( 51 | leading: const Icon(phoneIcon), 52 | title: Text('Mobile', 53 | style: context.textTheme.headline6! 54 | .merge(const TextStyle(fontSize: 12))), 55 | subtitle: Text(controller.userName!, 56 | style: context.textTheme.bodyText1! 57 | .merge(const TextStyle(fontSize: 14)))), 58 | const Divider(),*/ 59 | ListTile( 60 | onTap: () {}, 61 | leading: const Icon(themeIcon), 62 | title: Text('Change theme', 63 | style: context.textTheme.headline6! 64 | .merge(const TextStyle(fontSize: 12))), 65 | subtitle: Text('Chnage theme light, dart and default', 66 | style: context.textTheme.bodyText1! 67 | .merge(const TextStyle(fontSize: 14)))), 68 | const Divider(), 69 | ListTile( 70 | onTap: () {}, 71 | leading: const Icon(languageIcon), 72 | title: Text('Change language', 73 | style: context.textTheme.headline6! 74 | .merge(const TextStyle(fontSize: 12))), 75 | subtitle: Text('Select any one language english, hindi', 76 | style: context.textTheme.bodyText1! 77 | .merge(const TextStyle(fontSize: 14)))), 78 | const Divider(), 79 | ListTile( 80 | onTap: () {}, 81 | leading: const Icon(privacyPolicyIcon), 82 | subtitle: Text('Sharing and visibility', 83 | style: context.textTheme.bodyText1! 84 | .merge(const TextStyle(fontSize: 14))), 85 | title: Text('Privacy policy', 86 | style: context.textTheme.headline6! 87 | .merge(const TextStyle(fontSize: 12)))), 88 | const Divider(), 89 | ListTile( 90 | onTap: () { 91 | controller.logout(); 92 | }, 93 | leading: const Icon(logoutIcon), 94 | title: Text('Logout', 95 | style: context.textTheme.headline6! 96 | .merge(const TextStyle(fontSize: 12))), 97 | subtitle: Text('You are login in ${controller.loginInTime!}', 98 | style: context.textTheme.bodyText1! 99 | .merge(const TextStyle(fontSize: 14)))) 100 | ]))); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/qr_code_scanner_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:get/get.dart'; 4 | import 'package:qr_code_scanner/qr_code_scanner.dart'; 5 | import '../../../core/assets/assets.dart'; 6 | import '../../../core/theme/color.dart'; 7 | 8 | class QRCodeScannerPage extends StatefulWidget { 9 | const QRCodeScannerPage({Key? key}) : super(key: key); 10 | 11 | @override 12 | createState() => _QRCodeScannerState(); 13 | } 14 | 15 | class _QRCodeScannerState extends State { 16 | Barcode? result; 17 | QRViewController? controller; 18 | final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); 19 | 20 | @override 21 | void reassemble() { 22 | super.reassemble(); 23 | if (Platform.isAndroid) { 24 | controller!.pauseCamera(); 25 | } 26 | controller!.resumeCamera(); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return Scaffold( 32 | appBar: AppBar( 33 | leading: IconButton( 34 | icon: const Icon(arrowLefAndroidIcon), 35 | onPressed: () => Get.back()), 36 | backgroundColor: Get.theme.primaryColor, 37 | elevation: 0, 38 | title: Text('Scan QR Code', 39 | style: Get.textTheme.headline4!.copyWith(color: whiteColor))), 40 | body: Column(children: [ 41 | Expanded(flex: 1, child: _buildQrView(context)) 42 | ])); 43 | } 44 | 45 | Widget _buildQrView(BuildContext context) { 46 | var scanArea = (MediaQuery.of(context).size.width < 400 || 47 | MediaQuery.of(context).size.height < 400) 48 | ? 180.0 49 | : 300.0; 50 | return QRView( 51 | key: qrKey, 52 | onQRViewCreated: _onQRViewCreated, 53 | overlay: QrScannerOverlayShape( 54 | borderColor: Colors.red, 55 | borderRadius: 10, 56 | borderLength: 20, 57 | borderWidth: 8, 58 | cutOutSize: scanArea), 59 | onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p)); 60 | } 61 | 62 | void _onQRViewCreated(QRViewController controller) { 63 | setState(() { 64 | this.controller = controller; 65 | }); 66 | controller.scannedDataStream.listen((scanData) { 67 | setState(() { 68 | result = scanData; 69 | }); 70 | }); 71 | } 72 | 73 | void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) { 74 | if (!p) { 75 | ScaffoldMessenger.of(context).showSnackBar( 76 | const SnackBar(content: Text('no Permission')), 77 | ); 78 | } 79 | } 80 | 81 | @override 82 | void dispose() { 83 | controller?.dispose(); 84 | super.dispose(); 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/return_page.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:get/get.dart'; 8 | import '../../../core/constant/constant.dart'; 9 | import '../../../core/theme/color.dart'; 10 | import '../widget/itemview/customer_detail_itemview.dart'; 11 | import '../widget/option_widget.dart'; 12 | import '../../controller/controller.dart'; 13 | 14 | class ReturnPage extends GetView { 15 | ReturnPage({Key? key}) : super(key: key); 16 | 17 | final refreshKey = GlobalKey(); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return RefreshIndicator( 22 | key: refreshKey, 23 | color: loadingColor, 24 | onRefresh: () async { 25 | refreshKey.currentState!.show(); 26 | }, 27 | child: SafeArea( 28 | top: false, 29 | bottom: false, 30 | child: Builder(builder: (context) { 31 | return CustomScrollView(slivers: [ 32 | SliverOverlapInjector( 33 | handle: NestedScrollView.sliverOverlapAbsorberHandleFor( 34 | context)), 35 | SliverList( 36 | delegate: SliverChildBuilderDelegate((context, index) { 37 | return Container( 38 | margin: const EdgeInsets.only( 39 | left: 10, right: 10, top: 1, bottom: 1), 40 | child: Card( 41 | child: Container( 42 | margin: const EdgeInsets.all(8.0), 43 | child: Column( 44 | crossAxisAlignment: CrossAxisAlignment.start, 45 | children: [ 46 | const CustomerDetailItemView( 47 | dateTime: '', 48 | inquiryUniqueId: '000001', 49 | customerName: 'Lakhani kamlesh', 50 | mobileModel: 'MI', 51 | mobileBrand: 'A2', 52 | address: '4th Floor/A-WING, SHASHWAT BUSINESS PARK, Rakhial Rd, opp. SOMA TEXTILE, Ahmedabad, Gujarat 380023'), 53 | OptionWidget( 54 | mobile: '9586331823', 55 | address: 'Address', 56 | postponeButtonText: ' Postpone ', 57 | doneButtonText: ' Done ', 58 | listTypeEnum: ListTypeEnum.returnMobile, 59 | doneOnClick: () { 60 | }, 61 | postponeOnClick: () {}, 62 | cancelOnClick: () {}) 63 | ])))); 64 | }, childCount: 10)) 65 | ]); 66 | }))); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/splash_page.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 22-11-21 09:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter/services.dart'; 8 | import 'package:get/get.dart'; 9 | import '../../controller/controller.dart'; 10 | 11 | class SplashPage extends GetView { 12 | const SplashPage({Key? key}) : super(key: key); 13 | 14 | @override 15 | build(BuildContext context) => Scaffold( 16 | body: AnnotatedRegion( 17 | value: SystemUiOverlayStyle.dark, 18 | child: Center( 19 | child: Text(controller.appName!, 20 | style: Get.textTheme.headline2!.copyWith(fontSize: 28))))); 21 | } 22 | -------------------------------------------------------------------------------- /lib/presentation/ui/page/vendor_visit_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:get/get.dart'; 4 | import 'package:line_icons/line_icons.dart'; 5 | import '../widget/form_button_component.dart'; 6 | import '../widget/text_field_component.dart'; 7 | import '../../../core/assets/assets.dart'; 8 | import '../../../core/theme/color.dart'; 9 | 10 | class VendorVisitPage extends StatelessWidget { 11 | const VendorVisitPage({Key? key}) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return AnnotatedRegion( 16 | value: SystemUiOverlayStyle.dark, 17 | child: Scaffold( 18 | appBar: AppBar( 19 | leading: IconButton( 20 | icon: const Icon(arrowLefAndroidIcon), 21 | onPressed: () => Get.back()), 22 | backgroundColor: Get.theme.primaryColor, 23 | elevation: 0, 24 | title: Text('Vendor visit', 25 | style: 26 | Get.textTheme.headline4!.copyWith(color: whiteColor))), 27 | body: Column(children: [ 28 | Container( 29 | padding: const EdgeInsets.all(10), 30 | decoration: BoxDecoration( 31 | border: Border.all(color: Colors.grey), 32 | borderRadius: 33 | const BorderRadius.all(Radius.circular(10))), 34 | child: Row( 35 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 36 | children: [ 37 | Row(children: [ 38 | Icon(LineIcons.user, 39 | size: 18, color: Get.theme.focusColor), 40 | const SizedBox(width: 7.0), 41 | Column( 42 | crossAxisAlignment: CrossAxisAlignment.start, 43 | children: [ 44 | Text('Select vendor', 45 | style: context.textTheme.bodyText2), 46 | Text('No select vendor', 47 | style: context.textTheme.caption) 48 | ]).paddingAll(5.0) 49 | ]) 50 | ])), 51 | const SizedBox(height: 10), 52 | const TextFieldComponent( 53 | labelText: 'Feedback', maxLines: 3, minLines: 3), 54 | FormButtonComponent( 55 | onPressed: () {}, 56 | color: Get.theme.colorScheme.secondary, 57 | text: Text('Submit', 58 | style: Get.textTheme.headline2! 59 | .copyWith(color: whiteColor, fontSize: 14)), 60 | ).paddingSymmetric(vertical: 10.0, horizontal: 0.0) 61 | ]).paddingAll(10))); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/presentation/ui/widget/category_list_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import 'package:line_icons/line_icons.dart'; 4 | 5 | typedef CategoryHeaderTapCallback = Function(bool shouldOpenList); 6 | typedef SoldAvailableCallBack = Function(); 7 | 8 | class CategoryListItem extends StatefulWidget { 9 | const CategoryListItem( 10 | {Key? key, 11 | this.restorationId, 12 | this.initiallyExpanded = false, 13 | this.onTapEdit, 14 | this.onTapSold, 15 | this.onTapAvailable}) 16 | : super(key: key); 17 | 18 | final String? restorationId; 19 | final bool initiallyExpanded; 20 | final CategoryHeaderTapCallback? onTapEdit; 21 | final SoldAvailableCallBack? onTapSold, onTapAvailable; 22 | 23 | @override 24 | _CategoryListItemState createState() => _CategoryListItemState(); 25 | } 26 | 27 | class _CategoryListItemState extends State 28 | with SingleTickerProviderStateMixin { 29 | static final Animatable _easeInTween = 30 | CurveTween(curve: Curves.easeIn); 31 | static const _expandDuration = Duration(milliseconds: 200); 32 | late AnimationController _controller; 33 | late Animation _childrenHeightFactor; 34 | late Animation _headerChevronOpacity; 35 | late Animation _headerMargin; 36 | late Animation _childrenPadding; 37 | late Animation _headerBorderRadius; 38 | 39 | @override 40 | void initState() { 41 | super.initState(); 42 | 43 | _controller = AnimationController(duration: _expandDuration, vsync: this); 44 | _controller.addStatusListener((status) { 45 | setState(() {}); 46 | }); 47 | 48 | _childrenHeightFactor = _controller.drive(_easeInTween); 49 | _headerChevronOpacity = _controller.drive(_easeInTween); 50 | 51 | _headerMargin = EdgeInsetsGeometryTween( 52 | begin: const EdgeInsets.fromLTRB(16, 8, 16, 8), 53 | end: EdgeInsets.zero) 54 | .animate(_controller); 55 | _childrenPadding = EdgeInsetsGeometryTween( 56 | begin: const EdgeInsets.symmetric(horizontal: 16), 57 | end: EdgeInsets.zero) 58 | .animate(_controller); 59 | _headerBorderRadius = BorderRadiusTween( 60 | begin: BorderRadius.circular(10), end: BorderRadius.zero) 61 | .animate(_controller); 62 | 63 | if (widget.initiallyExpanded) { 64 | _controller.value = 1.0; 65 | } 66 | } 67 | 68 | @override 69 | void dispose() { 70 | _controller.dispose(); 71 | super.dispose(); 72 | } 73 | 74 | bool? _shouldOpenList() { 75 | switch (_controller.status) { 76 | case AnimationStatus.completed: 77 | case AnimationStatus.forward: 78 | return false; 79 | case AnimationStatus.dismissed: 80 | case AnimationStatus.reverse: 81 | return true; 82 | } 83 | } 84 | 85 | void _handleTap() { 86 | if (_shouldOpenList()!) { 87 | _controller.forward(); 88 | } else { 89 | _controller.reverse(); 90 | } 91 | } 92 | 93 | Widget _buildHeaderWithChildren(BuildContext context, Widget? child) { 94 | return Column(mainAxisSize: MainAxisSize.max, children: [ 95 | _CategoryHeader( 96 | margin: _headerMargin.value, 97 | borderRadius: _headerBorderRadius.value, 98 | chevronOpacity: _headerChevronOpacity.value, 99 | onTapEdit: _handleTap, 100 | onTapSold: widget.onTapSold, 101 | onTapAvailable: widget.onTapAvailable), 102 | Padding( 103 | padding: _childrenPadding.value, 104 | child: ClipRect( 105 | child: Align( 106 | heightFactor: _childrenHeightFactor.value, child: child))) 107 | ]); 108 | } 109 | 110 | @override 111 | Widget build(BuildContext context) { 112 | return AnimatedBuilder( 113 | animation: _controller.view, 114 | builder: _buildHeaderWithChildren, 115 | child: _shouldOpenList()! 116 | ? null 117 | : _ExpandedCategoryDemos(categoryId: 1, category: 'Name')); 118 | } 119 | } 120 | 121 | class _ExpandedCategoryDemos extends StatelessWidget { 122 | _ExpandedCategoryDemos({ 123 | Key? key, 124 | this.category, 125 | required this.categoryId, 126 | }) : super(key: key); 127 | 128 | final String? category; 129 | final int categoryId; 130 | 131 | final TextEditingController _controller = TextEditingController(); 132 | 133 | @override 134 | Widget build(BuildContext context) { 135 | return Column( 136 | key: ValueKey('${category}DemoList'), 137 | children: [_buildNewTaskField(context), const SizedBox(height: 12)]); 138 | } 139 | 140 | Widget _buildNewTaskField(BuildContext context) { 141 | return Container( 142 | padding: const EdgeInsets.only(top: 5, bottom: 5, left: 15, right: 15), 143 | child: TextField( 144 | controller: _controller, 145 | style: Get.textTheme.bodyText1!.copyWith(fontSize: 15), 146 | decoration: InputDecoration( 147 | border: UnderlineInputBorder( 148 | borderSide: 149 | BorderSide(color: Get.theme.primaryColor, width: 1)), 150 | enabledBorder: const UnderlineInputBorder( 151 | borderSide: BorderSide(color: Colors.grey, width: 1)), 152 | errorBorder: UnderlineInputBorder( 153 | borderSide: 154 | BorderSide(color: Get.theme.primaryColor, width: 1)), 155 | focusedBorder: UnderlineInputBorder( 156 | borderSide: 157 | BorderSide(color: Get.theme.primaryColor, width: 1)), 158 | hintText: 'Edit price', 159 | hintStyle: Get.textTheme.headline4!.merge( 160 | const TextStyle(fontSize: 15, color: Colors.black54)), 161 | prefixIconConstraints: 162 | const BoxConstraints(maxHeight: 35, maxWidth: 40), 163 | prefixIcon: const SizedBox( 164 | width: 25, child: Icon(LineIcons.edit, size: 20)), 165 | suffixIconConstraints: 166 | const BoxConstraints(maxHeight: 16, maxWidth: 51)), 167 | onSubmitted: (input) async { 168 | if (input != '') { 169 | _controller.text = ''; 170 | } 171 | })); 172 | } 173 | } 174 | 175 | class _CategoryHeader extends StatelessWidget { 176 | const _CategoryHeader({ 177 | Key? key, 178 | this.margin, 179 | this.borderRadius, 180 | this.chevronOpacity, 181 | this.onTapEdit, 182 | this.onTapSold, 183 | this.onTapAvailable, 184 | this.icon, 185 | }) : super(key: key); 186 | 187 | final EdgeInsetsGeometry? margin; 188 | final BorderRadiusGeometry? borderRadius; 189 | final double? chevronOpacity; 190 | final GestureTapCallback? onTapEdit, onTapSold, onTapAvailable; 191 | final Icon? icon; 192 | 193 | @override 194 | Widget build(BuildContext context) { 195 | return Container( 196 | decoration: const BoxDecoration( 197 | color: Colors.white, 198 | borderRadius: BorderRadius.only( 199 | topLeft: Radius.circular(10), 200 | topRight: Radius.circular(10), 201 | bottomLeft: Radius.circular(10), 202 | bottomRight: Radius.circular(10)), 203 | boxShadow: [ 204 | BoxShadow( 205 | color: Color(0xA3CAC9C9), 206 | spreadRadius: 0.1, 207 | blurRadius: 0.1, 208 | offset: Offset(0, 0.5)) 209 | ]), 210 | margin: margin, 211 | child: Material( 212 | shape: RoundedRectangleBorder(borderRadius: borderRadius!), 213 | color: const Color(0xFFFFFFFF), //Colors.green.withOpacity(0.1), 214 | clipBehavior: Clip.antiAlias, 215 | child: Row(children: [ 216 | const Icon(LineIcons.checkSquare, size: 20, color: Colors.green) 217 | .paddingAll(3.0), 218 | const SizedBox(width: 7.0), 219 | Expanded( 220 | child: Column( 221 | crossAxisAlignment: CrossAxisAlignment.start, 222 | children: [ 223 | Row( 224 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 225 | children: [ 226 | Text('Android - MI A2', 227 | style: context.textTheme.bodyText1! 228 | .copyWith(fontSize: 16)), 229 | Column( 230 | crossAxisAlignment: CrossAxisAlignment.end, 231 | children: [ 232 | Text('3 Dec | 3 days', 233 | style: context.textTheme.caption! 234 | .copyWith(fontSize: 12)), 235 | Text('Rs 8000', 236 | style: context.textTheme.headline3! 237 | .copyWith(fontSize: 14)) 238 | ]) 239 | ]), 240 | Row(children: [ 241 | Text('12/12', 242 | style: context.textTheme.bodyText1! 243 | .copyWith(fontSize: 14)), 244 | const SizedBox(width: 5.0), 245 | Text('Black', 246 | style: context.textTheme.bodyText1! 247 | .copyWith(fontSize: 14)) 248 | ]), 249 | const SizedBox(height: 3.0), 250 | Row(children: [ 251 | Text('Grade', 252 | style: context.textTheme.caption! 253 | .copyWith(fontSize: 14)), 254 | const SizedBox(width: 5.0), 255 | Text('A', 256 | style: context.textTheme.headline5! 257 | .copyWith(fontSize: 16)) 258 | ]), 259 | const SizedBox(height: 10.0), 260 | Row(mainAxisAlignment: MainAxisAlignment.end, children: [ 261 | InkWell( 262 | child: Container( 263 | width: 80, 264 | padding: const EdgeInsets.only( 265 | top: 3, bottom: 3, right: 5, left: 5), 266 | decoration: BoxDecoration( 267 | color: Colors.red.withOpacity(0.1), 268 | border: Border.all( 269 | color: Colors.red.withOpacity(0.4)), 270 | borderRadius: const BorderRadius.all( 271 | Radius.circular(15))), 272 | child: Text('SOLD', 273 | textAlign: TextAlign.center, 274 | style: Get.textTheme.bodyText1!.copyWith( 275 | fontSize: 12, color: Colors.red))), 276 | onTap: onTapSold), 277 | const SizedBox(width: 10.0), 278 | InkWell( 279 | borderRadius: BorderRadius.circular(15), 280 | onTap: onTapAvailable, 281 | child: Container( 282 | width: 85, 283 | padding: const EdgeInsets.only( 284 | top: 3, bottom: 3, right: 5, left: 5), 285 | decoration: BoxDecoration( 286 | color: Colors.green.withOpacity(0.1), 287 | border: Border.all( 288 | color: Colors.green.withOpacity(0.4)), 289 | borderRadius: const BorderRadius.all( 290 | Radius.circular(15))), 291 | child: Text('AVAILABLE', 292 | textAlign: TextAlign.center, 293 | style: context.textTheme.bodyText1!.copyWith( 294 | fontSize: 12, color: Colors.green)))), 295 | const SizedBox(width: 10.0), 296 | InkWell( 297 | child: Container( 298 | width: 85, 299 | padding: const EdgeInsets.only( 300 | top: 3, bottom: 3, right: 5, left: 5), 301 | decoration: BoxDecoration( 302 | color: Colors.grey.withOpacity(0.1), 303 | border: Border.all( 304 | color: Colors.grey.withOpacity(0.4)), 305 | borderRadius: const BorderRadius.all( 306 | Radius.circular(15))), 307 | child: Text('EDIT', 308 | textAlign: TextAlign.center, 309 | style: Get.textTheme.bodyText1! 310 | .copyWith(fontSize: 12))), 311 | onTap: onTapEdit) 312 | ]) 313 | ])) 314 | ]).paddingOnly(left: 5, right: 10, top: 10, bottom: 10))); 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /lib/presentation/ui/widget/form_button_component.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:get/get.dart'; 8 | 9 | class FormButtonComponent extends StatelessWidget { 10 | const FormButtonComponent( 11 | {Key? key, 12 | required this.color, 13 | required this.text, 14 | required this.onPressed}) 15 | : super(key: key); 16 | 17 | final Color color; 18 | final Widget text; 19 | final VoidCallback onPressed; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return Container( 24 | width: Get.width, 25 | decoration: BoxDecoration(boxShadow: [ 26 | BoxShadow( 27 | color: color.withOpacity(0.1), 28 | blurRadius: 40, 29 | offset: const Offset(0, 15)), 30 | BoxShadow( 31 | color: color.withOpacity(0.1), 32 | blurRadius: 13, 33 | offset: const Offset(0, 1)) 34 | ]), 35 | child: MaterialButton( 36 | elevation: 1, 37 | onPressed: onPressed, 38 | padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), 39 | color: color, 40 | shape: 41 | RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), 42 | child: text)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/presentation/ui/widget/form_icon_loading_component.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import 'package:rxdart/rxdart.dart'; 4 | 5 | enum ButtonState { idle, loading, success, error } 6 | 7 | class FormIconLoadingComponent extends StatefulWidget { 8 | const FormIconLoadingComponent({ 9 | Key? key, 10 | this.color = Colors.blue, 11 | this.height = 55, 12 | required this.child, 13 | required this.iconData, 14 | required this.onPressed, 15 | this.loaderSize = 50.0, 16 | this.loaderStrokeWidth = 1.5, 17 | this.animateOnTap = true, 18 | this.valueColor = Colors.blue, 19 | this.borderRadius = 25, 20 | this.elevation = 5, 21 | this.duration = const Duration(milliseconds: 500), 22 | this.curve = Curves.easeInOutCirc, 23 | this.errorColor = Colors.redAccent, 24 | this.successColor = Colors.green, 25 | this.resetDuration = const Duration(seconds: 15), 26 | this.resetAfterDuration = false, 27 | this.successIcon = Icons.check, 28 | this.failedIcon = Icons.close, 29 | this.completionCurve = Curves.elasticOut, 30 | this.completionDuration = const Duration(milliseconds: 1000), 31 | this.disabledColor, 32 | required this.controller, 33 | this.spaceBetween = 10, 34 | this.iconColor = Colors.white, 35 | }) : super(key: key); 36 | 37 | /// Required button controller 38 | final IconButtonController controller; 39 | 40 | /// Callback when button is pressed 41 | final VoidCallback? onPressed; 42 | 43 | /// Child widget 44 | final Widget child; 45 | 46 | /// Icon for button 47 | final IconData iconData; 48 | 49 | /// Icon color for button 50 | final Color iconColor; 51 | 52 | /// Primary color or the button 53 | final Color? color; 54 | 55 | /// Vertical extent of the button 56 | final double height; 57 | 58 | /// Spacing between icon and the child widget 59 | final double spaceBetween; 60 | 61 | /// Size of CircularProgressIndicator 62 | final double loaderSize; 63 | 64 | /// Stroke width of CircularProgressIndicator 65 | final double loaderStrokeWidth; 66 | 67 | /// Whether to trigger the animation on the tap event 68 | final bool animateOnTap; 69 | 70 | /// The color of the static icons 71 | final Color valueColor; 72 | 73 | /// Reset the animation after specified duration, 74 | final bool resetAfterDuration; 75 | 76 | /// The curve of the shrink animation 77 | final Curve curve; 78 | 79 | /// The radius of the button border 80 | final double borderRadius; 81 | 82 | /// The duration of the button animation 83 | final Duration duration; 84 | 85 | /// The elevation of the raised button 86 | final double elevation; 87 | 88 | /// Duration after which reset the button 89 | final Duration resetDuration; 90 | 91 | /// The color of the button when it is in the error state 92 | final Color? errorColor; 93 | 94 | /// The color of the button when it is in the success state 95 | final Color? successColor; 96 | 97 | /// The color of the button when it is disabled 98 | final Color? disabledColor; 99 | 100 | /// The icon for the success state 101 | final IconData successIcon; 102 | 103 | /// The icon for the failed state 104 | final IconData failedIcon; 105 | 106 | /// The duration of the success and failed animation 107 | final Curve completionCurve; 108 | 109 | final Duration completionDuration; 110 | 111 | Duration get _borderDuration { 112 | return Duration(milliseconds: (duration.inMilliseconds / 2).round()); 113 | } 114 | 115 | @override 116 | createState() => _FormIconLoadingState(); 117 | } 118 | 119 | class _FormIconLoadingState extends State 120 | with TickerProviderStateMixin { 121 | late AnimationController _buttonController; 122 | late AnimationController _borderController; 123 | late AnimationController _checkButtonController; 124 | 125 | late Animation _squeezeAnimation; 126 | late Animation _bounceAnimation; 127 | late Animation _borderAnimation; 128 | 129 | final _state = BehaviorSubject.seeded(ButtonState.idle); 130 | 131 | @override 132 | void initState() { 133 | super.initState(); 134 | 135 | _buttonController = 136 | AnimationController(duration: widget.duration, vsync: this); 137 | 138 | _checkButtonController = 139 | AnimationController(duration: widget.completionDuration, vsync: this); 140 | 141 | _borderController = 142 | AnimationController(duration: widget._borderDuration, vsync: this); 143 | 144 | _bounceAnimation = Tween(begin: 0, end: widget.height).animate( 145 | CurvedAnimation( 146 | parent: _checkButtonController, curve: widget.completionCurve)); 147 | _bounceAnimation.addListener(() { 148 | setState(() {}); 149 | }); 150 | 151 | _squeezeAnimation = Tween(begin: Get.width, end: widget.height) 152 | .animate( 153 | CurvedAnimation(parent: _buttonController, curve: widget.curve)); 154 | 155 | _squeezeAnimation.addListener(() { 156 | setState(() {}); 157 | }); 158 | 159 | _squeezeAnimation.addStatusListener((state) { 160 | if (state == AnimationStatus.completed && widget.animateOnTap) { 161 | if (widget.onPressed != null) { 162 | widget.onPressed!(); 163 | } 164 | } 165 | }); 166 | 167 | _borderAnimation = BorderRadiusTween( 168 | begin: BorderRadius.circular(widget.borderRadius), 169 | end: BorderRadius.circular(widget.height)) 170 | .animate(_borderController); 171 | 172 | _borderAnimation.addListener(() { 173 | setState(() {}); 174 | }); 175 | 176 | // There is probably a better way of doing this... 177 | _state.stream.listen((event) { 178 | widget.controller._state.sink.add(event); 179 | }); 180 | 181 | widget.controller._addListeners(_start, _stop, _success, _error, _reset); 182 | } 183 | 184 | @override 185 | void dispose() { 186 | _buttonController.dispose(); 187 | _checkButtonController.dispose(); 188 | _borderController.dispose(); 189 | _state.close(); 190 | super.dispose(); 191 | } 192 | 193 | @override 194 | Widget build(BuildContext context) { 195 | final theme = Theme.of(context); 196 | 197 | var _check = Container( 198 | alignment: FractionalOffset.center, 199 | decoration: BoxDecoration( 200 | color: _state.value == ButtonState.idle 201 | ? theme.primaryColor 202 | : Colors.transparent, 203 | border: Border.all( 204 | color: widget.successColor ?? theme.primaryColor, 205 | width: widget.loaderStrokeWidth, 206 | ), 207 | borderRadius: BorderRadius.all( 208 | Radius.circular( 209 | _bounceAnimation.value / 2, 210 | ), 211 | ), 212 | ), 213 | width: _bounceAnimation.value, 214 | height: _bounceAnimation.value, 215 | child: _bounceAnimation.value > 20 216 | ? Icon( 217 | widget.successIcon, 218 | color: widget.successColor ?? theme.primaryColor, 219 | ) 220 | : null, 221 | ); 222 | 223 | var _cross = Container( 224 | alignment: FractionalOffset.center, 225 | decoration: BoxDecoration( 226 | color: _state.value == ButtonState.idle 227 | ? theme.primaryColor 228 | : Colors.transparent, 229 | border: Border.all( 230 | color: widget.errorColor ?? theme.primaryColor, 231 | width: widget.loaderStrokeWidth, 232 | ), 233 | borderRadius: BorderRadius.all( 234 | Radius.circular( 235 | _bounceAnimation.value / 2, 236 | ), 237 | ), 238 | ), 239 | width: _bounceAnimation.value, 240 | height: _bounceAnimation.value, 241 | child: _bounceAnimation.value > 20 242 | ? Icon( 243 | widget.failedIcon, 244 | color: widget.errorColor ?? theme.primaryColor, 245 | ) 246 | : null, 247 | ); 248 | 249 | var _loader = SizedBox( 250 | width: widget.loaderSize, 251 | height: widget.loaderSize, 252 | child: Stack( 253 | children: [ 254 | SizedBox( 255 | height: widget.loaderSize, 256 | width: widget.loaderSize, 257 | child: CircularProgressIndicator( 258 | backgroundColor: widget.valueColor.withOpacity(0.10), 259 | valueColor: AlwaysStoppedAnimation(widget.valueColor), 260 | strokeWidth: widget.loaderStrokeWidth, 261 | ), 262 | ), 263 | Center( 264 | child: Icon( 265 | widget.iconData, 266 | color: _state.value == ButtonState.loading ? widget.valueColor : widget.iconColor, 267 | ), 268 | ), 269 | ], 270 | ), 271 | ); 272 | 273 | var childStream = StreamBuilder( 274 | stream: _state, 275 | builder: (context, snapshot) { 276 | return AnimatedSwitcher( 277 | duration: const Duration(milliseconds: 200), 278 | child: snapshot.data == ButtonState.loading 279 | ? _loader 280 | : Row( 281 | mainAxisSize: MainAxisSize.min, 282 | children: [ 283 | Icon( 284 | widget.iconData, 285 | color: widget.iconColor, 286 | ), 287 | SizedBox( 288 | width: widget.spaceBetween, 289 | ), 290 | widget.child, 291 | ], 292 | ), 293 | ); 294 | }, 295 | ); 296 | 297 | final _btn = ButtonTheme( 298 | shape: RoundedRectangleBorder(borderRadius: _borderAnimation.value), 299 | disabledColor: widget.disabledColor, 300 | padding: const EdgeInsets.all(0), 301 | child: ElevatedButton( 302 | style: ElevatedButton.styleFrom( 303 | onSurface: widget.disabledColor, 304 | minimumSize: Size(_squeezeAnimation.value, widget.height), 305 | shape: RoundedRectangleBorder( 306 | borderRadius: BorderRadius.circular(widget.borderRadius), 307 | ), 308 | primary: _state.value == ButtonState.idle 309 | ? widget.color 310 | : Colors.transparent, 311 | elevation: _state.value == ButtonState.idle ? widget.elevation : 0, 312 | padding: const EdgeInsets.all(0), 313 | ), 314 | onPressed: widget.onPressed == null ? null : _btnPressed, 315 | child: childStream, 316 | )); 317 | 318 | return SizedBox( 319 | height: widget.height, 320 | width: Get.width, 321 | child: Center( 322 | child: _state.value == ButtonState.error 323 | ? _cross 324 | : _state.value == ButtonState.success 325 | ? _check 326 | : _btn, 327 | ), 328 | ); 329 | } 330 | 331 | _btnPressed() async { 332 | if (widget.animateOnTap) { 333 | _start(); 334 | } else { 335 | if (widget.onPressed != null) { 336 | widget.onPressed!(); 337 | } 338 | } 339 | } 340 | 341 | _start() { 342 | _state.sink.add(ButtonState.loading); 343 | _borderController.forward(); 344 | _buttonController.forward(); 345 | if (widget.resetAfterDuration) _reset(); 346 | } 347 | 348 | _stop() { 349 | _state.sink.add(ButtonState.idle); 350 | _buttonController.reverse(); 351 | _borderController.reverse(); 352 | } 353 | 354 | _success() { 355 | _state.sink.add(ButtonState.success); 356 | _checkButtonController.forward(); 357 | } 358 | 359 | _error() { 360 | _state.sink.add(ButtonState.error); 361 | _checkButtonController.forward(); 362 | } 363 | 364 | _reset() async { 365 | if (widget.resetAfterDuration) await Future.delayed(widget.resetDuration); 366 | _state.sink.add(ButtonState.idle); 367 | _buttonController.reverse(); 368 | _borderController.reverse(); 369 | _checkButtonController.reset(); 370 | } 371 | } 372 | 373 | /// Options that can be chosen by the controller 374 | class IconButtonController { 375 | late VoidCallback _startListener; 376 | late VoidCallback _stopListener; 377 | late VoidCallback _successListener; 378 | late VoidCallback _errorListener; 379 | late VoidCallback _resetListener; 380 | 381 | _addListeners( 382 | VoidCallback startListener, 383 | VoidCallback stopListener, 384 | VoidCallback successListener, 385 | VoidCallback errorListener, 386 | VoidCallback resetListener) { 387 | _startListener = startListener; 388 | _stopListener = stopListener; 389 | _successListener = successListener; 390 | _errorListener = errorListener; 391 | _resetListener = resetListener; 392 | } 393 | 394 | final BehaviorSubject _state = 395 | BehaviorSubject.seeded(ButtonState.idle); 396 | 397 | /// A read-only stream of the button state 398 | Stream get stateStream => _state.stream; 399 | 400 | /// Gets the current state 401 | ButtonState? get currentState => _state.value; 402 | 403 | /// Notify listeners to start the loading animation 404 | void start() { 405 | _startListener(); 406 | } 407 | 408 | /// Notify listeners to start the stop animation 409 | void stop() { 410 | _stopListener(); 411 | } 412 | 413 | /// Notify listeners to start the sucess animation 414 | void success() { 415 | _successListener(); 416 | } 417 | 418 | /// Notify listeners to start the error animation 419 | void error() { 420 | _errorListener(); 421 | } 422 | 423 | /// Notify listeners to start the reset animation 424 | void reset() { 425 | _resetListener(); 426 | } 427 | } -------------------------------------------------------------------------------- /lib/presentation/ui/widget/itemview/customer_detail_itemview.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:get/get.dart'; 3 | import '../../../../core/assets/assets.dart'; 4 | 5 | class CustomerDetailItemView extends StatelessWidget { 6 | final String? inquiryUniqueId, 7 | dateTime, 8 | customerName, 9 | mobileModel, 10 | mobileBrand, 11 | address, 12 | reasonName; 13 | final bool isReason; 14 | 15 | const CustomerDetailItemView( 16 | {this.inquiryUniqueId, 17 | this.dateTime, 18 | this.customerName, 19 | this.mobileModel, 20 | this.mobileBrand, 21 | this.address, 22 | this.isReason = false, 23 | this.reasonName, 24 | Key? key}) 25 | : super(key: key); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ 30 | Column(crossAxisAlignment: CrossAxisAlignment.end, children: [ 31 | Row(mainAxisAlignment: MainAxisAlignment.end, children: [ 32 | const Icon(roadIcon, size: 15), 33 | const SizedBox(width: 3.0), 34 | Text('0', style: context.textTheme.headline3!.copyWith(fontSize: 12)) 35 | ]), 36 | const SizedBox(width: 5.0), 37 | Text('10-Dec | 12:10 AM', 38 | style: Get.textTheme.caption!.copyWith(fontSize: 12)) 39 | ]), 40 | const SizedBox(height: 5.0), 41 | Text(inquiryUniqueId!, 42 | style: context.textTheme.caption!.copyWith(fontSize: 14)), 43 | const SizedBox(height: 1.0), 44 | Text(customerName!, 45 | style: context.textTheme.headline5!.copyWith(fontSize: 14)), 46 | const SizedBox(height: 1.0), 47 | Wrap(children: [ 48 | Text('$mobileModel | $mobileBrand', 49 | style: context.textTheme.bodyText1!.copyWith(fontSize: 14)), 50 | const SizedBox(width: 10.0), 51 | Text('00/00', 52 | style: context.textTheme.bodyText1!.copyWith(fontSize: 14)), 53 | const SizedBox(width: 10.0), 54 | Text('Black', 55 | style: context.textTheme.bodyText1!.copyWith(fontSize: 14)), 56 | ]), 57 | const SizedBox(height: 1.0), 58 | Row(children: [ 59 | Text('Grade', style: Get.textTheme.caption!.copyWith(fontSize: 14)), 60 | const SizedBox(width: 5.0), 61 | Text('A', style: Get.textTheme.headline5!.copyWith(fontSize: 16)) 62 | ]), 63 | const SizedBox(height: 5.0), 64 | Text(address!, 65 | style: context.textTheme.bodyText1!.copyWith(fontSize: 14)), 66 | isReason 67 | ? Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ 68 | const SizedBox(height: 5.0), 69 | Text('reason'.tr, 70 | style: context.textTheme.headline6!.copyWith(fontSize: 12)), 71 | Text(reasonName!, 72 | style: context.textTheme.caption!.copyWith(fontSize: 12)) 73 | ]) 74 | : const SizedBox(), 75 | const Divider() 76 | ]); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/presentation/ui/widget/option_widget.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter_phone_direct_caller/flutter_phone_direct_caller.dart'; 8 | import 'package:get/get.dart'; 9 | import 'package:maps_launcher/maps_launcher.dart'; 10 | import 'package:vendor/core/constant/constant.dart'; 11 | import '../../../core/assets/assets.dart'; 12 | import '../../../core/theme/color.dart'; 13 | 14 | class OptionWidget extends StatelessWidget { 15 | final Function()? doneOnClick, postponeOnClick, cancelOnClick; 16 | final String? doneButtonText, postponeButtonText, mobile, address; 17 | final bool? isVisibleSubmit; 18 | final ListTypeEnum? listTypeEnum; 19 | 20 | const OptionWidget( 21 | {this.doneOnClick, 22 | this.postponeOnClick, 23 | this.cancelOnClick, 24 | this.doneButtonText, 25 | this.postponeButtonText, 26 | this.mobile, 27 | this.address, 28 | this.isVisibleSubmit = true, 29 | this.listTypeEnum, 30 | Key? key}) 31 | : super(key: key); 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ 36 | Row(children: [ 37 | InkWell( 38 | onTap: () { 39 | MapsLauncher.launchQuery(address!); 40 | }, 41 | customBorder: const CircleBorder(), 42 | child: const Padding( 43 | padding: EdgeInsets.all(5), child: Icon(mapIcon))), 44 | const SizedBox(width: 5.0), 45 | InkWell( 46 | onTap: () async { 47 | await FlutterPhoneDirectCaller.callNumber('$mobile'); 48 | }, 49 | customBorder: const CircleBorder(), 50 | child: const Padding( 51 | padding: EdgeInsets.all(5), child: Icon(callIcon))) 52 | ]), 53 | isVisibleSubmit! 54 | ? Row(children: [ 55 | InkWell( 56 | onTap: doneOnClick, 57 | customBorder: const CircleBorder(), 58 | child: _optionName( 59 | name: doneButtonText!.toUpperCase(), 60 | textStyle: context.textTheme.bodyText1! 61 | .copyWith(color: doneButtonBgColor, fontSize: 12))), 62 | const SizedBox(width: 10.0), 63 | InkWell( 64 | onTap: postponeOnClick, 65 | customBorder: const CircleBorder(), 66 | child: _optionName( 67 | name: postponeButtonText!.toUpperCase(), 68 | textStyle: context.textTheme.bodyText1!.copyWith( 69 | color: postponeButtonBgColor, fontSize: 12))), 70 | if (listTypeEnum == ListTypeEnum.returnMobile) ...[ 71 | const SizedBox(width: 10.0), 72 | InkWell( 73 | onTap: cancelOnClick, 74 | customBorder: const CircleBorder(), 75 | child: _optionName( 76 | name: ' cancel '.toUpperCase(), 77 | textStyle: context.textTheme.bodyText1!.copyWith( 78 | color: cancelButtonBgColor, fontSize: 12))) 79 | ] 80 | ]) 81 | : const SizedBox() 82 | ]); 83 | } 84 | 85 | _optionName({required String name, required TextStyle textStyle}) => 86 | Container( 87 | decoration: BoxDecoration( 88 | color: Colors.grey.withOpacity(0.1), 89 | borderRadius: const BorderRadius.all(Radius.circular(20))), 90 | padding: const EdgeInsets.all(5), 91 | child: Text(name, style: textStyle)); 92 | } 93 | -------------------------------------------------------------------------------- /lib/presentation/ui/widget/text_field_component.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter/services.dart'; 8 | import 'package:get/get.dart'; 9 | 10 | class TextFieldComponent extends StatelessWidget { 11 | final String labelText; 12 | final String? initialValue; 13 | final Widget? prefixIcon, suffixIcon; 14 | final TextInputType keyboardType; 15 | //final FormFieldValidator? validator; 16 | final String? Function(String?)? validator; 17 | final TextEditingController? controller; 18 | final ValueChanged? onChanged, onSaved; 19 | final int? maxLength, maxLines; 20 | final int minLines; 21 | final bool readOnly, addHint, enabled; 22 | final Function()? onTap; 23 | final AutovalidateMode autoValidateMode; 24 | final BoxConstraints? suffixIconConstraints; 25 | final bool obscureText; 26 | final FocusNode? focusNode; 27 | final TextInputAction? textInputAction; 28 | 29 | const TextFieldComponent( 30 | {Key? key, 31 | required this.labelText, 32 | this.controller, 33 | this.prefixIcon, 34 | this.suffixIcon, 35 | this.keyboardType = TextInputType.text, 36 | this.validator, 37 | this.onChanged, 38 | this.onSaved, 39 | this.maxLength, 40 | this.maxLines = 1, 41 | this.minLines = 1, 42 | this.textInputAction, 43 | this.initialValue, 44 | this.readOnly = false, 45 | this.focusNode, 46 | this.onTap, 47 | this.enabled = true, 48 | this.autoValidateMode = AutovalidateMode.onUserInteraction, 49 | this.addHint = false, 50 | this.suffixIconConstraints, 51 | this.obscureText = false}) 52 | : super(key: key); 53 | 54 | @override 55 | Widget build(BuildContext context) { 56 | return TextFormField( 57 | onTap: onTap, 58 | focusNode: focusNode, 59 | readOnly: readOnly, 60 | initialValue: initialValue, 61 | keyboardType: keyboardType, 62 | autovalidateMode: autoValidateMode, 63 | controller: controller, 64 | validator: validator, 65 | onChanged: onChanged, 66 | minLines: minLines, 67 | maxLines: maxLines, 68 | onSaved: onSaved, 69 | textInputAction: textInputAction, 70 | enabled: enabled, 71 | obscureText: obscureText, 72 | inputFormatters: maxLength == null 73 | ? null 74 | : [ 75 | LengthLimitingTextInputFormatter(maxLength), 76 | if (keyboardType == TextInputType.number) 77 | FilteringTextInputFormatter.digitsOnly 78 | ], 79 | style: Get.textTheme.bodyText1!.copyWith(fontSize: 14), 80 | decoration: InputDecoration( 81 | contentPadding: 82 | const EdgeInsets.symmetric(vertical: 10.0, horizontal: 12), 83 | border: OutlineInputBorder( 84 | borderRadius: BorderRadius.circular(10.0), 85 | borderSide: BorderSide( 86 | color: Get.theme.primaryColor)), 87 | enabledBorder: 88 | OutlineInputBorder(borderRadius: BorderRadius.circular(10.0), 89 | borderSide: const BorderSide( 90 | color: Colors.grey)), 91 | errorBorder: OutlineInputBorder( 92 | borderRadius: BorderRadius.circular(10.0), 93 | borderSide: BorderSide( 94 | color: Get.theme.primaryColor)), 95 | focusedBorder: OutlineInputBorder( 96 | borderRadius: BorderRadius.circular(10.0), 97 | borderSide: BorderSide( 98 | color: Get.theme.primaryColor, width: 1)), 99 | hintText: labelText, 100 | hintStyle: 101 | Get.textTheme.headline4!.merge(const TextStyle(fontSize: 13, color: Colors.black54)), 102 | prefixIconConstraints: 103 | const BoxConstraints(maxHeight: 25, maxWidth: 51), 104 | prefixIcon: prefixIcon == null 105 | ? null 106 | : SizedBox(width: 50, child: prefixIcon), 107 | suffixIcon: suffixIcon == null 108 | ? null 109 | : SizedBox(width: 50, child: suffixIcon), 110 | suffixIconConstraints: suffixIconConstraints ?? 111 | const BoxConstraints(maxHeight: 51, maxWidth: 51))); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /lib/presentation/ui/widget/text_field_search_component.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Developer: Lakhani kamlesh 3 | Create Date: 24-11-21 3:41 4 | */ 5 | 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter/services.dart'; 8 | import 'package:get/get.dart'; 9 | 10 | class TextFieldSearchComponent extends StatelessWidget { 11 | final String labelText; 12 | final String? initialValue; 13 | final Widget? prefixIcon, suffixIcon; 14 | final TextInputType keyboardType; 15 | //final FormFieldValidator? validator; 16 | final String? Function(String?)? validator; 17 | final TextEditingController? controller; 18 | final ValueChanged? onChanged, onSaved; 19 | final int? maxLength, maxLines; 20 | final int minLines; 21 | final bool readOnly, addHint, enabled; 22 | final Function()? onTap; 23 | final AutovalidateMode autoValidateMode; 24 | final BoxConstraints? suffixIconConstraints; 25 | final bool obscureText; 26 | final FocusNode? focusNode; 27 | final TextInputAction? textInputAction; 28 | 29 | const TextFieldSearchComponent( 30 | {Key? key, 31 | required this.labelText, 32 | this.controller, 33 | this.prefixIcon, 34 | this.suffixIcon, 35 | this.keyboardType = TextInputType.text, 36 | this.validator, 37 | this.onChanged, 38 | this.onSaved, 39 | this.maxLength, 40 | this.maxLines = 1, 41 | this.minLines = 1, 42 | this.textInputAction, 43 | this.initialValue, 44 | this.readOnly = false, 45 | this.focusNode, 46 | this.onTap, 47 | this.enabled = true, 48 | this.autoValidateMode = AutovalidateMode.onUserInteraction, 49 | this.addHint = false, 50 | this.suffixIconConstraints, 51 | this.obscureText = false}) 52 | : super(key: key); 53 | 54 | @override 55 | Widget build(BuildContext context) { 56 | return SizedBox( 57 | height: 40, 58 | child: TextFormField( 59 | onTap: onTap, 60 | focusNode: focusNode, 61 | readOnly: readOnly, 62 | initialValue: initialValue, 63 | keyboardType: keyboardType, 64 | autovalidateMode: autoValidateMode, 65 | controller: controller, 66 | validator: validator, 67 | onChanged: onChanged, 68 | minLines: minLines, 69 | maxLines: maxLines, 70 | onSaved: onSaved, 71 | textInputAction: textInputAction, 72 | enabled: enabled, 73 | obscureText: obscureText, 74 | inputFormatters: maxLength == null 75 | ? null 76 | : [ 77 | LengthLimitingTextInputFormatter(maxLength), 78 | if (keyboardType == TextInputType.number) 79 | FilteringTextInputFormatter.digitsOnly 80 | ], 81 | style: Get.textTheme.bodyText1!.copyWith(fontSize: 13), 82 | decoration: InputDecoration( 83 | contentPadding: 84 | const EdgeInsets.symmetric(vertical: 10.0, horizontal: 12), 85 | border: OutlineInputBorder( 86 | borderRadius: BorderRadius.circular(40.0), 87 | borderSide: const BorderSide( 88 | color: Colors.grey)), 89 | enabledBorder: 90 | OutlineInputBorder(borderRadius: BorderRadius.circular(40.0), 91 | borderSide: const BorderSide( 92 | color: Colors.grey)), 93 | errorBorder: OutlineInputBorder( 94 | borderRadius: BorderRadius.circular(40.0), 95 | borderSide: const BorderSide( 96 | color: Colors.grey)), 97 | focusedBorder: OutlineInputBorder( 98 | borderRadius: BorderRadius.circular(40.0), 99 | borderSide: const BorderSide( 100 | color: Colors.grey)), 101 | hintText: labelText, 102 | hintStyle: 103 | Get.textTheme.headline4!.merge(const TextStyle(fontSize: 13, color: Colors.grey)), 104 | prefixIconConstraints: 105 | const BoxConstraints(maxHeight: 25, maxWidth: 51), 106 | prefixIcon: prefixIcon == null 107 | ? null 108 | : SizedBox(width: 30, child: prefixIcon), 109 | suffixIcon: suffixIcon == null 110 | ? null 111 | : SizedBox(width: 30, child: suffixIcon), 112 | suffixIconConstraints: suffixIconConstraints ?? 113 | const BoxConstraints(maxHeight: 16, maxWidth: 51)))); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /lib/presentation/ui/widget/widget.dart: -------------------------------------------------------------------------------- 1 | export 'form_button_component.dart'; 2 | export 'form_icon_loading_component.dart'; 3 | export 'text_field_component.dart'; 4 | export 'text_field_search_component.dart'; -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: vendor 2 | description: A new Flutter project. 3 | 4 | publish_to: 'none' 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=2.16.0-134.5.beta<3.0.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | # GetX 16 | get: 17 | get_storage: 18 | 19 | cupertino_icons: 20 | connectivity_plus: 21 | logger: 22 | equatable: 23 | json_annotation: 24 | google_fonts: 25 | line_icons: 26 | flutter_phone_direct_caller: 27 | maps_launcher: 28 | intl: 29 | qr_code_scanner: 30 | dio_helper_flutter: 1.0.13 31 | dartz: 32 | dio: 33 | network_info_plus: 34 | rxdart: 35 | 36 | dev_dependencies: 37 | flutter_test: 38 | sdk: flutter 39 | flutter_lints: 40 | json_serializable: 41 | build_runner: 42 | 43 | flutter: 44 | uses-material-design: true 45 | 46 | assets: 47 | - assets/image/ -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | import 'package:vendor/main.dart'; 11 | 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | --------------------------------------------------------------------------------