commit 45850796dcc870af01134ad6abeb2c69bf18e7d3 Author: Azmat-7860 Date: Sat Sep 12 11:22:07 2026 +0530 Adding base project of flutter-hybrid diff --git a/README.md b/README.md new file mode 100644 index 0000000..303317e --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# authsec_flutter_hybrid + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..0d29021 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..9ee1421 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,67 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace "com.example.authsec_flutter_hybrid" + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.authsec_flutter_hybrid" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies {} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b09befd --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/authsec_flutter_hybrid/MainActivity.kt b/android/app/src/main/kotlin/com/example/authsec_flutter_hybrid/MainActivity.kt new file mode 100644 index 0000000..d2d6f4f --- /dev/null +++ b/android/app/src/main/kotlin/com/example/authsec_flutter_hybrid/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.authsec_flutter_hybrid + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/authsec_flutter_hybrid_android.iml b/android/authsec_flutter_hybrid_android.iml new file mode 100644 index 0000000..1899969 --- /dev/null +++ b/android/authsec_flutter_hybrid_android.iml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..e83fb5d --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,30 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..598d13f --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3c472b9 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..7cd7128 --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,29 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() + + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } + + plugins { + id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false +} + +include ":app" diff --git a/assets/.DS_Store b/assets/.DS_Store new file mode 100644 index 0000000..ee8f8e8 Binary files /dev/null and b/assets/.DS_Store differ diff --git a/assets/fonts/HadWinIcons.ttf b/assets/fonts/HadWinIcons.ttf new file mode 100644 index 0000000..869d8d6 Binary files /dev/null and b/assets/fonts/HadWinIcons.ttf differ diff --git a/assets/fonts/OCRAStd.otf b/assets/fonts/OCRAStd.otf new file mode 100644 index 0000000..aee7c35 Binary files /dev/null and b/assets/fonts/OCRAStd.otf differ diff --git a/assets/icon/icon.png b/assets/icon/icon.png new file mode 100644 index 0000000..41e834f Binary files /dev/null and b/assets/icon/icon.png differ diff --git a/assets/images/card_flow_assets/american-express-backside.png b/assets/images/card_flow_assets/american-express-backside.png new file mode 100644 index 0000000..1548444 Binary files /dev/null and b/assets/images/card_flow_assets/american-express-backside.png differ diff --git a/assets/images/card_flow_assets/american-express-frontside.png b/assets/images/card_flow_assets/american-express-frontside.png new file mode 100644 index 0000000..dd2c687 Binary files /dev/null and b/assets/images/card_flow_assets/american-express-frontside.png differ diff --git a/assets/images/card_flow_assets/default-backside.png b/assets/images/card_flow_assets/default-backside.png new file mode 100644 index 0000000..2e4bf1f Binary files /dev/null and b/assets/images/card_flow_assets/default-backside.png differ diff --git a/assets/images/card_flow_assets/default-frontside.png b/assets/images/card_flow_assets/default-frontside.png new file mode 100644 index 0000000..5c2f7f1 Binary files /dev/null and b/assets/images/card_flow_assets/default-frontside.png differ diff --git a/assets/images/card_flow_assets/discover-backside.png b/assets/images/card_flow_assets/discover-backside.png new file mode 100644 index 0000000..c9f4461 Binary files /dev/null and b/assets/images/card_flow_assets/discover-backside.png differ diff --git a/assets/images/card_flow_assets/discover-frontside.png b/assets/images/card_flow_assets/discover-frontside.png new file mode 100644 index 0000000..fbe7be7 Binary files /dev/null and b/assets/images/card_flow_assets/discover-frontside.png differ diff --git a/assets/images/card_flow_assets/maestro-backside.png b/assets/images/card_flow_assets/maestro-backside.png new file mode 100644 index 0000000..f5093be Binary files /dev/null and b/assets/images/card_flow_assets/maestro-backside.png differ diff --git a/assets/images/card_flow_assets/maestro-frontside.png b/assets/images/card_flow_assets/maestro-frontside.png new file mode 100644 index 0000000..6b892ed Binary files /dev/null and b/assets/images/card_flow_assets/maestro-frontside.png differ diff --git a/assets/images/card_flow_assets/mastercard-backside.png b/assets/images/card_flow_assets/mastercard-backside.png new file mode 100644 index 0000000..684530a Binary files /dev/null and b/assets/images/card_flow_assets/mastercard-backside.png differ diff --git a/assets/images/card_flow_assets/mastercard-frontside.png b/assets/images/card_flow_assets/mastercard-frontside.png new file mode 100644 index 0000000..b3739bb Binary files /dev/null and b/assets/images/card_flow_assets/mastercard-frontside.png differ diff --git a/assets/images/card_flow_assets/visa-backside.png b/assets/images/card_flow_assets/visa-backside.png new file mode 100644 index 0000000..21e0ae3 Binary files /dev/null and b/assets/images/card_flow_assets/visa-backside.png differ diff --git a/assets/images/card_flow_assets/visa-frontside.png b/assets/images/card_flow_assets/visa-frontside.png new file mode 100644 index 0000000..0d30ff5 Binary files /dev/null and b/assets/images/card_flow_assets/visa-frontside.png differ diff --git a/assets/images/checkmark.png b/assets/images/checkmark.png new file mode 100644 index 0000000..1b00724 Binary files /dev/null and b/assets/images/checkmark.png differ diff --git a/assets/images/cloudnsuresp.svg b/assets/images/cloudnsuresp.svg new file mode 100644 index 0000000..dd7dd7a --- /dev/null +++ b/assets/images/cloudnsuresp.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/download.jpeg b/assets/images/download.jpeg new file mode 100644 index 0000000..e5bca5d Binary files /dev/null and b/assets/images/download.jpeg differ diff --git a/assets/images/hadwin_system/cldnsure.png b/assets/images/hadwin_system/cldnsure.png new file mode 100644 index 0000000..890f7bd Binary files /dev/null and b/assets/images/hadwin_system/cldnsure.png differ diff --git a/assets/images/hadwin_system/cloudsure-logo.png b/assets/images/hadwin_system/cloudsure-logo.png new file mode 100644 index 0000000..dd996b9 Binary files /dev/null and b/assets/images/hadwin_system/cloudsure-logo.png differ diff --git a/assets/images/hadwin_system/hadwin-adaptive-logo.png b/assets/images/hadwin_system/hadwin-adaptive-logo.png new file mode 100644 index 0000000..8f867db Binary files /dev/null and b/assets/images/hadwin_system/hadwin-adaptive-logo.png differ diff --git a/assets/images/hadwin_system/hadwin-banner.png b/assets/images/hadwin_system/hadwin-banner.png new file mode 100644 index 0000000..4834883 Binary files /dev/null and b/assets/images/hadwin_system/hadwin-banner.png differ diff --git a/assets/images/hadwin_system/hadwin-logo-lite.png b/assets/images/hadwin_system/hadwin-logo-lite.png new file mode 100644 index 0000000..0eb33d9 Binary files /dev/null and b/assets/images/hadwin_system/hadwin-logo-lite.png differ diff --git a/assets/images/hadwin_system/hadwin-logo-with-name.png b/assets/images/hadwin_system/hadwin-logo-with-name.png new file mode 100644 index 0000000..d6595c7 Binary files /dev/null and b/assets/images/hadwin_system/hadwin-logo-with-name.png differ diff --git a/assets/images/hadwin_system/hadwin-logo.png b/assets/images/hadwin_system/hadwin-logo.png new file mode 100644 index 0000000..c3e60ee Binary files /dev/null and b/assets/images/hadwin_system/hadwin-logo.png differ diff --git a/assets/images/hadwin_system/hadwin-name.png b/assets/images/hadwin_system/hadwin-name.png new file mode 100644 index 0000000..66b7e8d Binary files /dev/null and b/assets/images/hadwin_system/hadwin-name.png differ diff --git a/assets/images/hadwin_system/hadwin-splash-screen-logo.png b/assets/images/hadwin_system/hadwin-splash-screen-logo.png new file mode 100644 index 0000000..4f3d4ce Binary files /dev/null and b/assets/images/hadwin_system/hadwin-splash-screen-logo.png differ diff --git a/assets/images/hadwin_system/magicpattern-blob-1652765120695.png b/assets/images/hadwin_system/magicpattern-blob-1652765120695.png new file mode 100644 index 0000000..b70b588 Binary files /dev/null and b/assets/images/hadwin_system/magicpattern-blob-1652765120695.png differ diff --git a/assets/images/image_not_found.png b/assets/images/image_not_found.png new file mode 100644 index 0000000..840d828 Binary files /dev/null and b/assets/images/image_not_found.png differ diff --git a/assets/images/img_1200pxdocxicon.png b/assets/images/img_1200pxdocxicon.png new file mode 100644 index 0000000..c7d4c9a Binary files /dev/null and b/assets/images/img_1200pxdocxicon.png differ diff --git a/assets/images/img_1200pxpdffileicon.png b/assets/images/img_1200pxpdffileicon.png new file mode 100644 index 0000000..9ede32e Binary files /dev/null and b/assets/images/img_1200pxpdffileicon.png differ diff --git a/assets/images/img_2560pxstripel.png b/assets/images/img_2560pxstripel.png new file mode 100644 index 0000000..d689612 Binary files /dev/null and b/assets/images/img_2560pxstripel.png differ diff --git a/assets/images/img_81_48x48.png b/assets/images/img_81_48x48.png new file mode 100644 index 0000000..ef55893 Binary files /dev/null and b/assets/images/img_81_48x48.png differ diff --git a/assets/images/img_airplane_black_900.svg b/assets/images/img_airplane_black_900.svg new file mode 100644 index 0000000..2ca1aa0 --- /dev/null +++ b/assets/images/img_airplane_black_900.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/img_appstoreicon.png b/assets/images/img_appstoreicon.png new file mode 100644 index 0000000..5e590c4 Binary files /dev/null and b/assets/images/img_appstoreicon.png differ diff --git a/assets/images/img_arrowdown.svg b/assets/images/img_arrowdown.svg new file mode 100644 index 0000000..fd39b88 --- /dev/null +++ b/assets/images/img_arrowdown.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowdown_blue_gray_200.svg b/assets/images/img_arrowdown_blue_gray_200.svg new file mode 100644 index 0000000..e096498 --- /dev/null +++ b/assets/images/img_arrowdown_blue_gray_200.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowdown_blue_gray_400.svg b/assets/images/img_arrowdown_blue_gray_400.svg new file mode 100644 index 0000000..370fd5c --- /dev/null +++ b/assets/images/img_arrowdown_blue_gray_400.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowdown_blue_gray_600.svg b/assets/images/img_arrowdown_blue_gray_600.svg new file mode 100644 index 0000000..790b643 --- /dev/null +++ b/assets/images/img_arrowdown_blue_gray_600.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowgrowthsolid_red_700.svg b/assets/images/img_arrowgrowthsolid_red_700.svg new file mode 100644 index 0000000..b9e0c8a --- /dev/null +++ b/assets/images/img_arrowgrowthsolid_red_700.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowleft.svg b/assets/images/img_arrowleft.svg new file mode 100644 index 0000000..580b8d8 --- /dev/null +++ b/assets/images/img_arrowleft.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowleft_blue_gray_900.svg b/assets/images/img_arrowleft_blue_gray_900.svg new file mode 100644 index 0000000..580b8d8 --- /dev/null +++ b/assets/images/img_arrowleft_blue_gray_900.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowright.svg b/assets/images/img_arrowright.svg new file mode 100644 index 0000000..63bc36f --- /dev/null +++ b/assets/images/img_arrowright.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowright_blue_a700_1.svg b/assets/images/img_arrowright_blue_a700_1.svg new file mode 100644 index 0000000..0b6911d --- /dev/null +++ b/assets/images/img_arrowright_blue_a700_1.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowright_blue_gray_400.svg b/assets/images/img_arrowright_blue_gray_400.svg new file mode 100644 index 0000000..63bc36f --- /dev/null +++ b/assets/images/img_arrowright_blue_gray_400.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowright_blue_gray_600.svg b/assets/images/img_arrowright_blue_gray_600.svg new file mode 100644 index 0000000..8dfeb18 --- /dev/null +++ b/assets/images/img_arrowright_blue_gray_600.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowright_blue_gray_600_1.svg b/assets/images/img_arrowright_blue_gray_600_1.svg new file mode 100644 index 0000000..6ca99c8 --- /dev/null +++ b/assets/images/img_arrowright_blue_gray_600_1.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowright_white_a700.svg b/assets/images/img_arrowright_white_a700.svg new file mode 100644 index 0000000..1d1f306 --- /dev/null +++ b/assets/images/img_arrowright_white_a700.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowup_blue_gray_400.svg b/assets/images/img_arrowup_blue_gray_400.svg new file mode 100644 index 0000000..4d9b7fb --- /dev/null +++ b/assets/images/img_arrowup_blue_gray_400.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_arrowup_green_600.svg b/assets/images/img_arrowup_green_600.svg new file mode 100644 index 0000000..e0b756c --- /dev/null +++ b/assets/images/img_arrowup_green_600.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_bluetoothbsolid.svg b/assets/images/img_bluetoothbsolid.svg new file mode 100644 index 0000000..66205bd --- /dev/null +++ b/assets/images/img_bluetoothbsolid.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_brightness.svg b/assets/images/img_brightness.svg new file mode 100644 index 0000000..92e26c8 --- /dev/null +++ b/assets/images/img_brightness.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/images/img_calendar.svg b/assets/images/img_calendar.svg new file mode 100644 index 0000000..6271087 --- /dev/null +++ b/assets/images/img_calendar.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/img_calendar_24x24.svg b/assets/images/img_calendar_24x24.svg new file mode 100644 index 0000000..79ad353 --- /dev/null +++ b/assets/images/img_calendar_24x24.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_calendar_blue_gray_400.svg b/assets/images/img_calendar_blue_gray_400.svg new file mode 100644 index 0000000..5e0e86b --- /dev/null +++ b/assets/images/img_calendar_blue_gray_400.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_call.svg b/assets/images/img_call.svg new file mode 100644 index 0000000..db62efd --- /dev/null +++ b/assets/images/img_call.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_car.svg b/assets/images/img_car.svg new file mode 100644 index 0000000..38a669c --- /dev/null +++ b/assets/images/img_car.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/img_chart.png b/assets/images/img_chart.png new file mode 100644 index 0000000..3c0460b Binary files /dev/null and b/assets/images/img_chart.png differ diff --git a/assets/images/img_chartsmicro_blue_50_1.svg b/assets/images/img_chartsmicro_blue_50_1.svg new file mode 100644 index 0000000..b1f9f9a --- /dev/null +++ b/assets/images/img_chartsmicro_blue_50_1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/img_chartsmicro_blue_50_45x150.svg b/assets/images/img_chartsmicro_blue_50_45x150.svg new file mode 100644 index 0000000..af4146e --- /dev/null +++ b/assets/images/img_chartsmicro_blue_50_45x150.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/img_check1.png b/assets/images/img_check1.png new file mode 100644 index 0000000..b9608d8 Binary files /dev/null and b/assets/images/img_check1.png differ diff --git a/assets/images/img_checkbox.svg b/assets/images/img_checkbox.svg new file mode 100644 index 0000000..eeba937 --- /dev/null +++ b/assets/images/img_checkbox.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_checkmark.svg b/assets/images/img_checkmark.svg new file mode 100644 index 0000000..5aeb0e3 --- /dev/null +++ b/assets/images/img_checkmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_checkmark_16x16.svg b/assets/images/img_checkmark_16x16.svg new file mode 100644 index 0000000..57ca573 --- /dev/null +++ b/assets/images/img_checkmark_16x16.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_checkmark_56x56.svg b/assets/images/img_checkmark_56x56.svg new file mode 100644 index 0000000..cb75c8f --- /dev/null +++ b/assets/images/img_checkmark_56x56.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_checkmark_green_600.svg b/assets/images/img_checkmark_green_600.svg new file mode 100644 index 0000000..cb75c8f --- /dev/null +++ b/assets/images/img_checkmark_green_600.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_clock.svg b/assets/images/img_clock.svg new file mode 100644 index 0000000..5528126 --- /dev/null +++ b/assets/images/img_clock.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_close.svg b/assets/images/img_close.svg new file mode 100644 index 0000000..35ac382 --- /dev/null +++ b/assets/images/img_close.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/img_close_18x18.svg b/assets/images/img_close_18x18.svg new file mode 100644 index 0000000..ec82728 --- /dev/null +++ b/assets/images/img_close_18x18.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_close_24x24.svg b/assets/images/img_close_24x24.svg new file mode 100644 index 0000000..01cf3bc --- /dev/null +++ b/assets/images/img_close_24x24.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_close_32x48.svg b/assets/images/img_close_32x48.svg new file mode 100644 index 0000000..74442be --- /dev/null +++ b/assets/images/img_close_32x48.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_close_53x53.svg b/assets/images/img_close_53x53.svg new file mode 100644 index 0000000..b850a2e --- /dev/null +++ b/assets/images/img_close_53x53.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/images/img_companylogo.png b/assets/images/img_companylogo.png new file mode 100644 index 0000000..6eac3d0 Binary files /dev/null and b/assets/images/img_companylogo.png differ diff --git a/assets/images/img_contrast.svg b/assets/images/img_contrast.svg new file mode 100644 index 0000000..fe4f391 --- /dev/null +++ b/assets/images/img_contrast.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_dashboard.svg b/assets/images/img_dashboard.svg new file mode 100644 index 0000000..45bd79d --- /dev/null +++ b/assets/images/img_dashboard.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_download.svg b/assets/images/img_download.svg new file mode 100644 index 0000000..730f783 --- /dev/null +++ b/assets/images/img_download.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_edit.svg b/assets/images/img_edit.svg new file mode 100644 index 0000000..e3c1696 --- /dev/null +++ b/assets/images/img_edit.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/img_ellipse12_24x24_1.png b/assets/images/img_ellipse12_24x24_1.png new file mode 100644 index 0000000..ae82ea4 Binary files /dev/null and b/assets/images/img_ellipse12_24x24_1.png differ diff --git a/assets/images/img_ellipse12_24x24_2.png b/assets/images/img_ellipse12_24x24_2.png new file mode 100644 index 0000000..3846b4e Binary files /dev/null and b/assets/images/img_ellipse12_24x24_2.png differ diff --git a/assets/images/img_ellipse13_24x25_1.png b/assets/images/img_ellipse13_24x25_1.png new file mode 100644 index 0000000..af45d4e Binary files /dev/null and b/assets/images/img_ellipse13_24x25_1.png differ diff --git a/assets/images/img_ellipse13_24x25_2.png b/assets/images/img_ellipse13_24x25_2.png new file mode 100644 index 0000000..981cdbb Binary files /dev/null and b/assets/images/img_ellipse13_24x25_2.png differ diff --git a/assets/images/img_ellipse15_24x24.png b/assets/images/img_ellipse15_24x24.png new file mode 100644 index 0000000..0b396af Binary files /dev/null and b/assets/images/img_ellipse15_24x24.png differ diff --git a/assets/images/img_ellipse27_18x18.png b/assets/images/img_ellipse27_18x18.png new file mode 100644 index 0000000..bf13985 Binary files /dev/null and b/assets/images/img_ellipse27_18x18.png differ diff --git a/assets/images/img_ellipse28.png b/assets/images/img_ellipse28.png new file mode 100644 index 0000000..3b025b3 Binary files /dev/null and b/assets/images/img_ellipse28.png differ diff --git a/assets/images/img_ellipse3_60x60_1.png b/assets/images/img_ellipse3_60x60_1.png new file mode 100644 index 0000000..0e73dd6 Binary files /dev/null and b/assets/images/img_ellipse3_60x60_1.png differ diff --git a/assets/images/img_ellipse3_60x60_2.png b/assets/images/img_ellipse3_60x60_2.png new file mode 100644 index 0000000..069646a Binary files /dev/null and b/assets/images/img_ellipse3_60x60_2.png differ diff --git a/assets/images/img_ellipse54_18x18.png b/assets/images/img_ellipse54_18x18.png new file mode 100644 index 0000000..43224d3 Binary files /dev/null and b/assets/images/img_ellipse54_18x18.png differ diff --git a/assets/images/img_ellipse5_150x150.png b/assets/images/img_ellipse5_150x150.png new file mode 100644 index 0000000..bf76190 Binary files /dev/null and b/assets/images/img_ellipse5_150x150.png differ diff --git a/assets/images/img_ellipse66_24x24.png b/assets/images/img_ellipse66_24x24.png new file mode 100644 index 0000000..8912bc2 Binary files /dev/null and b/assets/images/img_ellipse66_24x24.png differ diff --git a/assets/images/img_eye.svg b/assets/images/img_eye.svg new file mode 100644 index 0000000..23c96b8 --- /dev/null +++ b/assets/images/img_eye.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_facebook.svg b/assets/images/img_facebook.svg new file mode 100644 index 0000000..6bee2d5 --- /dev/null +++ b/assets/images/img_facebook.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_file.svg b/assets/images/img_file.svg new file mode 100644 index 0000000..1cea5a1 --- /dev/null +++ b/assets/images/img_file.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_file_16x16.svg b/assets/images/img_file_16x16.svg new file mode 100644 index 0000000..6fcb158 --- /dev/null +++ b/assets/images/img_file_16x16.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/img_file_24x24.svg b/assets/images/img_file_24x24.svg new file mode 100644 index 0000000..3b48b8f --- /dev/null +++ b/assets/images/img_file_24x24.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_file_26x26.svg b/assets/images/img_file_26x26.svg new file mode 100644 index 0000000..5b2d3cf --- /dev/null +++ b/assets/images/img_file_26x26.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_fingerprint.svg b/assets/images/img_fingerprint.svg new file mode 100644 index 0000000..2257974 --- /dev/null +++ b/assets/images/img_fingerprint.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_fire.svg b/assets/images/img_fire.svg new file mode 100644 index 0000000..ebcebf3 --- /dev/null +++ b/assets/images/img_fire.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/img_flagargentina1.png b/assets/images/img_flagargentina1.png new file mode 100644 index 0000000..d13fa2e Binary files /dev/null and b/assets/images/img_flagargentina1.png differ diff --git a/assets/images/img_flagargentina1_1.png b/assets/images/img_flagargentina1_1.png new file mode 100644 index 0000000..5c7964d Binary files /dev/null and b/assets/images/img_flagargentina1_1.png differ diff --git a/assets/images/img_flagargentina1_32x48.png b/assets/images/img_flagargentina1_32x48.png new file mode 100644 index 0000000..fada4f8 Binary files /dev/null and b/assets/images/img_flagargentina1_32x48.png differ diff --git a/assets/images/img_forward.svg b/assets/images/img_forward.svg new file mode 100644 index 0000000..2baed4d --- /dev/null +++ b/assets/images/img_forward.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_frame9880.svg b/assets/images/img_frame9880.svg new file mode 100644 index 0000000..5f91dff --- /dev/null +++ b/assets/images/img_frame9880.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/img_globe.svg b/assets/images/img_globe.svg new file mode 100644 index 0000000..d871f37 --- /dev/null +++ b/assets/images/img_globe.svg @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_globe_18x18.svg b/assets/images/img_globe_18x18.svg new file mode 100644 index 0000000..79407d2 --- /dev/null +++ b/assets/images/img_globe_18x18.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_globe_white_a700.svg b/assets/images/img_globe_white_a700.svg new file mode 100644 index 0000000..7ddbf38 --- /dev/null +++ b/assets/images/img_globe_white_a700.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_globe_white_a700_18x18.svg b/assets/images/img_globe_white_a700_18x18.svg new file mode 100644 index 0000000..3f745f1 --- /dev/null +++ b/assets/images/img_globe_white_a700_18x18.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_globe_yellow_800.svg b/assets/images/img_globe_yellow_800.svg new file mode 100644 index 0000000..19ef74f --- /dev/null +++ b/assets/images/img_globe_yellow_800.svg @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_globe_yellow_800_18x18.svg b/assets/images/img_globe_yellow_800_18x18.svg new file mode 100644 index 0000000..1c94314 --- /dev/null +++ b/assets/images/img_globe_yellow_800_18x18.svg @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_google.svg b/assets/images/img_google.svg new file mode 100644 index 0000000..3919517 --- /dev/null +++ b/assets/images/img_google.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/assets/images/img_googleadsenselogo.png b/assets/images/img_googleadsenselogo.png new file mode 100644 index 0000000..04781ed Binary files /dev/null and b/assets/images/img_googleadsenselogo.png differ diff --git a/assets/images/img_grid.svg b/assets/images/img_grid.svg new file mode 100644 index 0000000..1f8a0f1 --- /dev/null +++ b/assets/images/img_grid.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_group10210.svg b/assets/images/img_group10210.svg new file mode 100644 index 0000000..bb989fd --- /dev/null +++ b/assets/images/img_group10210.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/img_group10451.svg b/assets/images/img_group10451.svg new file mode 100644 index 0000000..bed88cb --- /dev/null +++ b/assets/images/img_group10451.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/images/img_group10720.svg b/assets/images/img_group10720.svg new file mode 100644 index 0000000..817a5b8 --- /dev/null +++ b/assets/images/img_group10720.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_group10737.svg b/assets/images/img_group10737.svg new file mode 100644 index 0000000..d84b62e --- /dev/null +++ b/assets/images/img_group10737.svg @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_group10785.svg b/assets/images/img_group10785.svg new file mode 100644 index 0000000..5babd1e --- /dev/null +++ b/assets/images/img_group10785.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/img_group1830.svg b/assets/images/img_group1830.svg new file mode 100644 index 0000000..b7a1412 --- /dev/null +++ b/assets/images/img_group1830.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_group185.svg b/assets/images/img_group185.svg new file mode 100644 index 0000000..f2880e6 --- /dev/null +++ b/assets/images/img_group185.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/img_group2507.svg b/assets/images/img_group2507.svg new file mode 100644 index 0000000..ca9b28b --- /dev/null +++ b/assets/images/img_group2507.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/assets/images/img_group97.svg b/assets/images/img_group97.svg new file mode 100644 index 0000000..e689767 --- /dev/null +++ b/assets/images/img_group97.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/img_group9839.svg b/assets/images/img_group9839.svg new file mode 100644 index 0000000..2a76589 --- /dev/null +++ b/assets/images/img_group9839.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_image122.png b/assets/images/img_image122.png new file mode 100644 index 0000000..96eb7dc Binary files /dev/null and b/assets/images/img_image122.png differ diff --git a/assets/images/img_image123.png b/assets/images/img_image123.png new file mode 100644 index 0000000..fe1acca Binary files /dev/null and b/assets/images/img_image123.png differ diff --git a/assets/images/img_image124.png b/assets/images/img_image124.png new file mode 100644 index 0000000..1f8103d Binary files /dev/null and b/assets/images/img_image124.png differ diff --git a/assets/images/img_image125.png b/assets/images/img_image125.png new file mode 100644 index 0000000..acd33cf Binary files /dev/null and b/assets/images/img_image125.png differ diff --git a/assets/images/img_info.svg b/assets/images/img_info.svg new file mode 100644 index 0000000..669b57a --- /dev/null +++ b/assets/images/img_info.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_lightbulb.svg b/assets/images/img_lightbulb.svg new file mode 100644 index 0000000..ef3c3db --- /dev/null +++ b/assets/images/img_lightbulb.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_linkedin.svg b/assets/images/img_linkedin.svg new file mode 100644 index 0000000..6e3cf85 --- /dev/null +++ b/assets/images/img_linkedin.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/img_linkedin_1_1.svg b/assets/images/img_linkedin_1_1.svg new file mode 100644 index 0000000..4b60552 --- /dev/null +++ b/assets/images/img_linkedin_1_1.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/images/img_location.svg b/assets/images/img_location.svg new file mode 100644 index 0000000..bb7b432 --- /dev/null +++ b/assets/images/img_location.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_location_20x20.svg b/assets/images/img_location_20x20.svg new file mode 100644 index 0000000..b71041b --- /dev/null +++ b/assets/images/img_location_20x20.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_lock.svg b/assets/images/img_lock.svg new file mode 100644 index 0000000..8f4e07e --- /dev/null +++ b/assets/images/img_lock.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_lock_24x24.svg b/assets/images/img_lock_24x24.svg new file mode 100644 index 0000000..9dd3176 --- /dev/null +++ b/assets/images/img_lock_24x24.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/img_lock_53x53.svg b/assets/images/img_lock_53x53.svg new file mode 100644 index 0000000..3587f28 --- /dev/null +++ b/assets/images/img_lock_53x53.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/img_mail.svg b/assets/images/img_mail.svg new file mode 100644 index 0000000..320c937 --- /dev/null +++ b/assets/images/img_mail.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_map.svg b/assets/images/img_map.svg new file mode 100644 index 0000000..9e3a578 --- /dev/null +++ b/assets/images/img_map.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/images/img_menu.svg b/assets/images/img_menu.svg new file mode 100644 index 0000000..2f9b93f --- /dev/null +++ b/assets/images/img_menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_menu_1.svg b/assets/images/img_menu_1.svg new file mode 100644 index 0000000..2f9b93f --- /dev/null +++ b/assets/images/img_menu_1.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_microphone.svg b/assets/images/img_microphone.svg new file mode 100644 index 0000000..a4c9c35 --- /dev/null +++ b/assets/images/img_microphone.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_microphone_20x20.svg b/assets/images/img_microphone_20x20.svg new file mode 100644 index 0000000..6ea429d --- /dev/null +++ b/assets/images/img_microphone_20x20.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_minimize.svg b/assets/images/img_minimize.svg new file mode 100644 index 0000000..c3f0024 --- /dev/null +++ b/assets/images/img_minimize.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_minussolid.svg b/assets/images/img_minussolid.svg new file mode 100644 index 0000000..d760f6a --- /dev/null +++ b/assets/images/img_minussolid.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_mobile.svg b/assets/images/img_mobile.svg new file mode 100644 index 0000000..06454c4 --- /dev/null +++ b/assets/images/img_mobile.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/img_moonoutline.svg b/assets/images/img_moonoutline.svg new file mode 100644 index 0000000..402b607 --- /dev/null +++ b/assets/images/img_moonoutline.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_music.svg b/assets/images/img_music.svg new file mode 100644 index 0000000..4afbd6e --- /dev/null +++ b/assets/images/img_music.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_notification.svg b/assets/images/img_notification.svg new file mode 100644 index 0000000..bc6f202 --- /dev/null +++ b/assets/images/img_notification.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_overflowmenu.svg b/assets/images/img_overflowmenu.svg new file mode 100644 index 0000000..5850aa5 --- /dev/null +++ b/assets/images/img_overflowmenu.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/img_overflowmenu_1.svg b/assets/images/img_overflowmenu_1.svg new file mode 100644 index 0000000..8a8af58 --- /dev/null +++ b/assets/images/img_overflowmenu_1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/img_overflowmenu_16x16.svg b/assets/images/img_overflowmenu_16x16.svg new file mode 100644 index 0000000..b2096fd --- /dev/null +++ b/assets/images/img_overflowmenu_16x16.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/img_overflowmenu_white_a700.svg b/assets/images/img_overflowmenu_white_a700.svg new file mode 100644 index 0000000..a0e6a66 --- /dev/null +++ b/assets/images/img_overflowmenu_white_a700.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/img_pic.png b/assets/images/img_pic.png new file mode 100644 index 0000000..e8892ed Binary files /dev/null and b/assets/images/img_pic.png differ diff --git a/assets/images/img_pic_1.png b/assets/images/img_pic_1.png new file mode 100644 index 0000000..8604403 Binary files /dev/null and b/assets/images/img_pic_1.png differ diff --git a/assets/images/img_pic_2.png b/assets/images/img_pic_2.png new file mode 100644 index 0000000..24c9ad3 Binary files /dev/null and b/assets/images/img_pic_2.png differ diff --git a/assets/images/img_pic_3.png b/assets/images/img_pic_3.png new file mode 100644 index 0000000..a1a8ba9 Binary files /dev/null and b/assets/images/img_pic_3.png differ diff --git a/assets/images/img_pic_4.png b/assets/images/img_pic_4.png new file mode 100644 index 0000000..c27807e Binary files /dev/null and b/assets/images/img_pic_4.png differ diff --git a/assets/images/img_pic_44x44.png b/assets/images/img_pic_44x44.png new file mode 100644 index 0000000..b761582 Binary files /dev/null and b/assets/images/img_pic_44x44.png differ diff --git a/assets/images/img_pic_44x44_1.png b/assets/images/img_pic_44x44_1.png new file mode 100644 index 0000000..e8892ed Binary files /dev/null and b/assets/images/img_pic_44x44_1.png differ diff --git a/assets/images/img_pic_44x44_2.png b/assets/images/img_pic_44x44_2.png new file mode 100644 index 0000000..8604403 Binary files /dev/null and b/assets/images/img_pic_44x44_2.png differ diff --git a/assets/images/img_pic_44x44_3.png b/assets/images/img_pic_44x44_3.png new file mode 100644 index 0000000..c27807e Binary files /dev/null and b/assets/images/img_pic_44x44_3.png differ diff --git a/assets/images/img_pic_50x50_1.png b/assets/images/img_pic_50x50_1.png new file mode 100644 index 0000000..4dc7bae Binary files /dev/null and b/assets/images/img_pic_50x50_1.png differ diff --git a/assets/images/img_pic_50x50_2.png b/assets/images/img_pic_50x50_2.png new file mode 100644 index 0000000..64143eb Binary files /dev/null and b/assets/images/img_pic_50x50_2.png differ diff --git a/assets/images/img_pic_50x50_3.png b/assets/images/img_pic_50x50_3.png new file mode 100644 index 0000000..3cc99de Binary files /dev/null and b/assets/images/img_pic_50x50_3.png differ diff --git a/assets/images/img_play.svg b/assets/images/img_play.svg new file mode 100644 index 0000000..d52124f --- /dev/null +++ b/assets/images/img_play.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_plus_1.svg b/assets/images/img_plus_1.svg new file mode 100644 index 0000000..fd05f6e --- /dev/null +++ b/assets/images/img_plus_1.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_plus_40x40.svg b/assets/images/img_plus_40x40.svg new file mode 100644 index 0000000..42d9426 --- /dev/null +++ b/assets/images/img_plus_40x40.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_plus_white_a700.svg b/assets/images/img_plus_white_a700.svg new file mode 100644 index 0000000..001057e --- /dev/null +++ b/assets/images/img_plus_white_a700.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_profileimglarge_25.png b/assets/images/img_profileimglarge_25.png new file mode 100644 index 0000000..8ac3543 Binary files /dev/null and b/assets/images/img_profileimglarge_25.png differ diff --git a/assets/images/img_profileimglarge_40x40_1.png b/assets/images/img_profileimglarge_40x40_1.png new file mode 100644 index 0000000..7556e22 Binary files /dev/null and b/assets/images/img_profileimglarge_40x40_1.png differ diff --git a/assets/images/img_profileimglarge_40x40_2.png b/assets/images/img_profileimglarge_40x40_2.png new file mode 100644 index 0000000..52e928c Binary files /dev/null and b/assets/images/img_profileimglarge_40x40_2.png differ diff --git a/assets/images/img_profileimglarge_40x40_3.png b/assets/images/img_profileimglarge_40x40_3.png new file mode 100644 index 0000000..cca8a2f Binary files /dev/null and b/assets/images/img_profileimglarge_40x40_3.png differ diff --git a/assets/images/img_profileimglarge_40x40_4.png b/assets/images/img_profileimglarge_40x40_4.png new file mode 100644 index 0000000..5ac2409 Binary files /dev/null and b/assets/images/img_profileimglarge_40x40_4.png differ diff --git a/assets/images/img_question.svg b/assets/images/img_question.svg new file mode 100644 index 0000000..c1b48a0 --- /dev/null +++ b/assets/images/img_question.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_question_24x24.svg b/assets/images/img_question_24x24.svg new file mode 100644 index 0000000..2158aa2 --- /dev/null +++ b/assets/images/img_question_24x24.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/img_rectangle1.png b/assets/images/img_rectangle1.png new file mode 100644 index 0000000..25f8be7 Binary files /dev/null and b/assets/images/img_rectangle1.png differ diff --git a/assets/images/img_rectangle1314_190x396_2.png b/assets/images/img_rectangle1314_190x396_2.png new file mode 100644 index 0000000..903065c Binary files /dev/null and b/assets/images/img_rectangle1314_190x396_2.png differ diff --git a/assets/images/img_rectangle1_16x16.png b/assets/images/img_rectangle1_16x16.png new file mode 100644 index 0000000..c2c6890 Binary files /dev/null and b/assets/images/img_rectangle1_16x16.png differ diff --git a/assets/images/img_rectangle1_16x16_1.png b/assets/images/img_rectangle1_16x16_1.png new file mode 100644 index 0000000..c2c6890 Binary files /dev/null and b/assets/images/img_rectangle1_16x16_1.png differ diff --git a/assets/images/img_rectangle458_530x396.png b/assets/images/img_rectangle458_530x396.png new file mode 100644 index 0000000..c5ed231 Binary files /dev/null and b/assets/images/img_rectangle458_530x396.png differ diff --git a/assets/images/img_rectangle458_706x396.png b/assets/images/img_rectangle458_706x396.png new file mode 100644 index 0000000..f58757a Binary files /dev/null and b/assets/images/img_rectangle458_706x396.png differ diff --git a/assets/images/img_rectangle_102x102_1.png b/assets/images/img_rectangle_102x102_1.png new file mode 100644 index 0000000..1e8b570 Binary files /dev/null and b/assets/images/img_rectangle_102x102_1.png differ diff --git a/assets/images/img_rectangle_126x126_1.png b/assets/images/img_rectangle_126x126_1.png new file mode 100644 index 0000000..16648a6 Binary files /dev/null and b/assets/images/img_rectangle_126x126_1.png differ diff --git a/assets/images/img_rectangle_126x126_2.png b/assets/images/img_rectangle_126x126_2.png new file mode 100644 index 0000000..08dc7b5 Binary files /dev/null and b/assets/images/img_rectangle_126x126_2.png differ diff --git a/assets/images/img_rectangle_126x126_3.png b/assets/images/img_rectangle_126x126_3.png new file mode 100644 index 0000000..add230a Binary files /dev/null and b/assets/images/img_rectangle_126x126_3.png differ diff --git a/assets/images/img_rectangle_126x126_4.png b/assets/images/img_rectangle_126x126_4.png new file mode 100644 index 0000000..7263027 Binary files /dev/null and b/assets/images/img_rectangle_126x126_4.png differ diff --git a/assets/images/img_rectangle_126x126_5.png b/assets/images/img_rectangle_126x126_5.png new file mode 100644 index 0000000..a440e54 Binary files /dev/null and b/assets/images/img_rectangle_126x126_5.png differ diff --git a/assets/images/img_rectangle_126x126_6.png b/assets/images/img_rectangle_126x126_6.png new file mode 100644 index 0000000..fdcc1c5 Binary files /dev/null and b/assets/images/img_rectangle_126x126_6.png differ diff --git a/assets/images/img_rectangle_126x126_7.png b/assets/images/img_rectangle_126x126_7.png new file mode 100644 index 0000000..84ea180 Binary files /dev/null and b/assets/images/img_rectangle_126x126_7.png differ diff --git a/assets/images/img_rectangle_126x126_8.png b/assets/images/img_rectangle_126x126_8.png new file mode 100644 index 0000000..c9a59ec Binary files /dev/null and b/assets/images/img_rectangle_126x126_8.png differ diff --git a/assets/images/img_refresh.svg b/assets/images/img_refresh.svg new file mode 100644 index 0000000..23836dd --- /dev/null +++ b/assets/images/img_refresh.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_refresh_24x24.svg b/assets/images/img_refresh_24x24.svg new file mode 100644 index 0000000..986c325 --- /dev/null +++ b/assets/images/img_refresh_24x24.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_rupaylogo1.png b/assets/images/img_rupaylogo1.png new file mode 100644 index 0000000..5f24744 Binary files /dev/null and b/assets/images/img_rupaylogo1.png differ diff --git a/assets/images/img_rupaylogo1_18x56.png b/assets/images/img_rupaylogo1_18x56.png new file mode 100644 index 0000000..7b7fe78 Binary files /dev/null and b/assets/images/img_rupaylogo1_18x56.png differ diff --git a/assets/images/img_search.svg b/assets/images/img_search.svg new file mode 100644 index 0000000..4fdc2f6 --- /dev/null +++ b/assets/images/img_search.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_search_blue_a100.svg b/assets/images/img_search_blue_a100.svg new file mode 100644 index 0000000..c47f242 --- /dev/null +++ b/assets/images/img_search_blue_a100.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_search_blue_a700.svg b/assets/images/img_search_blue_a700.svg new file mode 100644 index 0000000..34889c9 --- /dev/null +++ b/assets/images/img_search_blue_a700.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_search_blue_gray_200.svg b/assets/images/img_search_blue_gray_200.svg new file mode 100644 index 0000000..6b6560e --- /dev/null +++ b/assets/images/img_search_blue_gray_200.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_search_blue_gray_400.svg b/assets/images/img_search_blue_gray_400.svg new file mode 100644 index 0000000..5229c4d --- /dev/null +++ b/assets/images/img_search_blue_gray_400.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_search_blue_gray_900.svg b/assets/images/img_search_blue_gray_900.svg new file mode 100644 index 0000000..b609db6 --- /dev/null +++ b/assets/images/img_search_blue_gray_900.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_search_white_a700.svg b/assets/images/img_search_white_a700.svg new file mode 100644 index 0000000..30b5679 --- /dev/null +++ b/assets/images/img_search_white_a700.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/img_search_white_a700_20x20.svg b/assets/images/img_search_white_a700_20x20.svg new file mode 100644 index 0000000..1a2bbfe --- /dev/null +++ b/assets/images/img_search_white_a700_20x20.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/img_settings.svg b/assets/images/img_settings.svg new file mode 100644 index 0000000..1bae507 --- /dev/null +++ b/assets/images/img_settings.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_settings_1.svg b/assets/images/img_settings_1.svg new file mode 100644 index 0000000..70dd7e8 --- /dev/null +++ b/assets/images/img_settings_1.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/img_settings_24x24.svg b/assets/images/img_settings_24x24.svg new file mode 100644 index 0000000..6b5c8b8 --- /dev/null +++ b/assets/images/img_settings_24x24.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_share_24x24.svg b/assets/images/img_share_24x24.svg new file mode 100644 index 0000000..3f95560 --- /dev/null +++ b/assets/images/img_share_24x24.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_signal.svg b/assets/images/img_signal.svg new file mode 100644 index 0000000..1aaac0f --- /dev/null +++ b/assets/images/img_signal.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_signal_10x56.svg b/assets/images/img_signal_10x56.svg new file mode 100644 index 0000000..9b2a9c4 --- /dev/null +++ b/assets/images/img_signal_10x56.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_signal_gray_500.svg b/assets/images/img_signal_gray_500.svg new file mode 100644 index 0000000..5da6168 --- /dev/null +++ b/assets/images/img_signal_gray_500.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/img_smartwatchwhitesportband.svg b/assets/images/img_smartwatchwhitesportband.svg new file mode 100644 index 0000000..264ffd7 --- /dev/null +++ b/assets/images/img_smartwatchwhitesportband.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_sort.svg b/assets/images/img_sort.svg new file mode 100644 index 0000000..1d12390 --- /dev/null +++ b/assets/images/img_sort.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_sportscricket.svg b/assets/images/img_sportscricket.svg new file mode 100644 index 0000000..020d356 --- /dev/null +++ b/assets/images/img_sportscricket.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/images/img_star.svg b/assets/images/img_star.svg new file mode 100644 index 0000000..97b2176 --- /dev/null +++ b/assets/images/img_star.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_ticket.svg b/assets/images/img_ticket.svg new file mode 100644 index 0000000..f5cb64c --- /dev/null +++ b/assets/images/img_ticket.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_ticket_20x20.svg b/assets/images/img_ticket_20x20.svg new file mode 100644 index 0000000..07be546 --- /dev/null +++ b/assets/images/img_ticket_20x20.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_trash.svg b/assets/images/img_trash.svg new file mode 100644 index 0000000..138193f --- /dev/null +++ b/assets/images/img_trash.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_twitter.svg b/assets/images/img_twitter.svg new file mode 100644 index 0000000..af8d42f --- /dev/null +++ b/assets/images/img_twitter.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_twitter_20x20.svg b/assets/images/img_twitter_20x20.svg new file mode 100644 index 0000000..ad05a20 --- /dev/null +++ b/assets/images/img_twitter_20x20.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_uiiconmoonlight.svg b/assets/images/img_uiiconmoonlight.svg new file mode 100644 index 0000000..a172efa --- /dev/null +++ b/assets/images/img_uiiconmoonlight.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_unsplashenrurz62wui_50x50.png b/assets/images/img_unsplashenrurz62wui_50x50.png new file mode 100644 index 0000000..9b9c2d4 Binary files /dev/null and b/assets/images/img_unsplashenrurz62wui_50x50.png differ diff --git a/assets/images/img_upload.svg b/assets/images/img_upload.svg new file mode 100644 index 0000000..2273af0 --- /dev/null +++ b/assets/images/img_upload.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_user.svg b/assets/images/img_user.svg new file mode 100644 index 0000000..1d9b202 --- /dev/null +++ b/assets/images/img_user.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_user_24x24.svg b/assets/images/img_user_24x24.svg new file mode 100644 index 0000000..749b4eb --- /dev/null +++ b/assets/images/img_user_24x24.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/images/img_vector.svg b/assets/images/img_vector.svg new file mode 100644 index 0000000..35b78cf --- /dev/null +++ b/assets/images/img_vector.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_vector3_gray_900_01.svg b/assets/images/img_vector3_gray_900_01.svg new file mode 100644 index 0000000..6a9a90f --- /dev/null +++ b/assets/images/img_vector3_gray_900_01.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_vector_blue_a700_13x141.svg b/assets/images/img_vector_blue_a700_13x141.svg new file mode 100644 index 0000000..adf5001 --- /dev/null +++ b/assets/images/img_vector_blue_a700_13x141.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_vector_blue_a700_34x360.svg b/assets/images/img_vector_blue_a700_34x360.svg new file mode 100644 index 0000000..40be370 --- /dev/null +++ b/assets/images/img_vector_blue_a700_34x360.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_vector_red_600.svg b/assets/images/img_vector_red_600.svg new file mode 100644 index 0000000..9a4cb46 --- /dev/null +++ b/assets/images/img_vector_red_600.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_volume.svg b/assets/images/img_volume.svg new file mode 100644 index 0000000..ebf0037 --- /dev/null +++ b/assets/images/img_volume.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_vscodeiconsfiletypeexcel.svg b/assets/images/img_vscodeiconsfiletypeexcel.svg new file mode 100644 index 0000000..9782da0 --- /dev/null +++ b/assets/images/img_vscodeiconsfiletypeexcel.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/img_whatsapp.svg b/assets/images/img_whatsapp.svg new file mode 100644 index 0000000..aea236b --- /dev/null +++ b/assets/images/img_whatsapp.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/img_wordpresslogo1.png b/assets/images/img_wordpresslogo1.png new file mode 100644 index 0000000..a8d5239 Binary files /dev/null and b/assets/images/img_wordpresslogo1.png differ diff --git a/assets/images/img_x32location_red_700.svg b/assets/images/img_x32location_red_700.svg new file mode 100644 index 0000000..4293605 --- /dev/null +++ b/assets/images/img_x32location_red_700.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/notification_assets/file-error.png b/assets/images/notification_assets/file-error.png new file mode 100644 index 0000000..57c9996 Binary files /dev/null and b/assets/images/notification_assets/file-error.png differ diff --git a/assets/images/notification_assets/no-wifi.png b/assets/images/notification_assets/no-wifi.png new file mode 100644 index 0000000..7cbef0a Binary files /dev/null and b/assets/images/notification_assets/no-wifi.png differ diff --git a/assets/images/onboarding_assets/online-shopping-yuliia-osadcha-bg-less.png b/assets/images/onboarding_assets/online-shopping-yuliia-osadcha-bg-less.png new file mode 100644 index 0000000..bc72b5c Binary files /dev/null and b/assets/images/onboarding_assets/online-shopping-yuliia-osadcha-bg-less.png differ diff --git a/assets/images/onboarding_assets/wfh-mohamed-chahin-bg-less.png b/assets/images/onboarding_assets/wfh-mohamed-chahin-bg-less.png new file mode 100644 index 0000000..c1d4485 Binary files /dev/null and b/assets/images/onboarding_assets/wfh-mohamed-chahin-bg-less.png differ diff --git a/assets/images/piggy-bank.png b/assets/images/piggy-bank.png new file mode 100644 index 0000000..b3f37c5 Binary files /dev/null and b/assets/images/piggy-bank.png differ diff --git a/assets/images/transparent_card_brands/american-express.png b/assets/images/transparent_card_brands/american-express.png new file mode 100644 index 0000000..a34ecb8 Binary files /dev/null and b/assets/images/transparent_card_brands/american-express.png differ diff --git a/assets/images/transparent_card_brands/diners-club.png b/assets/images/transparent_card_brands/diners-club.png new file mode 100644 index 0000000..7d56622 Binary files /dev/null and b/assets/images/transparent_card_brands/diners-club.png differ diff --git a/assets/images/transparent_card_brands/discover.png b/assets/images/transparent_card_brands/discover.png new file mode 100644 index 0000000..dbe35b6 Binary files /dev/null and b/assets/images/transparent_card_brands/discover.png differ diff --git a/assets/images/transparent_card_brands/jcb.png b/assets/images/transparent_card_brands/jcb.png new file mode 100644 index 0000000..32ff876 Binary files /dev/null and b/assets/images/transparent_card_brands/jcb.png differ diff --git a/assets/images/transparent_card_brands/maestro.png b/assets/images/transparent_card_brands/maestro.png new file mode 100644 index 0000000..452aa7c Binary files /dev/null and b/assets/images/transparent_card_brands/maestro.png differ diff --git a/assets/images/transparent_card_brands/mastercard.png b/assets/images/transparent_card_brands/mastercard.png new file mode 100644 index 0000000..8013e43 Binary files /dev/null and b/assets/images/transparent_card_brands/mastercard.png differ diff --git a/assets/images/transparent_card_brands/rupay.png b/assets/images/transparent_card_brands/rupay.png new file mode 100644 index 0000000..c02984b Binary files /dev/null and b/assets/images/transparent_card_brands/rupay.png differ diff --git a/assets/images/transparent_card_brands/solo.png b/assets/images/transparent_card_brands/solo.png new file mode 100644 index 0000000..6b695a9 Binary files /dev/null and b/assets/images/transparent_card_brands/solo.png differ diff --git a/assets/images/transparent_card_brands/switch.png b/assets/images/transparent_card_brands/switch.png new file mode 100644 index 0000000..d064ae7 Binary files /dev/null and b/assets/images/transparent_card_brands/switch.png differ diff --git a/assets/images/transparent_card_brands/union-pay.png b/assets/images/transparent_card_brands/union-pay.png new file mode 100644 index 0000000..4db2002 Binary files /dev/null and b/assets/images/transparent_card_brands/union-pay.png differ diff --git a/assets/images/transparent_card_brands/visa.png b/assets/images/transparent_card_brands/visa.png new file mode 100644 index 0000000..888b313 Binary files /dev/null and b/assets/images/transparent_card_brands/visa.png differ diff --git a/authsec_flutter_hybrid.iml b/authsec_flutter_hybrid.iml new file mode 100644 index 0000000..f66303d --- /dev/null +++ b/authsec_flutter_hybrid.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9625e10 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a76b946 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,614 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807E294A63A400263BE5 /* Frameworks */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..87131a0 --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..dc9ada4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..7353c41 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..6ed2d93 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4cd7b00 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..fe73094 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..321773c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..502f463 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..e9f5fea Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..84ac32a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..8953cba Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..0467bf1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..09bd0d4 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Authsec Flutter Hybrid + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + authsec_flutter_hybrid + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/lib/.DS_Store b/lib/.DS_Store new file mode 100644 index 0000000..d0ba74e Binary files /dev/null and b/lib/.DS_Store differ diff --git a/lib/Entity/.DS_Store b/lib/Entity/.DS_Store new file mode 100644 index 0000000..f2458e1 Binary files /dev/null and b/lib/Entity/.DS_Store differ diff --git a/lib/Entity/test.dart b/lib/Entity/test.dart new file mode 100644 index 0000000..e2be432 --- /dev/null +++ b/lib/Entity/test.dart @@ -0,0 +1 @@ +class test {} diff --git a/lib/LocalStorage/DatabaseHelper.dart b/lib/LocalStorage/DatabaseHelper.dart new file mode 100644 index 0000000..5aaf546 --- /dev/null +++ b/lib/LocalStorage/DatabaseHelper.dart @@ -0,0 +1,128 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:authsec_flutter_hybrid/LocalStorage/TableQuery.dart'; +import 'package:path/path.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:sqflite_common_ffi/sqflite_ffi.dart'; + +class DatabaseHelper { + DatabaseHelper.internal(); + static final DatabaseHelper instance = DatabaseHelper.internal(); + TableQuery tablequery = TableQuery(); + // factory DatabaseHelper() => instance; + + static DatabaseHelper? _instance; + static Database? _database; + + DatabaseHelper._privateConstructor(); + + factory DatabaseHelper() { + _instance ??= DatabaseHelper._privateConstructor(); + return _instance!; + } + + Future get database async { + if (_database != null) { + print('get database ... $_database'); + return _database!; + } + _database = await initDatabase(); + return _database!; + } + + Future initDatabase() async { + try { + Directory directory = await getApplicationDocumentsDirectory(); + String path = join(directory.path, 'my_database.db'); + print('database path is $path'); + + // final db = await openDatabase('my_database.db'); + + var openDb = await openDatabase( + path, + version: 1, + onCreate: (db, version) => _createDatabaseTables(db), + onUpgrade: (db, int oldversion, int newversion) async { + if (oldversion < newversion) { + print("Version Upgrade"); + } + }, + ); + + // Check if the table exists + // var tableResult = await openDb.query('sqlite_master', + // columns: ['name'], + // where: 'type = ? AND name = ?', + // whereArgs: ['table', 'company']); + + // if (tableResult.isEmpty) { + // print('Table does not exist'); + // } else { + // print('table data is $tableResult'); + // print('company Table exists'); + // } + + print('open db is...... ${openDb.database}'); + return openDb; + } catch (e) { + print('Error initializing database: $e'); + rethrow; // rethrow the error to see the full stack trace + } + } + + Future _createDatabaseTables(Database db) async { + tablequery.createOtherTable(db); + } + +// create other table + + // Future _createOtherTable(Database db) async { + // _createTable(db, 'research_status', 'status_name'); + // } + + // Future _createTable( + // Database db, String tableName, String fieldName) async { + // var tableExists = await _isTableExists(db, tableName); + // if (!tableExists) { + // print('$tableName making.....'); + // await db.execute( + // ''' + // CREATE TABLE $tableName ( + // id INTEGER PRIMARY KEY AUTOINCREMENT, + // accountId TEXT, + // createdAt TEXT, + // createdBy TEXT, + // updatedAt TEXT, + // updatedBy TEXT, + // extn1 TEXT, + // extn2 TEXT, + // extn3 TEXT, + // extn4 TEXT, + // extn5 TEXT, + // extn6 TEXT, + // extn7 TEXT, + // extn8 TEXT, + // extn9 TEXT, + // extn10 TEXT, + // extn11 TEXT, + // extn12 TEXT, + // extn13 TEXT, + // extn14 TEXT, + // extn15 TEXT, + // active INTEGER, + // description TEXT, + // $fieldName TEXT + // )'''); + // } else { + // print('$tableName table exist'); + // } + // } + + // Future _isTableExists(Database db, String tableName) async { + // var result = await db.rawQuery( + // 'SELECT * FROM sqlite_master WHERE type = ? AND name = ?', + // ['table', tableName], + // ); + // return result.isNotEmpty; + // } +} diff --git a/lib/LocalStorage/TableQuery.dart b/lib/LocalStorage/TableQuery.dart new file mode 100644 index 0000000..4308a88 --- /dev/null +++ b/lib/LocalStorage/TableQuery.dart @@ -0,0 +1,104 @@ + + + + +import 'package:sqflite/sqflite.dart'; + +class TableQuery { + Future createOtherTable(Database db) async { + // Table Query + _createGauravt2(db, 'Gauravt2'); + + + _createGauravtest1(db, 'Gauravtest1'); + + + } + + // Table Query Data + + Future _createGauravt2(Database db, String tableName) async { + var tableExists = await _isTableExists(db, tableName); + if (!tableExists) { + print('$tableName making.....'); + await db.execute( + ''' + CREATE TABLE $tableName ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + accountId TEXT, + createdAt TEXT, + createdBy TEXT, + updatedAt TEXT, + updatedBy TEXT, + extn1 TEXT, + extn2 TEXT, + extn3 TEXT, + extn4 TEXT, + extn5 TEXT, + extn6 TEXT, + extn7 TEXT, + extn8 TEXT, + extn9 TEXT, + extn10 TEXT, + extn11 TEXT, + extn12 TEXT, + extn13 TEXT, + extn14 TEXT, + extn15 TEXT, + phone TEXT, + nme TEXT, + imageupload TEXT, + + )'''); + } else { + print('$tableName table exist'); + } + } + + + Future _createGauravtest1(Database db, String tableName) async { + var tableExists = await _isTableExists(db, tableName); + if (!tableExists) { + print('$tableName making.....'); + await db.execute( + ''' + CREATE TABLE $tableName ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + accountId TEXT, + createdAt TEXT, + createdBy TEXT, + updatedAt TEXT, + updatedBy TEXT, + extn1 TEXT, + extn2 TEXT, + extn3 TEXT, + extn4 TEXT, + extn5 TEXT, + extn6 TEXT, + extn7 TEXT, + extn8 TEXT, + extn9 TEXT, + extn10 TEXT, + extn11 TEXT, + extn12 TEXT, + extn13 TEXT, + extn14 TEXT, + extn15 TEXT, + college TEXT, + Name TEXT, + + )'''); + } else { + print('$tableName table exist'); + } + } + + + Future _isTableExists(Database db, String tableName) async { + var result = await db.rawQuery( + 'SELECT * FROM sqlite_master WHERE type = ? AND name = ?', + ['table', tableName], + ); + return result.isNotEmpty; + } +} \ No newline at end of file diff --git a/lib/LocalStorage/UniController.dart b/lib/LocalStorage/UniController.dart new file mode 100644 index 0000000..797b278 --- /dev/null +++ b/lib/LocalStorage/UniController.dart @@ -0,0 +1,96 @@ +import 'package:sqflite/sqflite.dart'; +import 'package:sqflite_common_ffi/sqflite_ffi.dart'; + +import 'databasehelper.dart'; + +class UniController { + final conn = DatabaseHelper.instance; + +// get entity + Future>> getentities(String tableName) async { + Database db = await conn.database; + return await db.query(tableName); + } + + // insert + Future insertEntity( + Map entity, String tableName) async { + Database db = await conn.database; + + // entity['active'] = entity['active'] ? 1 : 0; + + // Insert data + var entityId = await db.insert(tableName, entity); + if (entityId != null && entityId > 0) { + print('$tableName Id data is inserted. $tableName Id ID: $entityId'); + } else { + print('Failed to insert $tableName.'); + } + + return entityId; + } + +// insert multiple table + Future insertEntities( + List> entities, String tableName) async { + Database db = await conn.database; + Batch batch = db.batch(); + + print('multiple entity is com is $entities'); + + for (var entity in entities) { + insertEntity(entity, tableName); + } + + await batch.commit(); + } + +// update Entity + Future update(String tableName, int entityId, + Map updatedEntity) async { + Database db = await conn.database; + + int rowsAffected = await db.update(tableName, updatedEntity, + where: 'id = ?', whereArgs: [entityId]); + + if (rowsAffected > 0) { + print('$tableName data updated successfully.'); + } else { + print('Failed to update $tableName data.'); + } + + return rowsAffected; + } + +// Deleting entity + + Future delete(String tableName, int entityId) async { + Database db = await conn.database; + + // Delete the company + int rowsAffected = + await db.delete(tableName, where: 'id = ?', whereArgs: [entityId]); + + if (rowsAffected > 0) { + print('$tableName data deleted successfully.'); + } else { + print('Failed to delete comp $tableName any data.'); + } + + return rowsAffected; + } + +// get count + Future getDataCount(String tableNmae) async { + Database db = await conn.database; + + // Get the count of rows in the company table + int count = Sqflite.firstIntValue( + await db.rawQuery('SELECT COUNT(*) FROM $tableNmae'))! + .toInt(); + + print('Number of $tableNmae in the table: $count'); + + return count; + } +} diff --git a/lib/LocalStorage/localSyncronize.dart b/lib/LocalStorage/localSyncronize.dart new file mode 100644 index 0000000..c2e1f13 --- /dev/null +++ b/lib/LocalStorage/localSyncronize.dart @@ -0,0 +1,168 @@ +// import 'dart:io'; + +// import 'package:connectivity/connectivity.dart'; +// import 'package:sqflite_common_ffi/sqflite_ffi.dart'; +// import '../../providers/token_manager.dart'; +// import '../../resources/api_constants.dart'; + +// import 'UniController.dart'; +// import 'companycontroller.dart'; +// import 'databasehelper.dart'; + +// class LocalSyncronizationData { +// final String baseUrl = ApiConstants.baseUrl; + +// final UniController uniController = UniController(); + +// final companycontroller companyController = companycontroller(); +// final conn = DatabaseHelper.instance; + +// static Future isInternet() async { +// var connectivityResult = await (Connectivity().checkConnectivity()); +// if (connectivityResult == ConnectivityResult.mobile) { +// final result = await InternetAddress.lookup('www.google.com'); +// if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) { +// print('mobile network connected'); +// return true; +// } else { +// return false; +// } + +// // if (await DataConnectionChecker().hasConnection) { +// // print("Mobile data detected & internet connection confirmed."); +// // return true; +// // }else{ +// // print('No internet :( Reason:'); +// // return false; +// // } +// } else if (connectivityResult == ConnectivityResult.wifi) { +// final result = await InternetAddress.lookup('www.google.com'); +// if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) { +// print('wifi connected'); +// return true; +// } else { +// print('wifi not connected'); + +// return false; +// } +// } else { +// print( +// "Neither mobile data or WIFI detected, not internet connection found."); +// return false; +// } +// } + +// // Future saveCompanyToMysql() async { +// // Database db = await conn.database; +// // final token = await TokenManager.getToken(); + +// // print('company db is $db'); +// // final List> localEntities = +// // await db.query('company', orderBy: 'id DESC'); + +// // if (localEntities.isNotEmpty) { +// // final entities = (localEntities).cast>(); + +// // for (var element in entities) { +// // companyService.createEntity1(token!, element); +// // } +// // } +// // } + +// // for research status sync +// Future fetchResearchStatusData() async { +// List userList = []; +// Database db = await conn.database; + +// try { +// final List> localEntities = +// await db.query('research_status', orderBy: 'id DESC'); + +// if (localEntities.isNotEmpty) { +// final entities = (localEntities).cast>(); + +// for (var element in entities) { +// userList.add(element); +// } +// } +// } catch (e) { +// print(e.toString()); +// } +// return userList; +// } + +// Future>> fetchAllInfo() async { +// Database db = await conn.database; +// List> researchList = []; +// try { +// final maps = await db.query('research_status'); +// for (var item in maps!) { +// researchList.add(item); +// } +// } catch (e) { +// print(e.toString()); +// } +// return researchList; +// } + +// Future saveReserachToMysql(List researchList) async { +// final token = await TokenManager.getToken(); + +// for (var i = 0; i < researchList.length; i++) { +// Map data = { +// "id": researchList[i]['id'].toString(), +// "status_name": researchList[i]['status_name'], +// "description": researchList[i]['description'], +// "active": researchList[i]['active'], +// }; +// final response = researchService.createEntity1(token!, data); + +// print('eserach res is $response'); +// } +// } + +// // from online to offline for research status + +// Future fetchResearchStatusDataOnline() async { +// List userList = []; +// Database db = await conn.database; +// final token = await TokenManager.getToken(); + +// try { +// final List> entities = +// await researchService.getEntities1(token!); + +// if (entities.isNotEmpty) { +// for (var element in entities) { +// userList.add(element); +// } +// } +// } catch (e) { +// print(e.toString()); +// } +// return userList; +// } + +// Future>> fetchReserachOnlineInfo() async { +// Database db = await conn.database; +// List> researchList = []; +// final token = await TokenManager.getToken(); + +// try { +// final List> maps = +// await researchService.getEntities1(token!); +// for (var item in maps!) { +// researchList.add(item); +// } +// } catch (e) { +// print(e.toString()); +// } +// return researchList; +// } + +// Future saveReserachToMysqlOnline(List list) async { +// for (var element in list) { +// uniController.insertEntity(element, 'research_status'); +// } +// } +// } diff --git a/lib/Utils/color_constants.dart b/lib/Utils/color_constants.dart new file mode 100644 index 0000000..593fbeb --- /dev/null +++ b/lib/Utils/color_constants.dart @@ -0,0 +1,167 @@ +import 'dart:ui'; +import 'package:flutter/material.dart'; + +class ColorConstant { + static Color gray5001 = fromHex('#f6f7fb'); + + static Color gray5002 = fromHex('#f8f9fa'); + + static Color black900B2 = fromHex('#b2000000'); + + static Color gray5003 = fromHex('#fafcff'); + + static Color lightBlue100 = fromHex('#b0e5fc'); + + static Color gray80049 = fromHex('#493c3c43'); + + static Color yellow9003f = fromHex('#3feb9612'); + + static Color red200 = fromHex('#fa9a9a'); + + static Color gray4004c = fromHex('#4cc4c4c4'); + + static Color blueA200 = fromHex('#468ee5'); + + static Color greenA100 = fromHex('#b5eacd'); + + static Color black9003f = fromHex('#3f000000'); + + static Color gray30099 = fromHex('#99e4e4e4'); + + static Color black90087 = fromHex('#87000000'); + + static Color whiteA70099 = fromHex('#99ffffff'); + + static Color black90001 = fromHex('#000000'); + + static Color blueGray90002 = fromHex('#24363c'); + + static Color blueGray90001 = fromHex('#2e3637'); + + static Color blueGray700 = fromHex('#535763'); + + static Color blueGray900 = fromHex('#262b35'); + + static Color black90003 = fromHex('#0b0a0a'); + + static Color black90002 = fromHex('#090b0d'); + + static Color redA700 = fromHex('#d80027'); + + static Color black90004 = fromHex('#000000'); + + static Color gray400 = fromHex('#c4c4c4'); + + static Color blue900 = fromHex('#003399'); + + static Color blueGray100 = fromHex('#d6dae2'); + + static Color blue700 = fromHex('#1976d2'); + + static Color blueGray300 = fromHex('#9ea8ba'); + + static Color amber500 = fromHex('#feb909'); + + static Color redA200 = fromHex('#fe555d'); + + static Color gray80099 = fromHex('#993c3c43'); + + static Color black9000c = fromHex('#0c000000'); + + static Color gray200 = fromHex('#efefef'); + + static Color gray60026 = fromHex('#266d6d6d'); + + static Color blue50 = fromHex('#e0ebff'); + + static Color indigo400 = fromHex('#4168d7'); + + static Color blueGray1006c = fromHex('#6cd1d3d4'); + + static Color black90011 = fromHex('#11000000'); + + static Color gray40001 = fromHex('#b3b3b3'); + + static Color whiteA70067 = fromHex('#67ffffff'); + + static Color gray10001 = fromHex('#fbf1f2'); + + static Color black90019 = fromHex('#19000000'); + + static Color blueGray40001 = fromHex('#888888'); + + static Color whiteA700 = fromHex('#ffffff'); + + static Color blueGray50 = fromHex('#eaecf0'); + + static Color red700 = fromHex('#d03329'); + + static Color blueA700 = fromHex('#0061ff'); + + static Color blueGray10001 = fromHex('#d6d6d6'); + + static Color gray60019 = fromHex('#197e7e7e'); + + static Color green600 = fromHex('#349765'); + + static Color blueA70001 = fromHex('#0068ff'); + + static Color gray50 = fromHex('#f9fbff'); + + static Color red100 = fromHex('#f6d6d4'); + + static Color blueGray20001 = fromHex('#adb5bd'); + + static Color black900 = fromHex('#000919'); + + static Color blueGray800 = fromHex('#37334d'); + + static Color blue5001 = fromHex('#eef4ff'); + + static Color deepOrange400 = fromHex('#d58c48'); + + static Color deepOrangeA400 = fromHex('#ff4b00'); + + static Color gray70011 = fromHex('#11555555'); + + static Color indigoA20033 = fromHex('#334871e3'); + + static Color gray90002 = fromHex('#0d062d'); + + static Color gray700 = fromHex('#666666'); + + static Color blueGray200 = fromHex('#bac1ce'); + + static Color blueGray400 = fromHex('#74839d'); + + static Color blue800 = fromHex('#2953c7'); + + static Color blueGray600 = fromHex('#5f6c86'); + + static Color gray900 = fromHex('#2a2a2a'); + + static Color gray90001 = fromHex('#212529'); + + static Color gray300 = fromHex('#d2efe0'); + + static Color gray30001 = fromHex('#e3e4e5'); + + static Color gray100 = fromHex('#f3f4f5'); + + static Color black90075 = fromHex('#75000000'); + + static Color deepOrangeA10033 = fromHex('#33dfa874'); + + static Color gray70026 = fromHex('#26555555'); + + static Color black90033 = fromHex('#33000000'); + + static Color blue200 = fromHex('#a6c8ff'); + + static Color fromHex(String hexString) { + final buffer = StringBuffer(); + if (hexString.length == 6 || hexString.length == 7) buffer.write('ff'); + buffer.write(hexString.replaceFirst('#', '')); + return Color(int.parse(buffer.toString(), radix: 16)); + } +} diff --git a/lib/Utils/image_constant.dart b/lib/Utils/image_constant.dart new file mode 100644 index 0000000..f2e69f7 --- /dev/null +++ b/lib/Utils/image_constant.dart @@ -0,0 +1,465 @@ +class ImageConstant { + //cloudnsuresp.svg + + static String imgLogoSplash = + 'assets/images/cloudnsuresp.svg'; + + + static String imgRectangle458706x396 = + 'assets/images/img_rectangle458_706x396.png'; + + static String imgVscodeiconsfiletypeexcel = + 'assets/images/img_vscodeiconsfiletypeexcel.svg'; + + static String imgGroup10737 = 'assets/images/img_group10737.svg'; + + static String imgX32locationRed700 = + 'assets/images/img_x32location_red_700.svg'; + + static String imgCar = 'assets/images/img_car.svg'; + + static String imgArrowrightWhiteA700 = + 'assets/images/img_arrowright_white_a700.svg'; + + static String imgMinussolid = 'assets/images/img_minussolid.svg'; + + static String imgSearchWhiteA70020x20 = + 'assets/images/img_search_white_a700_20x20.svg'; + + static String imgSettings24x24 = 'assets/images/img_settings_24x24.svg'; + + static String imgArrowgrowthsolidRed700 = + 'assets/images/img_arrowgrowthsolid_red_700.svg'; + + static String imgPlus1 = 'assets/images/img_plus_1.svg'; + + static String imgArrowupBlueGray400 = + 'assets/images/img_arrowup_blue_gray_400.svg'; + + static String imgTwitter20x20 = 'assets/images/img_twitter_20x20.svg'; + + static String imgClose18x18 = 'assets/images/img_close_18x18.svg'; + + static String imgRectangle102x1021 = + 'assets/images/img_rectangle_102x102_1.png'; + + static String imgRectangle1 = 'assets/images/img_rectangle1.png'; + + static String imgGrid = 'assets/images/img_grid.svg'; + + static String imgClose24x24 = 'assets/images/img_close_24x24.svg'; + + static String imgRefresh = 'assets/images/img_refresh.svg'; + + static String imgPlus40x40 = 'assets/images/img_plus_40x40.svg'; + + static String imgVectorBlueA70034x360 = + 'assets/images/img_vector_blue_a700_34x360.svg'; + + static String imgMenu1 = 'assets/images/img_menu_1.svg'; + + static String imgInfo = 'assets/images/img_info.svg'; + + static String imgFile24x24 = 'assets/images/img_file_24x24.svg'; + + static String imgVector = 'assets/images/img_vector.svg'; + + static String imgArrowleft = 'assets/images/img_arrowleft.svg'; + + static String imgGroup9839 = 'assets/images/img_group9839.svg'; + + static String imgImage125 = 'assets/images/img_image125.png'; + + static String imgWordpresslogo1 = 'assets/images/img_wordpresslogo1.png'; + + static String imgRectangle126x1266 = + 'assets/images/img_rectangle_126x126_6.png'; + + static String imgArrowdown = 'assets/images/img_arrowdown.svg'; + + static String imgGroup10785 = 'assets/images/img_group10785.svg'; + + static String imgContrast = 'assets/images/img_contrast.svg'; + + static String imgLinkedin = 'assets/images/img_linkedin.svg'; + + static String imgClose = 'assets/images/img_close.svg'; + + static String imgMusic = 'assets/images/img_music.svg'; + + static String imgLock = 'assets/images/img_lock.svg'; + + static String imgEllipse1224x241 = 'assets/images/img_ellipse12_24x24_1.png'; + + static String img8148x48 = 'assets/images/img_81_48x48.png'; + + static String imgProfileimglarge40x404 = + 'assets/images/img_profileimglarge_40x40_4.png'; + + static String imgMenu = 'assets/images/img_menu.svg'; + + static String imgFile16x16 = 'assets/images/img_file_16x16.svg'; + + static String imgRefresh24x24 = 'assets/images/img_refresh_24x24.svg'; + + static String imgChartsmicroBlue5045x150 = + 'assets/images/img_chartsmicro_blue_50_45x150.svg'; + + static String imgSearchBlueGray400 = + 'assets/images/img_search_blue_gray_400.svg'; + + static String imgSort = 'assets/images/img_sort.svg'; + + static String imgDownload = 'assets/images/img_download.svg'; + + static String imgClock = 'assets/images/img_clock.svg'; + + static String imgSettings1 = 'assets/images/img_settings_1.svg'; + + static String imgPic50x503 = 'assets/images/img_pic_50x50_3.png'; + + static String imgRectangle1314190x3962 = + 'assets/images/img_rectangle1314_190x396_2.png'; + + static String imgFacebook = 'assets/images/img_facebook.svg'; + + static String imgRectangle116x161 = + 'assets/images/img_rectangle1_16x16_1.png'; + + static String imgFlagargentina1 = 'assets/images/img_flagargentina1.png'; + + static String imgFingerprint = 'assets/images/img_fingerprint.svg'; + + static String imgGoogleadsenselogo = + 'assets/images/img_googleadsenselogo.png'; + + static String imgRectangle116x16 = 'assets/images/img_rectangle1_16x16.png'; + + static String imgArrowrightBlueGray400 = + 'assets/images/img_arrowright_blue_gray_400.svg'; + + static String imgPic44x44 = 'assets/images/img_pic_44x44.png'; + + static String imgAppstoreicon = 'assets/images/img_appstoreicon.png'; + + static String imgChart = 'assets/images/img_chart.png'; + + static String imgArrowright = 'assets/images/img_arrowright.svg'; + + static String imgRupaylogo1 = 'assets/images/img_rupaylogo1.png'; + + static String imgRectangle126x1267 = + 'assets/images/img_rectangle_126x126_7.png'; + + static String imgProfileimglarge25 = + 'assets/images/img_profileimglarge_25.png'; + + static String imgRectangle126x1261 = + 'assets/images/img_rectangle_126x126_1.png'; + + static String imgEllipse1524x24 = 'assets/images/img_ellipse15_24x24.png'; + + static String imgPic3 = 'assets/images/img_pic_3.png'; + + static String imgPic50x502 = 'assets/images/img_pic_50x50_2.png'; + + static String imgPic4 = 'assets/images/img_pic_4.png'; + + static String imgRupaylogo118x56 = 'assets/images/img_rupaylogo1_18x56.png'; + + static String imgEllipse360x602 = 'assets/images/img_ellipse3_60x60_2.png'; + + static String imgUser24x24 = 'assets/images/img_user_24x24.svg'; + + static String imgImage123 = 'assets/images/img_image123.png'; + + static String imgArrowrightBlueGray6001 = + 'assets/images/img_arrowright_blue_gray_600_1.svg'; + + static String imgUser = 'assets/images/img_user.svg'; + + static String imgGlobeYellow80018x18 = + 'assets/images/img_globe_yellow_800_18x18.svg'; + + static String imgPic1 = 'assets/images/img_pic_1.png'; + + static String imgGlobe = 'assets/images/img_globe.svg'; + + static String imgCalendarBlueGray400 = + 'assets/images/img_calendar_blue_gray_400.svg'; + + static String imgClose53x53 = 'assets/images/img_close_53x53.svg'; + + static String imgDashboard = 'assets/images/img_dashboard.svg'; + + static String imgRectangle126x1263 = + 'assets/images/img_rectangle_126x126_3.png'; + + static String imgAirplaneBlack900 = + 'assets/images/img_airplane_black_900.svg'; + + static String imgForward = 'assets/images/img_forward.svg'; + + static String imgGroup10210 = 'assets/images/img_group10210.svg'; + + static String imgShare24x24 = 'assets/images/img_share_24x24.svg'; + + static String imgLightbulb = 'assets/images/img_lightbulb.svg'; + + static String imgSearchBlueGray900 = + 'assets/images/img_search_blue_gray_900.svg'; + + static String imgImage122 = 'assets/images/img_image122.png'; + + static String imgPic44x441 = 'assets/images/img_pic_44x44_1.png'; + + static String imgSignal10x56 = 'assets/images/img_signal_10x56.svg'; + + static String imgUiiconmoonlight = 'assets/images/img_uiiconmoonlight.svg'; + + static String img1200pxpdffileicon = + 'assets/images/img_1200pxpdffileicon.png'; + + static String imgSettings = 'assets/images/img_settings.svg'; + + static String imgChartsmicroBlue501 = + 'assets/images/img_chartsmicro_blue_50_1.svg'; + + static String imgArrowdownBlueGray200 = + 'assets/images/img_arrowdown_blue_gray_200.svg'; + + static String imgGlobeWhiteA700 = 'assets/images/img_globe_white_a700.svg'; + + static String imgFire = 'assets/images/img_fire.svg'; + + static String imgVector3Gray90001 = + 'assets/images/img_vector3_gray_900_01.svg'; + + static String imgEllipse5150x150 = 'assets/images/img_ellipse5_150x150.png'; + + static String imgClose32x48 = 'assets/images/img_close_32x48.svg'; + + static String imgArrowdownBlueGray600 = + 'assets/images/img_arrowdown_blue_gray_600.svg'; + + static String imgCheckmark16x16 = 'assets/images/img_checkmark_16x16.svg'; + + static String imgCheckmarkGreen600 = + 'assets/images/img_checkmark_green_600.svg'; + + static String imgArrowrightBlueGray600 = + 'assets/images/img_arrowright_blue_gray_600.svg'; + + static String imgSearchBlueGray200 = + 'assets/images/img_search_blue_gray_200.svg'; + + static String imgRectangle126x1262 = + 'assets/images/img_rectangle_126x126_2.png'; + + static String imgCalendar24x24 = 'assets/images/img_calendar_24x24.svg'; + + static String imgVectorRed600 = 'assets/images/img_vector_red_600.svg'; + + static String imgSignal = 'assets/images/img_signal.svg'; + + static String imgProfileimglarge40x403 = + 'assets/images/img_profileimglarge_40x40_3.png'; + + static String imgLinkedin11 = 'assets/images/img_linkedin_1_1.svg'; + + static String imgPlay = 'assets/images/img_play.svg'; + + static String imgUpload = 'assets/images/img_upload.svg'; + + static String imgEllipse1224x242 = 'assets/images/img_ellipse12_24x24_2.png'; + + static String imgMap = 'assets/images/img_map.svg'; + + static String imgLock24x24 = 'assets/images/img_lock_24x24.svg'; + + static String imgRectangle458530x396 = + 'assets/images/img_rectangle458_530x396.png'; + + static String imgEllipse5418x18 = 'assets/images/img_ellipse54_18x18.png'; + + static String imgGroup10720 = 'assets/images/img_group10720.svg'; + + static String imgNotification = 'assets/images/img_notification.svg'; + + static String imgSignalGray500 = 'assets/images/img_signal_gray_500.svg'; + + static String imgRectangle126x1265 = + 'assets/images/img_rectangle_126x126_5.png'; + + static String imgMobile = 'assets/images/img_mobile.svg'; + + static String imgArrowdownBlueGray400 = + 'assets/images/img_arrowdown_blue_gray_400.svg'; + + static String imgEllipse28 = 'assets/images/img_ellipse28.png'; + + static String imgGroup185 = 'assets/images/img_group185.svg'; + + static String imgCheck1 = 'assets/images/img_check1.png'; + + static String imgPic44x443 = 'assets/images/img_pic_44x44_3.png'; + + static String imgPic50x501 = 'assets/images/img_pic_50x50_1.png'; + + static String imgVolume = 'assets/images/img_volume.svg'; + + static String imgSearch = 'assets/images/img_search.svg'; + + static String imgMail = 'assets/images/img_mail.svg'; + + static String imgGlobeYellow800 = 'assets/images/img_globe_yellow_800.svg'; + + static String imgGlobe18x18 = 'assets/images/img_globe_18x18.svg'; + + static String imgBluetoothbsolid = 'assets/images/img_bluetoothbsolid.svg'; + + static String imgFile = 'assets/images/img_file.svg'; + + static String imgSearchWhiteA700 = 'assets/images/img_search_white_a700.svg'; + + static String imgFile26x26 = 'assets/images/img_file_26x26.svg'; + + static String imgPlusWhiteA700 = 'assets/images/img_plus_white_a700.svg'; + + static String imgEdit = 'assets/images/img_edit.svg'; + + static String imgRectangle126x1268 = + 'assets/images/img_rectangle_126x126_8.png'; + + static String imgWhatsapp = 'assets/images/img_whatsapp.svg'; + + static String imgCall = 'assets/images/img_call.svg'; + + static String imgLocation = 'assets/images/img_location.svg'; + + static String imgGroup10451 = 'assets/images/img_group10451.svg'; + + static String imgGroup97 = 'assets/images/img_group97.svg'; + + static String imgEllipse6624x24 = 'assets/images/img_ellipse66_24x24.png'; + + static String imgStar = 'assets/images/img_star.svg'; + + static String imgCheckmark = 'assets/images/img_checkmark.svg'; + + static String imgTwitter = 'assets/images/img_twitter.svg'; + + static String img2560pxstripel = 'assets/images/img_2560pxstripel.png'; + + static String imgSportscricket = 'assets/images/img_sportscricket.svg'; + + static String imgOverflowmenuWhiteA700 = + 'assets/images/img_overflowmenu_white_a700.svg'; + + static String imgGoogle = 'assets/images/img_google.svg'; + + static String imgFrame9880 = 'assets/images/img_frame9880.svg'; + + static String imgVectorBlueA70013x141 = + 'assets/images/img_vector_blue_a700_13x141.svg'; + + static String imgTicket = 'assets/images/img_ticket.svg'; + + static String imgSmartwatchwhitesportband = + 'assets/images/img_smartwatchwhitesportband.svg'; + + static String imgProfileimglarge40x402 = + 'assets/images/img_profileimglarge_40x40_2.png'; + + static String imgPic = 'assets/images/img_pic.png'; + + static String imgEllipse1324x252 = 'assets/images/img_ellipse13_24x25_2.png'; + + static String imgOverflowmenu1 = 'assets/images/img_overflowmenu_1.svg'; + + static String imgFlagargentina11 = 'assets/images/img_flagargentina1_1.png'; + + static String imgGlobeWhiteA70018x18 = + 'assets/images/img_globe_white_a700_18x18.svg'; + + static String imgEye = 'assets/images/img_eye.svg'; + + static String imgSearchBlueA700 = 'assets/images/img_search_blue_a700.svg'; + + static String imgPic2 = 'assets/images/img_pic_2.png'; + + static String imgQuestion = 'assets/images/img_question.svg'; + + static String imgMicrophone20x20 = 'assets/images/img_microphone_20x20.svg'; + + static String imgEllipse1324x251 = 'assets/images/img_ellipse13_24x25_1.png'; + + static String imgCheckmark56x56 = 'assets/images/img_checkmark_56x56.svg'; + + static String imgTicket20x20 = 'assets/images/img_ticket_20x20.svg'; + + static String imgLocation20x20 = 'assets/images/img_location_20x20.svg'; + + static String imgFlagargentina132x48 = + 'assets/images/img_flagargentina1_32x48.png'; + + static String imgTrash = 'assets/images/img_trash.svg'; + + static String imgProfileimglarge40x401 = + 'assets/images/img_profileimglarge_40x40_1.png'; + + static String imgCalendar = 'assets/images/img_calendar.svg'; + + static String imgEllipse2718x18 = 'assets/images/img_ellipse27_18x18.png'; + + static String imgSearchBlueA100 = 'assets/images/img_search_blue_a100.svg'; + + static String imgPic44x442 = 'assets/images/img_pic_44x44_2.png'; + + static String imgImage124 = 'assets/images/img_image124.png'; + + static String imgCheckbox = 'assets/images/img_checkbox.svg'; + + static String imgCompanylogo = 'assets/images/img_companylogo.png'; + + static String imgMinimize = 'assets/images/img_minimize.svg'; + + static String imgGroup1830 = 'assets/images/img_group1830.svg'; + + static String imgMicrophone = 'assets/images/img_microphone.svg'; + + static String imgArrowupGreen600 = 'assets/images/img_arrowup_green_600.svg'; + + static String img1200pxdocxicon = 'assets/images/img_1200pxdocxicon.png'; + + static String imgRectangle126x1264 = + 'assets/images/img_rectangle_126x126_4.png'; + + static String imgMoonoutline = 'assets/images/img_moonoutline.svg'; + + static String imgUnsplashenrurz62wui50x50 = + 'assets/images/img_unsplashenrurz62wui_50x50.png'; + + static String imgEllipse360x601 = 'assets/images/img_ellipse3_60x60_1.png'; + + static String imgQuestion24x24 = 'assets/images/img_question_24x24.svg'; + + static String imgArrowrightBlueA7001 = + 'assets/images/img_arrowright_blue_a700_1.svg'; + + static String imgLock53x53 = 'assets/images/img_lock_53x53.svg'; + + static String imgOverflowmenu16x16 = + 'assets/images/img_overflowmenu_16x16.svg'; + + static String imgBrightness = 'assets/images/img_brightness.svg'; + + static String imgArrowleftBlueGray900 = + 'assets/images/img_arrowleft_blue_gray_900.svg'; + + static String imgGroup2507 = 'assets/images/img_group2507.svg'; + + static String imgOverflowmenu = 'assets/images/img_overflowmenu.svg'; + + static String imageNotFound = 'assets/images/image_not_found.png'; +} diff --git a/lib/Utils/size_utils.dart b/lib/Utils/size_utils.dart new file mode 100644 index 0000000..12300e9 --- /dev/null +++ b/lib/Utils/size_utils.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; + +// This is where the magic happens. +// This functions are responsible to make UI responsive across all the mobile devices. + +Size size = WidgetsBinding.instance.window.physicalSize / + WidgetsBinding.instance.window.devicePixelRatio; + +// Caution! If you think these are static values and are used to build a static UI, you mustn’t. +// These are the Viewport values of your Figma Design. +// These are used in the code as a reference to create your UI Responsively. +const num FIGMA_DESIGN_WIDTH = 428; +const num FIGMA_DESIGN_HEIGHT = 926; +const num FIGMA_DESIGN_STATUS_BAR = 47; + +///This method is used to get device viewport width. +get width { + return size.width; +} + +///This method is used to get device viewport height. +get height { + num statusBar = + MediaQueryData.fromWindow(WidgetsBinding.instance.window).viewPadding.top; + num bottomBar = MediaQueryData.fromWindow(WidgetsBinding.instance.window) + .viewPadding + .bottom; + num screenHeight = size.height - statusBar - bottomBar; + return screenHeight; +} + +///This method is used to set padding/margin (for the left and Right side) & width of the screen or widget according to the Viewport width. +double getHorizontalSize(double px) { + return ((px * width) / FIGMA_DESIGN_WIDTH); +} + +///This method is used to set padding/margin (for the top and bottom side) & height of the screen or widget according to the Viewport height. +double getVerticalSize(double px) { + return ((px * height) / (FIGMA_DESIGN_HEIGHT - FIGMA_DESIGN_STATUS_BAR)); +} + +///This method is used to set smallest px in image height and width +double getSize(double px) { + var height = getVerticalSize(px); + var width = getHorizontalSize(px); + if (height < width) { + return height.toInt().toDouble(); + } else { + return width.toInt().toDouble(); + } +} + +///This method is used to set text font size according to Viewport +double getFontSize(double px) { + return getSize(px); +} + +///This method is used to set padding responsively +EdgeInsetsGeometry getPadding({ + double? all, + double? left, + double? top, + double? right, + double? bottom, +}) { + return getMarginOrPadding( + all: all, + left: left, + top: top, + right: right, + bottom: bottom, + ); +} + +///This method is used to set margin responsively +EdgeInsetsGeometry getMargin({ + double? all, + double? left, + double? top, + double? right, + double? bottom, +}) { + return getMarginOrPadding( + all: all, + left: left, + top: top, + right: right, + bottom: bottom, + ); +} + +///This method is used to get padding or margin responsively +EdgeInsetsGeometry getMarginOrPadding({ + double? all, + double? left, + double? top, + double? right, + double? bottom, +}) { + if (all != null) { + left = all; + top = all; + right = all; + bottom = all; + } + return EdgeInsets.only( + left: getHorizontalSize( + left ?? 0, + ), + top: getVerticalSize( + top ?? 0, + ), + right: getHorizontalSize( + right ?? 0, + ), + bottom: getVerticalSize( + bottom ?? 0, + ), + ); +} diff --git a/lib/dashboard_builder_authsec/.DS_Store b/lib/dashboard_builder_authsec/.DS_Store new file mode 100644 index 0000000..144d51d Binary files /dev/null and b/lib/dashboard_builder_authsec/.DS_Store differ diff --git a/lib/dashboard_builder_authsec/Dashboard/Dashboard_api_service.dart b/lib/dashboard_builder_authsec/Dashboard/Dashboard_api_service.dart new file mode 100644 index 0000000..bb91f22 --- /dev/null +++ b/lib/dashboard_builder_authsec/Dashboard/Dashboard_api_service.dart @@ -0,0 +1,50 @@ +import 'package:dio/dio.dart'; + +import '../../resources/api_constants.dart'; + +class DashboardBuilderApiService { + final String baseUrl = ApiConstants.baseUrl; + final Dio dio = Dio(); + + Future>> getEntities(String token) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + final response = await dio.get('$baseUrl/Dashboard/Dashboard'); + final entities = (response.data as List).cast>(); + return entities; + } catch (e) { + throw Exception('Failed to get all entities: $e'); + } + } + + Future createEntity(String token, Map entity) async { + try { + print("in post api" + entity.toString()); + dio.options.headers['Authorization'] = 'Bearer $token'; + await dio.post('$baseUrl/Dashboard/Dashboard', data: entity); + print(entity); + } catch (e) { + throw Exception('Failed to create entity: $e'); + } + } + + Future updateEntity( + String token, int entityId, Map entity) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + await dio.put('$baseUrl/Dashboard/Dashboard/$entityId', data: entity); + print(entity); + } catch (e) { + throw Exception('Failed to update entity: $e'); + } + } + + Future deleteEntity(String token, int entityId) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + await dio.delete('$baseUrl/Dashboard/Dashboard/$entityId'); + } catch (e) { + throw Exception('Failed to delete entity: $e'); + } + } +} diff --git a/lib/dashboard_builder_authsec/Dashboard/Dashboard_create_entity_screen.dart b/lib/dashboard_builder_authsec/Dashboard/Dashboard_create_entity_screen.dart new file mode 100644 index 0000000..d3c91fb --- /dev/null +++ b/lib/dashboard_builder_authsec/Dashboard/Dashboard_create_entity_screen.dart @@ -0,0 +1,119 @@ +// ignore_for_file: use_build_context_synchronously +import 'package:flutter/material.dart'; + +import 'package:flutter/services.dart'; + +import '../../providers/token_manager.dart'; +import 'Dashboard_api_service.dart'; + +class CreateEntityScreen extends StatefulWidget { + const CreateEntityScreen({super.key}); + + @override + _CreateEntityScreenState createState() => _CreateEntityScreenState(); +} + +class _CreateEntityScreenState extends State { + final DashboardBuilderApiService apiService = DashboardBuilderApiService(); + final Map formData = {}; + final _formKey = GlobalKey(); + + bool isisdashboard = false; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Create Dashboard')), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + decoration: const InputDecoration(labelText: 'name'), + onSaved: (value) => formData['name'] = value, + ), + const SizedBox(height: 16), + TextFormField( + decoration: const InputDecoration(labelText: 'model'), + onSaved: (value) => formData['model'] = value, + ), + const SizedBox(height: 16), + Switch( + value: isisdashboard, + onChanged: (newValue) { + setState(() { + isisdashboard = newValue; + }); + }, + ), + const SizedBox(width: 8), + const Text('isdashboard'), + Container( + margin: const EdgeInsets.symmetric(vertical: 5), // Add margin + child: ElevatedButton( + onPressed: () async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + + formData['isdashboard'] = isisdashboard; + + final token = await TokenManager.getToken(); + try { + print("token is : $token"); + print(formData); + + await apiService.createEntity(token!, formData); + + Navigator.pop(context); + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to create entity: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + }, + child: const SizedBox( + width: double.infinity, + height: 50, + child: const Center( + child: Text( + 'SUBMIT', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/dashboard_builder_authsec/Dashboard/Dashboard_entity_list_screen.dart b/lib/dashboard_builder_authsec/Dashboard/Dashboard_entity_list_screen.dart new file mode 100644 index 0000000..6bace83 --- /dev/null +++ b/lib/dashboard_builder_authsec/Dashboard/Dashboard_entity_list_screen.dart @@ -0,0 +1,303 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:flutter/services.dart'; + +import '../../providers/token_manager.dart'; +import 'Dashboard_api_service.dart'; +import 'Dashboard_create_entity_screen.dart'; +import 'Dashboard_update_entity_screen.dart'; + +class dashboard_entity_list_screen extends StatefulWidget { + static const String routeName = '/entity-list'; + + @override + _dashboard_entity_list_screenState createState() => + _dashboard_entity_list_screenState(); +} + +class _dashboard_entity_list_screenState + extends State { + final DashboardBuilderApiService apiService = DashboardBuilderApiService(); + List> entities = []; + bool showCardView = true; // Add this variable to control the view mode + + @override + void initState() { + super.initState(); + fetchEntities(); + } + + Future fetchEntities() async { + try { + final token = await TokenManager.getToken(); + + if (token != null) { + final fetchedEntities = await apiService.getEntities(token); + setState(() { + entities = fetchedEntities; + }); + } + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to fetch entities: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + + Future deleteEntity(Map entity) async { + try { + final token = await TokenManager.getToken(); + await apiService.deleteEntity(token!, entity['id']); + setState(() { + entities.remove(entity); + }); + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to delete entity: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Dashboard List'), + actions: [ + // Add a switch in the app bar to toggle between card view and normal view + Switch( + activeColor: Colors.greenAccent, + inactiveThumbColor: Colors.white, + value: showCardView, + onChanged: (value) { + setState(() { + showCardView = value; + }); + }, + ), + ], + ), + body: entities.isEmpty + ? const Center( + child: Text('No entities found.'), + ) + : ListView.builder( + itemCount: entities.length, + itemBuilder: (BuildContext context, int index) { + final entity = entities[index]; + return _buildListItem(entity); + }, + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const CreateEntityScreen(), + ), + ).then((_) { + fetchEntities(); + }); + }, + child: const Icon(Icons.add), + ), + ); + } + + // Function to build list items + Widget _buildListItem(Map entity) { + return showCardView ? _buildCardView(entity) : _buildNormalView(entity); + } + + // Function to build card view for a list item + Widget _buildCardView(Map entity) { + return Card( + elevation: 2, + margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + child: _buildNormalView(entity)); + } + + // Function to build normal view for a list item + Widget _buildNormalView(Map entity) { + return ListTile( + title: Text(entity['id'].toString()), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(entity['name'] ?? 'No name provided'), + const SizedBox(height: 4), + + Text(entity['model'] ?? 'No model provided'), + const SizedBox(height: 4), + + Text(entity['isdashboard'].toString() ?? 'No isdashboard provided'), + const SizedBox(height: 4), + + // Added address text + ], + ), + trailing: _buildPopupMenu(entity), + ); + } + + // Function to build popup menu for a list item + Widget _buildPopupMenu(Map entity) { + return PopupMenuButton( + itemBuilder: (BuildContext context) { + return [ + const PopupMenuItem( + value: 'edit', + child: Row( + children: [ + Icon(Icons.edit), + SizedBox(width: 8), + Text('Edit'), + ], + ), + ), + const PopupMenuItem( + value: 'delete', + child: Row( + children: [ + Icon(Icons.delete), + SizedBox(width: 8), + Text('Delete'), + ], + ), + ), + const PopupMenuItem( + value: 'WHO', + child: Row( + children: [ + Icon(Icons.manage_accounts_outlined), + SizedBox(width: 8), + Text('WHO'), + ], + ), + ), + ]; + }, + onSelected: (String value) { + if (value == 'edit') { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => UpdateEntityScreen(entity: entity), + ), + ).then((_) { + fetchEntities(); + }); + } else if (value == 'delete') { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Confirm Deletion'), + content: + const Text('Are you sure you want to delete this entity?'), + actions: [ + TextButton( + child: const Text('Cancel'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: const Text('Delete'), + onPressed: () { + Navigator.of(context).pop(); + deleteEntity(entity); + }, + ), + ], + ); + }, + ); + } else if (value == 'WHO') { + _showAdditionalFieldsDialog(context, entity); + } + }, + ); + } + + // Function to show additional fields in a dialog + void _showAdditionalFieldsDialog( + BuildContext context, + Map entity, + ) { + final dateFormat = + DateFormat('yyyy-MM-dd HH:mm:ss'); // Define your desired date format + + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Additional Fields'), + content: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Created At: ${_formatTimestamp(entity['createdAt'], dateFormat)}'), + Text('Created By: ${entity['createdBy'] ?? 'N/A'}'), + Text('Updated By: ${entity['updatedBy'] ?? 'N/A'}'), + Text( + 'Updated At: ${_formatTimestamp(entity['updatedAt'], dateFormat)}'), + Text('Account ID: ${entity['accountId'] ?? 'N/A'}'), + ], + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + + String _formatTimestamp(dynamic timestamp, DateFormat dateFormat) { + if (timestamp is int) { + // If it's an integer, assume it's a Unix timestamp in milliseconds + final DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp); + return dateFormat.format(dateTime); + } else if (timestamp is String) { + // If it's a string, assume it's already formatted as a date + return timestamp; + } else { + // Handle other cases here if needed + return 'N/A'; + } + } +} diff --git a/lib/dashboard_builder_authsec/Dashboard/Dashboard_update_entity_screen.dart b/lib/dashboard_builder_authsec/Dashboard/Dashboard_update_entity_screen.dart new file mode 100644 index 0000000..7a62daa --- /dev/null +++ b/lib/dashboard_builder_authsec/Dashboard/Dashboard_update_entity_screen.dart @@ -0,0 +1,146 @@ +// ignore_for_file: use_build_context_synchronously +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'dart:math'; +import 'package:flutter/services.dart'; + +import '../../providers/token_manager.dart'; +import 'Dashboard_api_service.dart'; + +class UpdateEntityScreen extends StatefulWidget { + final Map entity; + + UpdateEntityScreen({required this.entity}); + + @override + _UpdateEntityScreenState createState() => _UpdateEntityScreenState(); +} + +class _UpdateEntityScreenState extends State { + final DashboardBuilderApiService apiService = DashboardBuilderApiService(); + final _formKey = GlobalKey(); + + bool isisdashboard = false; + + @override + void initState() { + super.initState(); + + isisdashboard = widget.entity['isdashboard'] ?? false; // Set initial value + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Update Dashboard')), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + initialValue: widget.entity['name'], + decoration: const InputDecoration(labelText: 'name'), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter a name'; + } + return null; + }, + onSaved: (value) { + widget.entity['name'] = value; + }, + ), + const SizedBox(height: 16), + TextFormField( + initialValue: widget.entity['model'], + decoration: const InputDecoration(labelText: 'model'), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter a model'; + } + return null; + }, + onSaved: (value) { + widget.entity['model'] = value; + }, + ), + const SizedBox(height: 16), + Row( + children: [ + Switch( + value: isisdashboard, + onChanged: (newValue) { + setState(() { + isisdashboard = newValue; + }); + }, + ), + const SizedBox(width: 8), + const Text('isdashboard'), + ], + ), + Container( + margin: const EdgeInsets.symmetric(vertical: 5), // Add margin + child: ElevatedButton( + onPressed: () async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + + widget.entity['isdashboard'] = isisdashboard; + + final token = await TokenManager.getToken(); + try { + await apiService.updateEntity( + token!, + widget.entity[ + 'id'], // Assuming 'id' is the key in your entity map + widget.entity); + Navigator.pop(context); + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to update entity: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + }, + child: Container( + width: double.infinity, + height: 50, + child: const Center( + child: Text( + 'UPDATE', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/database/login_info_storage.dart b/lib/database/login_info_storage.dart new file mode 100644 index 0000000..b5c27e7 --- /dev/null +++ b/lib/database/login_info_storage.dart @@ -0,0 +1,61 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:path_provider/path_provider.dart'; + +class LoginInfoStorage { + Future get _localPath async { + final directory = await getApplicationDocumentsDirectory(); + return directory.path; + } + + Future get _userLoginDataFile async { + final path = await _localPath; + return File('$path/hadwin_user_login_info_storage.json'); + } + + Future setPersistentLoginData(String userId, String authToken) async { + try { + final file = await _userLoginDataFile; + var ss = file.writeAsString( + jsonEncode({'userId': userId, 'authToken': authToken})); + + print('ssss is ..........'); + print(ss); + + //* THE USER_ID AND AUTHENTICATION_TOKEN HAS BEEN SAVED + return file + .writeAsString(jsonEncode({'userId': userId, 'authToken': authToken})) + .then((value) { + //* THE USER_ID HAS BEEN SAVED + return true; + }); + } catch (e) { + //* THE USER_ID AND AUTHENTICATION_TOKEN COULD NOT BE SAVED + return false; + } + } + + Future> get getPersistentLoginData async { + try { + final file = await _userLoginDataFile; + final contents = await file.readAsString(); + return jsonDecode(contents); + } catch (e) { + return {'userId': null, 'authToken': null}; + } + } + + Future deleteFile() async { + try { + final file = await _userLoginDataFile; + + await file.delete(); + //* THE LOGIN DATA FILE HAS BEEN DELETED + return true; + } catch (e) { + //* THE LOGIN DATA FILE HAS NOT BEEN DELETED + return false; + } + } +} diff --git a/lib/database/user_data_storage.dart b/lib/database/user_data_storage.dart new file mode 100644 index 0000000..4b45faf --- /dev/null +++ b/lib/database/user_data_storage.dart @@ -0,0 +1,54 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:path_provider/path_provider.dart'; + +class UserDataStorage { + Future get _localPath async { + final directory = await getApplicationDocumentsDirectory(); + + return directory.path; + } + + Future get _userDataFile async { + final path = await _localPath; + return File('$path/hadwin_user_data.json'); + } + + Future> getUserData() async { + try { + final file = await _userDataFile; + + final contents = await file.readAsString(); + + return jsonDecode(contents); + } catch (e) { + return {"localDBError": "unable to parse data"}; + } + } + + Future saveUserData(Map userData) async { + try { + final file = await _userDataFile; + + print('userdata as is ..... '); + print(file.writeAsString(userData as String)); + return file.writeAsString(jsonEncode(userData)).then((value) => true); + } catch (e) { + return false; + } + } + + Future deleteFile() async { + try { + final file = await _userDataFile; + + await file.delete(); + //* THE USER DATA FILE HAS BEEN DELETED + return true; + } catch (e) { + //* THE USER DATA FILE HAS NOT BEEN DELETED + return false; + } + } +} diff --git a/lib/hadwin_components.dart b/lib/hadwin_components.dart new file mode 100644 index 0000000..d9e9102 --- /dev/null +++ b/lib/hadwin_components.dart @@ -0,0 +1,31 @@ +library hadwin_components; + +export 'resources/api_constants.dart'; + +//business logic + +//components + +// export 'components/wallet_screen/available_cards_loading.dart'; +export 'screens/settings_screen/credits_loading.dart'; +// export 'components/contacts_screen/contacts_loading.dart'; +export 'screens/sign_up_screen/sign_up_steps.dart'; + + + +//database + +//resources +export 'providers/tab_navigation_provider.dart'; + +//screens + +export 'screens/sign_up_screen/sign_up_screen.dart'; + +//utilities +export 'utilities/slide_right_route.dart'; +export 'utilities/make_api_request.dart'; +export 'utilities/url_external_launcher.dart'; +export 'utilities/custom_date_grouping.dart'; +export 'utilities/display_error_alert.dart'; +export 'utilities/hadwin_markdown_viewer.dart'; diff --git a/lib/logout/logoutbutton.dart b/lib/logout/logoutbutton.dart new file mode 100644 index 0000000..d90510d --- /dev/null +++ b/lib/logout/logoutbutton.dart @@ -0,0 +1,48 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; + +import '../Screens/Login Screen/login_screen.dart'; +import '../resources/api_constants.dart'; + +class LogoutButton extends StatefulWidget { + @override + _LogoutButtonState createState() => _LogoutButtonState(); +} + +class _LogoutButtonState extends State { + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: () { + _logoutUser(); + }, + child: const Text('Logout'), + ); + } + + Future _logoutUser() async { + try { + // Perform API logout request here + // Replace `apiLogoutEndpoint` with the actual logout endpoint URL + String logouturl = "${ApiConstants.baseUrl}" + "/token/logout"; + var response = await http.post(Uri.parse(logouturl)); + + // Handle logout success + if (response.statusCode == 200) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const LoginScreen(), + ), + ); + } else { + // Handle logout failure + // Display an error message or take appropriate action + } + } catch (error) { + // Handle any exceptions or errors that occur during the logout process + } + } +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..8525bd3 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,223 @@ +import 'package:flutter/material.dart'; +import 'package:sqflite/sqflite.dart'; +import 'package:sqflite_common_ffi/sqflite_ffi.dart'; +import 'package:sqlite3/sqlite3.dart'; + +import 'screens/splash_screen/splash_screen.dart'; + +//const simplePeriodicTask = "simplePeriodicTask"; + +// void showNotification(String v, FlutterLocalNotificationsPlugin flp) async { +// var android = const AndroidNotificationDetails( +// 'channel id', +// 'channel NAME', +// priority: Priority.high, +// importance: Importance.max, +// ); +// var iOS = const IOSNotificationDetails(); +// var platform = NotificationDetails(android: android, iOS: iOS); +// await flp.show(0, 'CloudnSure', '$v', platform, payload: 'VIS \n $v'); +// } + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + print(sqlite3.version); + sqfliteFfiInit(); + // Initialize the database factory for sqflite_common_ffi + databaseFactory = databaseFactoryFfi; + + //Request notification permissions + // await _requestNotificationPermissions(); + + // await Workmanager().initialize(callbackDispatcher); + // await Workmanager().registerPeriodicTask( + // "5", + // simplePeriodicTask, + // existingWorkPolicy: ExistingWorkPolicy.replace, + // frequency: const Duration(minutes: 15), + // initialDelay: const Duration(seconds: 5), + // constraints: Constraints(networkType: NetworkType.connected), + // ); + runApp(MyApp()); +} + +// Future _requestNotificationPermissions() async { +// final status = await Permission.notification.request(); +// if (status.isGranted) { +// print('Notification permissions granted'); +// } else { +// print('Notification permissions denied'); +// } +// } + +// void callbackDispatcher() { +// Workmanager().executeTask((task, inputData) async { +// FlutterLocalNotificationsPlugin flp = FlutterLocalNotificationsPlugin(); +// var android = const AndroidInitializationSettings('@mipmap/ic_launcher'); +// var iOS = const IOSInitializationSettings(); +// var initSettings = InitializationSettings(android: android, iOS: iOS); +// flp.initialize(initSettings); +// String baseUrl = ApiConstants.baseUrl; +// final apiUrl = '$baseUrl/user_notifications/get_unseen'; +// final token = await TokenManager.getToken(); +// final response = await http.get( +// Uri.parse(apiUrl), +// headers: { +// 'Authorization': 'Bearer $token', +// 'Content-Type': 'application/json', +// }, +// ); +// if (response.statusCode <= 209) { +// final List data = jsonDecode(response.body); +// List> notifications = +// data.cast>(); +// notifications.forEach((element) async { +// showNotification(element['notification'], flp); +// int id = element['id']; +// final apiUrl2 = '$baseUrl/user_notifications/seen_success/$id'; +// final response2 = await http.get( +// Uri.parse(apiUrl2), +// headers: { +// 'Authorization': 'Bearer $token', +// 'Content-Type': 'application/json', +// }, +// ); +// if (response2.statusCode <= 209) { +// print("seen request to web success"); +// } +// }); +// } else { +// print('Failed to fetch data'); +// } +// return Future.value(true); +// }); +// } + +// class MyApp extends StatelessWidget { +// const MyApp({super.key}); +// +// @override +// Widget build(BuildContext context) { +// return MaterialApp( +// debugShowCheckedModeBanner: false, +// title: 'Welcome to cloudNsure', +// theme: ThemeData( +// primarySwatch: Colors.blue, +// visualDensity: VisualDensity.adaptivePlatformDensity, +// ), +// home: const LoginScreen(), +// routes: { +// // '/load': (context) => const ProjectListScreen(), +// +// +// }, +// ); +// } +// } +final GlobalKey navigatorKey = GlobalKey(); +// +// class MyApp extends StatefulWidget { +// const MyApp({Key? key}) : super(key: key); +// +// @override +// _MyAppState createState() => _MyAppState(); +// } +// +// class _MyAppState extends State { +// +// +// double getMargin(BuildContext context) { +// // Calculate the margin based on a percentage of screen width +// double screenWidth = MediaQuery.of(context).size.width; +// double marginPercentage = 0.2; // Adjust the percentage as needed +// return screenWidth * marginPercentage; +// } +// +// @override +// Widget build(BuildContext context) { +// return kIsWeb +// ? Container( +// margin: EdgeInsets.symmetric( +// horizontal: getMargin(context), +// ), +// child: MaterialApp( +// navigatorKey: navigatorKey, +// debugShowCheckedModeBanner: false, +// title: 'Welcome to cloudNsure', +// theme: ThemeData( +// primarySwatch: Colors.blue, +// visualDensity: VisualDensity.adaptivePlatformDensity, +// ), +// home:SplashScreen(), +// routes: { +// '/drag': (context) => DragAndDropFormBuilder( +// projId: 11096, +// headerId: 1615, +// moduleId: 12867, +// backendId: 215, +// ), +// '/dash': (context) => Dashboard_screen( +// projId: 12802, +// moduleId: 12811, +// ), +// '/regi': (context) => +// RegistrationDetailsScreen(email: 'gaurav@dekatc.com'), +// '/user': (context) => CreateUserScreen(), +// '/list': (context) => +// ListBuilder_screen(projId: 13249, moduleId: 13258), +// '/log': (context) => const LiveLogsScreen( +// containerName: 'sukhantest_realnet_d-mysql', +// ), +// '/farm': (context) => SureFarmContent(projectId: 13261), +// '/g2': (context) => gtest2_entity_list_screen(), +// }, +// ), +// ) +// : MaterialApp( +// debugShowCheckedModeBanner: false, +// title: 'Welcome to cloudNsure', +// theme: ThemeData( +// primarySwatch: Colors.blue, +// visualDensity: VisualDensity.adaptivePlatformDensity, +// ), +// home: SplashScreen(), +// routes: { +// // '/load': (context) => const ProjectListScreen(), +// +// // '/drag': (context) => DragAndDropFormBuilder( +// // projId: 13249, +// // headerId: 1550, +// // moduleId: 13258, +// // ), +// '/drag': (context) => DragAndDropFormBuilder( +// projId: 11096, +// headerId: 1538, +// moduleId: 12867, +// backendId: 215, +// ), +// +// '/dash': (context) => Dashboard_screen( +// projId: 12802, +// moduleId: 12811, +// ), +// }, +// ); +// } +// } + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + home: const SplashScreen(), + routes: {}, + theme: ThemeData( + primaryColor: Colors.blue, + appBarTheme: const AppBarTheme( + color: Colors.blue, + ), + ), + ); + } +} diff --git a/lib/providers/tab_navigation_provider.dart b/lib/providers/tab_navigation_provider.dart new file mode 100644 index 0000000..e01978c --- /dev/null +++ b/lib/providers/tab_navigation_provider.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +class TabNavigationProvider with ChangeNotifier { + List _tabHistory = [0]; + + int get lastTab => _tabHistory.last; + + void removeLastTab() { + _tabHistory.removeLast(); + notifyListeners(); + } + + void updateTabs(int tab) { + if (tab == 0) { + _tabHistory = [0]; + } else { + _tabHistory.removeWhere((element) => element == tab); + _tabHistory.add(tab); + } + notifyListeners(); + } +} diff --git a/lib/providers/token_manager.dart b/lib/providers/token_manager.dart new file mode 100644 index 0000000..d33e633 --- /dev/null +++ b/lib/providers/token_manager.dart @@ -0,0 +1,17 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +class TokenManager { + static const storage = FlutterSecureStorage(); + + static Future setToken(String token) async { + await storage.write(key: 'token', value: token); + } + + static Future getToken() async { + return await storage.read(key: 'token'); + } + + static Future removeToken() async { + await storage.delete(key: 'token'); + } +} diff --git a/lib/resources/api_constants.dart b/lib/resources/api_constants.dart new file mode 100644 index 0000000..7652075 --- /dev/null +++ b/lib/resources/api_constants.dart @@ -0,0 +1,3 @@ +class ApiConstants { + static const baseUrl = 'http://localhost:9292'; +} diff --git a/lib/screens/.DS_Store b/lib/screens/.DS_Store new file mode 100644 index 0000000..1d03a9a Binary files /dev/null and b/lib/screens/.DS_Store differ diff --git a/lib/screens/Bookmarks/Bookmarks_api_service.dart b/lib/screens/Bookmarks/Bookmarks_api_service.dart new file mode 100644 index 0000000..88e06ee --- /dev/null +++ b/lib/screens/Bookmarks/Bookmarks_api_service.dart @@ -0,0 +1,106 @@ +import 'package:dio/dio.dart'; +import 'package:http_parser/http_parser.dart'; +import 'dart:typed_data'; +import 'dart:convert'; + +import '../../resources/api_constants.dart'; +import '../LogoutService/Logoutservice.dart'; + +class ApiService { + final String baseUrl = ApiConstants.baseUrl; + final Dio dio = Dio(); + + Future>> getEntities(String token) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + final response = await dio.get('$baseUrl/Bookmarks/Bookmarks'); + + if (response.statusCode == 401) { + LogoutService.logout(); + } + final entities = (response.data as List).cast>(); + return entities; + } catch (e) { + throw Exception('Failed to get all entities: $e'); + } + } + + Future createEntity( + String token, Map fData, dynamic selectedFile) async { + try { + String apiUrl = "$baseUrl/Bookmarks/Bookmarks"; + + final Uint8List fileBytes = selectedFile.bytes!; + final mimeType = lookupMimeType(selectedFile.name!); + + FormData formData = FormData.fromMap({ + 'file': MultipartFile.fromBytes( + fileBytes, + filename: selectedFile.name!, + contentType: MediaType.parse(mimeType!), + ), + 'data': jsonEncode( + fData), // Convert the map to JSON and include it as a parameter + }); + + Dio dio = Dio(); // Create a new Dio instance + dio.options.headers['Authorization'] = 'Bearer $token'; + + final response = await dio.post(apiUrl, data: formData); + if (response.statusCode == 401) { + LogoutService.logout(); + } + if (response.statusCode == 200) { + // Handle successful response + print('File uploaded successfully'); + } else { + print('Failed to upload file with status: ${response.statusCode}'); + } + } catch (error) { + print('Error occurred during form submission: $error'); + } + } + + String lookupMimeType(String filePath) { + final ext = filePath.split('.').last; + switch (ext) { + case 'jpg': + case 'jpeg': + return 'image/jpeg'; + case 'png': + return 'image/png'; + case 'pdf': + return 'application/pdf'; + // Add more cases for other file types as needed + default: + return 'application/octet-stream'; // Default MIME type + } + } + + Future updateEntity( + String token, int entityId, Map entity) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + var response = + await dio.put('$baseUrl/Bookmarks/Bookmarks/$entityId', data: entity); + if (response.statusCode == 401) { + LogoutService.logout(); + } + print(entity); + } catch (e) { + throw Exception('Failed to update entity: $e'); + } + } + + Future deleteEntity(String token, int entityId) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + var response = await dio.delete('$baseUrl/Bookmarks/Bookmarks/$entityId'); + if (response.statusCode == 401) { + LogoutService.logout(); + } + } catch (e) { + throw Exception('Failed to delete entity: $e'); + } + } +} diff --git a/lib/screens/Bookmarks/Bookmarks_create_entity_screen.dart b/lib/screens/Bookmarks/Bookmarks_create_entity_screen.dart new file mode 100644 index 0000000..274a4c5 --- /dev/null +++ b/lib/screens/Bookmarks/Bookmarks_create_entity_screen.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import '../../providers/token_manager.dart'; +import 'Bookmarks_api_service.dart'; + +class CreateEntityScreen extends StatefulWidget { + const CreateEntityScreen({super.key}); + + @override + _CreateEntityScreenState createState() => _CreateEntityScreenState(); +} + +class _CreateEntityScreenState extends State { + final ApiService apiService = ApiService(); + final Map formData = {}; + final _formKey = GlobalKey(); + var selectedFileupload_Field; + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Create Bookmarks')), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + decoration: + const InputDecoration(labelText: 'bookmark_firstletter'), + onSaved: (value) => formData['bookmark_firstletter'] = value, + ), + const SizedBox(height: 16), + TextFormField( + decoration: const InputDecoration(labelText: 'bookmark_link'), + onSaved: (value) => formData['bookmark_link'] = value, + ), + const SizedBox(height: 16), + TextFormField( + decoration: + const InputDecoration(labelText: 'fileupload_field'), + onSaved: (value) => formData['fileupload_field'] = value, + ), + const SizedBox(height: 16), + Container( + margin: const EdgeInsets.symmetric(vertical: 5), // Add margin + child: ElevatedButton( + onPressed: () async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + + final token = await TokenManager.getToken(); + try { + print("token is : $token"); + print(formData); + + await apiService.createEntity( + token!, formData, selectedFileupload_Field); + + Navigator.pop(context); + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to create entity: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + }, + child: Container( + width: double.infinity, + height: 50, + child: const Center( + child: Text( + 'SUBMIT', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/Bookmarks/Bookmarks_entity_list_screen.dart b/lib/screens/Bookmarks/Bookmarks_entity_list_screen.dart new file mode 100644 index 0000000..ae3832f --- /dev/null +++ b/lib/screens/Bookmarks/Bookmarks_entity_list_screen.dart @@ -0,0 +1,562 @@ +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../theme/app_decoration.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import 'Bookmarks_api_service.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class bookmarks_entity_list_screen extends StatefulWidget { + static const String routeName = '/entity-list'; + + @override + _bookmarks_entity_list_screenState createState() => + _bookmarks_entity_list_screenState(); +} + +class _bookmarks_entity_list_screenState + extends State { + final ApiService apiService = ApiService(); + List> entities = []; + bool showCardView = true; // Add this variable to control the view mode + + @override + void initState() { + super.initState(); + fetchEntities(); + } + + Future fetchEntities() async { + try { + final token = await TokenManager.getToken(); + + if (token != null) { + final fetchedEntities = await apiService.getEntities(token); + setState(() { + entities = fetchedEntities; + }); + } + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to fetch entities: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + + Future deleteEntity(Map entity) async { + try { + final token = await TokenManager.getToken(); + await apiService.deleteEntity(token!, entity['id']); + setState(() { + entities.remove(entity); + }); + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to delete entity: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "Bookmarks")), + body: entities.isEmpty + ? const Center( + child: Text('No BookMarks found.'), + ) + : Container( + width: double.maxFinite, + padding: getPadding(left: 16, top: 16, right: 16, bottom: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: getPadding(top: 22), + child: entities.length != 0 + ? ListView.separated( + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + separatorBuilder: (context, index) { + return SizedBox(height: getVerticalSize(24)); + }, + itemCount: entities.length, + itemBuilder: (context, index) { + Map entity = entities[index]; + return Container( + width: double.maxFinite, + child: Container( + padding: getPadding( + left: 16, + top: 5, + right: 5, + bottom: 17, + ), + decoration: AppDecoration.outlineGray70011 + .copyWith( + borderRadius: BorderRadiusStyle + .roundedBorder6, + color: Colors.grey[100]), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Padding( + padding: getPadding( + //right: 13, + ), + child: Row( + children: [ + Container( + width: MediaQuery.of(context) + .size + .width * + 0.30, + // getHorizontalSize( + // 147, + // ), + margin: getMargin( + left: 8, + top: 3, + bottom: 1, + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + mainAxisAlignment: + MainAxisAlignment.start, + children: [ + Text( + entity['bookmark_firstletter'] ?? + 'No bookmark_firstletter provided', + overflow: TextOverflow + .ellipsis, + textAlign: + TextAlign.left, + style: AppStyle + .txtGreenSemiBold16, + ), + ], + ), + ), + Spacer(), + // PopupMenuButton( + // icon: Icon(Icons.more_vert,color: Colors.black,size: 16,), + // itemBuilder: (BuildContext context) { + // return [ + // PopupMenuItem( + // value: 'edit', + // child: Row( + // children: [ + // Icon( + // Icons.edit, + // size: 16, // Adjust the icon size as needed + // ), + // SizedBox(width: 8), + // Text( + // 'Edit', + // style: AppStyle.txtGilroySemiBold16, // Adjust the text size as needed + // ), + // ], + // ), + // ), + // PopupMenuItem( + // value: 'delete', + // child: Row( + // children: [ + // Icon( + // Icons.delete, + // size: 16, // Adjust the icon size as needed + // ), + // SizedBox(width: 8), + // Text( + // 'Delete', + // style: AppStyle.txtGilroySemiBold16, // Adjust the text size as needed + // ), + // ], + // ), + // ), + // ]; + // }, + // onSelected: (String value) { + // if (value == 'edit') { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => UpdateDatabseScreen( + // projectId: widget.projectId, + // entity: entity, + // ), + // ), + // ).then((_) { + // fetchEntities(); + // }); + // } else if (value == 'delete') { + // showDialog( + // context: context, + // builder: (BuildContext context) { + // return AlertDialog( + // title: const Text('Confirm Deletion'), + // content: const Text('Are you sure you want to delete?'), + // actions: [ + // TextButton( + // child: const Text('Cancel'), + // onPressed: () { + // Navigator.of(context).pop(); + // }, + // ), + // TextButton( + // child: const Text('Delete'), + // onPressed: () { + // Navigator.of(context).pop(); + // deleteEntity(entity, context).then((value) => { + // fetchEntities() + // }); + // }, + // ), + // ], + // ); + // }, + // ); + // } + // }, + // ), + ], + ), + ), + Padding( + padding: getPadding( + top: 10, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + 'BookMark Link', + overflow: + TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray800, + ), + GestureDetector( + onTap: () { + _launchURL(entity[ + 'bookmark_link']); + }, + child: Text( + entity['bookmark_link'] ?? + 'No bookmark_link provided', + overflow: + TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Green600, + ), + ) + ], + ), + ), + ], + ), + ), + ); + }) + : Container( + height: MediaQuery.of(context).size.height, + child: const Center( + child: Text("No Databases available"), + )), + ) + ])) + // floatingActionButton: FloatingActionButton( + // onPressed: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => const CreateEntityScreen(), + // ), + // ).then((_) { + // fetchEntities(); + // }); + // }, + // child: const Icon(Icons.add), + // ), + ); + } + + // Function to build list items + Widget _buildListItem(Map entity) { + return showCardView ? _buildCardView(entity) : _buildNormalView(entity); + } + + // Function to build card view for a list item + Widget _buildCardView(Map entity) { + return Card( + elevation: 2, + margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), + child: _buildNormalView(entity)); + } + + // Function to build normal view for a list item + // Widget _buildNormalView(Map entity) { + // return ListTile( + // title: Text(entity['id'].toString()), + // subtitle: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // + // Text(entity['bookmark_firstletter'] ?? 'No bookmark_firstletter provided'), + // const SizedBox(height: 4), + // Text(entity['bookmark_link'] ?? 'No bookmark_link provided'), + // const SizedBox(height: 4), + // Text(entity['fileupload_field'] ?? 'No fileupload_field provided'), + // const SizedBox(height: 4), // Added address text + // ], + // + // ), + // trailing: _buildPopupMenu(entity), + // onTap: () { + // _showAdditionalFieldsDialog(context, entity); + // }, + // ); + // } + + Widget _buildNormalView(Map entity) { + return ListTile( + title: Text(entity['id'].toString()), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(entity['bookmark_firstletter'] ?? + 'No bookmark_firstletter provided'), + const SizedBox(height: 4), + GestureDetector( + onTap: () { + _launchURL(entity['bookmark_link']); + }, + child: Text( + entity['bookmark_link'] ?? 'No bookmark_link provided', + style: TextStyle( + color: + Colors.blue, // Change the color to make it look like a link + decoration: TextDecoration.underline, // Underline the link + ), + ), + ), + const SizedBox(height: 4), + Text(entity['fileupload_field'] ?? 'No fileupload_field provided'), + const SizedBox(height: 4), + // Added address text + ], + ), + // trailing: _buildPopupMenu(entity), + // onTap: () { + // _showAdditionalFieldsDialog(context, entity); + // }, + ); + } + +// Function to launch a URL in the browser + Future _launchURL(String? url) async { + if (url != null) { + try { + if (await canLaunch(url)) { + await launch(url); + } else { + throw 'Could not launch $url'; + } + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to launch URL: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + } + + // // Function to build popup menu for a list item + // Widget _buildPopupMenu(Map entity) { + // return PopupMenuButton( + // itemBuilder: (BuildContext context) { + // return [ + // const PopupMenuItem( + // value: 'edit', + // child: Row( + // children: [ + // Icon(Icons.edit), + // SizedBox(width: 8), + // Text('Edit'), + // ], + // ), + // ), + // const PopupMenuItem( + // value: 'delete', + // child: Row( + // children: [ + // Icon(Icons.delete), + // SizedBox(width: 8), + // Text('Delete'), + // ], + // ), + // ), + // ]; + // }, + // onSelected: (String value) { + // if (value == 'edit') { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => UpdateEntityScreen(entity: entity), + // ), + // ).then((_) { + // fetchEntities(); + // }); + // } else if (value == 'delete') { + // showDialog( + // context: context, + // builder: (BuildContext context) { + // return AlertDialog( + // title: const Text('Confirm Deletion'), + // content: + // const Text('Are you sure you want to delete this entity?'), + // actions: [ + // TextButton( + // child: const Text('Cancel'), + // onPressed: () { + // Navigator.of(context).pop(); + // }, + // ), + // TextButton( + // child: const Text('Delete'), + // onPressed: () { + // Navigator.of(context).pop(); + // deleteEntity(entity); + // }, + // ), + // ], + // ); + // }, + // ); + // } + // }, + // ); + // } + + // Function to show additional fields in a dialog + void _showAdditionalFieldsDialog( + BuildContext context, + Map entity, + ) { + final dateFormat = + DateFormat('yyyy-MM-dd HH:mm:ss'); // Define your desired date format + + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Additional Fields'), + content: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Created At: ${_formatTimestamp(entity['createdAt'], dateFormat)}'), + Text('Created By: ${entity['createdBy'] ?? 'N/A'}'), + Text('Updated By: ${entity['updatedBy'] ?? 'N/A'}'), + Text( + 'Updated At: ${_formatTimestamp(entity['updatedAt'], dateFormat)}'), + Text('Account ID: ${entity['accountId'] ?? 'N/A'}'), + ], + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + + String _formatTimestamp(dynamic timestamp, DateFormat dateFormat) { + if (timestamp is int) { + // If it's an integer, assume it's a Unix timestamp in milliseconds + final DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp); + return dateFormat.format(dateTime); + } else if (timestamp is String) { + // If it's a string, assume it's already formatted as a date + return timestamp; + } else { + // Handle other cases here if needed + return 'N/A'; + } + } +} diff --git a/lib/screens/Bookmarks/Bookmarks_update_entity_screen.dart b/lib/screens/Bookmarks/Bookmarks_update_entity_screen.dart new file mode 100644 index 0000000..1802ba1 --- /dev/null +++ b/lib/screens/Bookmarks/Bookmarks_update_entity_screen.dart @@ -0,0 +1,140 @@ +import 'package:flutter/material.dart'; +import 'dart:math'; + +import 'package:flutter/services.dart'; + +import '../../providers/token_manager.dart'; +import 'Bookmarks_api_service.dart'; + +class UpdateEntityScreen extends StatefulWidget { + final Map entity; + + UpdateEntityScreen({required this.entity}); + + @override + _UpdateEntityScreenState createState() => _UpdateEntityScreenState(); +} + +class _UpdateEntityScreenState extends State { + final ApiService apiService = ApiService(); + final _formKey = GlobalKey(); + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Update Bookmarks')), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Column( + children: [ + TextFormField( + initialValue: widget.entity['bookmark_firstletter'], + decoration: + const InputDecoration(labelText: 'bookmark_firstletter'), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter a bookmark_firstletter'; + } + return null; + }, + onSaved: (value) { + widget.entity['bookmark_firstletter'] = value; + }, + ), + const SizedBox(height: 16), + TextFormField( + initialValue: widget.entity['bookmark_link'], + decoration: const InputDecoration(labelText: 'bookmark_link'), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter a bookmark_link'; + } + return null; + }, + onSaved: (value) { + widget.entity['bookmark_link'] = value; + }, + ), + const SizedBox(height: 16), + TextFormField( + initialValue: widget.entity['fileupload_field'], + decoration: + const InputDecoration(labelText: 'fileupload_field'), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter a fileupload_field'; + } + return null; + }, + onSaved: (value) { + widget.entity['fileupload_field'] = value; + }, + ), + const SizedBox(height: 16), + Container( + margin: const EdgeInsets.symmetric(vertical: 5), // Add margin + child: ElevatedButton( + onPressed: () async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + + final token = await TokenManager.getToken(); + try { + await apiService.updateEntity( + token!, + widget.entity[ + 'id'], // Assuming 'id' is the key in your entity map + widget.entity); + Navigator.pop(context); + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to update entity: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + }, + child: Container( + width: double.infinity, + height: 50, + child: const Center( + child: Text( + 'UPDATE', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/Incident_Ticket/.DS_Store b/lib/screens/Incident_Ticket/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/lib/screens/Incident_Ticket/.DS_Store differ diff --git a/lib/screens/Incident_Ticket/ticket_create.dart b/lib/screens/Incident_Ticket/ticket_create.dart new file mode 100644 index 0000000..df29e61 --- /dev/null +++ b/lib/screens/Incident_Ticket/ticket_create.dart @@ -0,0 +1,293 @@ +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:http/http.dart' as http; +import 'package:image_picker/image_picker.dart'; +import 'dart:convert'; + +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../resources/api_constants.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import '../../widgets/custom_button.dart'; +import '../../widgets/custom_text_form_field.dart'; +import '../LogoutService/Logoutservice.dart'; + +class RaisedTicketScreen extends StatefulWidget { + final Map userData; + + const RaisedTicketScreen({Key? key, required this.userData}) + : super(key: key); + + @override + _RaisedTicketScreenState createState() => _RaisedTicketScreenState(); +} + +class _RaisedTicketScreenState extends State { + List> tickets = []; + + @override + void initState() { + super.initState(); + fetchTickets(); + } + + Future fetchTickets() async { + int userid = widget.userData['userId']; + String baseUrl = ApiConstants.baseUrl; + final token = await TokenManager.getToken(); + String apiUrl = '$baseUrl/gettickets/$userid'; + final response = await http.get(Uri.parse(apiUrl), headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }); + if (response.statusCode == 401) { + LogoutService.logout(); + } + if (response.statusCode == 200) { + List data = json.decode(response.body); + setState(() { + tickets = data.cast>(); + }); + } else { + print('Failed to fetch data'); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + actions: [ + GestureDetector( + child: Icon( + Icons.add, + color: Colors.black, + size: 20, + ), + onTap: () { + Navigator.of(context) + .push( + MaterialPageRoute( + builder: (context) => TicketFormScreen( + userData: widget.userData, + )), + ) + .then((value) => {fetchTickets()}); + }, + ), + const SizedBox( + width: 20, + ) + ], + centerTitle: true, + title: AppbarTitle(text: "Raised Tickets")), + body: ListView.builder( + itemCount: tickets.length, + itemBuilder: (context, index) { + final ticket = tickets[index]; + return ListTile( + title: Text( + 'Ticket ID: ${ticket['ticketid']}', + style: const TextStyle(fontSize: 12), + ), + subtitle: Text('Ticket Name: ${ticket['ticketname']}', + style: const TextStyle(fontSize: 10)), + // Add more fields as needed + ); + }, + ), + ); + } +} + +class TicketFormScreen extends StatefulWidget { + final Map userData; + + const TicketFormScreen({Key? key, required this.userData}) : super(key: key); + @override + _TicketFormScreenState createState() => _TicketFormScreenState(); +} + +class _TicketFormScreenState extends State { + final TextEditingController titleController = TextEditingController(); + final TextEditingController descriptionController = TextEditingController(); + TextEditingController projectNameController = TextEditingController(); + var screenshot; + + Future submitTicket(File file) async { + print(widget.userData); + String title = titleController.text; + String description = descriptionController.text; + String baseUrl = ApiConstants.baseUrl; + final token = await TokenManager.getToken(); + String apiUrl = '$baseUrl/service_request/raise_ticket'; + + // Create a multipart request + var request = http.MultipartRequest('POST', Uri.parse(apiUrl)); + request.headers['Authorization'] = 'Bearer $token'; + + // Add text fields to the request + request.fields['title'] = title; + request.fields['description'] = description; + request.fields['userid'] = widget.userData['userId'].toString(); + request.fields['username'] = widget.userData['fullname']; + + // Add file to the request + if (file != null) { + request.files.add( + await http.MultipartFile.fromPath('file', file.path), + ); + } + + try { + // Send the request + final response = await request.send(); + + if (response.statusCode == 401) { + LogoutService.logout(); + } + + if (response.statusCode == 200) { + Fluttertoast.showToast( + msg: 'Ticket submitted successfully', + backgroundColor: Colors.green, + ); + print('Ticket submitted successfully'); + Navigator.pop(context); + } else { + Fluttertoast.showToast( + msg: 'Failed to submit ticket.', + backgroundColor: Colors.red, + ); + print('Failed to submit ticket. Status code: ${response.statusCode}'); + } + } catch (e) { + // Handle exceptions + print('Error: $e'); + } + } + + Future _pickImage() async { + final picker = ImagePicker(); + final pickedFile = await picker.pickImage(source: ImageSource.gallery); + + setState(() { + if (pickedFile != null) { + screenshot = File(pickedFile.path); + } else { + print('No image selected.'); + } + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "Raise a Ticket")), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Title", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Title", + controller: titleController, + margin: getMargin(top: 6)) + ])), + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Description", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Description", + controller: descriptionController, + margin: getMargin(top: 6)) + ])), + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Project Name", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Project Name", + controller: projectNameController, + margin: getMargin(top: 6)) + ])), // Adjusted the spacing + Row( + children: [ + Text('Pick Screenshot of issue'), + IconButton( + onPressed: () { + _pickImage(); // Call the function to pick an image + }, + icon: Icon(Icons.file_copy), + ), + SizedBox(width: 8.0), + // Display the selected screenshot file name + Text(screenshot != null ? screenshot.path.split('/').last : ''), + ], + ), + CustomButton( + height: getVerticalSize(50), + text: "Submit", + margin: getMargin(top: 24, bottom: 5), + onTap: () async { + submitTicket(screenshot); + }, + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/LayoutReportBuilder/LayoutReportBuilder.dart b/lib/screens/LayoutReportBuilder/LayoutReportBuilder.dart new file mode 100644 index 0000000..f39311c --- /dev/null +++ b/lib/screens/LayoutReportBuilder/LayoutReportBuilder.dart @@ -0,0 +1,975 @@ +import 'package:flutter/material.dart'; +import 'dart:convert'; + +// class ReportEditor extends StatefulWidget { +// @override +// _ReportEditorState createState() => _ReportEditorState(); +// } +// +// class _ReportEditorState extends State { +// List> droppedFields = []; +// GlobalKey _scaffoldKey = GlobalKey(); +// TextEditingController keyController = TextEditingController(); +// TextEditingController valueController = TextEditingController(); +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// key: _scaffoldKey, +// appBar: AppBar(title: Text('Report Editor')), +// body: Row( +// children: [ +// Container( +// width: 200, +// padding: EdgeInsets.all(10), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text('Drag and Drop Fields:'), +// Draggable( +// data: 'Title', +// child: DragField(text: 'Title'), +// feedback: DragField(text: 'Title'), +// ), +// Draggable( +// data: 'Phone Number', +// child: DragField(text: 'Phone Number'), +// feedback: DragField(text: 'Phone Number'), +// ), +// Draggable( +// data: 'Date', +// child: DragField(text: 'Date'), +// feedback: DragField(text: 'Date'), +// ), +// ], +// ), +// ), +// Expanded( +// child: SingleChildScrollView( +// child: Container( +// color: Colors.white, +// child: Stack( +// children: [ +// Container( +// margin: EdgeInsets.all(10), +// width: 793, // A4 width +// height: 1122, // A4 height +// decoration: BoxDecoration( +// border: Border.all( +// color: Colors.black, +// width: 1.0, +// ), +// ), +// ), +// Align( +// alignment: Alignment.bottomRight, +// child: Text('Scale Bar Report Editor'), +// ), +// ...droppedFields.asMap().entries.map((entry) { +// final index = entry.key; +// final field = entry.value; +// return DraggableField( +// key: Key(index.toString()), +// field: field, +// onDrag: (Offset position) { +// setState(() { +// droppedFields[index]['left'] = position.dx; +// droppedFields[index]['top'] = position.dy; +// }); +// }, +// onEdit: (String key, String value) { +// setState(() { +// droppedFields[index]['key'] = key; +// droppedFields[index]['value'] = value; +// }); +// }, +// +// ); +// }).toList(), +// DraggableTarget( +// onAccept: (String field) { +// final RenderBox renderBox = context.findRenderObject() as RenderBox; +// final offset = renderBox.localToGlobal(Offset.zero); +// print(offset.dx); +// setState(() { +// droppedFields.add({ +// 'type': field, +// 'left': offset.dx, // Set left coordinate +// 'top': offset.dy, // Set top coordinate +// 'key': field, +// 'value': '', +// 'isEditing': true, // Set the newly dropped field to be in edit mode +// }); +// }); +// }, +// ), +// +// ], +// ), +// ), +// ), +// ), +// ], +// ), +// floatingActionButton: FloatingActionButton( +// onPressed: () { +// _submitReport(); +// }, +// child: Icon(Icons.save), +// ), +// ); +// } +// +// void _submitReport() { +// final reportJson = jsonEncode(droppedFields); +// print(reportJson); +// +// ScaffoldMessenger.of(context).showSnackBar( +// SnackBar( +// content: Text('Report JSON created and printed!'), +// ), +// ); +// } +// } +// +// class DragField extends StatelessWidget { +// final String text; +// +// DragField({required this.text}); +// +// @override +// Widget build(BuildContext context) { +// return Container( +// width: 120, +// padding: EdgeInsets.all(8), +// margin: EdgeInsets.symmetric(vertical: 5), +// decoration: BoxDecoration( +// color: Colors.blue, +// borderRadius: BorderRadius.circular(5), +// ), +// child: Text( +// text, +// style: TextStyle(color: Colors.white), +// ), +// ); +// } +// } +// +// class DraggableField extends StatefulWidget { +// final Map field; +// final Function(Offset) onDrag; +// final Function(String, String) onEdit; +// +// DraggableField({ +// required Key key, +// required this.field, +// required this.onDrag, +// required this.onEdit, +// }) : super(key: key); +// +// @override +// _DraggableFieldState createState() => _DraggableFieldState(); +// } +// +// class _DraggableFieldState extends State { +// Offset position = Offset(0, 0); +// +// @override +// void initState() { +// super.initState(); +// final left = widget.field['left'] as double; +// final top = widget.field['top'] as double; +// position = Offset(left, top); +// } +// +// @override +// Widget build(BuildContext context) { +// return Positioned( +// left: position.dx, +// top: position.dy, +// child: GestureDetector( +// onLongPress: () { +// widget.onEdit(widget.field['key'], widget.field['value']); +// setState(() { +// // Set the field to be in edit mode when long-pressed +// widget.field['isEditing'] = true; +// }); +// }, +// child: Draggable( +// data: widget.field['type'], +// child: widget.field['isEditing'] +// ? EditableField( +// key: widget.key as Key, +// keyText: widget.field['key'], +// valueText: widget.field['value'], +// onEdit: widget.onEdit, +// ) +// : DragField(text: widget.field['type']), +// feedback: DragField(text: widget.field['type']), +// onDragEnd: (details) { +// setState(() { +// position = details.offset; +// widget.onDrag(details.offset); +// }); +// }, +// ), +// ), +// ); +// } +// } +// +// class EditableField extends StatefulWidget { +// final String keyText; +// final String valueText; +// final Function(String, String) onEdit; +// +// EditableField({ +// required Key key, +// required this.keyText, +// required this.valueText, +// required this.onEdit, +// }) : super(key: key); +// +// @override +// _EditableFieldState createState() => _EditableFieldState(); +// } +// +// class _EditableFieldState extends State { +// TextEditingController keyController = TextEditingController(); +// TextEditingController valueController = TextEditingController(); +// +// @override +// void initState() { +// super.initState(); +// keyController.text = widget.keyText; +// valueController.text = widget.valueText; +// } +// +// @override +// Widget build(BuildContext context) { +// return Container( +// width: 120, +// padding: EdgeInsets.all(8), +// margin: EdgeInsets.symmetric(vertical: 5), +// decoration: BoxDecoration( +// color: Colors.blue, +// borderRadius: BorderRadius.circular(5), +// ), +// child: Column( +// children: [ +// TextFormField( +// controller: keyController, +// decoration: InputDecoration(labelText: 'Key'), +// onChanged: (value) { +// widget.onEdit(value, valueController.text); +// }, +// ), +// TextFormField( +// controller: valueController, +// decoration: InputDecoration(labelText: 'Value'), +// onChanged: (value) { +// widget.onEdit(keyController.text, value); +// }, +// ), +// ], +// ), +// ); +// } +// } +// +// class DraggableTarget extends StatelessWidget { +// final Function(String) onAccept; +// +// DraggableTarget({required this.onAccept}); +// +// @override +// Widget build(BuildContext context) { +// return Container( +// width: 793, +// height: 1122, +// child: DragTarget( +// builder: (context, candidateData, rejectedData) { +// return Center( +// child: Text('Drop Here', style: TextStyle(fontSize: 24)), +// ); +// }, +// onAccept: (String field) { +// onAccept(field); +// }, +// )); +// } +// } + + + + + + + +// import 'package:flutter/material.dart'; +// +// class ReportEditor extends StatefulWidget { +// @override +// _ReportEditorState createState() => _ReportEditorState(); +// } +// +// class _ReportEditorState extends State { +// List> droppedFields = []; +// GlobalKey _scaffoldKey = GlobalKey(); +// TextEditingController keyController = TextEditingController(); +// TextEditingController valueController = TextEditingController(); +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// key: _scaffoldKey, +// appBar: AppBar(title: Text('Report Editor')), +// body: Row( +// children: [ +// Container( +// width: 200, +// padding: EdgeInsets.all(10), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text('Drag and Drop Fields:'), +// Draggable( +// data: 'Title', +// child: DragField(text: 'Title'), +// feedback: DragField(text: 'Title'), +// ), +// Draggable( +// data: 'Phone Number', +// child: DragField(text: 'Phone Number'), +// feedback: DragField(text: 'Phone Number'), +// ), +// Draggable( +// data: 'Date', +// child: DragField(text: 'Date'), +// feedback: DragField(text: 'Date'), +// ), +// ], +// ), +// ), +// Expanded( +// child: SingleChildScrollView( +// child: Container( +// color: Colors.white, +// child: Stack( +// children: [ +// Container( +// margin: EdgeInsets.all(10), +// width: 793, // A4 width +// height: 1122, // A4 height +// decoration: BoxDecoration( +// border: Border.all( +// color: Colors.black, +// width: 1.0, +// ), +// ), +// ), +// Align( +// alignment: Alignment.bottomRight, +// child: Text('Scale Bar Report Editor'), +// ), +// ...droppedFields.asMap().entries.map((entry) { +// final index = entry.key; +// final field = entry.value; +// return DraggableField( +// key: Key(index.toString()), +// field: field, +// onDrag: (Offset position) { +// setState(() { +// droppedFields[index]['left'] = position.dx; +// droppedFields[index]['top'] = position.dy; +// }); +// }, +// onEdit: (String key, String value) { +// setState(() { +// droppedFields[index]['key'] = key; +// droppedFields[index]['value'] = value; +// }); +// }, +// onDelete: () { +// setState(() { +// droppedFields.removeAt(index); +// }); +// }, +// ); +// }).toList(), +// DraggableTarget( +// onAccept: (String field) { +// final RenderBox renderBox = context.findRenderObject() as RenderBox; +// final offset = renderBox.localToGlobal(Offset.zero); +// setState(() { +// droppedFields.add({ +// 'type': field, +// 'left': offset.dx, // Set left coordinate +// 'top': offset.dy, // Set top coordinate +// 'key': field, +// 'value': '', +// 'isEditing': true, // Set the newly dropped field to be in edit mode +// }); +// }); +// }, +// ), +// ], +// ), +// ), +// ), +// ), +// ], +// ), +// floatingActionButton: FloatingActionButton( +// onPressed: () { +// _submitReport(); +// }, +// child: Icon(Icons.save), +// ), +// ); +// } +// +// void _submitReport() { +// final reportJson = jsonEncode(droppedFields); +// print(reportJson); +// +// ScaffoldMessenger.of(context).showSnackBar( +// SnackBar( +// content: Text('Report JSON created and printed!'), +// ), +// ); +// } +// } +// +// +// class DragField extends StatelessWidget { +// final String text; +// +// DragField({required this.text}); +// +// @override +// Widget build(BuildContext context) { +// return Container( +// width: 120, +// padding: EdgeInsets.all(8), +// margin: EdgeInsets.symmetric(vertical: 5), +// decoration: BoxDecoration( +// color: Colors.blue, +// borderRadius: BorderRadius.circular(5), +// ), +// child: Text( +// text, +// style: TextStyle(color: Colors.white), +// ), +// ); +// } +// } +// +// class DraggableField extends StatefulWidget { +// final Map field; +// final Function(Offset) onDrag; +// final Function(String, String) onEdit; +// final Function onDelete; +// +// DraggableField({ +// required Key key, +// required this.field, +// required this.onDrag, +// required this.onEdit, +// required this.onDelete, +// }) : super(key: key); +// +// @override +// _DraggableFieldState createState() => _DraggableFieldState(); +// } +// +// class _DraggableFieldState extends State { +// Offset position = Offset(0, 0); +// bool isEditing = false; +// +// @override +// void initState() { +// super.initState(); +// final left = widget.field['left'] as double; +// final top = widget.field['top'] as double; +// position = Offset(left, top); +// } +// +// @override +// Widget build(BuildContext context) { +// return Positioned( +// left: position.dx, +// top: position.dy, +// child: GestureDetector( +// onLongPress: () { +// widget.onEdit(widget.field['key'], widget.field['value']); +// setState(() { +// isEditing = true; +// }); +// }, +// child: Draggable( +// data: widget.field['type'], +// child: isEditing +// ? EditableField( +// key: widget.key as Key, +// keyText: widget.field['key'], +// valueText: widget.field['value'], +// onEdit: widget.onEdit, +// ) +// : Stack( +// children: [ +// DragField(text: widget.field['type']), +// Positioned( +// top: -10, +// right: -10, +// child: IconButton( +// icon: Icon(Icons.delete), +// onPressed: () { +// widget.onDelete(); +// }, +// ), +// ), +// ], +// ), +// feedback: DragField(text: widget.field['type']), +// onDragEnd: (details) { +// setState(() { +// position = details.offset; +// widget.onDrag(details.offset); +// }); +// }, +// ), +// ), +// ); +// } +// } +// +// class EditableField extends StatefulWidget { +// final String keyText; +// final String valueText; +// final Function(String, String) onEdit; +// +// EditableField({ +// required Key key, +// required this.keyText, +// required this.valueText, +// required this.onEdit, +// }) : super(key: key); +// +// @override +// _EditableFieldState createState() => _EditableFieldState(); +// } +// +// class _EditableFieldState extends State { +// TextEditingController keyController = TextEditingController(); +// TextEditingController valueController = TextEditingController(); +// +// @override +// void initState() { +// super.initState(); +// keyController.text = widget.keyText; +// valueController.text = widget.valueText; +// } +// +// @override +// Widget build(BuildContext context) { +// return Container( +// width: 120, +// padding: EdgeInsets.all(8), +// margin: EdgeInsets.symmetric(vertical: 5), +// decoration: BoxDecoration( +// color: Colors.blue, +// borderRadius: BorderRadius.circular(5), +// ), +// child: Column( +// children: [ +// TextFormField( +// controller: keyController, +// decoration: InputDecoration(labelText: 'Key'), +// onChanged: (value) { +// widget.onEdit(value, valueController.text); +// }, +// ), +// TextFormField( +// controller: valueController, +// decoration: InputDecoration(labelText: 'Value'), +// onChanged: (value) { +// widget.onEdit(keyController.text, value); +// }, +// ), +// ], +// ), +// ); +// } +// } +// +// class DraggableTarget extends StatelessWidget { +// final Function(String) onAccept; +// +// DraggableTarget({required this.onAccept}); +// +// @override +// Widget build(BuildContext context) { +// return Container( +// width: 793, +// height: 1122, +// child: DragTarget( +// builder: (context, candidateData, rejectedData) { +// return Center( +// child: Text('Drop Here', style: TextStyle(fontSize: 24)), +// ); +// }, +// onAccept: (String field) { +// onAccept(field); +// }, +// ), +// ); +// } +// } + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pdf/pdf.dart'; +import 'package:pdf/widgets.dart' as pdfLib; +import 'dart:io'; +import 'dart:typed_data'; + +class ReportEditor extends StatefulWidget { + @override + _ReportEditorState createState() => _ReportEditorState(); +} + +class _ReportEditorState extends State { + List> droppedFields = []; + GlobalKey _scaffoldKey = GlobalKey(); + TextEditingController keyController = TextEditingController(); + TextEditingController valueController = TextEditingController(); + + Future generatePdf() async { + final pdf = pdfLib.Document(); + + for (final field in droppedFields) { + final left = field['left'] as double; + final top = field['top'] as double; + final type = field['type']; + final key = field['key']; + final value = field['value']; + + final widget = pdfLib.Container( + child: pdfLib.Text('$type: $key - $value'), + decoration: const pdfLib.BoxDecoration( + border: pdfLib.Border(), + ), + padding: pdfLib.EdgeInsets.all(5), + ); + + pdf.addPage( + pdfLib.Page( + build: (context) { + return pdfLib.Positioned( + left: left, + top: top, + child: widget, + ); + }, + ), + ); + } + + return pdf.save(); + } + + Future savePdf() async { + final pdfBytes = await generatePdf(); + final dir = await getApplicationDocumentsDirectory(); + final pdfFile = File('${dir.path}/report.pdf'); + await pdfFile.writeAsBytes(pdfBytes); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('PDF saved to ${pdfFile.path}'), + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + key: _scaffoldKey, + appBar: AppBar(title: Text('Report Editor')), + body: Row( + children: [ + Container( + width: 200, + padding: EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Drag and Drop Fields:'), + Draggable( + data: 'Title', + child: DragField(text: 'Title'), + feedback: DragField(text: 'Title'), + ), + Draggable( + data: 'Phone Number', + child: DragField(text: 'Phone Number'), + feedback: DragField(text: 'Phone Number'), + ), + Draggable( + data: 'Date', + child: DragField(text: 'Date'), + feedback: DragField(text: 'Date'), + ), + ], + ), + ), + Expanded( + child: SingleChildScrollView( + child: Container( + color: Colors.white, + child: Stack( + children: [ + Container( + margin: EdgeInsets.all(10), + width: 793, // A4 width + height: 1122, // A4 height + decoration: BoxDecoration( + border: Border.all( + color: Colors.black, + width: 1.0, + ), + ), + ), + Align( + alignment: Alignment.bottomRight, + child: Text('Scale Bar Report Editor'), + ), + ...droppedFields.asMap().entries.map((entry) { + final index = entry.key; + final field = entry.value; + return DraggableField( + key: Key(index.toString()), + field: field, + onDrag: (Offset position) { + setState(() { + droppedFields[index]['left'] = position.dx; + droppedFields[index]['top'] = position.dy; + }); + }, + onEdit: (String key, String value) { + setState(() { + droppedFields[index]['key'] = key; + droppedFields[index]['value'] = value; + }); + }, + ); + }).toList(), + DraggableTarget( + onAccept: (String field) { + final RenderBox renderBox = + context.findRenderObject() as RenderBox; + final offset = renderBox.localToGlobal(Offset.zero); + + setState(() { + droppedFields.add({ + 'type': field, + 'left': offset.dx, + 'top': offset.dy, + 'key': field, + 'value': '', + 'isEditing': true, + }); + }); + }, + ), + ], + ), + ), + ), + ), + ], + ), + floatingActionButton: FloatingActionButton( + onPressed: savePdf, + child: Icon(Icons.save), + ), + ); + } +} + +class DragField extends StatelessWidget { + final String text; + + DragField({required this.text}); + + @override + Widget build(BuildContext context) { + return Container( + width: 120, + padding: EdgeInsets.all(8), + margin: EdgeInsets.symmetric(vertical: 5), + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(5), + ), + child: Text( + text, + style: TextStyle(color: Colors.white), + ), + ); + } +} + +class DraggableField extends StatefulWidget { + final Map field; + final Function(Offset) onDrag; + final Function(String, String) onEdit; + + DraggableField({ + required Key key, + required this.field, + required this.onDrag, + required this.onEdit, + }) : super(key: key); + + @override + _DraggableFieldState createState() => _DraggableFieldState(); +} + +class _DraggableFieldState extends State { + Offset position = Offset(0, 0); + + @override + void initState() { + super.initState(); + final left = widget.field['left'] as double; + final top = widget.field['top'] as double; + position = Offset(left, top); + } + + @override + Widget build(BuildContext context) { + return Positioned( + left: position.dx, + top: position.dy, + child: GestureDetector( + onLongPress: () { + widget.onEdit(widget.field['key'], widget.field['value']); + setState(() { + widget.field['isEditing'] = true; + }); + }, + child: Draggable( + data: widget.field['type'], + child: widget.field['isEditing'] + ? EditableField( + key: widget.key as Key, + keyText: widget.field['key'], + valueText: widget.field['value'], + onEdit: widget.onEdit, + ) + : DragField(text: widget.field['type']), + feedback: DragField(text: widget.field['type']), + onDragEnd: (details) { + setState(() { + position = details.offset; + widget.onDrag(details.offset); + }); + }, + ), + ), + ); + } +} + +class EditableField extends StatefulWidget { + final String keyText; + final String valueText; + final Function(String, String) onEdit; + + EditableField({ + required Key key, + required this.keyText, + required this.valueText, + required this.onEdit, + }) : super(key: key); + + @override + _EditableFieldState createState() => _EditableFieldState(); +} + +class _EditableFieldState extends State { + TextEditingController keyController = TextEditingController(); + TextEditingController valueController = TextEditingController(); + + @override + void initState() { + super.initState(); + keyController.text = widget.keyText; + valueController.text = widget.valueText; + } + + @override + Widget build(BuildContext context) { + return Container( + width: 120, + padding: EdgeInsets.all(8), + margin: EdgeInsets.symmetric(vertical: 5), + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(5), + ), + child: Column( + children: [ + TextFormField( + controller: keyController, + decoration: InputDecoration(labelText: 'Key'), + onChanged: (value) { + widget.onEdit(value, valueController.text); + }, + ), + TextFormField( + controller: valueController, + decoration: InputDecoration(labelText: 'Value'), + onChanged: (value) { + widget.onEdit(keyController.text, value); + }, + ), + ], + ), + ); + } +} + +class DraggableTarget extends StatelessWidget { + final Function(String) onAccept; + + DraggableTarget({required this.onAccept}); + + @override + Widget build(BuildContext context) { + return Container( + width: 793, + height: 1122, + child: DragTarget( + builder: (context, candidateData, rejectedData) { + return Center( + child: Text('Drop Here', style: TextStyle(fontSize: 24)), + ); + }, + onAccept: (String field) { + onAccept(field); + }, + ), + ); + } +} + +void main() { + runApp(MaterialApp( + home: ReportEditor(), + )); +} + + diff --git a/lib/screens/Login Screen/.DS_Store b/lib/screens/Login Screen/.DS_Store new file mode 100644 index 0000000..b28b719 Binary files /dev/null and b/lib/screens/Login Screen/.DS_Store differ diff --git a/lib/screens/Login Screen/form_component.dart b/lib/screens/Login Screen/form_component.dart new file mode 100644 index 0000000..f162d9d --- /dev/null +++ b/lib/screens/Login Screen/form_component.dart @@ -0,0 +1,342 @@ +import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../../Utils/color_constants.dart'; +import '../../providers/token_manager.dart'; +import '../../utilities/make_api_request.dart'; +import '../main_app_screen/tabbed_layout_component.dart'; + +class LoginFormComponent extends StatefulWidget { + const LoginFormComponent({Key? key}) : super(key: key); + + @override + LoginFormComponentState createState() { + return LoginFormComponentState(); + } +} + +class LoginFormComponentState extends State { + final _formKey = GlobalKey(); + String errorMessage1 = ""; + String errorMessage2 = ""; + String userInput = ""; + String password = ""; + bool isPasswordVisible = false; + bool stayLoggedIn = false; + + void errorMessageSetter(int fieldNumber, String message) { + setState(() { + if (fieldNumber == 1) { + errorMessage1 = message; + } else { + errorMessage2 = message; + } + }); + } + + void tryLoggingIn() async { + final dataReceived = await sendData( + urlPath: "/token/session", + data: {"email": userInput, "password": password}, + ); + + if (dataReceived.containsValue('ERROR')) { + var error = dataReceived['operationMessage'].toString(); + // ignore: use_build_context_synchronously + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar( + content: Text(error), + backgroundColor: Colors.redAccent, + )) + .closed; + } else { + var token = dataReceived['item']['token']; + var user = dataReceived['item']; + await TokenManager.setToken(token); + + if (stayLoggedIn) { + await _saveLoggedInUserData(token, user); + } + // ignore: use_build_context_synchronously + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text("Login Successful"), + backgroundColor: Colors.green, + )) + .closed + .then( + (value) => Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute( + builder: (context) => TabbedLayoutComponent(), + ), + (route) => false, + ), + ); + + print('after login'); + } + } + + Future _saveLoggedInUserData( + String loggedInUserAuthKey, Map user) async { + try { + var userId = user['userId'].toString(); + var firstName = user['firstName'].toString(); + + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('userData', json.encode(user)); + await prefs.setBool('isLoggedIn', true); + await prefs.setString('token', loggedInUserAuthKey); + + print('userId ....$userId'); + print('firstName ....$firstName'); + + if (mounted) { + debugPrint("user data saved"); + } + + return true; + } catch (e) { + return false; + } + } + + @override + Widget build(BuildContext context) { + return Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Color(0xFFF5F7FA), + ), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100, + ), + ], + ), + child: TextFormField( + textInputAction: TextInputAction.next, + validator: (value) { + if (value == null || value.isEmpty) { + errorMessageSetter( + 1, 'You must provide an email or username'); + } else { + errorMessageSetter(1, ""); + + setState(() { + userInput = value; + }); + } + + return null; + }, + autocorrect: false, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: + EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15), + hintText: "Username or email address", + hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + ), + if (errorMessage1 != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Text( + "\t\t\t\t$errorMessage1", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + Container( + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + border: Border.all(width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + color: Colors.white, + boxShadow: [ + const BoxShadow( + spreadRadius: 0.618, + blurRadius: 6.18, + offset: Offset(-4, -4), + color: Color(0xFFF5F7FA), + ), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100, + ), + ], + ), + child: TextFormField( + textInputAction: TextInputAction.done, + onFieldSubmitted: (value) => _validateLoginDetails(), + validator: (value) { + if (value == null || value.isEmpty) { + errorMessageSetter(2, 'Password cannot be empty'); + } else { + errorMessageSetter(2, ""); + setState(() { + password = value; + }); + } + return null; + }, + obscureText: !isPasswordVisible, + enableSuggestions: false, + autocorrect: false, + decoration: InputDecoration( + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: const EdgeInsets.only( + left: 15, bottom: 11, top: 11, right: 15), + hintText: "Password", + hintStyle: + const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + suffixIcon: IconButton( + icon: Icon( + isPasswordVisible ? Icons.visibility : Icons.visibility_off, + ), + onPressed: () { + setState(() { + isPasswordVisible = !isPasswordVisible; + }); + }, + ), + ), + ), + ), + if (errorMessage2 != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Text( + "\t\t\t\t$errorMessage2", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + CheckboxListTile( + activeColor: ColorConstant.blue700, + title: const Text('Stay Logged In'), + value: stayLoggedIn, + onChanged: (value) { + setState(() { + stayLoggedIn = value!; + }); + }, + ), + Container( + margin: const EdgeInsets.symmetric(vertical: 16.0), + width: double.infinity, + height: 64, + child: ElevatedButton( + onPressed: _validateLoginDetails, + style: ElevatedButton.styleFrom( + backgroundColor: ColorConstant.blue700, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + ), + child: const Text( + 'Log in', + style: TextStyle( + fontSize: 16, + color: Colors.white, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + // Container( + // margin: const EdgeInsets.symmetric(vertical: 16.0), + // width: double.infinity, + // height: 64, + // decoration: BoxDecoration( + // boxShadow: [ + // BoxShadow( + // color: Colors.blueGrey.shade100, + // offset: const Offset(0, 4), + // blurRadius: 5.0, + // ), + // ], + // gradient: const RadialGradient( + // colors: [Color(0xff0070BA), Color(0xff1546A0)], + // radius: 8.4, + // center: Alignment(-0.24, -0.36), + // ), + // borderRadius: BorderRadius.circular(20), + // ), + // child: ElevatedButton( + // onPressed: _validateLoginDetails, + // style: ElevatedButton.styleFrom( + // primary: Colors.transparent, + // shadowColor: Colors.transparent, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(20), + // ), + // ), + // child: const Text( + // 'Log in', + // style: TextStyle( + // fontSize: 16, + // fontWeight: FontWeight.w600, + // ), + // ), + // ), + // ), + ], + ), + ); + } + + void _validateLoginDetails() { + FocusManager.instance.primaryFocus?.unfocus(); + if (_formKey.currentState!.validate()) { + if (errorMessage1 != "" || errorMessage2 != "") { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('Please provide all required details'), + backgroundColor: Colors.red, + ), + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + onVisible: tryLoggingIn, + content: const Text('Processing...'), + backgroundColor: Colors.blue, + ), + ); + } + } + } +} diff --git a/lib/screens/Login Screen/login_screen.dart b/lib/screens/Login Screen/login_screen.dart new file mode 100644 index 0000000..b66ce03 --- /dev/null +++ b/lib/screens/Login Screen/login_screen.dart @@ -0,0 +1,586 @@ +// import 'dart:convert'; +// import 'package:flutter/material.dart'; +// import 'package:authsec_flutter/hadwin_components.dart'; +// import 'package:shared_preferences/shared_preferences.dart'; +// import '../../Utils/color_constants.dart'; +// import '../../Utils/image_constant.dart'; +// import '../../Utils/size_utils.dart'; +// import '../../providers/token_manager.dart'; +// import '../../theme/app_style.dart'; +// import '../../widgets/app_bar/appbar_title.dart'; +// import '../../widgets/app_bar/custom_app_bar.dart'; +// import '../../widgets/custom_button.dart'; +// import '../../widgets/custom_image_view.dart'; +// import '../../widgets/custom_text_form_field.dart'; +// import '../forgot_password/forgotPasswordScreen.dart'; +// import '../main_app_screen/newlanding_page.dart'; +// import '../sign_up_screen/sign_up_step_1.dart'; +// +// +// +// class LoginScreen extends StatefulWidget { +// const LoginScreen({Key? key}) : super(key: key); +// +// @override +// _LoginScreenState createState() => _LoginScreenState(); +// } +// +// class _LoginScreenState extends State { +// TextEditingController inputFieldController = TextEditingController(); +// TextEditingController inputFieldOneController = TextEditingController(); +// +// String errorMessage1 = ""; +// String errorMessage2 = ""; +// bool isPasswordVisible = false; +// bool stayLoggedIn = false; +// +// @override +// initState(){ +// super.initState(); +// } +// +// GlobalKey _formKey = GlobalKey(); +// +// void errorMessageSetter(int fieldNumber, String message) { +// setState(() { +// if (fieldNumber == 1) { +// errorMessage1 = message; +// } else { +// errorMessage2 = message; +// } +// }); +// } +// +// void tryLoggingIn() async { +// final dataReceived = await sendData( +// urlPath: "/token/session", +// data: {"email": inputFieldController.text, "password": inputFieldOneController.text}, +// ); +// +// if (dataReceived.containsValue('ERROR')) { +// var error = dataReceived['operationMessage'].toString(); +// // ignore: use_build_context_synchronously +// ScaffoldMessenger.of(context) +// .showSnackBar(SnackBar( +// content: Text(error), +// backgroundColor: Colors.redAccent, +// )) +// .closed; +// } else { +// var token = dataReceived['item']['token']; +// var user = dataReceived['item']; +// await TokenManager.setToken(token); +// +// if (stayLoggedIn) { +// await _saveLoggedInUserData(token, user); +// } +// // ignore: use_build_context_synchronously +// ScaffoldMessenger.of(context) +// .showSnackBar(const SnackBar( +// content: Text("Login Successful"), +// backgroundColor: Colors.green, +// )) +// .closed +// .then( +// (value) => Navigator.of(context).pushAndRemoveUntil( +// MaterialPageRoute( +// builder: (context) => TabbedLayoutComponentb(), +// ), +// (route) => false, +// ), +// ); +// +// print('after login'); +// } +// } +// +// Future _saveLoggedInUserData( +// String loggedInUserAuthKey, Map user) async { +// try { +// var userId = user['userId'].toString(); +// var firstName = user['firstName'].toString(); +// +// final prefs = await SharedPreferences.getInstance(); +// await prefs.setString('userData', json.encode(user)); +// await prefs.setBool('isLoggedIn', true); +// await prefs.setString('token', loggedInUserAuthKey); +// +// print('userId ....$userId'); +// print('firstName ....$firstName'); +// +// if (mounted) { +// debugPrint("user data saved"); +// } +// +// return true; +// } catch (e) { +// return false; +// } +// } +// +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// backgroundColor: ColorConstant.gray50, +// appBar: CustomAppBar( +// height: getVerticalSize(54), +// leadingWidth: 40, +// centerTitle: true, +// title: AppbarTitle(text: "Login")), +// body: SingleChildScrollView( +// child: Form( +// key: _formKey, +// child: Container( +// width: double.maxFinite, +// padding: +// getPadding(left: 16, top: 22, right: 16, bottom: 22), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// Padding( +// padding: getPadding(top: 19), +// child: Text("Email", +// overflow: TextOverflow.ellipsis, +// textAlign: TextAlign.left, +// style: AppStyle.txtGilroyMedium16Bluegray900),), +// +// CustomTextFormField( +// focusNode: FocusNode(), +// controller: inputFieldController, +// hintText: "Enter Your Email", +// padding: TextFormFieldPadding.PaddingT12, +// +// margin: getMargin(top: 7), +// textInputType: TextInputType.emailAddress), +// Padding( +// padding: getPadding(top: 19), +// child: Text("Password", +// overflow: TextOverflow.ellipsis, +// textAlign: TextAlign.left, +// style: +// AppStyle.txtGilroyMedium16Bluegray900)), +// CustomTextFormField( +// focusNode: FocusNode(), +// controller: inputFieldOneController, +// hintText: "Enter Password", +// margin: getMargin(top: 6), +// padding: TextFormFieldPadding.PaddingT12, +// textInputAction: TextInputAction.done, +// textInputType:TextInputType.visiblePassword, +// suffix: IconButton( +// icon: Icon( +// isPasswordVisible ? Icons.visibility_off : Icons.visibility, +// size: 12, +// ), +// onPressed: () { +// setState(() { +// isPasswordVisible = !isPasswordVisible; +// }); +// }, +// ), +// suffixConstraints: BoxConstraints( +// maxHeight: getVerticalSize(44)), +// isObscureText: !isPasswordVisible), +// Padding( +// padding: getPadding(top: 17), +// child: Row(children: [ +// Checkbox(value: stayLoggedIn, +// activeColor: ColorConstant.blueA700, +// onChanged: (value) { +// setState(() { +// stayLoggedIn = value!; +// }); +// },), +// Padding( +// padding: +// getPadding(left: 8, top: 1, bottom: 1), +// child: Text("Remember me", +// overflow: TextOverflow.ellipsis, +// textAlign: TextAlign.left, +// style: AppStyle.txtGilroyMedium14)), +// Spacer(), +// GestureDetector( +// onTap: getLoginHelp, +// child: Padding( +// padding: getPadding(top: 3), +// child: Text("Forgot Password?", +// overflow: TextOverflow.ellipsis, +// textAlign: TextAlign.left, +// style: +// AppStyle.txtGilroyMedium14BlueA700)), +// ) +// ])), +// CustomButton( +// height: getVerticalSize(50), +// width: getHorizontalSize(396), +// text: "Log in", +// margin: getMargin(top: 25), +// onTap: (){ +// if(inputFieldOneController.text==''||inputFieldController.text==''){ +// ScaffoldMessenger.of(context).showSnackBar( +// const SnackBar( +// content: Text('Please provide all required details'), +// backgroundColor: Colors.red, +// ), +// ); +// }else{ +// _validateLoginDetails(); +// } +// }, +// ), +// Padding( +// padding: getPadding(top: 26), +// child: Row( +// mainAxisAlignment: +// MainAxisAlignment.spaceBetween, +// crossAxisAlignment: CrossAxisAlignment.end, +// children: [ +// Padding( +// padding: getPadding(top: 10, bottom: 7), +// child: Divider( +// height: getVerticalSize(1), +// thickness: getVerticalSize(1), +// color: ColorConstant.blueGray200)), +// Text("Or continue with", +// overflow: TextOverflow.ellipsis, +// textAlign: TextAlign.left, +// style: AppStyle +// .txtGilroyRegular16Bluegray200), +// Padding( +// padding: getPadding(top: 10, bottom: 7), +// child: Divider( +// height: getVerticalSize(1), +// thickness: getVerticalSize(1), +// color: ColorConstant.blueGray200)) +// ])), +// CustomButton( +// height: getVerticalSize(50), +// text: "Sign Up", +// margin: getMargin(top: 28), +// variant: ButtonVariant.OutlineBlueA700, +// padding: ButtonPadding.PaddingT14, +// fontStyle: ButtonFontStyle.GilroyMedium16BlueA700, +// onTap:goToSignUpScreen , +// // prefixWidget: Container( +// // margin: getMargin(right: 8), +// // child: CustomImageView( +// // svgPath: ImageConstant.imgGoogle)) +// ), +// CustomButton( +// height: getVerticalSize(50), +// text: "Sign in with Google", +// margin: getMargin(top: 28), +// variant: ButtonVariant.OutlineBlueA700, +// padding: ButtonPadding.PaddingT14, +// fontStyle: ButtonFontStyle.GilroyMedium16BlueA700, +// prefixWidget: Container( +// margin: getMargin(right: 8), +// child: CustomImageView( +// svgPath: ImageConstant.imgGoogle))), +// CustomButton( +// height: getVerticalSize(50), +// text: "Sign in with Facebook", +// margin: getMargin(top: 17), +// variant: ButtonVariant.OutlineBlueA700, +// padding: ButtonPadding.PaddingT14, +// fontStyle: ButtonFontStyle.GilroyMedium16BlueA700, +// prefixWidget: Container( +// padding: +// getPadding(left: 9, top: 4, right: 3), +// margin: getMargin(right: 8), +// decoration: BoxDecoration( +// color: ColorConstant.blue700, +// borderRadius: BorderRadius.circular( +// getHorizontalSize(3))), +// child: CustomImageView( +// svgPath: ImageConstant.imgFacebook))), +// CustomButton( +// height: getVerticalSize(50), +// text: "Sign in with Linkedin", +// margin: getMargin(top: 17), +// variant: ButtonVariant.OutlineBlueA700, +// padding: ButtonPadding.PaddingT14, +// fontStyle: ButtonFontStyle.GilroyMedium16BlueA700, +// prefixWidget: Container( +// margin: getMargin(right: 8), +// child: CustomImageView( +// svgPath: ImageConstant.imgLinkedin11))), +// Align( +// alignment: Alignment.center, +// child: Padding( +// padding: getPadding(top: 28, bottom: 5), +// child: RichText( +// text: TextSpan(children: [ +// TextSpan( +// text: "", +// style: TextStyle( +// color: ColorConstant.fromHex( +// "#ff12282a"), +// fontSize: getFontSize(16), +// fontFamily: 'Gilroy', +// fontWeight: FontWeight.w400)), +// TextSpan( +// text: " ", +// style: TextStyle( +// color: ColorConstant.fromHex( +// "#ff12282a"), +// fontSize: getFontSize(16), +// fontFamily: 'Gilroy', +// fontWeight: FontWeight.w700)), +// TextSpan( +// text: "", +// style: TextStyle( +// color: ColorConstant.fromHex( +// "#ff0061ff"), +// fontSize: getFontSize(16), +// fontFamily: 'Gilroy', +// fontWeight: FontWeight.w700, +// decoration: +// TextDecoration.underline)) +// ]), +// textAlign: TextAlign.left))) +// ]))), +// ), +// ); +// } +// +// // onTapArrowleft6(BuildContext context) { +// // Navigator.pop(context); +// // } +// +// void _validateLoginDetails() { +// FocusManager.instance.primaryFocus?.unfocus(); +// if (_formKey.currentState!.validate()) { +// if (errorMessage1 != "" || errorMessage2 != "") { +// ScaffoldMessenger.of(context).showSnackBar( +// const SnackBar( +// content: Text('Please provide all required details'), +// backgroundColor: Colors.red, +// ), +// ); +// } else { +// ScaffoldMessenger.of(context).showSnackBar( +// SnackBar( +// onVisible: tryLoggingIn, +// content: const Text('Processing...'), +// backgroundColor: Colors.blue, +// ), +// ); +// } +// } +// } +// +// void getLoginHelp() { +// //ForgotPasswordPage +// Navigator.push( +// context, MaterialPageRoute(builder: (context) => ForgotPasswordPage())); +// // Navigator.push( +// // context, +// // SlideRightRoute( +// // page: const HadWinMarkdownViewer( +// // screenName: 'Login Help', +// // urlRequested: +// // 'https://raw.githubusercontent.com/brownboycodes/HADWIN/master/docs/HADWIN_WIKI.md'))); +// } +// +// void goToSignUpScreen() { +// // Navigator.push(context, +// // MaterialPageRoute(builder: (context) => SignUpUserScreen())) +// // .then((value) => const LoginScreen()); +// +// Navigator.push(context, +// MaterialPageRoute(builder: (context) => SignUpUserScreenNew())) +// .then((value) => const LoginScreen()); +// +// +// } +// +// } + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; + +import '../../Utils/color_constants.dart'; +import '../../utilities/hadwin_markdown_viewer.dart'; +import '../../utilities/slide_right_route.dart'; +import '../sign_up_screen/SignUpUser.dart'; +import '../sign_up_screen/sign_up_step_1.dart'; +import 'form_component.dart'; + +class LoginScreen extends StatefulWidget { + const LoginScreen({Key? key}) : super(key: key); + + @override + _LoginScreenState createState() => _LoginScreenState(); +} + +class _LoginScreenState extends State { + @override + Widget build(BuildContext context) { + Widget helpInfoContainer = SizedBox( + width: double.infinity, + height: 36, + child: Center( + child: InkWell( + onTap: getLoginHelp, + child: const Text( + 'Having trouble logging in?', + style: TextStyle(fontSize: 14, color: Color(0xFF929BAB)), + ), // FOR LOGIN HELP + ), + ), + ); + + Widget signUpContainer = const SizedBox( + width: double.infinity, + height: 36, + child: Center( + child: InkWell( + //onTap: goToSignUpScreen, + child: Text( + 'Or Continue with', + style: TextStyle(fontSize: 14, color: Color(0xFF929BAB)), + ), // FOR SIGN UP + ), + ), + ); + + List loginScreenContents = [ + _spacing(30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: SvgPicture.asset( + 'assets/images/cloudnsuresp.svg', + width: 300, + ), + ), + _spacing(30), + const LoginFormComponent(), // ON LOGIN SCREEN + _spacing(10), + signUpContainer, + _spacing(10), + Container( + margin: const EdgeInsets.symmetric(vertical: 16.0), + width: double.infinity, + height: 64, + child: ElevatedButton( + onPressed: goToSignUpScreen, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + side: BorderSide(color: ColorConstant.blue700, width: 2.0), + ), + ), + child: Text( + 'Sign Up', + style: TextStyle( + fontSize: 16, + color: ColorConstant.blue700, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + Container( + margin: const EdgeInsets.symmetric(vertical: 16.0), + width: double.infinity, + height: 64, + child: ElevatedButton( + onPressed: () {}, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + side: BorderSide(color: ColorConstant.blue700, width: 2.0), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/images/img_google.svg', + ), + const SizedBox( + width: 10, + ), + Text( + 'Sign in with Google', + style: TextStyle( + fontSize: 16, + color: Colors.grey, //ColorConstant.blue700, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + Container( + margin: const EdgeInsets.symmetric(vertical: 16.0), + width: double.infinity, + height: 64, + child: ElevatedButton( + onPressed: () {}, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + side: BorderSide(color: ColorConstant.blue700, width: 2.0), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset( + 'assets/images/img_linkedin_1_1.svg', + ), + const SizedBox( + width: 10, + ), + Text( + 'Sign in with LinkedIn', + style: TextStyle( + fontSize: 16, + color: Colors.grey, //ColorConstant.blue700, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ), + ), + ]; + + return Scaffold( + body: SingleChildScrollView( + padding: const EdgeInsets.all(45), + child: Column( + children: loginScreenContents, + ), + ), + ); + } + + void getLoginHelp() { + Navigator.push( + context, + SlideRightRoute( + page: const HadWinMarkdownViewer( + screenName: 'Login Help', + urlRequested: + 'https://raw.githubusercontent.com/brownboycodes/HADWIN/master/docs/HADWIN_WIKI.md'))); + } + + void goToSignUpScreen() { + Navigator.push(context, + MaterialPageRoute(builder: (context) => SignUpUserScreenNew())) + .then((value) => const LoginScreen()); + } + + SizedBox _spacing(double height) => SizedBox( + height: height, + ); +} diff --git a/lib/screens/LogoutService/Logoutservice.dart b/lib/screens/LogoutService/Logoutservice.dart new file mode 100644 index 0000000..7c198bf --- /dev/null +++ b/lib/screens/LogoutService/Logoutservice.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../../main.dart'; +import '../Login Screen/login_screen.dart'; + +class LogoutService { + static Future logout() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + await prefs.remove('userData'); + await prefs.remove('isLoggedIn'); + const storage = FlutterSecureStorage(); + await storage.delete(key: 'token'); + navigatorKey.currentState!.pushAndRemoveUntil( + MaterialPageRoute(builder: (context) => LoginScreen()), + (route) => false, // Remove all routes from the stack + ); + } +} + + diff --git a/lib/screens/QrBarCode/Barcode/Barcode_create_entity_screen.dart b/lib/screens/QrBarCode/Barcode/Barcode_create_entity_screen.dart new file mode 100644 index 0000000..24d3fb1 --- /dev/null +++ b/lib/screens/QrBarCode/Barcode/Barcode_create_entity_screen.dart @@ -0,0 +1,75 @@ +// ignore_for_file: use_build_context_synchronously +import 'package:flutter/material.dart'; +import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; + +class BarcodeScreen extends StatefulWidget { + const BarcodeScreen({super.key}); + + @override + _BarcodeScreenState createState() => _BarcodeScreenState(); +} + +class _BarcodeScreenState extends State { + final _formKey = GlobalKey(); + + String scannedbar_code_scanner = 'No data'; + + Future scanBarcode() async { + final result = await FlutterBarcodeScanner.scanBarcode( + '#ff6666', // Background color + 'Cancel', // Cancel button text + true, // Show flash icon + ScanMode.BARCODE, // Scan mode (you can change to QR code if needed) + ); + + if (!mounted) return; + + setState(() { + scannedbar_code_scanner = result; + }); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('BAR CODE')), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Center( + child: Column( + children: [ + const Text( + 'Scanned Barcode:', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Text( + scannedbar_code_scanner, + style: const TextStyle(fontSize: 16), + ), + const SizedBox(height: 16), + ElevatedButton.icon( + onPressed: () { + scanBarcode(); // Trigger barcode scanning + }, + icon: const Icon(Icons.camera_alt), // Camera icon + label: const Text('Scan Barcode'), + ), + const SizedBox(height: 16), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/QrBarCode/Qr_BarCode/Qr_BarCode_create_entity_screen.dart b/lib/screens/QrBarCode/Qr_BarCode/Qr_BarCode_create_entity_screen.dart new file mode 100644 index 0000000..eac8996 --- /dev/null +++ b/lib/screens/QrBarCode/Qr_BarCode/Qr_BarCode_create_entity_screen.dart @@ -0,0 +1,170 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:flutter/material.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +// import 'package:qr_code_scanner/qr_code_scanner.dart'; +import 'package:barcode_widget/barcode_widget.dart'; + +import '../Barcode/Barcode_create_entity_screen.dart'; +import '../Qrcode/Qrcode_create_entity_screen.dart'; + +class QrBarCodeScreen extends StatefulWidget { + const QrBarCodeScreen({super.key}); + + @override + _QrBarCodeScreenState createState() => _QrBarCodeScreenState(); +} + +class _QrBarCodeScreenState extends State { + final _formKey = GlobalKey(); + + TextEditingController qr_code_dataController = TextEditingController(); + + // Function to show the QR code in a dialog + void _showqr_code_dataDialog() { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Generated QR Code'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: 200, // Set a fixed width for the QR code + height: 200, // Set a fixed height for the QR code + child: QrImageView( + data: qr_code_dataController.text, + version: QrVersions.auto, + embeddedImageStyle: + const QrEmbeddedImageStyle(size: Size(100, 100)), + ), + ), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + }, + child: const Text('Close'), + ), + ], + ), + ); + }, + ); + } + + TextEditingController bar_code_dataController = TextEditingController(); + + // Function to show the barcode in a dialog + void _show_bar_code_dataDialog(String barcodeData) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Generated Bar Code'), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Card( + color: Colors.white, + elevation: 6, + shadowColor: Colors.amber, + child: Padding( + padding: const EdgeInsets.all(16), + child: BarcodeWidget( + data: barcodeData, + barcode: Barcode.code128(), + color: Colors.black, + width: 200, + height: 100, + drawText: false, + ), + ), + ), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () { + Navigator.of(context).pop(); // Close the dialog + }, + child: const Text('Close'), + ), + ], + ), + ); + }, + ); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('QR AND BAR CODE')), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Column( + children: [ + // GENERATE QR CODE + TextFormField( + controller: qr_code_dataController, + decoration: const InputDecoration(labelText: 'qr_code_data'), + ), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () { + _showqr_code_dataDialog(); + }, + child: const Text('Generate Qr')), + + // GENERATE BAR CODE + TextFormField( + controller: bar_code_dataController, + decoration: const InputDecoration(labelText: 'Bar Code Data'), + ), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () { + _show_bar_code_dataDialog(bar_code_dataController.text); + }, + child: const Text('Generate Bar code'), + ), +// QR CODE SCANNER + + const SizedBox(height: 16), + ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const qrcodeScreen())); + }, + child: const Text('QR Code Scanner'), + ), +// BAR CODE SCANNER + + const SizedBox(height: 16), + ElevatedButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const BarcodeScreen())); + }, + child: const Text('Bar Code Scanner'), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/QrBarCode/Qrcode/Qrcode_create_entity_screen.dart b/lib/screens/QrBarCode/Qrcode/Qrcode_create_entity_screen.dart new file mode 100644 index 0000000..feeae8b --- /dev/null +++ b/lib/screens/QrBarCode/Qrcode/Qrcode_create_entity_screen.dart @@ -0,0 +1,75 @@ +// ignore_for_file: use_build_context_synchronously +import 'package:flutter/material.dart'; +import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; + +class qrcodeScreen extends StatefulWidget { + const qrcodeScreen({super.key}); + + @override + _qrcodeScreenState createState() => _qrcodeScreenState(); +} + +class _qrcodeScreenState extends State { + final _formKey = GlobalKey(); + + String scannedqr_code_scanner = 'No data'; + + Future scanQRcode() async { + final result = await FlutterBarcodeScanner.scanBarcode( + '#ff6666', // Background color + 'Cancel', // Cancel button text + true, // Show flash icon + ScanMode.QR, // Scan mode (you can change to QR code if needed) + ); + + if (!mounted) return; + + setState(() { + scannedqr_code_scanner = result; + }); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('QR Code')), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Center( + child: Column( + children: [ + const Text( + 'Scanned QRcode:', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + Text( + scannedqr_code_scanner, + style: const TextStyle(fontSize: 16), + ), + const SizedBox(height: 16), + ElevatedButton.icon( + onPressed: () { + scanQRcode(); // Trigger barcode scanning + }, + icon: const Icon(Icons.camera_alt), // Camera icon + label: const Text('Scan QRcode'), + ), + const SizedBox(height: 16), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/Setup/setup.dart b/lib/screens/Setup/setup.dart new file mode 100644 index 0000000..8a033f5 --- /dev/null +++ b/lib/screens/Setup/setup.dart @@ -0,0 +1,127 @@ +import 'package:flutter/material.dart'; +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import '../SysParameters/SystemParameterScreen.dart'; + +class SetupScreen extends StatelessWidget { + const SetupScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "Setup Screen")), + body: SingleChildScrollView( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + buildSetupBlock(context, 'User Maintenance', SysParameter()), + buildSetupBlock(context, 'User Group Maintenance', SysParameter()), + buildSetupBlock(context, 'Menu Maintenance', SysParameter()), + buildSetupBlock(context, 'Menu Access', SysParameter()), + buildSetupBlock(context, 'System Parameter', SysParameter()), + buildSetupBlock(context, 'Access Type', SysParameter()), + // buildSetupBlock(context, 'Report', ReportPage()), + buildSetupBlock(context, 'Dashboard', SysParameter()), + ], + ), + ), + ), + ); + } + + Widget buildSetupBlock(BuildContext context, String title, Widget screen) { + return GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => screen), + ); + }, + child: Card( + color: Colors.white, + elevation: 0.0, + child: Padding( + padding: const EdgeInsets.fromLTRB(20, 40, 20, 40), + child: Column( + children: [ + // Container( + // height: getSize( + // 55, + // ), + // width: getSize( + // 55, + // ), + // margin: getMargin( + // top: 2, + // ), + // child: Stack( + // alignment: Alignment.center, + // children: [ + // Align( + // alignment: Alignment.center, + // child: Container( + // height: getSize( + // 55, + // ), + // width: getSize( + // 55, + // ), + // child: CircularProgressIndicator( + // value: 0.5, + // backgroundColor: ColorConstant.gray30099, + // color: ColorConstant.blueA700, + // ), + // ), + // ), + // Align( + // alignment: Alignment.center, + // child: Text( + // myProjectcount.toString(), + // overflow: TextOverflow.ellipsis, + // textAlign: TextAlign.left, + // style: AppStyle.txtGilroyBold18, + // ), + // ), + // ], + // ), + // ), + // Text( + // myProjectcount.toString(), + // style: const TextStyle( + // color: Colors.black, + // fontSize: 12, + // ), + // ), + const SizedBox(height: 3,), + Text( + title, + style: const TextStyle( + color: Colors.black, + fontSize: 10, + ), + ), + ], + ), + ), + ), + ); + } +} + + diff --git a/lib/screens/SysParameters/.DS_Store b/lib/screens/SysParameters/.DS_Store new file mode 100644 index 0000000..447b43d Binary files /dev/null and b/lib/screens/SysParameters/.DS_Store differ diff --git a/lib/screens/SysParameters/SystemParameterApiService.dart b/lib/screens/SysParameters/SystemParameterApiService.dart new file mode 100644 index 0000000..d57aefb --- /dev/null +++ b/lib/screens/SysParameters/SystemParameterApiService.dart @@ -0,0 +1,77 @@ +import 'dart:typed_data'; +import 'package:dio/dio.dart'; +import 'package:http_parser/http_parser.dart'; + +import '../../resources/api_constants.dart'; +import '../LogoutService/Logoutservice.dart'; + +class SystemParameterApiService { + final String baseUrl = ApiConstants.baseUrl; + final Dio dio = Dio(); + + Future> getsystemparameters(String token, int id) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + final response = await dio.get('$baseUrl/sysparam/getSysParams/$id'); + if (response.statusCode == 401) { + LogoutService.logout(); + } + final entities = (response.data); + return entities; + } catch (e) { + throw Exception('Failed to get all projects: $e'); + } + } + + Future updateParameter( + String token, int entityId, Map entity) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + var response = await dio + .put('$baseUrl/sysparam/updateSysParams/$entityId', data: entity); + if (response.statusCode == 401) { + LogoutService.logout(); + } + print(entity); + } catch (e) { + throw Exception('Failed to update projects: $e'); + } + } + + Future> createFile( + Uint8List fileBytes, String fileName, String token) async { + try { + String apiUrl = "$baseUrl/api/logos/upload?ref=test"; + + final mimeType = 'image/jpeg'; // You can set the appropriate MIME type + + FormData formData = FormData.fromMap({ + 'file': MultipartFile.fromBytes( + fileBytes, + filename: fileName, + contentType: MediaType.parse(mimeType), + ), + }); + + Dio dio = Dio(); // Create a new Dio instance + dio.options.headers['Authorization'] = 'Bearer $token'; + + final response = await dio.post(apiUrl, data: formData); + if (response.statusCode == 401) { + LogoutService.logout(); + } + if (response.statusCode == 200) { + print('File uploaded successfully'); + return response.data; // Return the response data on success + } else { + print('Failed to upload file with status: ${response.statusCode}'); + // You might want to handle this error case more explicitly + throw Exception('Failed to upload file'); + } + } catch (error) { + print('Error occurred during form submission: $error'); + // You might want to handle this error case more explicitly + throw Exception('Error during file upload: $error'); + } + } +} diff --git a/lib/screens/SysParameters/SystemParameterScreen.dart b/lib/screens/SysParameters/SystemParameterScreen.dart new file mode 100644 index 0000000..0d5f69f --- /dev/null +++ b/lib/screens/SysParameters/SystemParameterScreen.dart @@ -0,0 +1,533 @@ +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; + +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import '../../widgets/custom_button.dart'; +import '../../widgets/custom_text_form_field.dart'; +import 'SystemParameterApiService.dart'; + + +class SysParameter extends StatefulWidget { + final int sysparameter=1; + + // const SysParameter({Key? key, required this.sysparameter}) : super(key: key); + @override + _SysParameterState createState() => _SysParameterState(); +} + +class _SysParameterState extends State { + TextEditingController schedulerTimerController = TextEditingController(); + TextEditingController leaseTaxCodeController = TextEditingController(); + TextEditingController vesselConfirmationController = TextEditingController(); + TextEditingController rowToDisplayController = TextEditingController(); + TextEditingController linkToDisplayController = TextEditingController(); + TextEditingController rowToAddController = TextEditingController(); + TextEditingController lovRowToDisplayController = TextEditingController(); + TextEditingController lovLinkToDisplayController = TextEditingController(); + TextEditingController oidServerNameController = TextEditingController(); + TextEditingController oidBaseController = TextEditingController(); + TextEditingController oidAdminUserController = TextEditingController(); + TextEditingController oidServerPortController = TextEditingController(); + TextEditingController userDefaultGroupController = TextEditingController(); + TextEditingController defaultDepartmentController = TextEditingController(); + TextEditingController defaultPositionController = TextEditingController(); + TextEditingController singleChargeController = TextEditingController(); + TextEditingController firstDayOfWeekController = TextEditingController(); + TextEditingController hourPerShiftController = TextEditingController(); + TextEditingController cnBillingFrequencyController = TextEditingController(); + TextEditingController billingDepartmentCodeController = TextEditingController(); + TextEditingController basePriceListController = TextEditingController(); + TextEditingController nonContainerServiceController = TextEditingController(); + TextEditingController ediMaeSchedulerController = TextEditingController(); + TextEditingController ediSchedulerController = TextEditingController(); + TextEditingController lastController = TextEditingController(); + TextEditingController companynameController = TextEditingController(); + bool isRegistrationAllow=false; + + Map formData = {}; + var logoname; + var logopath; + + SystemParameterApiService apiService = SystemParameterApiService(); + + String? uploadimageurl; + Uint8List? _imageBytes; // Uint8List to store the image data + String? _imageFileName; + + + late Map sysparameter; + + @override + void initState() { + _loadParameters(); + } + + Future _loadParameters() async { + final token = await TokenManager.getToken(); + try { + final projectData = await apiService.getsystemparameters(token!,widget.sysparameter); + setState(() { + sysparameter = projectData; + lastController.text = "('SYSADMIN','ITSUPPORTMSC')"; + schedulerTimerController.text = sysparameter['schedulerTime'].toString()??''; + isRegistrationAllow = sysparameter['regitrationAllowed']??false; + leaseTaxCodeController.text = sysparameter['leaseTaxCode'].toString()??''; + vesselConfirmationController.text = sysparameter['vesselConfProcessLimit'].toString()??''; + rowToDisplayController.text = sysparameter['rowToDisplay'].toString()??''; + linkToDisplayController.text = sysparameter['linkToDisplay'].toString()??''; + rowToAddController.text = sysparameter['rowToAdd'].toString()??''; + lovRowToDisplayController.text = sysparameter['lovRowToDisplay'].toString()??''; + lovLinkToDisplayController.text = sysparameter['lovLinkToDisplay'].toString()??''; + oidServerNameController.text = sysparameter['oidserverName'].toString()??''; + oidBaseController.text = sysparameter['oidBase'].toString()??''; + oidAdminUserController.text = sysparameter['oidAdminUser'].toString()??''; + oidServerPortController.text = sysparameter['oidServerPort'].toString()??''; + userDefaultGroupController.text = sysparameter['userDefaultGroup'].toString()??''; + defaultDepartmentController.text = sysparameter['defaultDepartment'].toString()??''; + defaultPositionController.text = sysparameter['defaultPosition'].toString()??''; + singleChargeController.text = sysparameter['singleCharge'].toString()??''; + firstDayOfWeekController.text = sysparameter['firstDayOftheWeek'].toString()??''; + hourPerShiftController.text = sysparameter['hourPerShift'].toString()??''; + cnBillingFrequencyController.text = sysparameter['cnBillingFrequency'].toString()??''; + billingDepartmentCodeController.text = sysparameter['billingDepartmentCode'].toString()??''; + basePriceListController.text = sysparameter['basePriceList'].toString()??''; + nonContainerServiceController.text = sysparameter['nonContainerServiceOrder'].toString()??''; + ediMaeSchedulerController.text = sysparameter['ediMaeSchedulerONOFF'].toString()??''; + ediSchedulerController.text = sysparameter['ediSchedulerONOFF'].toString()??''; + lastController.text = "('SYSADMIN','ITSUPPORTMSC')"??''; + companynameController.text = sysparameter['company_Display_Name'].toString()??''; + print(sysparameter['schedulerTime']); + }); + } catch (e) { + print('Failed to load projects: $e'); + } + } + + Future _uploadImageFile() async { + final imagePicker = ImagePicker(); + + try { + final pickedImage = + await imagePicker.pickImage(source: ImageSource.gallery); + + if (pickedImage != null) { + final imageBytes = await pickedImage.readAsBytes(); + + setState(() { + _imageBytes = imageBytes; + _imageFileName = pickedImage.name; // Store the file name + }); + } + _submitImage(); + } catch (e) { + print(e); + } + } + + Future _submitImage() async { + if (_imageBytes == null) { + // Show an error message if no image is selected + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Please select an image.'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + return; + } + + if (_imageFileName == null) { + // Handle the case where _imageFileName is null (no file name provided) + print('File name is missing.'); + return; + } + try { + final token = await TokenManager.getToken(); + Map fileuploadeddata = await apiService.createFile(_imageBytes!, _imageFileName!, token!); + logoname = fileuploadeddata['image_name']; + logopath = fileuploadeddata['image_path']; + + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to upload image: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "System Parameter")), + body: Material(child:SingleChildScrollView( // Wrap the form in a SingleChildScrollView + scrollDirection: Axis.vertical, // Allow vertical scrolling + child:Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildFieldWithTooltip( + fieldName: 'Scheduler Timer', + controller: schedulerTimerController, + tooltip: 'Tooltip for Scheduler Timer', + ), + _buildFieldWithTooltip( + fieldName: 'Lease Tax Code', + controller: leaseTaxCodeController, + tooltip: 'Tooltip for Lease Tax Code', + ), + _buildFieldWithTooltip( + fieldName: 'Vessel Confirmation Process Limit', + controller: vesselConfirmationController, + tooltip: 'Tooltip for Vessel Confirmation Process Limit', + ), + _buildFieldWithTooltip( + fieldName: 'Row To Display', + controller: rowToDisplayController, + tooltip: 'Tooltip for Row To Display', + ), + _buildFieldWithTooltip( + fieldName: 'Link To Display', + controller: linkToDisplayController, + tooltip: 'Tooltip for Link To Display', + ), + _buildFieldWithTooltip( + fieldName: 'Row To Add', + controller: rowToAddController, + tooltip: 'Tooltip for Row To Add', + ), + _buildFieldWithTooltip( + fieldName: 'LOV Row To Display', + controller: lovRowToDisplayController, + tooltip: 'Tooltip for LOV Row To Display', + ), + _buildFieldWithTooltip( + fieldName: 'LOV Link To Display', + controller: lovLinkToDisplayController, + tooltip: 'Tooltip for LOV Link To Display', + ), + _buildFieldWithTooltip( + fieldName: 'OID Server Name', + controller: oidServerNameController, + tooltip: 'Tooltip for OID Server Name', + ), + _buildFieldWithTooltip( + fieldName: 'OID Base', + controller: oidBaseController, + tooltip: 'Tooltip for OID Base', + ), + _buildFieldWithTooltip( + fieldName: 'OID Admin User', + controller: oidAdminUserController, + tooltip: 'Tooltip for OID Admin User', + ), + _buildFieldWithTooltip( + fieldName: 'OID Server Port', + controller: oidServerPortController, + tooltip: 'Tooltip for OID Server Port', + ), + _buildFieldWithTooltip( + fieldName: 'User Default Group', + controller: userDefaultGroupController, + tooltip: 'Tooltip for User Default Group', + ), + _buildFieldWithTooltip( + fieldName: 'Default Department', + controller: defaultDepartmentController, + tooltip: 'Tooltip for Default Department', + ), + _buildFieldWithTooltip( + fieldName: 'Default Position', + controller: defaultPositionController, + tooltip: 'Tooltip for Default Position', + ), + _buildFieldWithTooltip( + fieldName: 'Single Charge', + controller: singleChargeController, + tooltip: 'Tooltip for Single Charge', + ), + _buildFieldWithTooltip( + fieldName: 'First Day of The Week', + controller: firstDayOfWeekController, + tooltip: 'Tooltip for First Day of The Week', + ), + _buildFieldWithTooltip( + fieldName: 'Hour per Shift', + controller: hourPerShiftController, + tooltip: 'Tooltip for Hour per Shift', + ), + _buildFieldWithTooltip( + fieldName: 'CN Billing Frequency', + controller: cnBillingFrequencyController, + tooltip: 'Tooltip for CN Billing Frequency', + ), + _buildFieldWithTooltip( + fieldName: 'Billing Department Code', + controller: billingDepartmentCodeController, + tooltip: 'Tooltip for Billing Department Code', + ), + _buildFieldWithTooltip( + fieldName: 'Base Price List', + controller: basePriceListController, + tooltip: 'Tooltip for Base Price List', + ), + _buildFieldWithTooltip( + fieldName: 'Non-Container Service Order Auto-Approval Department Code', + controller: nonContainerServiceController, + tooltip: 'Tooltip for Non-Container Service Order Auto-Approval Department Code', + ), + _buildFieldWithTooltip( + fieldName: 'EDI MAE Scheduler ON/OFF', + controller: ediMaeSchedulerController, + tooltip: 'Tooltip for EDI MAE Scheduler ON/OFF', + ), + _buildFieldWithTooltip( + fieldName: 'EDI Scheduler ON/OFF', + controller: ediSchedulerController, + tooltip: 'Tooltip for EDI Scheduler ON/OFF', + ), + _buildFieldWithTooltip( + fieldName: 'Company Name', + controller: companynameController, + tooltip: 'Company Name', + ), + Text("Is Registration Allowed?", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray800), + Row( + children: [ + Radio( + value: true, + groupValue: isRegistrationAllow, + onChanged: (value) { + setState(() { + isRegistrationAllow = value as bool; + }); + }, + ), + Text("Yes", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray800), + Radio( + value: false, + groupValue: isRegistrationAllow, + onChanged: (value) { + setState(() { + isRegistrationAllow = value as bool; + }); + }, + ), + Text("No", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray800), + ], + ), + + ElevatedButton( + onPressed: () { + _uploadImageFile(); + }, + style: ButtonStyle( + backgroundColor: _imageBytes==null?MaterialStateProperty.all(Colors.red):MaterialStateProperty.all(Colors.green), // Change to the desired color + ), + child: _imageBytes == null + ? Text("Pick a Company Logo", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray800) + : Text("Company Logo uploaded Successful", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray800), + ), + + Tooltip( + message: 'Allow customer code for MSC taulia CSV generation', + child: Column( + children: [ + Text("i", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray800), + CustomTextFormField( + focusNode: FocusNode(), + controller:lastController, + margin: getMargin(top: 7), + textInputType: + TextInputType.text), + ], + ) + // TextFormField( + // controller: lastController, + // decoration: const InputDecoration( + // labelText: 'i', + // ), + // ), + ), + + CustomButton( + height: getVerticalSize(50), + text: "Save", + margin: getMargin(top: 24, bottom: 5), + onTap: () async { + formData['regitrationAllowed'] = isRegistrationAllow; + formData['schedulerTime']=schedulerTimerController.text; + formData['leaseTaxCode']=leaseTaxCodeController.text; + formData['vesselConfProcessLimit']=vesselConfirmationController.text; + formData['rowToDisplay']=rowToDisplayController.text; + formData['linkToDisplay']=linkToDisplayController.text; + formData['rowToAdd']=rowToAddController.text; + formData['lovRowToDisplay']=lovRowToDisplayController.text; + formData['lovLinkToDisplay']=lovLinkToDisplayController.text; + formData['oidserverName']=oidServerNameController.text; + formData['oidBase']=oidBaseController.text; + formData['oidAdminUser']=oidAdminUserController.text; + formData['oidServerPort']=oidServerPortController.text; + formData['userDefaultGroup']=userDefaultGroupController.text; + formData['defaultDepartment']=defaultDepartmentController.text; + formData['defaultPosition']=defaultPositionController.text; + formData['singleCharge']=singleChargeController.text; + formData['firstDayOftheWeek']=firstDayOfWeekController.text; + formData['hourPerShift']=hourPerShiftController.text; + formData['cnBillingFrequency']=cnBillingFrequencyController.text; + formData['billingDepartmentCode']=billingDepartmentCodeController.text; + formData['basePriceList']=basePriceListController.text; + formData['nonContainerServiceOrder']=nonContainerServiceController.text; + formData['ediMaeSchedulerONOFF']=ediMaeSchedulerController.text; + formData['ediSchedulerONOFF']=ediSchedulerController.text; + //formData['']=lastController.text; + formData['upload_Logo_name']=logoname; + formData['upload_Logo_path']=logopath; + formData['company_Display_Name']=companynameController.text; + final token = await TokenManager.getToken(); + try { + print("token is : $token"); + print(formData); + + if (formData != null) { + // Create new project + apiService.updateParameter(token!, widget.sysparameter, formData); + } + Navigator.pop(context); + // Add navigation or any other logic after successful create/update + } catch (e) { + print('error is $e'); + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text( + 'Failed to ${widget.sysparameter == null ? 'create' : 'update'} project: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + }, + ), + ], + ), + ), + ))); + } + + Widget _buildFieldWithTooltip({ + required String fieldName, + required TextEditingController controller, + required String tooltip, + }) { + return Tooltip( + message: tooltip, + child: + Padding( + padding: getPadding(top: 18), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("$fieldName", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray800), + CustomTextFormField( + focusNode: FocusNode(), + controller:controller, + hintText: "Enter Your $fieldName", + margin: getMargin(top: 7), + textInputType: + TextInputType.text) + ])), + + // TextFormField( + // controller: controller, + // decoration: InputDecoration( + // labelText: fieldName, + // ), + // ), + ); + } + + +} diff --git a/lib/screens/dynamic_form/UpdatedynamicForm.dart b/lib/screens/dynamic_form/UpdatedynamicForm.dart new file mode 100644 index 0000000..bbac4af --- /dev/null +++ b/lib/screens/dynamic_form/UpdatedynamicForm.dart @@ -0,0 +1,279 @@ +import 'package:flutter/material.dart'; + +import '../../providers/token_manager.dart'; +import 'dynamic_form_service.dart'; + +class EditForm extends StatefulWidget { + final Map formData; + + EditForm({required this.formData}); + + @override + _EditFormState createState() => _EditFormState(); +} + +class _EditFormState extends State { + TextEditingController formNameController = TextEditingController(); + TextEditingController formDescController = TextEditingController(); + TextEditingController relatedToController = TextEditingController(); + TextEditingController pageEventController = TextEditingController(); + TextEditingController buttonCaptionController = TextEditingController(); + + final DynamicForApiService apiService = DynamicForApiService(); + + List components = []; // List to store table data + List relatedToFixedDropdown = ['Menu', 'Related To',]; + List pageEventFixedDropdown = ['OnClick', 'OnBlur',]; + + List typeFixedDropdown = ['text', 'dropdown','date','checkbox','textarea','togglebutton']; + List mappingFixedDropdown = ['TEXTFIELD1', 'TEXTFIELD2','TEXTFIELD3','TEXTFIELD4','TEXTFIELD5','TEXTFIELD6','TEXTFIELD7','TEXTFIELD8','TEXTFIELD9','TEXTFIELD10','TEXTFIELD11','TEXTFIELD12','TEXTFIELD13','TEXTFIELD14','TEXTFIELD15','TEXTFIELD16','TEXTFIELD17','TEXTFIELD18','TEXTFIELD19','TEXTFIELD20','TEXTFIELD21','TEXTFIELD22','TEXTFIELD23', + 'TEXTFIELD24','TEXTFIELD25','TEXTFIELD26','LONGTEXT1','LONGTEXT2','LONGTEXT3','LONGTEXT4',]; + List truefalseFixedDropdown = ['true', 'false',]; + + @override + void initState() { + super.initState(); + // Initialize text controllers with the data from the selected row + formNameController.text = widget.formData['form_name'] ?? ''; + formDescController.text = widget.formData['form_desc'] ?? ''; + relatedToController.text = widget.formData['related_to'] ?? ''; + pageEventController.text = widget.formData['page_event'] ?? ''; + buttonCaptionController.text = widget.formData['button_caption'] ?? ''; + + // Initialize the components data, or you can load it from formData['components']. + // For this example, we'll use an empty list. + components = widget.formData['components'] ?? []; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Edit Form'), + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + TextFormField( + controller: formNameController, + decoration: InputDecoration(labelText: 'Form Name'), + ), + TextFormField( + controller: formDescController, + decoration: InputDecoration(labelText: 'Form Description'), + ), + DropdownButtonFormField( + value: relatedToController.text, + decoration: + const InputDecoration(labelText: 'Select Related To'), + items: [ + ...relatedToFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + relatedToController.text = value!; + }); + }, + ), + DropdownButtonFormField( + value: pageEventController.text, + decoration: + const InputDecoration(labelText: 'Select Page Event'), + items: [ + ...pageEventFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + pageEventController.text = value!; + }); + }, + ), + TextFormField( + controller: buttonCaptionController, + decoration: InputDecoration(labelText: 'Button Caption'), + ), + + const Text('Components Details'), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + columns: const [ + DataColumn(label: Text('Label')), + DataColumn(label: Text('Type')), + DataColumn(label: Text('Mapping')), + DataColumn(label: Text('Mandatory')), + DataColumn(label: Text('Readonly')), + DataColumn(label: Text('Drop Values')), + DataColumn(label: Text('SP')), + DataColumn(label: Text('Actions'), numeric: false), // Add Actions column + ], + rows: components.asMap().entries.map((entry) { + final index = entry.key; + final component = entry.value; + + return DataRow( + cells: [ + DataCell(TextField( + controller: TextEditingController(text: component['label'] ?? ''), + onChanged: (value){ + component['label']=value; + }, + )), + DataCell( + DropdownButtonFormField( + value: component['type'], + decoration: + const InputDecoration(labelText: 'Select Type'), + items: [ + ...typeFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + component['type'] = value; + }); + }, + ), + + ), + DataCell( + DropdownButtonFormField( + value: component['mapping'], + decoration: + const InputDecoration(labelText: 'Select Mapping'), + items: [ + ...mappingFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + component['mapping'] = value; + }); + }, + ), + + ), + DataCell(TextField( + controller: TextEditingController(text: component['mandatory'] ?? ''), + onChanged: (value){ + component['mandatory']=value; + }, + )), + DataCell( + DropdownButtonFormField( + value: component['readonly'], + decoration: + const InputDecoration(labelText: 'Select Read Only'), + items: [ + ...truefalseFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + component['readonly'] = value; + }); + }, + ), + ), + DataCell(TextField( + controller: TextEditingController(text: component['drop_values'] ?? ''), + onChanged: (value){ + component['drop_values']=value; + }, + )), + DataCell(TextField( + controller: TextEditingController(text: component['sp'] ?? ''), + onChanged: (value){ + component['sp']=value; + }, + )), + DataCell( + ElevatedButton( + onPressed: () { + setState(() { + components.removeAt(index); + }); + }, + child: Text('Delete'), + ), + ), + ], + ); + }).toList(), + ), + ), + ElevatedButton( + onPressed: () { + // Add a new row to the components table + components.add({ + 'label': '', + 'type': null, + 'mapping': null, + 'mandatory': '', + 'readonly': null, + 'drop_values': '', + 'sp': '', + }); + setState(() {}); // Refresh the UI to show the new row + }, + child: Text('Add Row'), + ), + + ElevatedButton( + onPressed: () async { + // Save the updated data back to the original data list + widget.formData['form_name'] = formNameController.text; + widget.formData['form_desc'] = formDescController.text; + widget.formData['related_to'] = relatedToController.text; + widget.formData['page_event'] = pageEventController.text; + widget.formData['button_caption'] = buttonCaptionController.text; + widget.formData['components'] = components; + final token = await TokenManager.getToken(); + apiService.updateDynamicForm(token!, widget.formData['form_id'], widget.formData); + Navigator.of(context).pop(); + }, + child: Text('Update'), + ), + ], + ), + ), + ), + ); + } +} + + diff --git a/lib/screens/dynamic_form/create_dynamicform.dart b/lib/screens/dynamic_form/create_dynamicform.dart new file mode 100644 index 0000000..39107c5 --- /dev/null +++ b/lib/screens/dynamic_form/create_dynamicform.dart @@ -0,0 +1,333 @@ +import 'package:flutter/material.dart'; + +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import '../../widgets/custom_button.dart'; +import '../../widgets/custom_dropdown_field.dart'; +import '../../widgets/custom_text_form_field.dart'; +import 'dynamic_form_service.dart'; + +class CreateForm extends StatefulWidget { + @override + _CreateFormState createState() => _CreateFormState(); +} + +class _CreateFormState extends State { + TextEditingController formNameController = TextEditingController(); + TextEditingController formDescController = TextEditingController(); + TextEditingController relatedToController = TextEditingController(); + TextEditingController pageEventController = TextEditingController(); + TextEditingController buttonCaptionController = TextEditingController(); + + final DynamicForApiService apiService = DynamicForApiService(); + + List> components = []; + + List relatedToFixedDropdown = ['Menu', 'Related To',]; + List pageEventFixedDropdown = ['OnClick', 'OnBlur',]; + + List typeFixedDropdown = ['text', 'dropdown','date','checkbox','textarea','togglebutton']; + List mappingFixedDropdown = ['TEXTFIELD1', 'TEXTFIELD2','TEXTFIELD3','TEXTFIELD4','TEXTFIELD5','TEXTFIELD6','TEXTFIELD7','TEXTFIELD8','TEXTFIELD9','TEXTFIELD10','TEXTFIELD11','TEXTFIELD12','TEXTFIELD13','TEXTFIELD14','TEXTFIELD15','TEXTFIELD16','TEXTFIELD17','TEXTFIELD18','TEXTFIELD19','TEXTFIELD20','TEXTFIELD21','TEXTFIELD22','TEXTFIELD23', + 'TEXTFIELD24','TEXTFIELD25','TEXTFIELD26','LONGTEXT1','LONGTEXT2','LONGTEXT3','LONGTEXT4',]; + List truefalseFixedDropdown = ['true', 'false',]; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleft, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "Create Dynamic Form"),), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Form Name", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Form Name", + controller: formNameController, + margin: getMargin(top: 6)) + ])), + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Form Description", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Form Description", + controller: formDescController, + margin: getMargin(top: 6)) + ])), + + Padding( + padding: getPadding(top: 18), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Select Related To", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900, + ), + CustomDropdownFormField( + items: [ + ...relatedToFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item, style: AppStyle.txtGilroyMedium16Bluegray900), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + relatedToController.text = value!; + }); + }, + ) + ], + ), + ), + + Padding( + padding: getPadding(top: 18), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Select Page Event", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900, + ), + CustomDropdownFormField( + items: [ + ...pageEventFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + pageEventController.text = value!; + }); + }, + ) + ], + ), + ), + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Button Caption", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle + .txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Button Caption", + controller: buttonCaptionController, + margin: getMargin(top: 6)) + ])), + const Text('Components Details'), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + columns: const [ + DataColumn(label: Text('Label')), + DataColumn(label: Text('Type')), + DataColumn(label: Text('Mapping')), + DataColumn(label: Text('Mandatory')), + DataColumn(label: Text('Readonly')), + DataColumn(label: Text('Drop Values')), + DataColumn(label: Text('SP')), + ], + rows: components.asMap().entries.map((entry) { + final index = entry.key; + final component = entry.value; + bool? isReadonly = false; + return DataRow( + cells: [ + DataCell(TextField( + controller: TextEditingController(text: component['label'] ?? ''), + onChanged: (value) { + component['label'] = value; + }, + )), + DataCell( + DropdownButtonFormField( + decoration: + const InputDecoration(labelText: 'Select Type'), + items: [ + ...typeFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + component['type'] = value; + }); + }, + ), + + ), + DataCell( + DropdownButtonFormField( + decoration: + const InputDecoration(labelText: 'Select Mapping'), + items: [ + ...mappingFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + component['mapping'] = value; + }); + }, + ), + + ), + DataCell(TextField( + controller: TextEditingController(text: component['mandatory'] ?? ''), + onChanged: (value) { + component['mandatory'] = value; + }, + )), + DataCell( + DropdownButtonFormField( + decoration: + const InputDecoration(labelText: 'Select Read Only'), + items: [ + ...truefalseFixedDropdown.map>( + (item) { + return DropdownMenuItem( + value: item.toString(), + child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900), + ); + }, + ), + ], + onChanged: (value) { + setState(() { + component['readonly'] = value; + }); + }, + ), + + ), + DataCell(TextField( + controller: TextEditingController(text: component['drop_values'] ?? ''), + onChanged: (value) { + component['drop_values'] = value; + }, + )), + DataCell(TextField( + controller: TextEditingController(text: component['sp'] ?? ''), + onChanged: (value) { + component['sp'] = value; + }, + )), + ], + ); + }).toList(), + ), + ), + CustomButton( + height: getVerticalSize(50), + text: "Add Row", + margin: getMargin(top: 24, bottom: 5), + onTap: () async { + components.add({ + 'label': '', + 'type': '', + 'mapping': '', + 'mandatory': '', + 'readonly': '', + 'drop_values': '', + 'sp': '', + }); + setState(() {}); + }, + ), + + CustomButton( + height: getVerticalSize(50), + text: "Create Dynamic Form", + margin: getMargin(top: 24, bottom: 5), + onTap: () async { + final dynamicFormData = { + 'form_name': formNameController.text, + 'form_desc': formDescController.text, + 'related_to': relatedToController.text, + 'page_event': pageEventController.text, + 'button_caption': buttonCaptionController.text, + 'components': components, + }; + final token = await TokenManager.getToken(); + apiService.createDynamicForm(token!, dynamicFormData); + Navigator.of(context).pop(); + }, + ), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/dynamic_form/dynamic_form_service.dart b/lib/screens/dynamic_form/dynamic_form_service.dart new file mode 100644 index 0000000..eda9109 --- /dev/null +++ b/lib/screens/dynamic_form/dynamic_form_service.dart @@ -0,0 +1,100 @@ +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import '../../resources/api_constants.dart'; +import '../LogoutService/Logoutservice.dart'; + +class DynamicForApiService { + final String baseUrl = ApiConstants.baseUrl; + final Dio dio = Dio(); +//api/dynamic_form_build + Future BuildForms(String token, int id) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + final response = + await dio.get('$baseUrl/api/dynamic_form_build?form_id=$id'); + if (response.statusCode == 401) { + LogoutService.logout(); + } + if (response.statusCode! <= 209) { + Fluttertoast.showToast( + msg: 'Build success', + backgroundColor: Colors.red, + ); + } else { + Fluttertoast.showToast( + msg: 'Unable to build', + backgroundColor: Colors.red, + ); + throw Exception('Unexpected response type'); + } + } catch (e) { + throw Exception('Failed to Build form: $e'); + } + } + + Future>> getallDynamicForms( + String token, + ) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + final response = await dio.get('$baseUrl/api/form_setup'); + if (response.statusCode == 401) { + LogoutService.logout(); + } + final responseData = response.data['items']; + if (responseData is List) { + final entities = responseData.cast>(); + return entities; + } else if (responseData is Map) { + return [responseData]; + } else { + throw Exception('Unexpected response type'); + } + } catch (e) { + throw Exception('Failed to get modules by projectId: $e'); + } + } + + Future createDynamicForm( + String token, Map entity) async { + try { + print("in post api...$entity"); + dio.options.headers['Authorization'] = 'Bearer $token'; + var response = await dio.post('$baseUrl/api/form_setup', data: entity); + if (response.statusCode == 401) { + LogoutService.logout(); + } + print(entity); + } catch (e) { + throw Exception('Failed to create Dynamic form: $e'); + } + } + + Future updateDynamicForm( + String token, int entityId, Map entity) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + var response = + await dio.put('$baseUrl/api/form_setup/$entityId', data: entity); + if (response.statusCode == 401) { + LogoutService.logout(); + } + print(entity); + } catch (e) { + throw Exception('Failed to update Dynamic form: $e'); + } + } + + Future deleteDynamicForm(String token, int entityId) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + var response = await dio.delete('$baseUrl/api/form_setup/$entityId'); + if (response.statusCode == 401) { + LogoutService.logout(); + } + } catch (e) { + throw Exception('Failed to delete Dynamic form: $e'); + } + } +} diff --git a/lib/screens/dynamic_form/list_dynamic_form_screen.dart b/lib/screens/dynamic_form/list_dynamic_form_screen.dart new file mode 100644 index 0000000..081f541 --- /dev/null +++ b/lib/screens/dynamic_form/list_dynamic_form_screen.dart @@ -0,0 +1,224 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import '../../Utils/color_constants.dart'; +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import 'UpdatedynamicForm.dart'; +import 'create_dynamicform.dart'; +import 'dynamic_form_service.dart'; + +class DynamicForm extends StatefulWidget { + @override + _DynamicFormState createState() => _DynamicFormState(); +} + +class _DynamicFormState extends State { + final DynamicForApiService apiService = DynamicForApiService(); + + late List> allData = []; + + bool isLoading = false; + + @override + void initState() { + super.initState(); + _loadDynamicForms(); + } + + Future _loadDynamicForms() async { + final token = await TokenManager.getToken(); + try { + final alData = await apiService.getallDynamicForms(token!); + + setState(() { + allData = alData; + + print('allData fetched...'); + }); + isLoading = true; + } catch (e) { + isLoading = true; + print('Failed to load allData: $e'); + } + } + + Future deleteEntity(Map entity) async { + try { + final token = await TokenManager.getToken(); + await apiService.deleteDynamicForm(token!, entity['form_id']); + setState(() { + allData.remove(entity); + }); + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to delete entity: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + actions: [ + GestureDetector( + child: Icon( + Icons.add, + color: Colors.black, + size: 20, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CreateForm(), + ), + ).then((value) => {_loadDynamicForms()}); + }, + ), + const SizedBox( + width: 20, + ) + ], + centerTitle: true, + title: AppbarTitle(text: "Dynamic Form")), + body: isLoading == false + ? const Center(child: CircularProgressIndicator()) + : allData.isEmpty + ? const Center( + child: Text('No Services available.'), + ) + : Scrollable( + viewportBuilder: + (BuildContext context, ViewportOffset position) { + return SingleChildScrollView( + scrollDirection: Axis.vertical, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable( + columns: [ + DataColumn(label: Text('Form Name')), + DataColumn(label: Text('Form Description')), + DataColumn(label: Text('Related To')), + DataColumn(label: Text('Page Event')), + DataColumn(label: Text('Button Caption')), + DataColumn(label: Text('Build')), + DataColumn(label: Text('Actions')), + ], + rows: allData.map((module) { + return DataRow( + cells: [ + DataCell( + Text('${module['form_name'] ?? 'N/A'}')), + DataCell( + Text('${module['form_desc'] ?? 'N/A'}')), + DataCell( + Text('${module['related_to'] ?? 'N/A'}')), + DataCell( + Text('${module['page_event'] ?? 'N/A'}')), + DataCell(Text( + '${module['button_caption'] ?? 'N/A'}')), + DataCell(Row( + children: [ + ElevatedButton( + onPressed: () async { + print(module); + final token = + await TokenManager.getToken(); + apiService.BuildForms( + token!, module['form_id']); + }, + child: Text("build"), + style: ElevatedButton.styleFrom( + backgroundColor: ColorConstant.blue700, + ), + ) + ], + )), + DataCell(Row( + children: [ + IconButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + EditForm(formData: module), + ), + ).then( + (value) => {_loadDynamicForms()}); + }, + icon: Icon(Icons.edit), + ), + IconButton( + onPressed: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text( + 'Confirm Deletion'), + content: const Text( + 'Are you sure you want to delete this Module?'), + actions: [ + TextButton( + child: const Text('Cancel'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: const Text('Delete'), + onPressed: () { + Navigator.of(context).pop(); + deleteEntity(module); + }, + ), + ], + ); + }, + ); + }, + icon: Icon(Icons.delete), + ), + ], + )), + ], + ); + }).toList(), + ), + ), + ); + }, + ), + ); + } +} diff --git a/lib/screens/forgot_password/forgotPasswordScreen.dart b/lib/screens/forgot_password/forgotPasswordScreen.dart new file mode 100644 index 0000000..9597219 --- /dev/null +++ b/lib/screens/forgot_password/forgotPasswordScreen.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import '../../Utils/color_constants.dart'; +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../resources/api_constants.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import '../../widgets/custom_button.dart'; +import '../../widgets/custom_text_form_field.dart'; +import '../Login Screen/login_screen.dart'; + +class ForgotPasswordPage extends StatefulWidget { + @override + _ForgotPasswordPageState createState() => _ForgotPasswordPageState(); +} + +class _ForgotPasswordPageState extends State { + final TextEditingController emailController = TextEditingController(); + String message = ''; + bool isLoading = false; // Added to track loading state + + Future sendForgotPasswordRequest() async { + setState(() { + isLoading = true; // Show loading indicator when sending request + }); + + final email = emailController.text; + final token = await TokenManager.getToken(); + const String baseUrl = ApiConstants.baseUrl; + + final response = await http.post( + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + Uri.parse('$baseUrl/api/resources/forgotpassword?email=$email'), + ); + + if (response.statusCode == 200) { + setState(() { + message = 'An email with a reset link has been sent to $email.'; + }); + + // Delay for 3 seconds and then navigate to the login page + Future.delayed(Duration(seconds: 3), () { + Navigator.push( + context, MaterialPageRoute(builder: (context) => LoginScreen())); + }); + } else { + setState(() { + message = 'Failed to send the reset link. Please try again.'; + }); + } + + setState(() { + isLoading = false; // Hide loading indicator when the request is complete + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "Forgot Password")), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Email", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Email", + controller: emailController, + margin: getMargin(top: 6)) + ])), + CustomButton( + height: getVerticalSize(50), + text: "Send me an access link", + margin: getMargin(top: 24, bottom: 5), + onTap: () async { + sendForgotPasswordRequest(); + }, + ), + isLoading + ? CircularProgressIndicator( + color: ColorConstant.blue700, + ) // Show loading indicator when isLoading is true + : Text(message, style: AppStyle.txtGilroyMedium16Bluegray900), + if (message.contains('An email with a reset link')) + InkWell( + child: Text('Click here to return to login', + style: AppStyle.txtGilroyMedium16Bluegray900), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const LoginScreen())); + }, + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/main_app_screen/CustomizeFooter.dart b/lib/screens/main_app_screen/CustomizeFooter.dart new file mode 100644 index 0000000..a518f37 --- /dev/null +++ b/lib/screens/main_app_screen/CustomizeFooter.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; + +class CustomizedFooter extends StatelessWidget { + final IconData homeIcon; + final IconData squareIcon; + final IconData addIcon; + final List labels; + final List onTapActions; + + CustomizedFooter({ + required this.homeIcon, + required this.squareIcon, + required this.addIcon, + required this.labels, + required this.onTapActions, + }); + + @override + Widget build(BuildContext context) { + assert(labels.length == 3 && onTapActions.length == 3); + + return Container( + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 5, + blurRadius: 7, + offset: const Offset(0, 3), + ), + ], + ), + child: BottomNavigationBar( + onTap: (index) { + onTapActions[index](); + }, + items: [ + BottomNavigationBarItem( + icon: Icon(homeIcon), + label: labels[0], + ), + BottomNavigationBarItem( + icon: Icon(squareIcon), + label: labels[1], + ), + BottomNavigationBarItem( + icon: Icon(addIcon), + label: labels[2], + ), + ], + ), + ); + } +} diff --git a/lib/screens/main_app_screen/list_group_524.dart b/lib/screens/main_app_screen/list_group_524.dart new file mode 100644 index 0000000..6c1ac5c --- /dev/null +++ b/lib/screens/main_app_screen/list_group_524.dart @@ -0,0 +1,339 @@ +import 'dart:convert'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg_provider/flutter_svg_provider.dart' as fs; +import '../../Utils/color_constants.dart'; +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../resources/api_constants.dart'; +import '../../theme/app_style.dart'; +import '../LogoutService/Logoutservice.dart'; +import 'package:http/http.dart' as http; + +class Listgroup524ItemWidget extends StatefulWidget { + final Map userData; + Listgroup524ItemWidget({required this.userData}); + + @override + State createState() => _Listgroup524ItemWidgetState(); +} + +class _Listgroup524ItemWidgetState extends State { + int myProjectcount = 0; + int sharedWithMeCount = 0; + int allprojectCount = 0; + + @override + void initState() { + super.initState(); + fetchData(); + } + + Future fetchData() async { + print("working"); + final token = await TokenManager.getToken(); + print(token); + String baseUrl = ApiConstants.baseUrl; + var myProjectcountres = await http.get( + Uri.parse('$baseUrl/workspace/secworkspaceuser/count_myproject'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': + 'application/json', // You may need to adjust the content type as needed + }, + ); + var sharedWithMeCountres = await http.get( + Uri.parse('$baseUrl/workspace/secworkspaceuser/count_sharedwithme'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': + 'application/json', // You may need to adjust the content type as needed + }, + ); + var allProjectsCountres = await http.get( + Uri.parse('$baseUrl/workspace/secworkspaceuser/count_allproject'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': + 'application/json', // You may need to adjust the content type as needed + }, + ); + if (myProjectcountres.statusCode == 401) { + LogoutService.logout(); + } + print(myProjectcountres.statusCode); + if (myProjectcountres.statusCode <= 209 && + sharedWithMeCountres.statusCode <= 209) { + final myProjectData = jsonDecode(myProjectcountres.body); + final sharedData = jsonDecode(sharedWithMeCountres.body); + final allData = jsonDecode(allProjectsCountres.body); + setState(() { + myProjectcount = myProjectData; + sharedWithMeCount = sharedData; + allprojectCount = allData; + }); + } else { + // Handle errors + print('Failed to fetch data'); + } + } + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + GestureDetector( + onTap: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => ProjectListScreen( + // userData: widget.userData, + // type: "myproject"), // Get all projects + // ), + // ); + }, + child: Card( + color: Colors.white, + elevation: 0.0, + child: Padding( + padding: const EdgeInsets.fromLTRB(20, 10, 20, 10), + child: Column( + children: [ + Container( + height: getSize( + 55, + ), + width: getSize( + 55, + ), + margin: getMargin( + top: 2, + ), + child: Stack( + alignment: Alignment.center, + children: [ + Align( + alignment: Alignment.center, + child: Container( + height: getSize( + 55, + ), + width: getSize( + 55, + ), + child: CircularProgressIndicator( + value: 0.5, + backgroundColor: ColorConstant.gray30099, + color: ColorConstant.blueA700, + ), + ), + ), + Align( + alignment: Alignment.center, + child: Text( + myProjectcount.toString(), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyBold18, + ), + ), + ], + ), + ), + // Text( + // myProjectcount.toString(), + // style: const TextStyle( + // color: Colors.black, + // fontSize: 12, + // ), + // ), + const SizedBox( + height: 3, + ), + const Text( + 'My Projects', + style: TextStyle( + color: Colors.black, + fontSize: 10, + ), + ), + ], + ), + ), + ), + ), + GestureDetector( + onTap: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => ProjectListScreen( + // userData: widget.userData, + // type: "sharedproject"), // Get all projects + // ), + // ); + }, + child: Card( + color: Colors.white, + elevation: 0.0, + child: Padding( + padding: const EdgeInsets.fromLTRB(20, 10, 20, 10), + child: Column( + children: [ + Container( + height: getSize( + 55, + ), + width: getSize( + 55, + ), + margin: getMargin( + top: 2, + ), + child: Stack( + alignment: Alignment.center, + children: [ + Align( + alignment: Alignment.center, + child: Container( + height: getSize( + 55, + ), + width: getSize( + 55, + ), + child: CircularProgressIndicator( + value: 0.5, + backgroundColor: ColorConstant.gray30099, + color: ColorConstant.blueA700, + ), + ), + ), + Align( + alignment: Alignment.center, + child: Text( + sharedWithMeCount.toString(), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyBold18, + ), + ), + ], + ), + ), + // Text( + // myProjectcount.toString(), + // style: const TextStyle( + // color: Colors.black, + // fontSize: 12, + // ), + // ), + const SizedBox( + height: 3, + ), + const Text( + 'Shared with me', + style: TextStyle( + color: Colors.black, + fontSize: 10, + ), + ), + ], + ), + ), + ), + ), + GestureDetector( + onTap: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => ProjectListScreen( + // userData: widget.userData, + // type: "allproject"), // Get all projects + // ), + // ); + }, + child: Card( + color: Colors.white, + elevation: 0.0, + child: Padding( + padding: const EdgeInsets.fromLTRB(20, 10, 20, 10), + child: Column( + children: [ + Container( + height: getSize( + 55, + ), + width: getSize( + 55, + ), + margin: getMargin( + top: 2, + ), + child: Stack( + alignment: Alignment.center, + children: [ + Align( + alignment: Alignment.center, + child: Container( + height: getSize( + 55, + ), + width: getSize( + 55, + ), + child: CircularProgressIndicator( + value: 0.5, + backgroundColor: ColorConstant.gray30099, + color: ColorConstant.blueA700, + ), + ), + ), + Align( + alignment: Alignment.center, + child: Text( + allprojectCount.toString(), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyBold18, + ), + ), + ], + ), + ), + // Text( + // myProjectcount.toString(), + // style: const TextStyle( + // color: Colors.black, + // fontSize: 12, + // ), + // ), + const SizedBox( + height: 3, + ), + const Text( + 'All Projects', + style: TextStyle( + color: Colors.black, + fontSize: 10, + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/main_app_screen/list_group__.dart b/lib/screens/main_app_screen/list_group__.dart new file mode 100644 index 0000000..13de6ac --- /dev/null +++ b/lib/screens/main_app_screen/list_group__.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; + +import '../../Utils/size_utils.dart'; +import '../../theme/app_style.dart'; + +// ignore: must_be_immutable +class ListtextItemWidget extends StatelessWidget { + ListtextItemWidget(); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + "Lorem ipsum", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroySemiBold16, + ), + Padding( + padding: getPadding( + top: 10, + ), + child: Text( + "Lorem ipsum", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyRegular14, + ), + ), + ], + ), + Padding( + padding: getPadding( + top: 11, + bottom: 13, + ), + child: Text( + "7.5", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroySemiBold18, + ), + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/screens/main_app_screen/local_splash_screen_component.dart b/lib/screens/main_app_screen/local_splash_screen_component.dart new file mode 100644 index 0000000..79ead6e --- /dev/null +++ b/lib/screens/main_app_screen/local_splash_screen_component.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class LocalSplashScreenComponent extends StatelessWidget { + const LocalSplashScreenComponent({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + color: Color(0xff2f73b9), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/hadwin_system/hadwin-splash-screen-logo.png', + height: 128.0, + ), + ], + ), + ); + } +} diff --git a/lib/screens/main_app_screen/newlanding_page.dart b/lib/screens/main_app_screen/newlanding_page.dart new file mode 100644 index 0000000..3e7ded3 --- /dev/null +++ b/lib/screens/main_app_screen/newlanding_page.dart @@ -0,0 +1,1018 @@ + +// /../Entity/gaurav/Gauravtest1/Gauravtest1_entity_list_screen.dart'; + +// import 'dart:convert'; +// import 'dart:io'; + +// import 'package:flutter/material.dart'; +// import 'package:shared_preferences/shared_preferences.dart'; +// import '../../Utils/color_constants.dart'; +// import '../../Utils/image_constant.dart'; +// import '../../Utils/size_utils.dart'; +// import '../../providers/token_manager.dart'; +// import '../../resources/api_constants.dart'; +// import '../../theme/app_decoration.dart'; +// import '../../theme/app_style.dart'; +// import '../../widgets/app_bar/appbar_image.dart'; +// import '../../widgets/app_bar/appbar_title.dart'; +// import '../../widgets/app_bar/custom_app_bar.dart'; +// import '../../widgets/custom_image_view.dart'; +// import '../Bookmarks/Bookmarks_entity_list_screen.dart'; +// import '../Incident_Ticket/ticket_create.dart'; +// import '../LayoutReportBuilder/LayoutReportBuilder.dart'; +// import '../Login Screen/login_screen.dart'; +// import '../LogoutService/Logoutservice.dart'; +// import '../QrBarCode/Qr_BarCode/Qr_BarCode_create_entity_screen.dart'; +// import '../Setup/setup.dart'; +// import '../SysParameters/SystemParameterScreen.dart'; +// import '../dynamic_form/list_dynamic_form_screen.dart'; +// import '../profileManagement/Profilesettings.dart'; +// import '../profileManagement/about.dart'; +// import '../profileManagement/changepassword.dart'; + +// import 'list_group_524.dart'; +// import 'list_group__.dart'; +// import 'notification_item.dart'; +// import 'package:http/http.dart' as http; + +// class TabbedLayoutComponentb extends StatefulWidget { +// // final Map userData; +// // const TabbedLayoutComponentb({required this.userData, Key? key}) +// // : super(key: key); +// @override +// _TabbedLayoutComponentState createState() => _TabbedLayoutComponentState(); +// } + +// class _TabbedLayoutComponentState extends State { +// List> notifications = []; + +// Map userData = {}; + +// @override +// void initState() { +// super.initState(); +// getUserData(); +// fetchData(); +// } + +// getUserData() async { +// SharedPreferences prefs = await SharedPreferences.getInstance(); +// var userdatastr = prefs.getString('userData'); +// if (userdatastr != null) { +// try { +// setState(() { +// userData = json.decode(userdatastr); +// }); +// print(userData['token']); +// } catch (e) { +// print("error is ..................$e"); +// } +// } +// } + +// Future _logoutUser() async { +// try { +// SharedPreferences prefs = await SharedPreferences.getInstance(); + +// await prefs.remove('userData'); +// await prefs.remove('isLoggedIn'); +// String logouturl = "${ApiConstants.baseUrl}/token/logout"; +// var response = await http.get(Uri.parse(logouturl)); +// if (response.statusCode == 401) { +// LogoutService.logout(); +// } +// if (response.statusCode <= 209) { +// // ignore: use_build_context_synchronously +// Navigator.pushAndRemoveUntil( +// context, +// MaterialPageRoute(builder: (context) => LoginScreen()), +// (route) => false, // Remove all routes from the stack +// ); +// } else { +// const Text('failed to logout'); +// } +// } catch (error) { +// print('Error occurred during logout: $error'); +// } +// } + +// Future fetchData() async { +// String baseUrl = ApiConstants.baseUrl; +// final apiUrl = '$baseUrl/notification/get_notification'; +// final token = await TokenManager.getToken(); +// final response = await http.get( +// Uri.parse(apiUrl), +// headers: { +// 'Authorization': 'Bearer $token', +// 'Content-Type': 'application/json', +// }, +// ); +// if (response.statusCode == 401) { +// LogoutService.logout(); +// } +// if (response.statusCode <= 209) { +// final List data = jsonDecode(response.body); +// setState(() { +// notifications = data.cast>(); +// }); +// } else { +// // Handle errors +// print('Failed to fetch data'); +// } +// } + +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// backgroundColor: ColorConstant.gray50, +// appBar: CustomAppBar( +// height: getVerticalSize(53), +// leadingWidth: 40, +// // leading: AppbarImage( +// // height: getSize(24), +// // width: getSize(24), +// // svgPath: ImageConstant.imgArrowleft, +// // margin: getMargin(left: 16, top: 12, bottom: 17), +// // onTap: () { +// // onTapArrowleft(context); +// // }), +// centerTitle: true, +// title: AppbarTitle(text: "CloudnSure"), +// actions: [ +// // AppbarImage( +// // height: getSize(24), +// // width: getSize(24), +// // +// // svgPath: ImageConstant.imgOverflowmenu, +// // margin: +// // getMargin(left: 16, top: 12, right: 16, bottom: 17)), + +// //-- +// PopupMenuButton( +// icon: Icon( +// Icons.more_vert, +// color: Colors.black, +// ), +// onSelected: (String result) { +// // Handle the selected option +// print("Selected: $result"); +// }, +// itemBuilder: (BuildContext context) => [ +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'Raise A Ticket', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => RaisedTicketScreen( +// userData: userData, +// ), +// ), +// ); +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'Profile Settings', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// // Closes the drawer +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => ProfileSettingsScreen( +// userData: userData), //go to get all entity +// ), +// ); +// // Add your logic for menu 2 here +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'Change Password', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// // Closes the drawer +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => ResetPasswordScreen( +// userEmail: userData['email'], +// userData: userData), //go to get all entity +// ), +// ); +// // Add your logic for menu 2 here +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'DynamicForm', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// // Closes the drawer +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => +// DynamicForm(), //go to get all entity +// ), +// ); +// // Add your logic for menu 2 here +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'Setup Screen', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => +// SetupScreen(), //go to get all entity +// ), +// ); +// // Add your logic for menu 2 here +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'BookMark', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// // Closes the drawer +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => +// bookmarks_entity_list_screen(), //go to get all entity +// ), +// ); +// // Add your logic for menu 2 here +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'Report layout builder', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => ReportEditor(), +// ), +// ); +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'System Parameter', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => +// SysParameter(), //go to get all entity +// ), +// ); +// // Add your logic for menu 2 here +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'Addition Menu', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => const QrBarCodeScreen(), +// ), +// ); +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'About', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => +// AboutScreen(), //go to get all entity +// ), +// ); +// // Add your logic for menu 2 here +// }, +// ), +// PopupMenuItem( +// //value: 'Option 1', +// child: Text( +// 'LogOut', +// style: AppStyle.txtGilroySemiBold16, +// ), +// onTap: () { +// _logoutUser(); +// }, +// ), +// ], +// ), +// ]), +// body: SingleChildScrollView( +// child: Container( +// width: double.maxFinite, +// padding: getPadding(left: 16, top: 20, right: 16, bottom: 20), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.center, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Container( +// height: getVerticalSize(158), +// child: ListView.separated( +// separatorBuilder: (context, index) { +// return SizedBox(height: getVerticalSize(16)); +// }, +// itemCount: 1, +// itemBuilder: (context, index) { +// return Listgroup524ItemWidget( +// userData: userData, +// ); +// })), +// Card( +// clipBehavior: Clip.antiAlias, +// elevation: 0, +// margin: getMargin(top: 5), +// color: ColorConstant.whiteA70099, +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadiusStyle.roundedBorder6), +// child: Container( +// height: getVerticalSize(224), +// width: MediaQuery.of(context) +// .size +// .width, //getHorizontalSize(396), +// // padding: getPadding( +// // left: 16, top: 17, right: 16, bottom: 17), +// decoration: AppDecoration.outlineGray70026.copyWith( +// borderRadius: BorderRadiusStyle.roundedBorder6), +// child: Stack( +// alignment: Alignment.centerRight, +// children: [ +// Align( +// alignment: Alignment.topCenter, +// child: Padding( +// padding: getPadding(left: 1), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// mainAxisAlignment: +// MainAxisAlignment.start, +// children: [ +// Row( +// mainAxisAlignment: +// MainAxisAlignment +// .center, +// children: [ +// Text("08", +// overflow: TextOverflow +// .ellipsis, +// textAlign: +// TextAlign.left, +// style: AppStyle +// .txtGilroyMedium10), +// Expanded( +// child: Padding( +// padding: getPadding( +// top: 6, +// bottom: 5), +// child: Divider( +// height: +// getVerticalSize( +// 1), +// thickness: +// getVerticalSize( +// 1), +// color: ColorConstant +// .blueGray400, +// indent: +// getHorizontalSize( +// 9)))) +// ]), +// Padding( +// padding: +// getPadding(top: 28), +// child: Row( +// mainAxisAlignment: +// MainAxisAlignment +// .center, +// children: [ +// Text("06", +// overflow: +// TextOverflow +// .ellipsis, +// textAlign: +// TextAlign +// .left, +// style: AppStyle +// .txtGilroyMedium10), +// Expanded( +// child: Padding( +// padding: +// getPadding( +// top: +// 6, +// bottom: +// 5), +// child: Divider( +// height: +// getVerticalSize( +// 1), +// thickness: +// getVerticalSize( +// 1), +// color: ColorConstant +// .blueGray400, +// indent: +// getHorizontalSize( +// 9)))) +// ])), +// Padding( +// padding: +// getPadding(top: 28), +// child: Row( +// mainAxisAlignment: +// MainAxisAlignment +// .center, +// children: [ +// Text("04", +// overflow: +// TextOverflow +// .ellipsis, +// textAlign: +// TextAlign +// .left, +// style: AppStyle +// .txtGilroyMedium10), +// Expanded( +// child: Padding( +// padding: +// getPadding( +// top: +// 6, +// bottom: +// 5), +// child: Divider( +// height: +// getVerticalSize( +// 1), +// thickness: +// getVerticalSize( +// 1), +// color: ColorConstant +// .blueGray400, +// indent: +// getHorizontalSize( +// 9)))) +// ])), +// Padding( +// padding: +// getPadding(top: 28), +// child: Row( +// mainAxisAlignment: +// MainAxisAlignment +// .center, +// children: [ +// Text("02", +// overflow: +// TextOverflow +// .ellipsis, +// textAlign: +// TextAlign +// .left, +// style: AppStyle +// .txtGilroyMedium10), +// Expanded( +// child: Padding( +// padding: +// getPadding( +// top: +// 6, +// bottom: +// 5), +// child: Divider( +// height: +// getVerticalSize( +// 1), +// thickness: +// getVerticalSize( +// 1), +// color: ColorConstant +// .blueGray400, +// indent: getHorizontalSize( +// 10)))) +// ])), +// Padding( +// padding: +// getPadding(top: 28), +// child: Row( +// mainAxisAlignment: +// MainAxisAlignment +// .center, +// children: [ +// Text("00", +// overflow: +// TextOverflow +// .ellipsis, +// textAlign: +// TextAlign +// .left, +// style: AppStyle +// .txtGilroyMedium10), +// Expanded( +// child: Padding( +// padding: +// getPadding( +// top: +// 6, +// bottom: +// 5), +// child: Divider( +// height: +// getVerticalSize( +// 1), +// thickness: +// getVerticalSize( +// 1), +// color: ColorConstant +// .blueGray400, +// indent: +// getHorizontalSize( +// 9)))) +// ])) +// ]))), +// Align( +// alignment: Alignment.centerRight, +// child: Row( +// mainAxisAlignment: +// MainAxisAlignment.center, +// crossAxisAlignment: +// CrossAxisAlignment.end, +// children: [ +// buildContainer( +// height: 97, +// width: MediaQuery.of(context) +// .size +// .width * +// 0.016, +// margin: EdgeInsets.only(top: 45), +// text: "08/21"), +// buildContainer( +// height: 138, +// width: MediaQuery.of(context) +// .size +// .width * +// 0.016, +// margin: EdgeInsets.only( +// left: 23, top: 19), +// text: "08/22"), +// buildContainer( +// height: 160, +// width: MediaQuery.of(context) +// .size +// .width * +// 0.016, +// margin: EdgeInsets.only( +// left: 21, top: 5), +// text: "08/23"), +// buildContainer( +// height: 83, +// width: MediaQuery.of(context) +// .size +// .width * +// 0.016, +// margin: EdgeInsets.only( +// left: 21, top: 53), +// text: "08/24"), +// buildContainer( +// height: 64, +// width: MediaQuery.of(context) +// .size +// .width * +// 0.016, +// margin: EdgeInsets.only( +// left: 20, top: 65), +// text: "08/25"), +// buildContainer( +// height: 126, +// width: MediaQuery.of(context) +// .size +// .width * +// 0.016, +// margin: EdgeInsets.only( +// left: 21, top: 26), +// text: "08/26"), +// buildContainer( +// height: 83, +// width: MediaQuery.of(context) +// .size +// .width * +// 0.016, +// margin: EdgeInsets.only( +// left: 22, top: 53), +// text: "08/27"), +// ], +// ), +// ) +// // Align( +// // alignment: Alignment.centerRight, +// // child: Padding( +// // padding: getPadding(right: 8), +// // child: Row( +// // mainAxisAlignment: +// // MainAxisAlignment.center, +// // crossAxisAlignment: +// // CrossAxisAlignment.end, +// // mainAxisSize: MainAxisSize.min, +// // children: [ +// // Container( +// // width: +// // getHorizontalSize(25), +// // margin: +// // getMargin(top: 63), +// // child: Column( +// // mainAxisAlignment: +// // MainAxisAlignment +// // .start, +// // children: [ +// // Container( +// // height: +// // getVerticalSize( +// // 97), +// // width: +// // getHorizontalSize( +// // 24), +// // decoration: BoxDecoration( +// // color: ColorConstant +// // .blueA700, +// // borderRadius: BorderRadius.only( +// // topLeft: +// // Radius.circular(getHorizontalSize( +// // 4)), +// // topRight: +// // Radius.circular(getHorizontalSize(4))))), +// // Padding( +// // padding: +// // getPadding( +// // top: 9), +// // child: Text( +// // "08/21", +// // overflow: +// // TextOverflow +// // .ellipsis, +// // textAlign: +// // TextAlign +// // .left, +// // style: AppStyle +// // .txtGilroyMedium10)) +// // ])), +// // Container( +// // width: +// // getHorizontalSize(28), +// // margin: getMargin( +// // left: 23, top: 22), +// // child: Column( +// // mainAxisAlignment: +// // MainAxisAlignment +// // .start, +// // children: [ +// // Container( +// // height: +// // getVerticalSize( +// // 138), +// // width: +// // getHorizontalSize( +// // 24), +// // decoration: BoxDecoration( +// // color: ColorConstant +// // .blueA700, +// // borderRadius: BorderRadius.only( +// // topLeft: +// // Radius.circular(getHorizontalSize( +// // 4)), +// // topRight: +// // Radius.circular(getHorizontalSize(4))))), +// // Padding( +// // padding: +// // getPadding( +// // top: 9), +// // child: Text( +// // "08/22", +// // overflow: +// // TextOverflow +// // .ellipsis, +// // textAlign: +// // TextAlign +// // .left, +// // style: AppStyle +// // .txtGilroyMedium10)) +// // ])), +// // Container( +// // width: +// // getHorizontalSize(28), +// // margin: +// // getMargin(left: 21), +// // child: Column( +// // mainAxisAlignment: +// // MainAxisAlignment +// // .start, +// // children: [ +// // Container( +// // height: +// // getVerticalSize( +// // 160), +// // width: +// // getHorizontalSize( +// // 24), +// // decoration: BoxDecoration( +// // color: ColorConstant +// // .blueA700, +// // borderRadius: BorderRadius.only( +// // topLeft: +// // Radius.circular(getHorizontalSize( +// // 4)), +// // topRight: +// // Radius.circular(getHorizontalSize(4))))), +// // Padding( +// // padding: +// // getPadding( +// // top: 9), +// // child: Text( +// // "08/23", +// // overflow: +// // TextOverflow +// // .ellipsis, +// // textAlign: +// // TextAlign +// // .left, +// // style: AppStyle +// // .txtGilroyMedium10)) +// // ])), +// // Container( +// // width: +// // getHorizontalSize(29), +// // margin: getMargin( +// // left: 21, top: 77), +// // child: Column( +// // mainAxisAlignment: +// // MainAxisAlignment +// // .start, +// // children: [ +// // Container( +// // height: +// // getVerticalSize( +// // 83), +// // width: +// // getHorizontalSize( +// // 24), +// // decoration: BoxDecoration( +// // color: ColorConstant +// // .blueA700, +// // borderRadius: BorderRadius.only( +// // topLeft: +// // Radius.circular(getHorizontalSize( +// // 4)), +// // topRight: +// // Radius.circular(getHorizontalSize(4))))), +// // Padding( +// // padding: +// // getPadding( +// // top: 9), +// // child: Text( +// // "08/24", +// // overflow: +// // TextOverflow +// // .ellipsis, +// // textAlign: +// // TextAlign +// // .left, +// // style: AppStyle +// // .txtGilroyMedium10)) +// // ])), +// // Container( +// // width: +// // getHorizontalSize(28), +// // margin: getMargin( +// // left: 20, top: 96), +// // child: Column( +// // mainAxisAlignment: +// // MainAxisAlignment +// // .start, +// // children: [ +// // Container( +// // height: +// // getVerticalSize( +// // 64), +// // width: +// // getHorizontalSize( +// // 24), +// // decoration: BoxDecoration( +// // color: ColorConstant +// // .blueA700, +// // borderRadius: BorderRadius.only( +// // topLeft: +// // Radius.circular(getHorizontalSize( +// // 4)), +// // topRight: +// // Radius.circular(getHorizontalSize(4))))), +// // Padding( +// // padding: +// // getPadding( +// // top: 9), +// // child: Text( +// // "08/25", +// // overflow: +// // TextOverflow +// // .ellipsis, +// // textAlign: +// // TextAlign +// // .left, +// // style: AppStyle +// // .txtGilroyMedium10)) +// // ])), +// // Container( +// // width: +// // getHorizontalSize(28), +// // margin: getMargin( +// // left: 21, top: 34), +// // child: Column( +// // mainAxisAlignment: +// // MainAxisAlignment +// // .start, +// // children: [ +// // Container( +// // height: +// // getVerticalSize( +// // 126), +// // width: +// // getHorizontalSize( +// // 24), +// // decoration: BoxDecoration( +// // color: ColorConstant +// // .blueA700, +// // borderRadius: BorderRadius.only( +// // topLeft: +// // Radius.circular(getHorizontalSize( +// // 4)), +// // topRight: +// // Radius.circular(getHorizontalSize(4))))), +// // Padding( +// // padding: +// // getPadding( +// // top: 9), +// // child: Text( +// // "08/26", +// // overflow: +// // TextOverflow +// // .ellipsis, +// // textAlign: +// // TextAlign +// // .left, +// // style: AppStyle +// // .txtGilroyMedium10)) +// // ])), +// // Container( +// // width: +// // getHorizontalSize(27), +// // margin: getMargin( +// // left: 22, top: 77), +// // child: Column( +// // mainAxisAlignment: +// // MainAxisAlignment +// // .start, +// // children: [ +// // Container( +// // height: +// // getVerticalSize( +// // 83), +// // width: +// // getHorizontalSize( +// // 24), +// // decoration: BoxDecoration( +// // color: ColorConstant +// // .blueA700, +// // borderRadius: BorderRadius.only( +// // topLeft: +// // Radius.circular(getHorizontalSize( +// // 4)), +// // topRight: +// // Radius.circular(getHorizontalSize(4))))), +// // Padding( +// // padding: +// // getPadding( +// // top: 9), +// // child: Text( +// // "08/27", +// // overflow: +// // TextOverflow +// // .ellipsis, +// // textAlign: +// // TextAlign +// // .left, +// // style: AppStyle +// // .txtGilroyMedium10)) +// // ])) +// // ]))) +// ]))), +// Padding( +// padding: getPadding(top: 29), +// child: Text("Notifications", +// overflow: TextOverflow.ellipsis, +// textAlign: TextAlign.left, +// style: AppStyle.txtGilroySemiBold18)), +// Padding( +// padding: getPadding(top: 21), +// child: ListView.separated( +// physics: NeverScrollableScrollPhysics(), +// shrinkWrap: true, +// separatorBuilder: (context, index) { +// return Padding( +// padding: getPadding(top: 18.5, bottom: 18.5), +// child: SizedBox( +// width: getHorizontalSize(396), +// child: Divider( +// height: getVerticalSize(1), +// thickness: getVerticalSize(1), +// color: ColorConstant.blueGray100))); +// }, +// itemCount: notifications.length, +// itemBuilder: (context, index) { +// return NotificationItem( +// notification: notifications[index]); +// })), +// Padding( +// padding: getPadding(top: 17, bottom: 5), +// child: Divider( +// height: getVerticalSize(1), +// thickness: getVerticalSize(1), +// color: ColorConstant.blueGray100)) +// ])), +// )); +// } + +// Widget buildContainer( +// {required double height, +// required double width, +// required EdgeInsets margin, +// required String text}) { +// return Container( +// width: getHorizontalSize(width), +// margin: margin, +// child: Column( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// Container( +// height: getVerticalSize(height), +// decoration: BoxDecoration( +// color: ColorConstant.blueA700, +// borderRadius: BorderRadius.only( +// topLeft: Radius.circular(getHorizontalSize(4)), +// topRight: Radius.circular(getHorizontalSize(4)), +// ), +// ), +// ), +// Padding( +// padding: getPadding(top: 9), +// child: Text( +// text, +// overflow: TextOverflow.ellipsis, +// textAlign: TextAlign.left, +// style: AppStyle.txtGilroyMedium10, +// ), +// ), +// ], +// ), +// ); +// } +// } \ No newline at end of file diff --git a/lib/screens/main_app_screen/notification_item.dart b/lib/screens/main_app_screen/notification_item.dart new file mode 100644 index 0000000..cbd0155 --- /dev/null +++ b/lib/screens/main_app_screen/notification_item.dart @@ -0,0 +1,88 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../Utils/size_utils.dart'; +import '../../theme/app_style.dart'; + +class NotificationItem extends StatelessWidget { + final Map notification; + + const NotificationItem({required this.notification}); + + @override + Widget build(BuildContext context) { + final notificationText = notification['notification'] as String; + final time = notification['time'] as String; + final timeDifference = calculateTimeDifference(time); + + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + // Text( + // notificationText, + // overflow: TextOverflow.ellipsis, + // textAlign: TextAlign.left, + // style: AppStyle.txtGilroySemiBold16, + // ), + Padding( + padding: getPadding( + top: 10, + ), + child: Text( + notificationText, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyRegular14, + ), + ), + ], + ), + Padding( + padding: getPadding( + top: 11, + bottom: 13, + ), + child: Text( + timeDifference, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroySemiBold18, + ), + ), + ], + ); + + + + ListTile( + title: Text(notificationText), + subtitle: Text(timeDifference), + ); + } + + String calculateTimeDifference(String time) { + final currentTime = DateTime.now(); + final notificationTime = DateTime.parse(time); + + final difference = currentTime.difference(notificationTime); + + if (difference.inDays >= 365) { + final years = (difference.inDays / 365).floor(); + return '${years} ${years == 1 ? 'year' : 'years'} ago'; + } else if (difference.inDays >= 30) { + final months = (difference.inDays / 30).floor(); + return '${months} ${months == 1 ? 'month' : 'months'} ago'; + } else if (difference.inDays > 0) { + return '${difference.inDays} ${difference.inDays == 1 ? 'day' : 'days'} ago'; + } else if (difference.inHours > 0) { + return '${difference.inHours} ${difference.inHours == 1 ? 'hour' : 'hours'} ago'; + } else { + return 'Just now'; + } + } +} diff --git a/lib/screens/main_app_screen/tabbed_layout_component.dart b/lib/screens/main_app_screen/tabbed_layout_component.dart new file mode 100644 index 0000000..4ae9fac --- /dev/null +++ b/lib/screens/main_app_screen/tabbed_layout_component.dart @@ -0,0 +1,993 @@ + + + + + + + + + +import 'package:intl/intl.dart'; + +import '../../Entity/gaurav/Gauravtest1/Gauravtest1_entity_list_screen.dart'; + +import 'dart:async'; +import 'dart:convert'; + +import 'package:fluentui_system_icons/fluentui_system_icons.dart'; +import 'package:flutter/material.dart'; +import 'package:google_nav_bar/google_nav_bar.dart'; +import 'package:provider/provider.dart'; +import 'package:http/http.dart' as http; +import 'package:shared_preferences/shared_preferences.dart'; +import '../../Utils/color_constants.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/tab_navigation_provider.dart'; +import '../../providers/token_manager.dart'; +import '../../resources/api_constants.dart'; +import '../../theme/app_decoration.dart'; +import '../../theme/app_style.dart'; +import '../Bookmarks/Bookmarks_entity_list_screen.dart'; +import '../Incident_Ticket/ticket_create.dart'; +import '../LayoutReportBuilder/LayoutReportBuilder.dart'; +import '../Login Screen/login_screen.dart'; +import '../LogoutService/Logoutservice.dart'; +import '../QrBarCode/Qr_BarCode/Qr_BarCode_create_entity_screen.dart'; +import '../Setup/setup.dart'; +import '../SysParameters/SystemParameterScreen.dart'; +import '../dynamic_form/list_dynamic_form_screen.dart'; +import '../profileManagement/Profilesettings.dart'; +import '../profileManagement/about.dart'; +import '../profileManagement/changepassword.dart'; + +class TabbedLayoutComponent extends StatefulWidget { + @override + _TabbedLayoutComponentState createState() => _TabbedLayoutComponentState(); +} + +class _TabbedLayoutComponentState extends State { + int _currentTab = 0; + final GlobalKey _scaffoldKey = GlobalKey(); + + Map userData = {}; + + @override + void initState() { + super.initState(); + getUserData(); + fetchData(); + } + + getUserData() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var userdatastr = prefs.getString('userData'); + if (userdatastr != null) { + try { + setState(() { + userData = json.decode(userdatastr); + }); + print(userData['token']); + } catch (e) { + print("error is ..................$e"); + } + } + } + + void setTab(int index) { + setState(() { + _currentTab = index; + }); + } + + List> notifications = []; + + Future fetchData() async { + String baseUrl = ApiConstants.baseUrl; + final apiUrl = '$baseUrl/notification/get_notification'; + final token = await TokenManager.getToken(); + final response = await http.get( + Uri.parse(apiUrl), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + ); + if (response.statusCode == 401) { + LogoutService.logout(); + } + if (response.statusCode <= 209) { + final List data = jsonDecode(response.body); + setState(() { + notifications = data.cast>(); + }); + } else { + // Handle errors + print('Failed to fetch data'); + } + } + + @override + Widget build(BuildContext context) { + final userAuthKey = TokenManager.getToken().toString(); + + print('user auth key is .....' + userAuthKey); + + List screens = [ + Padding( + padding: const EdgeInsets.all(10.0), + child: StaticChartsScreen( + userData: userData, + ), + ), + HomeDashboardScreen( + userData: userData, + ), + // const SizedBox(height: 15), + + Container( + padding: const EdgeInsets.all(16.0), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Activity', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 16.0), // Adjust the spacing as needed + //ActivityList(), // This widget should contain the list of notifications + for (final notification in notifications) + NotificationItem(notification: notification), + ], + ), + ), + ) + ]; + + return WillPopScope( + onWillPop: _onBackPress, + child: Scaffold( + key: _scaffoldKey, + appBar: AppBar( + backgroundColor: Colors.white, + toolbarHeight: 50, + leading: IconButton( + icon: const Icon( + Icons.circle_outlined, + color: Colors.black, + ), + onPressed: () {}), + title: const Text( + "Authsec", + style: TextStyle(color: Colors.black), + ), + actions: [ + PopupMenuButton( + icon: const Icon( + Icons.more_vert, + color: Colors.black, + ), + onSelected: (String result) { + // Handle the selected option + print("Selected: $result"); + }, + itemBuilder: (BuildContext context) => [ + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'Raise A Ticket', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => RaisedTicketScreen( + userData: userData, + ), + ), + ); + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'Profile Settings', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + // Closes the drawer + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + ProfileSettingsScreen(userData: userData), + ), + ); + // Add your logic for menu 2 here + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'Change Password', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + // Closes the drawer + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ResetPasswordScreen( + userEmail: userData['email'], + userData: userData), //go to get all entity + ), + ); + // Add your logic for menu 2 here + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'DynamicForm', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + // Closes the drawer + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + DynamicForm(), //go to get all entity + ), + ); + // Add your logic for menu 2 here + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'Setup Screen', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const SetupScreen(), //go to get all entity + ), + ); + // Add your logic for menu 2 here + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'BookMark', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + // Closes the drawer + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + bookmarks_entity_list_screen(), //go to get all entity + ), + ); + // Add your logic for menu 2 here + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'System Parameter', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + SysParameter(), //go to get all entity + ), + ); + // Add your logic for menu 2 here + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'Addition Menu', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const QrBarCodeScreen(), + ), + ); + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'About', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + AboutScreen(), //go to get all entity + ), + ); + // Add your logic for menu 2 here + }, + ), + + // NEW MENU + + + + + + + + + + + + + + + + + + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'Gauravtest1', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + gauravtest1_entity_list_screen(), //go to get all entity + ), + ); + // Add your logic for menu 2 here + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'gtest', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => gauravtest1_entity_list_screen(), + ), + ); + }, + ), + + PopupMenuItem( + //value: 'Option 1', + child: Text( + 'LogOut', + style: AppStyle.txtGilroySemiBold16, + ), + onTap: () { + _logoutUser(); + }, + ), + ], + ), + ], + ), + backgroundColor: const Color(0xfffefefe), + extendBodyBehindAppBar: true, + //bottomNavigationBar: AppFooter(), + body: screens.isEmpty + ? const Text("Loading...") + : ListView.builder( + itemCount: screens.length, + scrollDirection: Axis.vertical, + itemBuilder: (context, index) => screens[index], + ), + ), + ); + } + + Future _logoutUser() async { + try { + SharedPreferences prefs = await SharedPreferences.getInstance(); + + // Remove 'userData' and 'isLoggedIn' from SharedPreferences + await prefs.remove('userData'); + await prefs.remove('isLoggedIn'); + String logouturl = "${ApiConstants.baseUrl}/token/logout"; + var response = await http.get(Uri.parse(logouturl)); + if (response.statusCode == 401) { + LogoutService.logout(); + } + if (response.statusCode <= 209) { + // ignore: use_build_context_synchronously + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => const LoginScreen()), + (route) => false, // Remove all routes from the stack + ); + } else { + const Text('failed to logout'); + } + } catch (error) { + print('Error occurred during logout: $error'); + } + } + + Widget googleNavBar() { + return Container( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 6.18, vertical: 1), + child: GNav( + haptic: false, + gap: 6, + activeColor: const Color(0xFF0070BA), + iconSize: 24, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 11), + duration: const Duration(milliseconds: 300), + color: const Color(0xFF243656), + tabs: [ + GButton( + icon: FluentIcons.home_32_regular, + iconSize: 36, + text: 'Home', + onPressed: () { + print('home'); + }, + ), + GButton( + icon: FluentIcons.people_32_regular, + iconSize: 36, + text: 'Contacts', + onPressed: () { + print('contacts'); + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => AllContactsScreen( + // setTab: setTab, + // ), + // ), + // ); + }, + ), + GButton( + icon: Icons.wallet, + text: 'Wallet', + iconSize: 34, + onPressed: () { + print('wallet'); + }, + ), + ], + selectedIndex: _currentTab, + onTabChange: _onTabChange, + ), + ), + ); + } + + void _onTabChange(int index) { + if (_currentTab == 1 || _currentTab == 2) { + FocusManager.instance.primaryFocus?.unfocus(); + } + Provider.of(context, listen: false) + .updateTabs(_currentTab); + setState(() { + _currentTab = index; + }); + } + + Future _onBackPress() { + if (_currentTab == 0) { + return Future.value(true); + } else { + int lastTab = + Provider.of(context, listen: false).lastTab; + Provider.of(context, listen: false) + .removeLastTab(); + setTab(lastTab); + } + return Future.value(false); + } +} + +class StaticChartsScreen extends StatefulWidget { + final Map userData; + const StaticChartsScreen({required this.userData, Key? key}) + : super(key: key); + @override + _StaticChartsScreenState createState() => _StaticChartsScreenState(); +} + +class _StaticChartsScreenState extends State { + int myProjectcount = 0; + int sharedWithMeCount = 0; + int allprojectCount = 0; + + @override + void initState() { + super.initState(); + fetchData(); + } + + Future fetchData() async { + print("working"); + final token = await TokenManager.getToken(); + print(token); + String baseUrl = ApiConstants.baseUrl; + var myProjectcountres = await http.get( + Uri.parse('$baseUrl/workspace/secworkspaceuser/count_myproject'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': + 'application/json', // You may need to adjust the content type as needed + }, + ); + var sharedWithMeCountres = await http.get( + Uri.parse('$baseUrl/workspace/secworkspaceuser/count_sharedwithme'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': + 'application/json', // You may need to adjust the content type as needed + }, + ); + var allProjectsCountres = await http.get( + Uri.parse('$baseUrl/workspace/secworkspaceuser/count_allproject'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': + 'application/json', // You may need to adjust the content type as needed + }, + ); + if (myProjectcountres.statusCode == 401) { + LogoutService.logout(); + } + print(myProjectcountres.statusCode); + if (myProjectcountres.statusCode <= 209 && + sharedWithMeCountres.statusCode <= 209) { + final myProjectData = jsonDecode(myProjectcountres.body); + final sharedData = jsonDecode(sharedWithMeCountres.body); + final allData = jsonDecode(allProjectsCountres.body); + setState(() { + myProjectcount = myProjectData; + sharedWithMeCount = sharedData; + allprojectCount = allData; + }); + } else { + // Handle errors + print('Failed to fetch data'); + } + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + GestureDetector( + onTap: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => ProjectListScreen( + // userData: widget.userData, + // type: "myproject"), // Get all projects + // ), + // ); + print('test1'); + }, + child: Card( + color: Colors.white, + elevation: 5.0, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Text( + myProjectcount.toString(), + style: const TextStyle( + color: Colors.black, + fontSize: 12, + ), + ), + const Text( + 'Test1', + style: TextStyle( + color: Colors.black, + fontSize: 12, + ), + ), + ], + ), + ), + ), + ), + GestureDetector( + onTap: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => ProjectListScreen( + // userData: widget.userData, + // type: "sharedproject"), // Get all projects + // ), + // ); + print('test2'); + }, + child: Card( + color: Colors.white, + elevation: 5.0, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Text( + sharedWithMeCount.toString(), + style: const TextStyle( + fontSize: 12, + ), + ), + const Text( + 'Test2', + style: TextStyle( + fontSize: 12, + ), + ), + ], + ), + ), + ), + ), + GestureDetector( + onTap: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => ProjectListScreen( + // userData: widget.userData, + // type: "allproject"), // Get all projects + // ), + // ); + print('test3'); + }, + child: Card( + color: Colors.white, + elevation: 5.0, + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Text( + allprojectCount.toString(), + style: const TextStyle( + fontSize: 12, + ), + ), + const Text( + 'Test3', + style: TextStyle( + fontSize: 12, + ), + ), + ], + ), + ), + ), + ), + ], + ); + } +} + +class HomeDashboardScreen extends StatelessWidget { + final Map userData; + + const HomeDashboardScreen({super.key, required this.userData}); + + @override + Widget build(BuildContext context) { + var firstName = userData['firstName'].toString(); + return Container( + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Card( + clipBehavior: Clip.antiAlias, + elevation: 0, + margin: getMargin(top: 5), + color: ColorConstant.whiteA70099, + shape: RoundedRectangleBorder( + borderRadius: BorderRadiusStyle.roundedBorder6), + child: Container( + height: getVerticalSize(224), + width: + MediaQuery.of(context).size.width, //getHorizontalSize(396), + // padding: getPadding( + // left: 16, top: 17, right: 16, bottom: 17), + decoration: AppDecoration.outlineGray70026 + .copyWith(borderRadius: BorderRadiusStyle.roundedBorder6), + child: Stack(alignment: Alignment.centerRight, children: [ + Align( + alignment: Alignment.topCenter, + child: Padding( + padding: getPadding(left: 1), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("08", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium10), + Expanded( + child: Padding( + padding: + getPadding(top: 6, bottom: 5), + child: Divider( + height: getVerticalSize(1), + thickness: getVerticalSize(1), + color: + ColorConstant.blueGray400, + indent: getHorizontalSize(9)))) + ]), + Padding( + padding: getPadding(top: 28), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text("06", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium10), + Expanded( + child: Padding( + padding: getPadding( + top: 6, bottom: 5), + child: Divider( + height: getVerticalSize(1), + thickness: + getVerticalSize(1), + color: ColorConstant + .blueGray400, + indent: + getHorizontalSize(9)))) + ])), + Padding( + padding: getPadding(top: 28), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text("04", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium10), + Expanded( + child: Padding( + padding: getPadding( + top: 6, bottom: 5), + child: Divider( + height: getVerticalSize(1), + thickness: + getVerticalSize(1), + color: ColorConstant + .blueGray400, + indent: + getHorizontalSize(9)))) + ])), + Padding( + padding: getPadding(top: 28), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text("02", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium10), + Expanded( + child: Padding( + padding: getPadding( + top: 6, bottom: 5), + child: Divider( + height: getVerticalSize(1), + thickness: + getVerticalSize(1), + color: ColorConstant + .blueGray400, + indent: + getHorizontalSize(10)))) + ])), + Padding( + padding: getPadding(top: 28), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text("00", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium10), + Expanded( + child: Padding( + padding: getPadding( + top: 6, bottom: 5), + child: Divider( + height: getVerticalSize(1), + thickness: + getVerticalSize(1), + color: ColorConstant + .blueGray400, + indent: + getHorizontalSize(9)))) + ])) + ]))), + Align( + alignment: Alignment.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + buildContainer( + height: 97, + width: MediaQuery.of(context).size.width * 0.016, + margin: const EdgeInsets.only(top: 45), + text: "08/21"), + buildContainer( + height: 138, + width: MediaQuery.of(context).size.width * 0.016, + margin: const EdgeInsets.only(left: 23, top: 19), + text: "08/22"), + buildContainer( + height: 160, + width: MediaQuery.of(context).size.width * 0.016, + margin: const EdgeInsets.only(left: 21, top: 5), + text: "08/23"), + buildContainer( + height: 83, + width: MediaQuery.of(context).size.width * 0.016, + margin: const EdgeInsets.only(left: 21, top: 53), + text: "08/24"), + buildContainer( + height: 64, + width: MediaQuery.of(context).size.width * 0.016, + margin: const EdgeInsets.only(left: 20, top: 65), + text: "08/25"), + buildContainer( + height: 126, + width: MediaQuery.of(context).size.width * 0.016, + margin: const EdgeInsets.only(left: 21, top: 26), + text: "08/26"), + buildContainer( + height: 83, + width: MediaQuery.of(context).size.width * 0.016, + margin: const EdgeInsets.only(left: 22, top: 53), + text: "08/27"), + ], + ), + ) + ]))), + )); + // ); + } + + Widget buildContainer( + {required double height, + required double width, + required EdgeInsets margin, + required String text}) { + return Container( + width: getHorizontalSize(width), + margin: margin, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + height: getVerticalSize(height), + decoration: BoxDecoration( + color: ColorConstant.blueA700, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(getHorizontalSize(4)), + topRight: Radius.circular(getHorizontalSize(4)), + ), + ), + ), + Padding( + padding: getPadding(top: 9), + child: Text( + text, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium10, + ), + ), + ], + ), + ); + } +} + +class NotificationItem extends StatelessWidget { + final Map notification; + + const NotificationItem({required this.notification}); + + @override + Widget build(BuildContext context) { + final notificationText = notification['notification'] as String; + final time = notification['time'] as String; + final timeDifference = calculateTimeDifference(time); + + return ListTile( + title: Text( + notificationText, + style: TextStyle(fontSize: 12, color: Colors.grey[800]), + ), + subtitle: Text(timeDifference), + ); + } + + String calculateTimeDifference(String time) { + final currentTime = DateTime.now(); + final formatter = DateFormat('yyyy/MM/dd HH:mm:ss'); + final notificationTime = formatter.parse(time); + final difference = currentTime.difference(notificationTime); + + if (difference.inDays >= 365) { + final years = (difference.inDays / 365).floor(); + return '${years} ${years == 1 ? 'year' : 'years'} ago'; + } else if (difference.inDays >= 30) { + final months = (difference.inDays / 30).floor(); + return '${months} ${months == 1 ? 'month' : 'months'} ago'; + } else if (difference.inDays > 0) { + return '${difference.inDays} ${difference.inDays == 1 ? 'day' : 'days'} ago'; + } else if (difference.inHours > 0) { + return '${difference.inHours} ${difference.inHours == 1 ? 'hour' : 'hours'} ago'; + } else { + return 'Just now'; + } + } +} \ No newline at end of file diff --git a/lib/screens/profileManagement/Profilesettings.dart b/lib/screens/profileManagement/Profilesettings.dart new file mode 100644 index 0000000..3ff118b --- /dev/null +++ b/lib/screens/profileManagement/Profilesettings.dart @@ -0,0 +1,524 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; + +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../resources/api_constants.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import '../../widgets/custom_button.dart'; +import '../../widgets/custom_text_form_field.dart'; +import '../Login Screen/login_screen.dart'; +import '../LogoutService/Logoutservice.dart'; +import 'apiserviceprofilemanagement.dart'; +import 'package:http/http.dart' as http; + +import 'changepassword.dart'; + +class ProfileSettingsScreen extends StatefulWidget { + final Map userData; + + ProfileSettingsScreen({required this.userData}); + + @override + _ProfileSettingsScreenState createState() => _ProfileSettingsScreenState(); +} + +class _ProfileSettingsScreenState extends State { + ApiServiceProfileManagement apiService = ApiServiceProfileManagement(); + String? fetchedimageurl = + 'http://43.205.154.152:30165/assets/images/profile-icon.png'; + Uint8List? _imageBytes; // Uint8List to store the image data + String? _imageFileName; + final _formKey = GlobalKey(); + + TextEditingController fullNameController = TextEditingController(); + TextEditingController pronounsController = TextEditingController(); + TextEditingController roleController = TextEditingController(); + TextEditingController departmentController = TextEditingController(); + TextEditingController emailController = TextEditingController(); + TextEditingController aboutMeController = TextEditingController(); + + @override + void initState() { + super.initState(); + //fetchProfileImageData(); + fetchUserProfileData(); + } + + Future _uploadImageFile() async { + final imagePicker = ImagePicker(); + + try { + final pickedImage = + await imagePicker.pickImage(source: ImageSource.gallery); + + if (pickedImage != null) { + final imageBytes = await pickedImage.readAsBytes(); + + setState(() { + _imageBytes = imageBytes; + _imageFileName = pickedImage.name; // Store the file name + }); + } + } catch (e) { + print(e); + } + } + + //api/user-profile + Future fetchUserProfileData() async { + final token = await TokenManager.getToken(); + final String baseUrl = ApiConstants.baseUrl; + final String apiUrl = '$baseUrl/api/user-profile'; + try { + final response = await http.get( + Uri.parse(apiUrl), + headers: { + 'Authorization': 'Bearer $token', + }, + ); + if (response.statusCode == 401) { + LogoutService.logout(); + } + if (response.statusCode >= 200 && response.statusCode <= 209) { + final Map jsonData = json.decode(response.body); + setState(() { + fullNameController.text = + jsonData['fullName'] != null ? jsonData['fullName'] : ''; + pronounsController.text = + jsonData['pronouns'] != null ? jsonData['pronouns'] : ''; + roleController.text = + jsonData['role'] != null ? jsonData['role'] : ''; + departmentController.text = + jsonData['department'] != null ? jsonData['department'] : ''; + emailController.text = + jsonData['email'] != null ? jsonData['email'] : ''; + aboutMeController.text = + jsonData['about'] != null ? jsonData['about'] : ''; + }); + } else { + throw Exception('Failed to load data: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load data: $e'); + } + } + + Future fetchProfileImageData() async { + final token = await TokenManager.getToken(); + final String baseUrl = ApiConstants.baseUrl; + final String apiUrl = '$baseUrl/api/retrieve-image'; + try { + final response = await http.get( + Uri.parse(apiUrl), + headers: { + 'Authorization': 'Bearer $token', + }, + ); + if (response.statusCode == 401) { + LogoutService.logout(); + } + if (response.statusCode >= 200 && response.statusCode <= 209) { + final Map jsonData = json.decode(response.body); + final trustedImageUrl = Uri.dataFromString(jsonData['image'], + mimeType: 'image/*', encoding: Encoding.getByName('utf-8')) + .toString(); + fetchedimageurl = trustedImageUrl; + } else { + throw Exception('Failed to load data: ${response.statusCode}'); + } + } catch (e) { + throw Exception('Failed to load data: $e'); + } + } + + Future _submitImage() async { + if (_imageBytes == null) { + // Show an error message if no image is selected + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Please select an image.'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + return; + } + + if (_imageFileName == null) { + // Handle the case where _imageFileName is null (no file name provided) + print('File name is missing.'); + return; + } + try { + final token = await TokenManager.getToken(); + await apiService.createFile(_imageBytes!, _imageFileName!, token!); + } catch (e) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Failed to upload image: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + + Future _updateProfile() async { + if (_formKey.currentState!.validate()) { + // Create a JSON object with the form data + final profileData = { + 'fullName': fullNameController.text, + 'pronouns': pronounsController.text, + 'role': roleController.text, + 'department': departmentController.text, + 'email': emailController.text, + 'aboutMe': aboutMeController.text, + }; + + //api/user-profile + + final token = await TokenManager.getToken(); + final String baseUrl = ApiConstants.baseUrl; + final String apiUrl = '$baseUrl/api/user-profile'; + try { + final response = await http.put(Uri.parse(apiUrl), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + body: json.encode(profileData)); + if (response.statusCode == 401) { + LogoutService.logout(); + } + if (response.statusCode <= 209) { + print("success"); + Navigator.of(context).pop(); + } else { + print(response.statusCode); + } + } catch (e) { + throw Exception('Failed to Update: $e'); + } + } + } + + Future _logoutUser() async { + try { + String logouturl = "${ApiConstants.baseUrl}/token/logout"; + var response = await http.get(Uri.parse(logouturl)); + + if (response.statusCode <= 209) { + // ignore: use_build_context_synchronously + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => LoginScreen()), + (route) => false, // Remove all routes from the stack + ); + } else { + const Text('failed to logout'); + } + } catch (error) { + print('Error occurred during logout: $error'); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "My Profile Settings")), + body: SingleChildScrollView( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Section: Show Profile Photo + Center( + child: Column( + children: [ + CircleAvatar( + radius: 70, // Adjust as needed + backgroundImage: NetworkImage( + "$fetchedimageurl"), // Replace with your API URL + ), + SizedBox(height: 10), + CustomButton( + height: getVerticalSize(50), + text: _imageBytes == null + ? "Pick a Profile Photo" + : 'Upload Success', + margin: getMargin(top: 24, bottom: 5), + onTap: () async { + if (_imageBytes != null) { + _submitImage(); + } else { + _uploadImageFile(); + } + }, + ), + ], + ), + ), + + SizedBox(height: 20), + // Section: Profile Form + Text( + 'Your Profile Information', + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + SizedBox(height: 10), + Form( + key: _formKey, + child: Column( + children: [ + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Your Full Name", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + controller: fullNameController, + hintText: "Enter Full Name", + validator: (value) { + if (value!.isEmpty) { + return 'Please enter your full name'; + } + return null; + }, + onChanged: (value) { + fullNameController.text = value; + }, + margin: getMargin(top: 6)) + ])), + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Pronouns", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Pronouns", + controller: pronounsController, + onChanged: (value) { + pronounsController.text = value; + }, + margin: getMargin(top: 6)) + ])), + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Role", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Role", + controller: roleController, + onChanged: (value) { + roleController.text = value; + }, + margin: getMargin(top: 6)) + ])), + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Department or Team", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Department or Team", + controller: departmentController, + onChanged: (value) { + departmentController.text = value; + }, + margin: getMargin(top: 6)) + ])), + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Email", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Enter Email", + controller: emailController, + validator: (value) { + if (value!.isEmpty || !value!.contains('@')) { + return 'Please enter a valid email address'; + } + return null; + }, + onChanged: (value) { + emailController.text = value; + }, + margin: getMargin(top: 6)) + ])), + Padding( + padding: getPadding(top: 19), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("About Me", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "About Me", + controller: aboutMeController, + maxLines: 3, + onChanged: (value) { + aboutMeController.text = value; + }, + margin: getMargin(top: 6)) + ])), + CustomButton( + height: getVerticalSize(50), + text: "Update Profile", + margin: getMargin(top: 24, bottom: 5), + onTap: _updateProfile, + ), + ], + ), + ), + + SizedBox(height: 20), + GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ResetPasswordScreen( + userData: widget.userData, + userEmail: emailController.text, + ), //go to get all entity + ), + ); + }, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: + "Password:Change Password for your account Change password", + style: TextStyle( + fontWeight: FontWeight.normal, + color: Colors.blue, + ), + ), + ], + ), + ), + ), + SizedBox(height: 20), + GestureDetector( + onTap: () { + print("change password"); + }, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: + 'Security:Logout of all sessions except this current browser Logout other sessions', + style: TextStyle( + fontWeight: FontWeight.normal, + color: Colors.blue, + ), + ), + ], + ), + ), + ), + SizedBox(height: 20), + GestureDetector( + onTap: () { + _logoutUser(); + }, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: + 'Deactivation:Remove access to all organizations and workspace in cloudnsure Deactivate account', + style: TextStyle( + fontWeight: FontWeight.normal, + color: Colors.blue, + ), + ), + ], + ), + ), + ), + SizedBox(height: 20), + ], + ), + ), + ); + } +} diff --git a/lib/screens/profileManagement/about.dart b/lib/screens/profileManagement/about.dart new file mode 100644 index 0000000..052406d --- /dev/null +++ b/lib/screens/profileManagement/about.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; + +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; + +class AboutScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "About Us")), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'About Us', + style: AppStyle.txtGilroyBold18Bluegray900, + ), + const SizedBox(height: 20), + Text( + 'Create a new project if you have access, if you don\'t have access, then contact the admin.', + textAlign: TextAlign.center, + style: AppStyle.txtGilroyBold16BlueA700, + ), + ], + ), + ), + ); + } +} diff --git a/lib/screens/profileManagement/apiserviceprofilemanagement.dart b/lib/screens/profileManagement/apiserviceprofilemanagement.dart new file mode 100644 index 0000000..2e486b0 --- /dev/null +++ b/lib/screens/profileManagement/apiserviceprofilemanagement.dart @@ -0,0 +1,57 @@ +import 'dart:typed_data'; +import 'package:http/http.dart' as http; +import 'package:http_parser/http_parser.dart'; +import 'package:dio/dio.dart'; +import '../../resources/api_constants.dart'; + +class ApiServiceProfileManagement { + final String baseUrl = ApiConstants.baseUrl; + final Dio dio = Dio(); + + Future createFile( + Uint8List fileBytes, String fileName, String token) async { + try { + String apiUrl = "$baseUrl/api/upload"; + + final mimeType = 'image/jpeg'; // You can set the appropriate MIME type + + FormData formData = FormData.fromMap({ + 'imageFile': MultipartFile.fromBytes( + fileBytes, + filename: fileName, + contentType: MediaType.parse(mimeType), + ), + }); + + Dio dio = Dio(); // Create a new Dio instance + dio.options.headers['Authorization'] = 'Bearer $token'; + + final response = await dio.post(apiUrl, data: formData); + + if (response.statusCode == 200) { + // Handle successful response + print('File uploaded successfully'); + } else { + print('Failed to upload file with status: ${response.statusCode}'); + } + } catch (error) { + print('Error occurred during form submission: $error'); + } + } + + String lookupMimeType(String filePath) { + final ext = filePath.split('.').last; + switch (ext) { + case 'jpg': + case 'jpeg': + return 'image/jpeg'; + case 'png': + return 'image/png'; + case 'pdf': + return 'application/pdf'; + // Add more cases for other file types as needed + default: + return 'application/octet-stream'; // Default MIME type + } + } +} diff --git a/lib/screens/profileManagement/changepassword.dart b/lib/screens/profileManagement/changepassword.dart new file mode 100644 index 0000000..b34b153 --- /dev/null +++ b/lib/screens/profileManagement/changepassword.dart @@ -0,0 +1,318 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; + +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../resources/api_constants.dart'; +import 'package:http/http.dart' as http; + +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import '../../widgets/custom_button.dart'; +import '../../widgets/custom_text_form_field.dart'; +import '../Login Screen/login_screen.dart'; +import '../LogoutService/Logoutservice.dart'; + +class ResetPasswordScreen extends StatelessWidget { + final String userEmail; + + final Map userData; + + ResetPasswordScreen({required this.userEmail,required this.userData}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: + CustomAppBar( + height: getVerticalSize(49), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleftBlueGray900, + margin: getMargin(left: 16, top: 12, bottom: 13), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "Reset Password")), + body: SingleChildScrollView( + padding: EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "You're signed in as $userEmail", + style: AppStyle.txtGilroyMedium16Bluegray800 + ), + const SizedBox(height: 20), + ResetPasswordForm(userData: userData,userEmail: userEmail), + const SizedBox(height: 20), + GestureDetector( + onTap: () { + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => const LoginScreen()), + (route) => false, // Remove all routes from the stack + ); + }, + child: Text( + 'Wrong account? Log in instead.', + style: AppStyle.txtGreenSemiBold16, + ), + ), + ], + ), + ), + ); + } +} + +class ResetPasswordForm extends StatefulWidget { + final String userEmail; + + final Map userData; + + const ResetPasswordForm({super.key, required this.userEmail,required this.userData}); + + + + @override + _ResetPasswordFormState createState() => _ResetPasswordFormState(); +} + +class _ResetPasswordFormState extends State { + final TextEditingController oldPasswordController = TextEditingController(); + final TextEditingController newPasswordController = TextEditingController(); + final TextEditingController reEnterNewPasswordController = + TextEditingController(); + + var responseMessage; + var isVisible=false; + bool issuccess = false; + + bool isOldPasswordVisible = false; + bool isNewPasswordVisible = false; + bool isReEnterNewPasswordVisible = false; + + bool _isPasswordValid1 = true; + void _validatePassword1(String password) { + setState(() { + _isPasswordValid1 = password.isNotEmpty; + }); + } + + bool _isPasswordValid2 = true; + void _validatePassword2(String password) { + setState(() { + _isPasswordValid2 = password.isNotEmpty; + }); + } + + bool _isPasswordValid3 = true; + void _validatePassword3(String password) { + setState(() { + _isPasswordValid3 = password.isNotEmpty&&password==newPasswordController.text; + }); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + isVisible?Text(responseMessage,style: TextStyle( + color: issuccess?Colors.green:Colors.red, // Set the text color to red + )):const Text(''), + + Padding( + padding: getPadding(top: 19), + child: Text("Enter Old Password", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + controller: oldPasswordController, + hintText: "Enter Old Password", + margin: getMargin(top: 6), + errorText: + _isPasswordValid1 ? null : 'Please enter your old password', + padding: TextFormFieldPadding.PaddingT12, + textInputAction: TextInputAction.done, + onChanged: _validatePassword1, + validator: (value) { + if (value!.isEmpty) { + return 'Please enter your old password'; + } + return null; // Return null to indicate no error + }, + textInputType:TextInputType.visiblePassword, + suffix: IconButton( + icon: Icon( + isOldPasswordVisible ? Icons.visibility : Icons.visibility_off, + ), + onPressed: () { + setState(() { + isOldPasswordVisible = !isOldPasswordVisible; + }); + }, + ), + suffixConstraints: BoxConstraints( + maxHeight: getVerticalSize(44)), + isObscureText: !isOldPasswordVisible), + + Padding( + padding: getPadding(top: 19), + child: Text("Enter New Password", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + controller: newPasswordController, + hintText: "Enter New Password", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputAction: TextInputAction.done, + suffix: IconButton( + icon: Icon( + isNewPasswordVisible ? Icons.visibility : Icons.visibility_off, + ), + onPressed: () { + setState(() { + isNewPasswordVisible = !isNewPasswordVisible; + }); + }, + ), + errorText: + _isPasswordValid2 ? null : 'Please enter your new password', + onChanged: _validatePassword2, + validator: (value) { + if (value!.isEmpty) { + return 'Please enter your new password'; + } + return null; + }, + suffixConstraints: BoxConstraints( + maxHeight: getVerticalSize(44)), + isObscureText:!isNewPasswordVisible,), + + Padding( + padding: getPadding(top: 19), + child: Text("Re-Enter New Password", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + controller: reEnterNewPasswordController, + hintText: "Re-Enter New Password", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + onChanged: _validatePassword3, + validator: (value) { + if (value!.isEmpty) { + return 'Please re-enter your new password'; + } + if (value != newPasswordController.text) { + return 'Passwords do not match'; + } + return null; + }, + suffix: IconButton( + icon: Icon( + isReEnterNewPasswordVisible + ? Icons.visibility + : Icons.visibility_off, + ), + onPressed: () { + setState(() { + isReEnterNewPasswordVisible = !isReEnterNewPasswordVisible; + }); + }, + ), + errorText: + _isPasswordValid3 ? null : 'Please re-enter your new password', + textInputAction: TextInputAction.done, + suffixConstraints: BoxConstraints( + maxHeight: getVerticalSize(44)), + isObscureText:!isReEnterNewPasswordVisible,), + + CustomButton( + height: getVerticalSize(50), + text: "Continue", + margin: getMargin(top: 24, bottom: 5), + onTap: () async { + if (oldPasswordController.text.isEmpty || + newPasswordController.text.isEmpty || + reEnterNewPasswordController.text.isEmpty) { + print(oldPasswordController.text); + print(newPasswordController.text); + print(reEnterNewPasswordController.text); + } else { + Map passwordData = { + "userId":widget.userData['userId'], + "oldPassword": oldPasswordController.text, + "newPassword": newPasswordController.text, + "confirmPassword": reEnterNewPasswordController.text, + }; + final token = await TokenManager.getToken(); + final String baseUrl = ApiConstants.baseUrl; + final String apiUrl = '$baseUrl/api/reset_password'; + + try { + final response = await http.post(Uri.parse(apiUrl), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }, + body: json.encode(passwordData)); + if(response.statusCode==401){ + LogoutService.logout(); + } + if (response.statusCode <= 209) { + setState(() { + isVisible=true; + issuccess=true; + responseMessage = "Password Changes Successfully"; + }); + print("success"); + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute(builder: (context) => LoginScreen()), + (route) => false, + ); + } else { + setState(() { + isVisible=true; + responseMessage = "Incorrect Password"; + }); + print(response.statusCode); + } + } catch (e) { + throw Exception('Failed to Update: $e'); + } + } + }, + ), + ], + ); + } + + @override + void dispose() { + oldPasswordController.dispose(); + newPasswordController.dispose(); + reEnterNewPasswordController.dispose(); + super.dispose(); + } +} diff --git a/lib/screens/settings_screen/credits_loading.dart b/lib/screens/settings_screen/credits_loading.dart new file mode 100644 index 0000000..fa4a8c1 --- /dev/null +++ b/lib/screens/settings_screen/credits_loading.dart @@ -0,0 +1,102 @@ +import 'package:fade_shimmer/fade_shimmer.dart'; +import 'package:flutter/material.dart'; + +Widget _creditsloadingTile(BuildContext context) { + List socialLinks = List.generate( + 6, + (index) => Container( + child: const FadeShimmer( + radius: 16.18, + height: 48, + width: 48, + fadeTheme: FadeTheme.light, + ), + padding: const EdgeInsets.all(2), + ), + ); + return Container( + width: MediaQuery.of(context).size.width - 10, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.blueGrey.shade100.withOpacity(0.1618), + borderRadius: const BorderRadius.all(Radius.circular(16.18))), + margin: const EdgeInsets.symmetric(vertical: 3, horizontal: 6.18), + child: Wrap( + direction: Axis.vertical, + children: [ + Container( + width: MediaQuery.of(context).size.width - 48, + padding: const EdgeInsets.all(6.18), + child: Wrap( + alignment: WrapAlignment.spaceBetween, + children: [ + Wrap(direction: Axis.vertical, children: [ + Container( + child: const FadeShimmer( + radius: 16.18, + height: 27, + width: 96, + fadeTheme: FadeTheme.light, + ), + padding: const EdgeInsets.all(2), + ), + Container( + child: const FadeShimmer( + radius: 16.18, + height: 20, + width: 72, + fadeTheme: FadeTheme.light, + ), + padding: const EdgeInsets.all(2), + ), + ]), + Container( + child: const FadeShimmer( + radius: 16.18, + height: 64, + width: 64, + fadeTheme: FadeTheme.light, + ), + ), + ], + ), + ), + Container( + child: const FadeShimmer( + radius: 16.18, + height: 16, + width: 96, + fadeTheme: FadeTheme.light, + ), + padding: const EdgeInsets.all(2), + ), + Container( + height: 72, + width: MediaQuery.of(context).size.width - 48, + padding: const EdgeInsets.all(0), + color: Colors.transparent, + child: ListView.separated( + scrollDirection: Axis.horizontal, + itemBuilder: (_, index) => socialLinks[index], + separatorBuilder: (_, b) => const SizedBox( + width: 16.18, + ), + itemCount: socialLinks.length), + ) + ], + ), + ); +} + +Widget creditsLoadingList(int items, BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 5), + child: ListView.builder( + padding: const EdgeInsets.all(0), + itemBuilder: (_, index) => Padding( + padding: const EdgeInsets.all(5), + child: _creditsloadingTile(context)), + itemCount: items, + ), + ); +} diff --git a/lib/screens/sign_up_screen/.DS_Store b/lib/screens/sign_up_screen/.DS_Store new file mode 100644 index 0000000..da02ee8 Binary files /dev/null and b/lib/screens/sign_up_screen/.DS_Store differ diff --git a/lib/screens/sign_up_screen/CreateAccount.dart b/lib/screens/sign_up_screen/CreateAccount.dart new file mode 100644 index 0000000..bb0876d --- /dev/null +++ b/lib/screens/sign_up_screen/CreateAccount.dart @@ -0,0 +1,263 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter/services.dart'; + +import '../../Utils/size_utils.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/custom_button.dart'; +import '../../widgets/custom_text_form_field.dart'; +import 'SignUpService.dart'; + +class CreateAccountScreen extends StatefulWidget { + CreateAccountScreen({Key? key}) : super(key: key); + + @override + _CreateAccountScreenState createState() => _CreateAccountScreenState(); +} + +class _CreateAccountScreenState extends State { + final SignUpApiService userService = SignUpApiService(); + + final Map formData = {}; + final _formKey = GlobalKey(); + + late BuildContext _context; // Store the current context + late var account_id; // Store the account_id + + bool _isEmailValid = true; + void _validateEmail(String email) { + setState(() { + _isEmailValid = + RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$').hasMatch(email); + }); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + _context = context; // Store the context + + return Scaffold( + appBar: AppBar(title: const Text('Create Account')), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Column( + children: [ + Padding( + padding: getPadding(top: 19), + child: Text("Company Name", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + onsaved: (value) => formData['companyName'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Company Name'; + } + return null; + }, + hintText: "enter Company Name", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputType: TextInputType.text + ), + Padding( + padding: getPadding(top: 19), + child: Text("Email", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + onsaved: (value) => formData['email'] = value, + onChanged: _validateEmail, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Email'; + }else if(!_isEmailValid){ + return 'Please enter a valid email'; + } + return null; + }, + hintText: "enter Email", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputType: TextInputType.text + ), + Padding( + padding: getPadding(top: 19), + child: Text("Mobile Number", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + textInputType: TextInputType.phone, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[0-9]')) + ], + onsaved: (value) => formData['mobile'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Mob No'; + } + return null; + }, + hintText: "enter Mobile Number", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + ), + Padding( + padding: getPadding(top: 19), + child: Text("Workspace", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + onsaved: (value) => formData['workspace'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Workspace'; + } + return null; + }, + hintText: "enter Workspace", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputType: TextInputType.text + ), + Padding( + padding: getPadding(top: 19), + child: Text("Gst Number", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + onsaved: (value) => formData['gstNumber'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Gst Number'; + } + return null; + }, + hintText: "enter Gst Number", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputType: TextInputType.text + ), + Padding( + padding: getPadding(top: 19), + child: Text("pancard", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + onsaved: (value) => formData['pancard'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Pancard'; + } + return null; + }, + hintText: "enter pancard", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputType: TextInputType.text + ), + Padding( + padding: getPadding(top: 19), + child: Text("Working", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + onsaved: (value) => formData['working'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Working'; + } + return null; + }, + hintText: "enter Working", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputType: TextInputType.text + ), + Container( + margin: const EdgeInsets.symmetric(vertical: 5), // Add margin + child: CustomButton( + height: getVerticalSize(50), + width: getHorizontalSize(396), + text: "SUBMIT", + margin: getMargin(top: 25), + onTap: () async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + { + try { + print('form data is $formData'); + + final response = + await userService.createAccount(formData); + + account_id = response['account_id'].toString(); + print( + 'after create account account id is $account_id'); + // ignore: use_build_context_synchronously + Navigator.pop( + _context, account_id); // Pop with account_id + + // Navigator.pop(context); + } catch (e) { + // ignore: use_build_context_synchronously + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Account Creation Failed: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + } + }, + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/sign_up_screen/CreateUser.dart b/lib/screens/sign_up_screen/CreateUser.dart new file mode 100644 index 0000000..2369817 --- /dev/null +++ b/lib/screens/sign_up_screen/CreateUser.dart @@ -0,0 +1,328 @@ +import 'package:flutter/material.dart'; + +import 'SignUpService.dart'; + +class CreateUserScreen extends StatefulWidget { + CreateUserScreen({Key? key}) : super(key: key); + + @override + _CreateUserScreenState createState() => _CreateUserScreenState(); +} + +class _CreateUserScreenState extends State { + int _currentStep = 0; + + // Create a global key for each step + final GlobalKey createAccountKey = + GlobalKey(); + + final GlobalKey emailVerificationKey = + GlobalKey(); + + final GlobalKey registrationKey = + GlobalKey(); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Sign Up - Step ${_currentStep + 1}'), + ), + body: Column( + children: [ + // Display the current step + Expanded( + child: _buildStep(_currentStep), + ), + + // Navigation buttons + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (_currentStep > 0) + ElevatedButton( + onPressed: () { + setState(() { + _currentStep--; + }); + }, + child: const Text('Previous'), + ), + if (_currentStep < 2) + ElevatedButton( + onPressed: () { + _proceedToNextStep(); + }, + child: const Text('Next'), + ), + ], + ), + ], + ), + ); + } + + // Function to build the appropriate step based on the current step index + Widget _buildStep(int stepIndex) { + switch (stepIndex) { + case 0: + return StepCreateAccount( + key: createAccountKey, + onNext: () { + _proceedToNextStep(); + }, + ); + case 1: + return StepGetEmailVerification( + key: emailVerificationKey, + onNext: () { + _proceedToNextStep(); + }, + ); + case 2: + return StepGetRegistration( + key: registrationKey, + onNext: () { + _proceedToNextStep(); + }, + ); + default: + return Container(); // Return an empty container by default + } + } + + // Function to proceed to the next step + void _proceedToNextStep() { + if (_currentStep < 2) { + setState(() { + _currentStep++; + }); + } + } +} + +// Define your individual step widgets here + +class StepCreateAccount extends StatefulWidget { + final Function onNext; + + const StepCreateAccount({Key? key, required this.onNext}) : super(key: key); + + @override + StepCreateAccountState createState() => StepCreateAccountState(); +} + +class StepCreateAccountState extends State { + // Add your state variables for this step here + String? accountId; + final Map formData = {}; + final _formKey = GlobalKey(); + final SignUpApiService userService = SignUpApiService(); + + @override + Widget build(BuildContext context) { + return Container( + alignment: Alignment.center, + child: Column( + children: [ + const Text('Step 1: Create Account'), + TextFormField( + decoration: const InputDecoration(labelText: 'Company Name'), + onSaved: (value) => formData['companyName'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Company Name'; + } + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + decoration: const InputDecoration(labelText: 'Email'), + onSaved: (value) => formData['email'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Email'; + } + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + decoration: const InputDecoration(labelText: 'Mobile No'), + onSaved: (value) => formData['mobile'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Mob No'; + } + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + decoration: const InputDecoration(labelText: 'Workspace'), + onSaved: (value) => formData['workspace'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Workspace'; + } + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + decoration: const InputDecoration(labelText: 'Gst Number'), + onSaved: (value) => formData['gstNumber'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Gst Number'; + } + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + decoration: const InputDecoration(labelText: 'pancard'), + onSaved: (value) => formData['pancard'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Pancard'; + } + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + decoration: const InputDecoration(labelText: 'Working'), + onSaved: (value) => formData['working'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Working'; + } + return null; + }, + ), + const SizedBox(height: 16), + Container( + margin: const EdgeInsets.symmetric(vertical: 5), // Add margin + child: ElevatedButton( + onPressed: () async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + { + try { + print('form data is $formData'); + + final response = + await userService.createAccount(formData); + + accountId = response['account_id'].toString(); + print('after create account account id is $accountId'); + // ignore: use_build_context_synchronously + // Navigator.pop( + // _context, accountId); // Pop with account_id + + // Navigator.pop(context); + } catch (e) { + // ignore: use_build_context_synchronously + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Error'), + content: Text('Account Creation Failed: $e'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + } + } + }, + child: const SizedBox( + width: double.infinity, + height: 50, + child: Center( + child: Text( + 'SUBMIT', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ), + if (accountId != null) Text('Selected Account ID: $accountId'), + ], + ), + ); + } +} + +class StepGetEmailVerification extends StatefulWidget { + final Function onNext; + + const StepGetEmailVerification({Key? key, required this.onNext}) + : super(key: key); + + @override + StepGetEmailVerificationState createState() => + StepGetEmailVerificationState(); +} + +class StepGetEmailVerificationState extends State { + @override + Widget build(BuildContext context) { + return Container( + alignment: Alignment.center, + child: Text('Step 2: Get Email Verification'), + ); + } +} + +class StepGetRegistration extends StatefulWidget { + final Function onNext; + + const StepGetRegistration({Key? key, required this.onNext}) : super(key: key); + + @override + StepGetRegistrationState createState() => StepGetRegistrationState(); +} + +class StepGetRegistrationState extends State { + @override + Widget build(BuildContext context) { + return Container( + alignment: Alignment.center, + child: Text('Step 3: Get Registration'), + ); + } +} + +// Example of a dialog to create an account +class CreateAccountDialog extends StatelessWidget { + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text('Create Account'), + content: Text('Account created successfully!'), + actions: [ + ElevatedButton( + onPressed: () { + Navigator.of(context).pop('12345'); // Pass the created account ID + }, + child: Text('OK'), + ), + ], + ); + } +} diff --git a/lib/screens/sign_up_screen/RegistrationDetails.dart b/lib/screens/sign_up_screen/RegistrationDetails.dart new file mode 100644 index 0000000..0a08069 --- /dev/null +++ b/lib/screens/sign_up_screen/RegistrationDetails.dart @@ -0,0 +1,359 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter/services.dart'; + +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../providers/token_manager.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import '../../widgets/custom_button.dart'; +import '../../widgets/custom_text_form_field.dart'; +import '../Login Screen/login_screen.dart'; +import 'CreateAccount.dart'; +import 'SignUpService.dart'; + +class RegistrationDetailsScreen extends StatefulWidget { + var email; + RegistrationDetailsScreen({required this.email}); + + @override + _RegistrationDetailsScreenState createState() => + _RegistrationDetailsScreenState(); +} + +class _RegistrationDetailsScreenState extends State { + final SignUpApiService userService = SignUpApiService(); + + final Map formData = {}; + final _formKey = GlobalKey(); + + late BuildContext _context; // Store the current context + var account_id = null; // Initialize with null + var selectedAccount; // Use nullable type + + var newPassword = ''; // Store the value of the confirm password field + var confirmPassword = ''; // Store the value of the confirm password field +// Validate that the passwords match + String? _validatePasswordMatch(String value) { + if (value != newPassword) { + print('value is $value and new is $newPassword'); + return 'Passwords do not match'; + } + return null; + } + + bool _newpasswordVisible = false; + bool _confirmpasswordVisible = false; + + bool _isPasswordValid = true; + void _validatePassword(String password) { + setState(() { + _isPasswordValid = password.isNotEmpty; + }); + } + + bool _isEmailValid = true; + void _validateEmail(String email) { + setState(() { + _isEmailValid = + RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$').hasMatch(email); + }); + } + + void showSuccessMessage(String message) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(message), + duration: const Duration(seconds: 2), + backgroundColor: Colors.green, + ), + ); + } + + void showErrorMessage(String error) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(error), + duration: const Duration(seconds: 2), + backgroundColor: Colors.red, + ), + ); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + _context = context; // Store the context + + return Scaffold( + appBar: CustomAppBar( + height: getVerticalSize(54), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleft, + margin: getMargin(left: 16, top: 13, bottom: 17), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "Registration")), + //AppBar(title: const Text('Registration')), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Container( + height: 500, + child: Column( + children: [ + Padding( + padding: getPadding(top: 19), + child: Text("First Name", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + onsaved: (value) => formData['first_name'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter First Name'; + } + return null; + }, + hintText: "enter First Name", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputType: TextInputType.text + ), + Padding( + padding: getPadding(top: 19), + child: Text("Last Name", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + onsaved: (value) => formData['last_name'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Last Name'; + } + return null; + }, + hintText: "enter Last Name", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputType: TextInputType.text + ), + + Padding( + padding: getPadding(top: 19), + child: Text("Mobile Number", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + textInputType: TextInputType.phone, + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[0-9]')) + ], + onsaved: (value) => formData['mob_no'] = value, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Mobile Number'; + } + return null; + }, + hintText: "enter Mobile Number", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + ), + Padding( + padding: getPadding(top: 19), + child: Text("New Password", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "New Password", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputAction: TextInputAction.done, + textInputType:TextInputType.visiblePassword, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Password'; + }else if(!_isPasswordValid){ + return 'Please enter a valid password'; + } + return null; + }, + suffix: IconButton( + icon: Icon( + _newpasswordVisible + ? Icons.visibility + : Icons.visibility_off, + ), + onPressed: () { + setState(() { + _newpasswordVisible = !_newpasswordVisible; + }); + }, + ), + onsaved: (value) => formData['new_password'] = value, + onChanged: (value) { + setState(() { + newPassword = value!; + }); + _validatePassword; + }, + suffixConstraints: BoxConstraints( + maxHeight: getVerticalSize(44)), + isObscureText: !_newpasswordVisible), + + Padding( + padding: getPadding(top: 19), + child: Text("Confirm Password", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium16Bluegray900)), + CustomTextFormField( + focusNode: FocusNode(), + hintText: "Confirm Password", + margin: getMargin(top: 6), + padding: TextFormFieldPadding.PaddingT12, + textInputAction: TextInputAction.done, + textInputType:TextInputType.visiblePassword, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Password'; + } + return _validatePasswordMatch(confirmPassword); + }, + onsaved: (value) => formData['confirm_password'] = value, + onChanged: (value) { + setState(() { + confirmPassword = value!; // Update confirmPassword + }); + }, + suffix: IconButton( + icon: Icon( + _confirmpasswordVisible + ? Icons.visibility + : Icons.visibility_off, + ), + onPressed: () { + setState(() { + _confirmpasswordVisible = !_confirmpasswordVisible; + }); + }, + ), + suffixConstraints: BoxConstraints( + maxHeight: getVerticalSize(44)), + isObscureText: !_confirmpasswordVisible,), + + + Row( + children: [ + const Expanded( + child: Text('Add Account'), + ), + IconButton( + onPressed: () async { + final accountId = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => CreateAccountScreen(), + ), + ); + + if (accountId != null) { + setState(() { + selectedAccount = accountId; + formData['account_id'] = accountId; + account_id = + accountId; // Update the account_id here + }); + } + }, + icon: const Icon(Icons.add), + ), + ], + ), + + if (account_id != null) + Container( + margin: + const EdgeInsets.symmetric(vertical: 5), // Add margin + child: CustomButton( + height: getVerticalSize(50), + width: getHorizontalSize(396), + text: "SUBMIT", + margin: getMargin(top: 25), + onTap: () async { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + + print('formdata is $formData'); + + formData['usrGrpId'] = 46; + formData['account_id'] = account_id; + formData['email'] = widget.email; + + { + final token = await TokenManager.getToken(); + try { + print(formData); + + await userService + .createuser(token!, formData) + .then((_) => { + const LoginScreen(), + }); + + await Future.delayed( + const Duration(seconds: 5)); + + showSuccessMessage('User created successfully'); + // ignore: use_build_context_synchronously + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const LoginScreen())); + // moveToNextStep(); + } catch (e) { + showErrorMessage('Failed to create User: $e'); + } + } + } + }, + ), + ), + ], + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/sign_up_screen/SignUpService.dart b/lib/screens/sign_up_screen/SignUpService.dart new file mode 100644 index 0000000..ce66627 --- /dev/null +++ b/lib/screens/sign_up_screen/SignUpService.dart @@ -0,0 +1,113 @@ +import 'package:dio/dio.dart'; + +import '../../resources/api_constants.dart'; + +class SignUpApiService { + final String baseUrl = ApiConstants.baseUrl; + final Dio dio = Dio(); + +// get all account + Future>> getallAccount(String token) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + final response = await dio.get('$baseUrl/users/sysaccount/sysaccount'); + + final responseData = response.data; + + print('response data is ... $responseData'); + + if (responseData is List) { + // If the response is a list, cast it to the expected type + final entities = responseData.cast>(); + return entities; + } else if (responseData is Map) { + // If the response is a single object, wrap it in a list + return [responseData]; + } else { + // Handle other unexpected response types here + throw Exception('Unexpected response type'); + } + } catch (e) { + throw Exception('Failed to Account: $e'); + } + } + +// Create account + Future> createAccount( + Map entity) async { + try { + // dio.options.headers['Authorization'] = 'Bearer $token'; + final response = await dio + .post('$baseUrl/token/users/sysaccount/savesysaccount', data: entity); + + print(' created account is $response'); + return response.data; + } catch (e) { + throw Exception('Failed To Create Account: $e'); + } + } + +// SEND EMAIL FOR OTP + Future sendEmail(Map entity) async { + try { + print("in post api...$entity"); + // dio.options.headers['Authorization'] = 'Bearer $token'; + await dio.post('$baseUrl/token/user/send_email', data: entity); + print(entity); + } catch (e) { + throw Exception('Failed to Send Email: $e'); + } + } + + // RESEND EMAIL FOR OTP + Future resendEmail(String email) async { + try { + // dio.options.headers['Authorization'] = 'Bearer $token'; + await dio.post('$baseUrl/token/user/resend_otp?email=$email'); + } catch (e) { + throw Exception('Failed to ReSend Email: $e'); + } + } + + // OTP VEFICATION + Future otpverification(String email, String otp) async { + try { + // dio.options.headers['Authorization'] = 'Bearer $token'; + await dio + .post('$baseUrl/token/user/otp_verification?email=$email&otp=$otp'); + } catch (e) { + throw Exception('Failed to Verify Otp: $e'); + } + } + + Future createuser(String token, Map entity) async { + try { + print("in post api...$entity"); + dio.options.headers['Authorization'] = 'Bearer $token'; + await dio.post('$baseUrl/token/addOneAppUser', data: entity); + print(entity); + } catch (e) { + throw Exception('Failed to create User: $e'); + } + } + + Future updateUser( + String token, int entityId, Map entity) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + await dio.put('$baseUrl/api/updateAppUserDto/$entityId', data: entity); + print(entity); + } catch (e) { + throw Exception('Failed to update Backend: $e'); + } + } + + Future deleteUser(String token, int entityId) async { + try { + dio.options.headers['Authorization'] = 'Bearer $token'; + await dio.delete('$baseUrl/api/delete_usr/$entityId'); + } catch (e) { + throw Exception('Failed to delete User: $e'); + } + } +} diff --git a/lib/screens/sign_up_screen/SignUpUser.dart b/lib/screens/sign_up_screen/SignUpUser.dart new file mode 100644 index 0000000..f0a06de --- /dev/null +++ b/lib/screens/sign_up_screen/SignUpUser.dart @@ -0,0 +1,295 @@ +// import 'package:flutter/material.dart'; +// +// import 'package:flutter/services.dart'; +// +// import 'RegistrationDetails.dart'; +// import 'SignUpService.dart'; +// +// enum RegistrationStep { +// SendOTP, +// VerifyOTP, +// EnterUserInfo, +// SelectAccount, +// } +// +// class SignUpUserScreen extends StatefulWidget { +// SignUpUserScreen({Key? key}) : super(key: key); +// +// @override +// _SignUpUserScreenState createState() => _SignUpUserScreenState(); +// } +// +// class _SignUpUserScreenState extends State { +// final SignUpApiService userService = SignUpApiService(); +// +// final GlobalKey _scaffoldKey = GlobalKey(); +// final Map formData = {}; +// final _formKey = GlobalKey(); +// +// var selectedAccount; +// var email; +// var otp; +// var confirmPassword; +// +// bool _passwordVisible = false; +// bool _isPasswordValid = true; +// void _validatePassword(String password) { +// setState(() { +// _isPasswordValid = password.isNotEmpty; +// }); +// } +// +// RegistrationStep currentStep = RegistrationStep.SendOTP; +// +// void moveToNextStep() { +// setState(() { +// if (currentStep == RegistrationStep.SendOTP) { +// currentStep = RegistrationStep.VerifyOTP; +// } else if (currentStep == RegistrationStep.VerifyOTP) { +// currentStep = RegistrationStep.EnterUserInfo; +// } else if (currentStep == RegistrationStep.EnterUserInfo) { +// currentStep = RegistrationStep.SelectAccount; +// } +// }); +// } +// +// void showSuccessMessage(String message) { +// ScaffoldMessenger.of(context).showSnackBar( +// SnackBar( +// content: Text(message), +// duration: const Duration(seconds: 2), +// backgroundColor: Colors.green, +// ), +// ); +// } +// +// void showErrorMessage(String error) { +// ScaffoldMessenger.of(context).showSnackBar( +// SnackBar( +// content: Text(error), +// duration: const Duration(seconds: 2), +// backgroundColor: Colors.red, +// ), +// ); +// } +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// key: _scaffoldKey, +// appBar: AppBar( +// title: const Text('Create User'), +// ), +// body: Builder( +// builder: (BuildContext context) { +// return SingleChildScrollView( +// child: Padding( +// padding: const EdgeInsets.all(16), +// child: Form( +// key: _formKey, +// child: SizedBox( +// height: MediaQuery.of(context).size.height * +// 0.5, // Use 50% of the screen height +// child: ListView.builder( +// itemCount: 1, +// itemBuilder: (BuildContext context, int index) { +// if (currentStep == RegistrationStep.SendOTP) { +// return Column( +// children: [ +// const SizedBox(height: 16), +// TextFormField( +// decoration: +// const InputDecoration(labelText: 'Email'), +// keyboardType: TextInputType.emailAddress, +// onSaved: (value) => email = value, +// validator: (value) { +// if (value == null || value.isEmpty) { +// return 'Please enter Email'; +// } +// return null; +// }, +// ), +// const SizedBox(height: 16), +// Container( +// margin: const EdgeInsets.symmetric(vertical: 5), +// child: ElevatedButton( +// onPressed: () async { +// if (_formKey.currentState!.validate()) { +// _formKey.currentState!.save(); +// +// formData['usrGrpId'] = 46; +// formData['email'] = email; +// try { +// print('send email data is $formData'); +// +// await userService.sendEmail(formData); +// +// await Future.delayed( +// const Duration(seconds: 2)); +// +// moveToNextStep(); +// } catch (e) { +// showErrorMessage( +// 'Failed to send OTP: $e'); +// } +// } +// }, +// child: const SizedBox( +// width: double.infinity, +// height: 50, +// child: Center( +// child: Text( +// 'Send OTP', +// style: TextStyle( +// fontSize: 16, +// fontWeight: FontWeight.w600, +// ), +// ), +// ), +// ), +// ), +// ), +// ], +// ); +// } else if (currentStep == RegistrationStep.VerifyOTP) { +// return Column( +// children: [ +// const SizedBox(height: 16), +// TextFormField( +// decoration: +// const InputDecoration(labelText: 'Email'), +// initialValue: email, +// readOnly: true, +// ), +// const SizedBox(height: 16), +// Row( +// children: [ +// Container( +// height: 100, +// width: 250, +// padding: const EdgeInsets.symmetric( +// horizontal: 16), +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular(10), +// border: Border.all(color: Colors.grey), +// ), +// child: TextFormField( +// decoration: +// const InputDecoration(labelText: 'OTP'), +// onChanged: (value) { +// otp = value; +// }, +// onSaved: (value) => otp = value, +// validator: (value) { +// if (value == null || value.isEmpty) { +// return 'Please enter OTP'; +// } +// return null; +// }, +// ), +// ), +// ElevatedButton( +// onPressed: () async { +// try { +// await userService.resendEmail(email); +// +// await Future.delayed( +// const Duration(seconds: 5)); +// showSuccessMessage('OTP RESEND'); +// } catch (e) { +// showErrorMessage( +// 'Failed to resend OTP: $e'); +// } +// }, +// child: const SizedBox( +// width: 100, +// height: 50, +// child: Center( +// child: Text( +// 'Resend OTP', +// style: TextStyle( +// fontSize: 16, +// fontWeight: FontWeight.w600, +// ), +// ), +// ), +// ), +// ), +// ], +// ), +// const SizedBox(height: 16), +// ElevatedButton( +// onPressed: () async { +// try { +// print('email is $email and otp is $otp'); +// await userService.otpverification(email, otp); +// +// moveToNextStep(); +// showSuccessMessage( +// 'Email verified successfully'); +// } catch (e) { +// showErrorMessage('Failed to verify OTP: $e'); +// } +// }, +// child: const SizedBox( +// width: double.infinity, +// height: 50, +// child: Center( +// child: Text( +// 'VERIFY EMAIL', +// style: TextStyle( +// fontSize: 16, +// fontWeight: FontWeight.w600, +// ), +// ), +// ), +// ), +// ), +// ], +// ); +// } else if (currentStep == +// RegistrationStep.EnterUserInfo) { +// return Column( +// children: [ +// // Other widgets for user information entry +// ElevatedButton( +// onPressed: () async { +// // Navigate to the RegistrationDetailsScreen when the button is pressed +// Navigator.push( +// context, +// MaterialPageRoute( +// builder: (context) => +// RegistrationDetailsScreen(email: email), +// ), +// ); +// }, +// child: const SizedBox( +// width: double.infinity, +// height: 50, +// child: Center( +// child: Text( +// 'Go to Registration Details', +// style: TextStyle( +// fontSize: 16, +// fontWeight: FontWeight.w600, +// ), +// ), +// ), +// ), +// ), +// ], +// ); +// } else { +// return Container(); // Return an empty container if none of the conditions match +// } +// }, +// ), +// ), +// ), +// ), +// ); +// }, +// ), +// ); +// } +// } diff --git a/lib/screens/sign_up_screen/StepGetEmailVerification.dart b/lib/screens/sign_up_screen/StepGetEmailVerification.dart new file mode 100644 index 0000000..a96aa5a --- /dev/null +++ b/lib/screens/sign_up_screen/StepGetEmailVerification.dart @@ -0,0 +1,138 @@ +import 'package:flutter/material.dart'; + +class StepGetEmailVerification extends StatefulWidget { + final LabeledGlobalKey emailPasswordFormKey; + // final Function updateSignUpDetails; + + // final String email; + final Function proceedToNextStep; + const StepGetEmailVerification( + {Key? key, + // required this.updateSignUpDetails, + // required this.email, + required this.emailPasswordFormKey, + required this.proceedToNextStep}) + : super(key: key); + + @override + _StepGetEmailVerificationState createState() => + _StepGetEmailVerificationState(); +} + +class _StepGetEmailVerificationState extends State { + String email = ""; + String emailErrorMessage = ""; + @override + void initState() { + super.initState(); + // email = widget.email; + } + + @override + void dispose() { + // widget.emailPasswordFormKey.currentState?.validate(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Form( + key: widget.emailPasswordFormKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: + Border.all(width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + // initialValue: email, + // validator: _validateNewPassword, + autofocus: mounted, + autocorrect: false, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: + EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15), + hintText: "email", + hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + keyboardType: TextInputType.name, + textInputAction: TextInputAction.next, + ), + ), + if (emailErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + width: double.infinity, + child: Text( + "\t\t\t\t$emailErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + // Email CODE END HERE + ], + )); + } + + // void errorMessageSetter(String fieldName, String message) { + // setState(() { + // switch (fieldName) { + // case 'NEW-PASSWORD': + // new_passwordErrorMessage = message; + // break; + + // case 'CONFIRM-PASSWORD': + // confirm_passwordErrorMessage = message; + // break; + // } + // }); + // } + + // String? _validateNewPassword(String? value) { + // if (value == null || value.isEmpty) { + // errorMessageSetter('NEW-PASSWORD', 'password cannot be empty'); + // } else { + // errorMessageSetter('NEW-PASSWORD', ""); + + // widget.updateSignUpDetails('new_password', value); + // } + // return null; + // } + + // String? _validateConfirmpassword(String? value) { + // if (value == null || value.isEmpty) { + // errorMessageSetter( + // 'CONFIRM-PASSWORD', 'you must provide a valid confirm-password'); + // } else { + // errorMessageSetter('CONFIRM-PASSWORD', ""); + // widget.updateSignUpDetails('confirm_password', value); + // } + + // return null; + // } +} diff --git a/lib/screens/sign_up_screen/StepGetRegistration.dart b/lib/screens/sign_up_screen/StepGetRegistration.dart new file mode 100644 index 0000000..4c4ce15 --- /dev/null +++ b/lib/screens/sign_up_screen/StepGetRegistration.dart @@ -0,0 +1,393 @@ +import 'package:flutter/material.dart'; + +class StepGetRegistration extends StatefulWidget { + final LabeledGlobalKey bankAccountFormKey; + // final Function updateSignUpDetails; + final Function showConfirmSignUpButton; + final Function registrationDetails; + final Function finalStepProccessing; + const StepGetRegistration( + {Key? key, + // required this.updateSignUpDetails, + required this.registrationDetails, + required this.bankAccountFormKey, + required this.showConfirmSignUpButton, + required this.finalStepProccessing}) + : super(key: key); + + @override + _StepGetRegistrationState createState() => _StepGetRegistrationState(); +} + +class _StepGetRegistrationState extends State { + String firstname = ""; + String firstnameErrorMessage = ""; + + String lastName = ""; + String lastNameErrorMessage = ""; + + String mobNo = ""; + String mobNoErrorMessage = ""; + + String password = ""; + String passwordErrorMessage = ""; + + String confirmPassword = ""; + String confirmPasswordErrorMessage = ""; + @override + void initState() { + super.initState(); + Map signUpDetails = widget.registrationDetails(); + if (mounted) { + setState(() { + firstname = signUpDetails['first_name']!; + lastName = signUpDetails['last_name']!; + mobNo = signUpDetails['mob_no']!; + password = signUpDetails['new_password']!; + confirmPassword = signUpDetails['confirm_password']!; + }); + } + } + + @override + void dispose() { + // widget.bankAccountFormKey.currentState?.validate(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Form( + key: widget.bankAccountFormKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: + Border.all(width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + initialValue: firstname, + onChanged: _toggleSignUpButtonVisibility, + // validator: _validateEmailId, + autofocus: mounted, + autocorrect: false, + onFieldSubmitted: (value) { + if (value.isNotEmpty) { + widget.finalStepProccessing(); + } + }, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: + EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15), + hintText: "first name", + hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + ), + if (firstnameErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Text( + "\t\t\t\t$firstnameErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + + // first name code end here + + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: + Border.all(width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + initialValue: lastName, + onChanged: _toggleSignUpButtonVisibility, + // validator: _validateEmailId, + autofocus: mounted, + autocorrect: false, + onFieldSubmitted: (value) { + if (value.isNotEmpty) { + widget.finalStepProccessing(); + } + }, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: + EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15), + hintText: "last name", + hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + ), + if (lastNameErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Text( + "\t\t\t\t$lastNameErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + + // last name code + + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: + Border.all(width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + initialValue: mobNo, + onChanged: _toggleSignUpButtonVisibility, + // validator: _validateEmailId, + autofocus: mounted, + autocorrect: false, + onFieldSubmitted: (value) { + if (value.isNotEmpty) { + widget.finalStepProccessing(); + } + }, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: + EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15), + hintText: "mob no", + hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + ), + if (mobNoErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Text( + "\t\t\t\t$mobNoErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + + // mob no code end + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: + Border.all(width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + initialValue: password, + onChanged: _toggleSignUpButtonVisibility, + // validator: _validateEmailId, + autofocus: mounted, + autocorrect: false, + onFieldSubmitted: (value) { + if (value.isNotEmpty) { + widget.finalStepProccessing(); + } + }, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: + EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15), + hintText: "password", + hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + ), + if (passwordErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Text( + "\t\t\t\t$passwordErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + + // new password code end + + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: + Border.all(width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + initialValue: confirmPassword, + onChanged: _toggleSignUpButtonVisibility, + // validator: _validateEmailId, + autofocus: mounted, + autocorrect: false, + onFieldSubmitted: (value) { + if (value.isNotEmpty) { + widget.finalStepProccessing(); + } + }, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: + EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15), + hintText: "confirmPassword", + hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + ), + if (confirmPasswordErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + child: Text( + "\t\t\t\t$confirmPasswordErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + + // confirm password code end here + ], + )); + } + + // void errorMessageSetter(String fieldName, String message) { + // setState(() { + // switch (fieldName) { + // case 'EMAIL-Id': + // emailErrorMessage = message; + // break; + // } + // }); + // } + + // String? _validateEmailId(String? value) { + // if (value == null || value.isEmpty) { + // errorMessageSetter('EMAIL-ID', 'you must provide a valid email-id'); + // } else if (!validEmailFormat.hasMatch(value)) { + // errorMessageSetter('EMAIL-ID', 'format of your email address is invalid'); + // } else { + // errorMessageSetter('EMAIL-ID', ""); + // widget.updateSignUpDetails('email', value); + // } + + // return null; + // } + + void _toggleSignUpButtonVisibility(String value) { + widget.registrationDetails('confirmPassword', value); + if (value.isNotEmpty) { + widget.showConfirmSignUpButton(true); + } else { + widget.showConfirmSignUpButton(false); + } + } +} diff --git a/lib/screens/sign_up_screen/sign_up_screen.dart b/lib/screens/sign_up_screen/sign_up_screen.dart new file mode 100644 index 0000000..69c189f --- /dev/null +++ b/lib/screens/sign_up_screen/sign_up_screen.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; + +import 'sign_up_steps.dart'; + +class SignUpScreen extends StatefulWidget { + const SignUpScreen({Key? key}) : super(key: key); + + @override + _SignUpScreenState createState() => _SignUpScreenState(); +} + +class _SignUpScreenState extends State { + @override + Widget build(BuildContext context) { + return WillPopScope( + child: Scaffold( + body: SingleChildScrollView( + padding: const EdgeInsets.all(45), + child: Column( + children: [ + const SizedBox( + height: 16, + ), + SizedBox( + height: 30, + child: Image.asset('/images/hadwin_system/cldnsure.png'), + ), + const SizedBox( + height: 30, + ), + const SignUpSteps(), // GO TO SIGN UP FORM + const SizedBox( + height: 27, + ), + SizedBox( + width: double.infinity, + height: 16, + child: Center( + child: InkWell( + child: const Text( + 'Already have an account? Sign in', + style: + TextStyle(fontSize: 14, color: Color(0xFF929BAB)), + ), + onTap: () { + Navigator.pop(context); + }, + ), + ), + ), + const SizedBox( + height: 3, + ) + ], + ), + ), + ), + onWillPop: () => Future.value(false)); + } +} diff --git a/lib/screens/sign_up_screen/sign_up_step_1.dart b/lib/screens/sign_up_screen/sign_up_step_1.dart new file mode 100644 index 0000000..36be82c --- /dev/null +++ b/lib/screens/sign_up_screen/sign_up_step_1.dart @@ -0,0 +1,398 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter/services.dart'; +import 'package:pinput/pinput.dart'; + +import '../../Utils/color_constants.dart'; +import '../../Utils/image_constant.dart'; +import '../../Utils/size_utils.dart'; +import '../../theme/app_style.dart'; +import '../../widgets/app_bar/appbar_image.dart'; +import '../../widgets/app_bar/appbar_title.dart'; +import '../../widgets/app_bar/custom_app_bar.dart'; +import '../../widgets/custom_button.dart'; +import '../../widgets/custom_image_view.dart'; +import '../../widgets/custom_text_form_field.dart'; +import 'RegistrationDetails.dart'; +import 'SignUpService.dart'; + +enum RegistrationStep { + SendOTP, + VerifyOTP, + EnterUserInfo, + SelectAccount, +} + +class SignUpUserScreenNew extends StatefulWidget { + SignUpUserScreenNew({Key? key}) : super(key: key); + + @override + _SignUpUserScreenState createState() => _SignUpUserScreenState(); +} + +class _SignUpUserScreenState extends State { + final SignUpApiService userService = SignUpApiService(); + + final GlobalKey _scaffoldKey = GlobalKey(); + final Map formData = {}; + final _formKey = GlobalKey(); + + var selectedAccount; + TextEditingController emailcontroller = TextEditingController(); + var email; + var otp; + var confirmPassword; + + bool _passwordVisible = false; + bool _isPasswordValid = true; + void _validatePassword(String password) { + setState(() { + _isPasswordValid = password.isNotEmpty; + }); + } + + RegistrationStep currentStep = RegistrationStep.SendOTP; + + void moveToNextStep() { + setState(() { + if (currentStep == RegistrationStep.SendOTP) { + currentStep = RegistrationStep.VerifyOTP; + } else if (currentStep == RegistrationStep.VerifyOTP) { + currentStep = RegistrationStep.EnterUserInfo; + } else if (currentStep == RegistrationStep.EnterUserInfo) { + currentStep = RegistrationStep.SelectAccount; + } + }); + } + + void showSuccessMessage(String message) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(message), + duration: const Duration(seconds: 2), + backgroundColor: Colors.green, + ), + ); + } + + void showErrorMessage(String error) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(error), + duration: const Duration(seconds: 2), + backgroundColor: Colors.red, + ), + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + key: _scaffoldKey, + appBar: CustomAppBar( + height: getVerticalSize(54), + leadingWidth: 40, + leading: AppbarImage( + height: getSize(24), + width: getSize(24), + svgPath: ImageConstant.imgArrowleft, + margin: getMargin(left: 16, top: 13, bottom: 17), + onTap: () { + Navigator.pop(context); + }), + centerTitle: true, + title: AppbarTitle(text: "Create User")), + body: Builder( + builder: (BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: _formKey, + child: SizedBox( + height: MediaQuery.of(context).size.height * + 0.5, // Use 50% of the screen height + child: ListView.builder( + itemCount: 1, + itemBuilder: (BuildContext context, int index) { + if(currentStep == RegistrationStep.SendOTP) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text("Email", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16Bluegray900), + CustomTextFormField( + focusNode: FocusNode(), + controller: emailcontroller, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter Email'; + } + return null; + }, + hintText: "Enter Your Email", + margin: getMargin(top: 7), + textInputType: TextInputType.emailAddress), + CustomButton( + height: getVerticalSize(50), + width: getHorizontalSize(396), + text: "Send OTP", + margin: getMargin(top: 25), + onTap: () async { + + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + + formData['usrGrpId'] = 46; + formData['email'] = emailcontroller.text; + try { + print('send email data is $formData'); + + await userService.sendEmail(formData); + + await Future.delayed( + const Duration(seconds: 2)); + + moveToNextStep(); + } catch (e) { + showErrorMessage( + 'Failed to send OTP: $e'); + } + } + + }, + ), + Align( + alignment: Alignment.center, + child: Padding( + padding: getPadding(top: 28, bottom: 5), + child: RichText( + text: TextSpan(children: [ + TextSpan( + text: "", + style: TextStyle( + color: ColorConstant.fromHex( + "#ff12282a"), + fontSize: getFontSize(16), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400)), + TextSpan( + text: " ", + style: TextStyle( + color: ColorConstant.fromHex( + "#ff12282a"), + fontSize: getFontSize(16), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700)), + TextSpan( + text: "", + style: TextStyle( + color: ColorConstant.fromHex( + "#ff0061ff"), + fontSize: getFontSize(16), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + decoration: + TextDecoration.underline)) + ]), + textAlign: TextAlign.left))) + ]); + } + else if(currentStep == RegistrationStep.VerifyOTP) { + return Container( + width: double.maxFinite, + padding: getPadding( + left: 16, + top: 76, + right: 16, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + CustomImageView( + svgPath: ImageConstant.imgMobile, + height: getVerticalSize( + 82, + ), + width: getHorizontalSize( + 51, + ), + ), + Padding( + padding: getPadding( + top: 29, + ), + child: Text( + "Email Verification", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroySemiBold24, + ), + ), + Container( + width: getHorizontalSize( + 302, + ), + margin: getMargin( + left: 46, + top: 19, + right: 46, + ), + child: Text( + "A mail with a 6-digit verification code was just sent to ${emailcontroller.text}", + maxLines: null, + textAlign: TextAlign.center, + style: AppStyle.txtGilroyMedium16, + ), + ), + Pinput( + length: 6, + showCursor: true, + defaultPinTheme: PinTheme( + width: 50, + height: 50, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + border: Border.all( + color: ColorConstant.blue50, + ), + ), + textStyle: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + ), + ), + onCompleted: (value) { + setState(() { + otp = value; + }); + }, + ), + + CustomButton( + height: getVerticalSize( + 50, + ), + text: "Next", + margin: getMargin( + top: 40, + ), + onTap: () async { + try { + print('email is $email and otp is $otp'); + await userService.otpverification(emailcontroller.text, otp); + + moveToNextStep(); + showSuccessMessage( + 'Email verified successfully'); + } catch (e) { + showErrorMessage('Failed to verify OTP: $e'); + } + }, + ), + GestureDetector( + onTap: () async { + try { + await userService.resendEmail(email); + + await Future.delayed( + const Duration(seconds: 5)); + showSuccessMessage('OTP RESEND'); + } catch (e) { + showErrorMessage( + 'Failed to resend OTP: $e'); + } + }, + child: Padding( + padding: getPadding(top: 3), + child: Text("Forgot Password?", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: + AppStyle.txtGilroyMedium14BlueA700)), + ), + + + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: getPadding( + top: 18, + bottom: 5, + ), + child: Row( + children: [ + Padding( + padding: getPadding( + top: 2, + ), + child: Text( + "Didn’t get the code?", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroyMedium16, + ), + ), + Padding( + padding: getPadding( + left: 12, + bottom: 1, + ), + child: Text( + "Resend", + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroySemiBold16BlueA700, + ), + ), + ], + ), + ), + ), + ], + ), + ); + } + else if (currentStep == + RegistrationStep.EnterUserInfo) { + return Column( + children: [ + CustomButton( + height: getVerticalSize( + 50, + ), + text: "Go to Registration Details", + margin: getMargin( + top: 40, + ), + onTap: () async { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + RegistrationDetailsScreen(email: emailcontroller.text), + ), + ); + }, + ), + ], + ); + } + else{ + return Container(); + } + }, + ), + ), + ), + ), + ); + }, + ), + ); + } + +} diff --git a/lib/screens/sign_up_screen/sign_up_steps.dart b/lib/screens/sign_up_screen/sign_up_steps.dart new file mode 100644 index 0000000..2c0f55f --- /dev/null +++ b/lib/screens/sign_up_screen/sign_up_steps.dart @@ -0,0 +1,545 @@ +import 'package:fluentui_system_icons/fluentui_system_icons.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +import '../../hadwin_components.dart'; +import '../../utilities/slide_right_route.dart'; +import '../Login Screen/login_screen.dart'; +import 'StepGetEmailVerification.dart'; +import 'StepGetRegistration.dart'; +import 'step_createAccount.dart'; + +class SignUpSteps extends StatefulWidget { + const SignUpSteps({Key? key}) : super(key: key); + + @override + _SignUpStepsState createState() => _SignUpStepsState(); +} + +class _SignUpStepsState extends State { + late PageController _signUpStepController; + final createAccountFormKey = LabeledGlobalKey("reateAccountForm"); + final emailVerificationFormKey = + LabeledGlobalKey("emailVerificationForm"); + final signUpFormKey = LabeledGlobalKey("signUpForm"); + Map accountDetails = { + 'companyName': '', + 'email': '', + 'mobile': '', + 'workspace': '', + 'gstNumber': '', + 'pancard': '', + }; + Map registrationDetails = { + 'first_name': '', + 'last_name': '', + 'mob_no': '', + 'new_password': '', + 'confirm_password': '', + }; + Map accountsDetails() => accountDetails; + Map registraionDetails() => registrationDetails; + String? email; + + int _currentStep = 0; + List stepHasError = [false, false, false]; + List stepCompletedSuccessfully = [false, false, false]; + late List signUpStepContent; + bool confirmSignUpButton = false; + @override + void initState() { + _signUpStepController = PageController(); + signUpStepContent = [ + StepCreateAccount( + registrationDetails: accountsDetails, + // updateSignUpDetails: updateSignUpDetails, + nameAddressFormKey: createAccountFormKey, + proceedToNextStep: _proceedToNextStep, + ), + StepGetEmailVerification( + // updateSignUpDetails: updateSignUpDetails, + emailPasswordFormKey: emailVerificationFormKey, + // registrationDetails: registraionDetails, + proceedToNextStep: _proceedToNextStep, + ), + StepGetRegistration( + // updateSignUpDetails: updateSignUpDetails, + bankAccountFormKey: signUpFormKey, + registrationDetails: registraionDetails, + showConfirmSignUpButton: showConfirmSignUpButton, + finalStepProccessing: _finalStepProccessing, + ) + ]; + + super.initState(); + } + + @override + void dispose() { + _signUpStepController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + child: Column( + children: [ + SizedBox( + width: double.infinity, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [0, 1, 2] + .map((e) => Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + GestureDetector( + onTap: () => changeStepOnTap(e), + child: CircleAvatar( + backgroundColor: stepHasError[e] + ? Colors.red.shade600 + : !stepCompletedSuccessfully[e] + ? const Color(0xffF5F7FA) + : Colors.green.shade600, + foregroundColor: !stepCompletedSuccessfully[e] + ? const Color(0xFF0070BA) + : Colors.white, + radius: 18, + child: stepHasError[e] + ? const Icon( + FluentIcons.warning_16_filled, + color: Colors.white, + ) + : stepCompletedSuccessfully[e] + ? const Icon( + FluentIcons.checkmark_16_regular) + : _currentStep == e + ? const Icon( + FluentIcons.edit_16_filled) + : Text("${e + 1}")), + ), + if (e < 2) + Container( + height: 10, + width: 70, + color: stepCompletedSuccessfully[e] + ? Colors.green.shade600 + : Colors.transparent, + ), + ], + )) + .toList(), + ), + ), + const SizedBox( + height: 50, + ), + SizedBox( + width: double.infinity, + height: _currentStep == 2 ? 230 : 300, + child: PageView( + clipBehavior: Clip.none, + controller: _signUpStepController, + physics: const NeverScrollableScrollPhysics(), + children: signUpStepContent, + ), + ), + if (_currentStep == 2) + Padding( + padding: + const EdgeInsets.symmetric(vertical: 3.6, horizontal: 10), + child: RichText( + text: TextSpan( + text: 'By signing up you are agreeing to the ', + style: const TextStyle( + fontSize: 14, color: Color(0xFF929BAB)), + children: [ + TextSpan( + text: 'Terms & Conditions', + style: const TextStyle( + fontSize: 14, color: Colors.blue), + recognizer: TapGestureRecognizer() + ..onTap = () { + FocusManager.instance.primaryFocus?.unfocus(); + Future.delayed( + const Duration(milliseconds: 300), + () => Navigator.push( + context, + SlideRightRoute( + page: const HadWinMarkdownViewer( + screenName: "Terms & Conditons", + urlRequested: + 'https://raw.githubusercontent.com/brownboycodes/HADWIN/master/docs/TERMS_AND_CONDITIONS.md', + )))); + }), + const TextSpan( + text: ' and our ', + style: + TextStyle(fontSize: 14, color: Color(0xFF929BAB)), + ), + TextSpan( + text: 'End User License Agreement', + style: const TextStyle( + fontSize: 14, color: Colors.blue), + recognizer: TapGestureRecognizer() + ..onTap = () { + FocusManager.instance.primaryFocus?.unfocus(); + Future.delayed( + const Duration(milliseconds: 300), + () => Navigator.push( + context, + SlideRightRoute( + page: const HadWinMarkdownViewer( + screenName: + "End User License Agreement", + urlRequested: + 'https://raw.githubusercontent.com/brownboycodes/HADWIN/master/docs/END_USER_LICENSE_AGREEMENT.md', + )))); + }) + ]))), + confirmSignUpButton + ? Container( + margin: const EdgeInsets.symmetric(vertical: 16.0), + width: double.infinity, + height: 64, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.blueGrey.shade100, + offset: const Offset(0, 4), + blurRadius: 5.0) + ], + gradient: const RadialGradient( + colors: [Color(0xff0070BA), Color(0xff1546A0)], + radius: 8.4, + center: Alignment(-0.24, -0.36)), + borderRadius: BorderRadius.circular(20), + ), + child: ElevatedButton( + onPressed: _finalStepProccessing, + style: ElevatedButton.styleFrom( + primary: Colors.transparent, + shadowColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20)), + ), + child: const Text( + 'Create Your Account', + style: TextStyle( + fontSize: 16, fontWeight: FontWeight.w600), + )), + ) + : Row( + children: [ + if (_currentStep > 0 && confirmSignUpButton == false) + Container( + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular(20), + ), + child: TextButton( + onPressed: _goBackToPreviousStep, + style: TextButton.styleFrom( + primary: Colors.transparent, + shadowColor: Colors.transparent, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20)), + ), + child: const Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 3.2, + children: [ + Icon( + FluentIcons.arrow_left_16_filled, + color: Colors.blue, + size: 18, + ), + Text( + 'Back', + style: TextStyle( + color: Colors.blue, fontSize: 16), + ), + ])), + ), + const Spacer(), + if (_currentStep < signUpStepContent.length - 1) + Container( + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular(20), + ), + child: TextButton( + onPressed: _proceedToNextStep, + style: TextButton.styleFrom( + primary: Colors.transparent, + shadowColor: Colors.transparent, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20)), + ), + child: const Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 3.2, + children: [ + Text( + 'Next', + style: TextStyle( + color: Colors.blue, fontSize: 16), + ), + Icon( + FluentIcons.arrow_right_16_filled, + color: Colors.blue, + size: 18, + ) + ])), + ), + ], + ), + ], + )); + } + + void _finalStepProccessing() { + FocusManager.instance.primaryFocus?.unfocus(); + _performErrorCheck(_currentStep + 1); + + if (stepHasError[_currentStep] == false && mounted) { + ScaffoldMessenger.of(context) + .showSnackBar( + const SnackBar( + content: Text('Processing'), + backgroundColor: Colors.blue, + // onVisible: _tryRegistering, + ), + ) + .closed + .then((value) => _tryRegistering()); + } + } + +//? FUNCTION TO GO BACK TO PREVIOUS STEP OF THE CURRENT STEP + void _goBackToPreviousStep() { + FocusManager.instance.primaryFocus?.unfocus(); + _performErrorCheck(_currentStep - 1); + if (_currentStep > 0) { + _signUpStepController.animateToPage(_currentStep - 1, + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOutCubic); + setState(() { + _currentStep--; + }); + } + } + +//? FUNCTION TO MOVE TO THE NEXT STEP FROM THE CURRENT STEP + void _proceedToNextStep() { + FocusManager.instance.primaryFocus?.unfocus(); + _performErrorCheck(_currentStep + 1); + + print(stepHasError[_currentStep]); + print(_currentStep); + + if (stepHasError[_currentStep] == false) { + if (_currentStep < signUpStepContent.length - 1) { + _signUpStepController.animateToPage(_currentStep + 1, + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOutCubic); + + setState(() { + _currentStep++; + }); + } + } + } + +//? FUNCTION TO UPDATE SIGN UP DETAILS + // void updateSignUpDetails(String key, String value) { + // setState(() { + // signUpDetails[key] = value; + // }); + // } + +//? FUNCTION TO TOGGLE VISIBILITY OF SIGN UP BUTTON + void showConfirmSignUpButton(bool value) { + if (value != confirmSignUpButton) { + setState(() { + confirmSignUpButton = value; + }); + } + } + +//? FUNCTION TO CHECK FOR ERRORS IN ANY STEPS PRIOR FROM THE ONE REQUESTED + void _performErrorCheck(int requestedIndex) { + if (_currentStep < requestedIndex) { + for (var i = 0; i < requestedIndex; i++) { + bool errorStatus = false; + switch (i) { + case 0: + createAccountFormKey.currentState?.validate(); + if (accountDetails["companyName"]!.isEmpty || + accountDetails['email']!.isEmpty || + accountDetails['mobile']!.isEmpty || + accountDetails['workspace']!.isEmpty || + accountDetails['gstNumber']!.isEmpty || + accountDetails['pancard']!.isEmpty || + accountDetails['working']!.isEmpty) { + errorStatus = true; + } + + break; + case 1: + emailVerificationFormKey.currentState?.validate(); + if (stepCompletedSuccessfully[1]) { + errorStatus = false; + } else if (stepCompletedSuccessfully[0] && _currentStep == 1) { + // emailPasswordFormKey.currentState?.validate(); + if (email!.isEmpty) { + errorStatus = true; + } + } else { + errorStatus = true; + } + break; + case 2: + signUpFormKey.currentState?.validate(); + if (email!.isEmpty) { + errorStatus = true; + } + + break; + } + + setState(() { + stepHasError[i] = errorStatus; + stepCompletedSuccessfully[i] = !stepHasError[i]; + }); + if (errorStatus) { + break; + } + } + } else { + for (var i = _currentStep; i >= 0; i--) { + bool errorStatus = false; + switch (i) { + case 0: + createAccountFormKey.currentState?.validate(); + if (accountDetails["companyName"]!.isEmpty || + accountDetails['email']!.isEmpty || + accountDetails['mobile']!.isEmpty || + accountDetails['workspace']!.isEmpty || + accountDetails['gstNumber']!.isEmpty || + accountDetails['pancard']!.isEmpty || + accountDetails['working']!.isEmpty) { + errorStatus = true; + } + + break; + case 1: + emailVerificationFormKey.currentState?.validate(); + if (stepCompletedSuccessfully[1]) { + errorStatus = false; + } else if (stepCompletedSuccessfully[0] && _currentStep == 1) { + // emailPasswordFormKey.currentState?.validate(); + if (email!.isEmpty) { + errorStatus = true; + } + } else { + errorStatus = true; + } + break; + case 2: + signUpFormKey.currentState?.validate(); + if (registrationDetails["first_name"]!.isEmpty || + registrationDetails["last_name"]!.isEmpty || + registrationDetails["mob_no"]!.isEmpty || + registrationDetails["new_password"]!.isEmpty || + registrationDetails["confirm_password"]!.isEmpty) { + errorStatus = true; + } + + break; + } + + setState(() { + stepHasError[i] = errorStatus; + stepCompletedSuccessfully[i] = !stepHasError[i]; + }); + if (errorStatus) { + break; + } + } + } + } + + void _tryRegistering() { + sendData(urlPath: '/token/addOneAppUser', data: registrationDetails) + .then((response) { + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + + if (response.keys.join().toLowerCase().contains("error")) { + showErrorAlert(context, response); + } else { + print('Account succesfully created'); + + ScaffoldMessenger.of(context) + .showSnackBar(const SnackBar( + content: Text("Account Created Successfully"), + backgroundColor: Colors.green)) + .closed + .then((value) => Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute(builder: (context) => const LoginScreen()), + (route) => false)); + // Navigator.of(context).pushAndRemoveUntil( + // MaterialPageRoute( + // builder: (context) => ChooseUsername( + // userAuthKey: response['authorization_token'], + // userData: response['user'], + // )), + // (route) => false); + } + }); + } + +//? FUNCTION TO CHANGE STEP ON TAPPING THE OVERHEAD STEP NUMBERS + void changeStepOnTap(int requestedIndex) { + FocusManager.instance.primaryFocus?.unfocus(); + + if (requestedIndex < _currentStep) { + _signUpStepController.animateToPage(requestedIndex, + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOutCubic); + + _performErrorCheck(requestedIndex); + setState(() { + _currentStep = requestedIndex; + }); + } else if (requestedIndex > _currentStep && + requestedIndex != _currentStep) { + _performErrorCheck(requestedIndex); + + if (!stepHasError.sublist(0, requestedIndex).contains(true)) { + if (_currentStep < signUpStepContent.length - 1) { + _signUpStepController.animateToPage(requestedIndex, + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOutCubic); + + setState(() { + _currentStep = requestedIndex; + }); + } + } else { + int stepWithError = + stepHasError.sublist(0, requestedIndex).indexOf(true); + _signUpStepController.animateToPage(stepWithError, + duration: const Duration(milliseconds: 500), + curve: Curves.easeInOutCubic); + + setState(() { + _currentStep = stepWithError; + }); + } + } + } +} diff --git a/lib/screens/sign_up_screen/step_createAccount.dart b/lib/screens/sign_up_screen/step_createAccount.dart new file mode 100644 index 0000000..d0421a0 --- /dev/null +++ b/lib/screens/sign_up_screen/step_createAccount.dart @@ -0,0 +1,555 @@ +import 'package:flutter/material.dart'; + +class StepCreateAccount extends StatefulWidget { + final LabeledGlobalKey nameAddressFormKey; + // final Function updateSignUpDetails; + + final Function registrationDetails; + final Function proceedToNextStep; + const StepCreateAccount( + {Key? key, + // required this.updateSignUpDetails, + required this.nameAddressFormKey, + required this.registrationDetails, + required this.proceedToNextStep}) + : super(key: key); + + @override + _StepCreateAccountState createState() => _StepCreateAccountState(); +} + +class _StepCreateAccountState extends State { + String companyName = ""; + String companyNameErrorMessage = ""; + String email = ""; + String emailErrorMessage = ""; + RegExp validEmailFormat = RegExp( + r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+"); + + String mobNo = ""; + String mobNoErrorMessage = ""; + + String workspace = ""; + String workspaceErrorMessage = ""; + + String gstNumber = ""; + String gstNumberErrorMessage = ""; + + String pancard = ""; + String pancardErrorMessage = ""; + + String working = ""; + String workingErrorMessage = ""; + + @override + void initState() { + super.initState(); + Map signUpDetails = widget.registrationDetails(); + if (mounted) { + setState(() { + companyName = signUpDetails['companyName'].toString(); + email = signUpDetails['email'].toString(); + mobNo = signUpDetails['mobile'].toString(); + workspace = signUpDetails['workspace'].toString(); + gstNumber = signUpDetails['gstNumber'].toString(); + pancard = signUpDetails['pancard'].toString(); + working = signUpDetails['working'].toString(); + }); + } + } + + @override + void dispose() { + // widget.nameAddressFormKey.currentState?.validate(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Form( + key: widget.nameAddressFormKey, + child: Column( + children: [ + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + // initialValue: companyName, + validator: _validatecompanyName, + autofocus: mounted, + autocorrect: false, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15, bottom: 11, top: 11, right: 15), + hintText: "Company_Name", + hintStyle: + TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: + const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + keyboardType: TextInputType.name, + textInputAction: TextInputAction.next, + ), + ), + if (companyNameErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + width: double.infinity, + child: Text( + "\t\t\t\t$companyNameErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + // COMPANY NAME CODE END HERE + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + // initialValue: email, + // validator: _validatelastName, + autofocus: mounted, + autocorrect: false, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15, bottom: 11, top: 11, right: 15), + hintText: "email", + hintStyle: + TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: + const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + keyboardType: TextInputType.name, + textInputAction: TextInputAction.next, + ), + ), + if (emailErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + width: double.infinity, + child: Text( + "\t\t\t\t$emailErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + + // input field for email name ends here + + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + // initialValue: mobNo, + // validator: _validatemobno, + autofocus: mounted, + autocorrect: false, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15, bottom: 11, top: 11, right: 15), + hintText: "mob_no", + hintStyle: + TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: + const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + keyboardType: TextInputType.name, + textInputAction: TextInputAction.next, + onFieldSubmitted: (_) => widget.proceedToNextStep(), + ), + ), + if (mobNoErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + width: double.infinity, + child: Text( + "\t\t\t\t$mobNoErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + // input field for Mob No ends here + + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + // initialValue: workspace, + // validator: _validatelastName, + autofocus: mounted, + autocorrect: false, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15, bottom: 11, top: 11, right: 15), + hintText: "workspace", + hintStyle: + TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: + const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + keyboardType: TextInputType.name, + textInputAction: TextInputAction.next, + ), + ), + if (workspaceErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + width: double.infinity, + child: Text( + "\t\t\t\t$workspaceErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + // workspace code end + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + // initialValue: gstNumber, + // validator: _validatelastName, + autofocus: mounted, + autocorrect: false, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15, bottom: 11, top: 11, right: 15), + hintText: "gst number", + hintStyle: + TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: + const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + keyboardType: TextInputType.name, + textInputAction: TextInputAction.next, + ), + ), + if (gstNumberErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + width: double.infinity, + child: Text( + "\t\t\t\t$gstNumberErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + // gst number code end here + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + // initialValue: pancard, + // validator: _validatelastName, + autofocus: mounted, + autocorrect: false, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15, bottom: 11, top: 11, right: 15), + hintText: "pancard", + hintStyle: + TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: + const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + keyboardType: TextInputType.name, + textInputAction: TextInputAction.next, + ), + ), + if (pancardErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + width: double.infinity, + child: Text( + "\t\t\t\t$pancardErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + // pancard end here + Container( + width: double.infinity, + margin: const EdgeInsets.all(5), + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + width: 1.0, color: const Color(0xFFF5F7FA)), + borderRadius: BorderRadius.circular(20), + boxShadow: [ + const BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: Offset(-4, -4), + color: Colors.white38), + BoxShadow( + blurRadius: 6.18, + spreadRadius: 0.618, + offset: const Offset(4, 4), + color: Colors.blueGrey.shade100) + ]), + child: TextFormField( + // initialValue: working, + // validator: _validatelastName, + autofocus: mounted, + autocorrect: false, + decoration: const InputDecoration( + fillColor: Colors.white, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + errorBorder: InputBorder.none, + disabledBorder: InputBorder.none, + contentPadding: EdgeInsets.only( + left: 15, bottom: 11, top: 11, right: 15), + hintText: "working", + hintStyle: + TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + ), + style: + const TextStyle(fontSize: 16, color: Color(0xFF929BAB)), + keyboardType: TextInputType.name, + textInputAction: TextInputAction.next, + ), + ), + if (workingErrorMessage != '') + Container( + margin: const EdgeInsets.all(2), + padding: const EdgeInsets.all(2), + width: double.infinity, + child: Text( + "\t\t\t\t$workingErrorMessage", + style: const TextStyle(fontSize: 10, color: Colors.red), + ), + ), + ], + )), + ), + ); + } + + void errorMessageSetter(String fieldName, String message) { + setState(() { + switch (fieldName) { + case 'COMPANY_NAME': + companyNameErrorMessage = message; + break; + + // case 'LAST-NAME': + // last_nameErrorMessage = message; + // break; + + // case 'MOB-NO': + // mob_noErrorMessage = message; + // break; + } + }); + } + + String? _validatecompanyName(String? value) { + if (value == null || value.isEmpty) { + errorMessageSetter('COMPANY_NAME', 'you must provide your Company name'); + } else if (value.length > 100) { + errorMessageSetter( + 'COMPANY_NAME', 'name cannot contain more than 100 characters'); + } else { + errorMessageSetter('COMPANY_NAME', ""); + + // widget.updateSignUpDetails('first_name', value); + } + + return null; + } + + // String? _validatelastName(String? value) { + // if (value == null || value.isEmpty) { + // errorMessageSetter('LAST-NAME', 'you must provide your last name'); + // } else if (value.length > 100) { + // errorMessageSetter( + // 'LAST-NAME', 'name cannot contain more than 100 characters'); + // } else { + // errorMessageSetter('LAST-NAME', ""); + + // widget.updateSignUpDetails('last_name', value); + // } + + // return null; + // } + + // String? _validatemobno(String? value) { + // if (value == null || value.isEmpty) { + // errorMessageSetter('MOB-NO', 'you must provide your MOB-NO'); + // } else if (value.length > 100) { + // errorMessageSetter( + // 'MOB-NO', 'name cannot contain more than 100 characters'); + // } else { + // errorMessageSetter('MOB-NO', ""); + + // widget.updateSignUpDetails('mob_no', value); + // } + + // return null; + // } + + // String? _validateAddress(String? value) { + // if (value == null || value.isEmpty) { + // errorMessageSetter( + // 'RESIDENTIAL-ADDRESS', 'you must provide your residential address'); + // } else if (value.length > 300) { + // errorMessageSetter('RESIDENTIAL-ADDRESS', + // 'address cannot contain more than 300 characters'); + // } else { + // errorMessageSetter('RESIDENTIAL-ADDRESS', ""); + + // widget.updateSignUpDetails('address', value); + // } + + // return null; + // } +} diff --git a/lib/screens/splash_screen/splash_screen.dart b/lib/screens/splash_screen/splash_screen.dart new file mode 100644 index 0000000..9b21d5e --- /dev/null +++ b/lib/screens/splash_screen/splash_screen.dart @@ -0,0 +1,84 @@ +import 'dart:convert'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import '../Login Screen/login_screen.dart'; +import '../main_app_screen/tabbed_layout_component.dart'; + +class SplashScreen extends StatefulWidget { + const SplashScreen({super.key}); + + @override + State createState() => _SplashScreenState(); +} + +class _SplashScreenState extends State { + var isLogin = false; + + Map userData = {}; + + + + Future checkifLogin() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + bool? isLoggedIn = prefs.getBool('isLoggedIn'); + var userdatastr = prefs.getString('userData'); + + if (kDebugMode) { + print('userData....$userdatastr'); + } + if (isLoggedIn != null && isLoggedIn) { + setState(() { + isLogin = true; + }); + } + + if (userdatastr != null) { + try{ + userData = json.decode(userdatastr); + if (kDebugMode) { + print(userData['token']); + } + }catch(e){ + if (kDebugMode) { + print("error is ..................$e"); + } + } + + } else { + setState(() { + isLogin = false; + }); + } + } + + @override + void initState() { + checkifLogin().then((value) async => { + Future.delayed(const Duration(seconds: 2), () { + Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => isLogin + ? TabbedLayoutComponent(): const LoginScreen() + ),); + }) + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SingleChildScrollView( + child: Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + child: Center( + child: SvgPicture.asset( + 'assets/images/cloudnsuresp.svg', + width: 100, + ), + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/theme/app_decoration.dart b/lib/theme/app_decoration.dart new file mode 100644 index 0000000..c678d04 --- /dev/null +++ b/lib/theme/app_decoration.dart @@ -0,0 +1,480 @@ +import 'package:flutter/material.dart'; + +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; + + +class AppDecoration { + static BoxDecoration get fillBlue5001 => BoxDecoration( + color: ColorConstant.blue5001, + ); + static BoxDecoration get outlineGray5002 => BoxDecoration( + color: ColorConstant.gray5002, + border: Border.all( + color: ColorConstant.gray5002, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get outlineBlueA70001 => BoxDecoration( + border: Border.all( + color: ColorConstant.blueA70001, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get outlineGray60026 => BoxDecoration( + color: ColorConstant.whiteA700, + boxShadow: [ + BoxShadow( + color: ColorConstant.gray60026, + spreadRadius: getHorizontalSize( + 2, + ), + blurRadius: getHorizontalSize( + 2, + ), + offset: Offset( + 0, + 2.41, + ), + ), + ], + ); + static BoxDecoration get txtFillBluegray100 => BoxDecoration( + color: ColorConstant.blueGray100, + ); + static BoxDecoration get fillBlueA700 => BoxDecoration( + color: ColorConstant.blueA700, + ); + static BoxDecoration get fillBluegray50 => BoxDecoration( + color: ColorConstant.blueGray50, + ); + static BoxDecoration get outlineBlueA7002 => BoxDecoration( + color: ColorConstant.whiteA700, + border: Border.all( + color: ColorConstant.blueA700, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get outlineBlueA7001 => BoxDecoration( + color: ColorConstant.whiteA700, + border: Border.all( + color: ColorConstant.blueA700, + width: getHorizontalSize( + 1, + ), + ), + boxShadow: [ + BoxShadow( + color: ColorConstant.gray60019, + spreadRadius: getHorizontalSize( + 2, + ), + blurRadius: getHorizontalSize( + 2, + ), + offset: Offset( + 0, + 12, + ), + ), + ], + ); + static BoxDecoration get outlineGray70011 => BoxDecoration( + color: ColorConstant.whiteA700, + boxShadow: [ + BoxShadow( + color: ColorConstant.gray70011, + spreadRadius: getHorizontalSize( + 2, + ), + blurRadius: getHorizontalSize( + 2, + ), + offset: Offset( + 0, + 0, + ), + ), + ], + ); + static BoxDecoration get outlineGray600191 => BoxDecoration(); + static BoxDecoration get txtOutlineBlueA700 => BoxDecoration( + border: Border.all( + color: ColorConstant.blueA700, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get outlineBlue50 => BoxDecoration( + color: ColorConstant.whiteA700, + border: Border.all( + color: ColorConstant.blue50, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get txtFillBlueA700 => BoxDecoration( + color: ColorConstant.blueA700, + ); + static BoxDecoration get outlineBlack90019 => BoxDecoration( + color: ColorConstant.blueA700, + boxShadow: [ + BoxShadow( + color: ColorConstant.black90019, + spreadRadius: getHorizontalSize( + 2, + ), + blurRadius: getHorizontalSize( + 2, + ), + offset: Offset( + 0, + 2, + ), + ), + ], + ); + static BoxDecoration get outlineBluegray100 => BoxDecoration( + color: ColorConstant.gray50, + border: Border( + bottom: BorderSide( + color: ColorConstant.blueGray100, + width: getHorizontalSize( + 1, + ), + ), + ), + ); + static BoxDecoration get fillGray50 => BoxDecoration( + color: ColorConstant.gray50, + ); + static BoxDecoration get outlineBluegray10001 => BoxDecoration( + color: ColorConstant.whiteA700, + border: Border.all( + color: ColorConstant.blueGray10001, + width: getHorizontalSize( + 1, + ), + ), + boxShadow: [ + BoxShadow( + color: ColorConstant.black90033, + spreadRadius: getHorizontalSize( + 2, + ), + blurRadius: getHorizontalSize( + 2, + ), + offset: Offset( + 0, + 1, + ), + ), + ], + ); + static BoxDecoration get fillBlack900b2 => BoxDecoration( + color: ColorConstant.black900B2, + ); + static BoxDecoration get outlineBlack90033 => BoxDecoration( + border: Border.all( + color: ColorConstant.black90033, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get outlineBlack90011 => BoxDecoration( + color: ColorConstant.whiteA700, + boxShadow: [ + BoxShadow( + color: ColorConstant.black90011, + spreadRadius: getHorizontalSize( + 2, + ), + blurRadius: getHorizontalSize( + 2, + ), + offset: Offset( + 0, + 0, + ), + ), + ], + ); + static BoxDecoration get outlineGray30001 => BoxDecoration( + border: Border.all( + color: ColorConstant.gray30001, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get outlineBlue200 => BoxDecoration( + border: Border.all( + color: ColorConstant.blue200, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get outlineGray60019 => BoxDecoration( + color: ColorConstant.whiteA700, + boxShadow: [ + BoxShadow( + color: ColorConstant.gray60019, + spreadRadius: getHorizontalSize( + 2, + ), + blurRadius: getHorizontalSize( + 2, + ), + offset: Offset( + 0, + 12, + ), + ), + ], + ); + static BoxDecoration get outlineGray700261 => BoxDecoration( + color: ColorConstant.whiteA700, + boxShadow: [ + BoxShadow( + color: ColorConstant.gray70026, + spreadRadius: getHorizontalSize( + 2, + ), + blurRadius: getHorizontalSize( + 2, + ), + offset: Offset( + 0, + 0, + ), + ), + ], + ); + static BoxDecoration get fillWhiteA700 => BoxDecoration( + color: ColorConstant.whiteA700, + ); + static BoxDecoration get outlineBlueA700 => BoxDecoration( + color: ColorConstant.gray50, + border: Border.all( + color: ColorConstant.blueA700, + width: getHorizontalSize( + 2, + ), + strokeAlign: strokeAlignOutside, + ), + ); + static BoxDecoration get fillBlue900 => BoxDecoration( + color: ColorConstant.blue900, + ); + static BoxDecoration get outlineBluegray1002 => BoxDecoration( + color: ColorConstant.whiteA700, + border: Border( + top: BorderSide( + color: ColorConstant.blueGray100, + width: getHorizontalSize( + 1, + ), + ), + bottom: BorderSide( + color: ColorConstant.blueGray100, + width: getHorizontalSize( + 1, + ), + ), + ), + ); + static BoxDecoration get fillRed100 => BoxDecoration( + color: ColorConstant.red100, + ); + static BoxDecoration get outlineBluegray1001 => BoxDecoration( + color: ColorConstant.whiteA700, + border: Border.all( + color: ColorConstant.blueGray100, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get outlineYellow9003f => BoxDecoration( + color: ColorConstant.whiteA700, + border: Border.all( + color: ColorConstant.yellow9003f, + width: getHorizontalSize( + 1, + ), + strokeAlign: strokeAlignOutside, + ), + ); + static BoxDecoration get fillBlue50 => BoxDecoration( + color: ColorConstant.blue50, + ); + static BoxDecoration get outlineGray70026 => BoxDecoration( + color: ColorConstant.whiteA70099, + boxShadow: [ + BoxShadow( + color: ColorConstant.gray70026, + spreadRadius: getHorizontalSize( + 2, + ), + blurRadius: getHorizontalSize( + 2, + ), + offset: Offset( + 0, + 0, + ), + ), + ], + ); + static BoxDecoration get txtOutlineBlack9000c => BoxDecoration( + color: ColorConstant.gray100, + border: Border.all( + color: ColorConstant.black9000c, + width: getHorizontalSize( + 1, + ), + ), + ); + static BoxDecoration get fillRed700 => BoxDecoration( + color: ColorConstant.red700, + ); + static BoxDecoration get fillGray5003 => BoxDecoration( + color: ColorConstant.gray5003, + ); + static BoxDecoration get fillGray200 => BoxDecoration( + color: ColorConstant.gray200, + ); + static BoxDecoration get outlineBluegray50 => BoxDecoration( + color: ColorConstant.whiteA700, + border: Border.all( + color: ColorConstant.blueGray50, + width: getHorizontalSize( + 1, + ), + ), + ); +} + +class BorderRadiusStyle { + static BorderRadius customBorderTL50 = BorderRadius.only( + topLeft: Radius.circular( + getHorizontalSize( + 50, + ), + ), + bottomLeft: Radius.circular( + getHorizontalSize( + 50, + ), + ), + ); + + static BorderRadius customBorderTL10 = BorderRadius.only( + topLeft: Radius.circular( + getHorizontalSize( + 10, + ), + ), + topRight: Radius.circular( + getHorizontalSize( + 10, + ), + ), + ); + + static BorderRadius circleBorder9 = BorderRadius.circular( + getHorizontalSize( + 9, + ), + ); + + static BorderRadius circleBorder22 = BorderRadius.circular( + getHorizontalSize( + 22, + ), + ); + + static BorderRadius roundedBorder16 = BorderRadius.circular( + getHorizontalSize( + 16, + ), + ); + + static BorderRadius circleBorder12 = BorderRadius.circular( + getHorizontalSize( + 12, + ), + ); + + static BorderRadius roundedBorder6 = BorderRadius.circular( + getHorizontalSize( + 6, + ), + ); + + static BorderRadius circleBorder25 = BorderRadius.circular( + getHorizontalSize( + 25, + ), + ); + + static BorderRadius roundedBorder3 = BorderRadius.circular( + getHorizontalSize( + 3, + ), + ); + + static BorderRadius circleBorder30 = BorderRadius.circular( + getHorizontalSize( + 30, + ), + ); + + static BorderRadius circleBorder76 = BorderRadius.circular( + getHorizontalSize( + 76, + ), + ); + + static BorderRadius txtRoundedBorder6 = BorderRadius.circular( + getHorizontalSize( + 6, + ), + ); + + static BorderRadius circleBorder61 = BorderRadius.circular( + getHorizontalSize( + 61, + ), + ); +} + +// Comment/Uncomment the below code based on your Flutter SDK version. + +// For Flutter SDK Version 3.7.2 or greater. + +double get strokeAlignInside => BorderSide.strokeAlignInside; + +double get strokeAlignCenter => BorderSide.strokeAlignCenter; + +double get strokeAlignOutside => BorderSide.strokeAlignOutside; + +// For Flutter SDK Version 3.7.1 or less. + +// StrokeAlign get strokeAlignInside => StrokeAlign.inside; +// +// StrokeAlign get strokeAlignCenter => StrokeAlign.center; +// +// StrokeAlign get strokeAlignOutside => StrokeAlign.outside; + \ No newline at end of file diff --git a/lib/theme/app_style.dart b/lib/theme/app_style.dart new file mode 100644 index 0000000..bf02d84 --- /dev/null +++ b/lib/theme/app_style.dart @@ -0,0 +1,1014 @@ +import 'package:flutter/material.dart'; + +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; + +class AppStyle { + static TextStyle txtGilroySemiBold16Black90002 = TextStyle( + color: ColorConstant.black90002, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold10Bluegray900 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 10, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyBold36 = TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 36, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtSFProTextRegular15 = TextStyle( + color: ColorConstant.gray80099, + fontSize: getFontSize( + 15, + ), + fontFamily: 'SF Pro Text', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroySemiBold16WhiteA700 = TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyBold32 = TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 32, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroyRegular12Green600 = TextStyle( + color: ColorConstant.green600, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtSFProTextRegular11 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 11, + ), + fontFamily: 'SF Pro Text', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtRobotoBlack1418 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 14.18, + ), + fontFamily: 'Roboto', + fontWeight: FontWeight.w900, + ); + + static TextStyle txtGilroySemiBold24Black90001 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 24, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtLatoBold12 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Lato', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtLatoBold10 = TextStyle( + color: ColorConstant.gray400, + fontSize: getFontSize( + 10, + ), + fontFamily: 'Lato', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroyMedium16BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyRegular14Bluegray300 = TextStyle( + color: ColorConstant.blueGray300, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyRegular12Bluegray90001 = TextStyle( + color: ColorConstant.blueGray90001, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyMedium18Gray700 = TextStyle( + color: ColorConstant.gray700, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyBold18Bluegray900 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroyBold28 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 28, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroySemiBold18Green600 = TextStyle( + color: ColorConstant.green600, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyBold24WhiteA700 = TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 24, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroyBold24 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 24, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroyBold20 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 20, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroyMedium16Bluegray900 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold14Bluegray300 = TextStyle( + color: ColorConstant.blueGray300, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyMedium8Black90001 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 8, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold1047 = TextStyle( + color: ColorConstant.black900, + fontSize: getFontSize( + 10.47, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold16Black900 = TextStyle( + color: ColorConstant.black900, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyMedium14Bluegray400 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold18BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyMedium8Red700 = TextStyle( + color: ColorConstant.red700, + fontSize: getFontSize( + 8, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium12Black90087 = TextStyle( + color: ColorConstant.black90087, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold20BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 20, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtSFUIDisplayRegular10 = TextStyle( + color: ColorConstant.black90087, + fontSize: getFontSize( + 10, + ), + fontFamily: 'SF UI Display', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyRegular14WhiteA700 = TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroySemiBold10Bluegray400 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 10, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtPilatExtendedHeavy16 = TextStyle( + color: ColorConstant.black90075, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Pilat Extended', + fontWeight: FontWeight.w800, + ); + + static TextStyle txtGilroyBold18BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtPilatExtendedHeavy18 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Pilat Extended', + fontWeight: FontWeight.w800, + ); + + static TextStyle txtGilroyMedium16Bluegray800 = TextStyle( + color: ColorConstant.blueGray800, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium18WhiteA700 = TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold24BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 24, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold14Bluegray900 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyRegular14Bluegray400 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyMedium16Green600 = TextStyle( + color: ColorConstant.green600, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium14Black90001 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium14Black90002 = TextStyle( + color: ColorConstant.black90002, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold10 = TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 10, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyRegular16Bluegray400 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyRegular12 = TextStyle( + color: ColorConstant.red700, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroySemiBold18Bluegray90002 = TextStyle( + color: ColorConstant.blueGray90002, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold18 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold16 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGreenSemiBold16 = TextStyle( + color: ColorConstant.green600, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyRegular16 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroySemiBold14Bluegray400 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtPilatExtendedHeavy18Black90087 = TextStyle( + color: ColorConstant.black90087, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Pilat Extended', + fontWeight: FontWeight.w800, + ); + + static TextStyle txtGilroyRegular14 = TextStyle( + color: ColorConstant.blueGray600, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroySemiBold14 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtRobotoRegular12 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Roboto', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyRegular14Black90003 = TextStyle( + color: ColorConstant.black90003, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtRobotoRegular16 = TextStyle( + color: ColorConstant.blueGray40001, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Roboto', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyMedium14Bluegray300 = TextStyle( + color: ColorConstant.blueGray300, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium18Bluegray400 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium16WhiteA700 = TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyBold24Blue800 = TextStyle( + color: ColorConstant.blue800, + fontSize: getFontSize( + 24, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroySemiBold24 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 24, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyBold36BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 36, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroySemiBold28WhiteA700 = TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 28, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold20 = TextStyle( + color: ColorConstant.green600, + fontSize: getFontSize( + 20, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold16Bluegray300 = TextStyle( + color: ColorConstant.blueGray300, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold28 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 28, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold18Red700 = TextStyle( + color: ColorConstant.red700, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtInterExtraBold16 = TextStyle( + color: ColorConstant.gray90002, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Inter', + fontWeight: FontWeight.w800, + ); + + static TextStyle txtGilroyMedium16Indigo400 = TextStyle( + color: ColorConstant.indigo400, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold18Bluegray900 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyMedium12Bluegray400 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium8 = TextStyle( + color: ColorConstant.blueGray300, + fontSize: getFontSize( + 8, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtRobotoRegular20 = TextStyle( + color: ColorConstant.black90004, + fontSize: getFontSize( + 20, + ), + fontFamily: 'Roboto', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyMedium14BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold18Bluegray400 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyMedium16Black90001 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold36 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 36, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyMedium18Bluegray900 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium14Bluegray20001 = TextStyle( + color: ColorConstant.blueGray20001, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtPilatExtendedHeavy16Black90001 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Pilat Extended', + fontWeight: FontWeight.w800, + ); + + static TextStyle txtGilroyMedium14Gray40001 = TextStyle( + color: ColorConstant.gray40001, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold16BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold14Gray900 = TextStyle( + color: ColorConstant.gray900, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyBold16 = TextStyle( + color: ColorConstant.amber500, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroyBold18 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroyMedium10Bluegray400 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 10, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyBold12 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtGilroyRegular12Bluegray900 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyMedium14Bluegray900 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold14Bluegray700 = TextStyle( + color: ColorConstant.blueGray700, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroyBold16BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w700, + ); + + static TextStyle txtRubikMedium12 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Rubik', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyRegular14BlueA700 = TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyMedium14Black900 = TextStyle( + color: ColorConstant.black900, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium12Bluegray900 = TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium10 = TextStyle( + color: ColorConstant.blueGray300, + fontSize: getFontSize( + 10, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtMontserratMedium14 = TextStyle( + color: ColorConstant.redA200, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Montserrat', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyRegular16Bluegray200 = TextStyle( + color: ColorConstant.blueGray200, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyMedium14 = TextStyle( + color: ColorConstant.blueGray200, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium12 = TextStyle( + color: ColorConstant.blueGray300, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyRegular16Gray900 = TextStyle( + color: ColorConstant.gray900, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + + static TextStyle txtGilroyMedium18 = TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium16 = TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroyMedium18Bluegray600 = TextStyle( + color: ColorConstant.blueGray600, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + + static TextStyle txtGilroySemiBold16Bluegray700 = TextStyle( + color: ColorConstant.blueGray700, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold18Gray90002 = TextStyle( + color: ColorConstant.gray90002, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + + static TextStyle txtGilroySemiBold18Gray90001 = TextStyle( + color: ColorConstant.gray90001, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); +} diff --git a/lib/utilities/custom_date_grouping.dart b/lib/utilities/custom_date_grouping.dart new file mode 100644 index 0000000..115446f --- /dev/null +++ b/lib/utilities/custom_date_grouping.dart @@ -0,0 +1,240 @@ + + +int calcDaysBetween(DateTime from, DateTime to) { + from = DateTime(from.year, from.month, from.day); + to = DateTime(to.year, to.month, to.day); + return (to.difference(from).inHours ~/ 24); +} + +int calcSecondsBetween(DateTime from, DateTime to) { + from = DateTime( + from.year, from.month, from.day, from.hour, from.minute, from.second); + to = DateTime(to.year, to.month, to.day, to.hour, to.minute, to.second); + return to.difference(from).inSeconds; +} + +String customGroup(DateTime transactionDate) { + String response = ''; + DateTime latestDate = DateTime.now(); + int nDaysInBetween = calcDaysBetween(transactionDate, latestDate); + + int years = nDaysInBetween ~/ 365; + + if (years == 1) { + response = 'Last year'; + } else if (years > 1 && years <= 5) { + response = '$years years ago'; + } else if (years > 5) { + response = 'More than 5 years ago'; + } else { + nDaysInBetween -= 365 * years; + + int months = nDaysInBetween ~/ 30; + if (months == 1) { + response = 'Last month'; + } else if (months > 1 && months <= 6) { + response = '$months months ago'; + } else if (months >= 6) { + response = 'More than 6 months ago'; + } else { + int days = latestDate.day - transactionDate.day; + + if (days == 1) { + response = 'Yesterday'; + + + } else if (days > 1 && days <= 7) { + response = 'This week'; + } else if (days > 7 && days <= 14) { + response = 'Last week'; + } else if (days > 14 && days <= 30) { + int weeks = days ~/ 7; + response = '$weeks weeks ago'; + } else { + response = 'Today'; + } + } + } + return response; +} + +int customGroupComparator(String group1, String group2) { + int comparison = -1; + int group1Match = 0; + int group2Match = 0; + List dateGroups = [ + r'Today', + r'Yesterday', + r'This week', + r'Last week', + r'\d{1} weeks ago', + r'Last month', + r'\d{1} months ago', + r'More than 6 months ago', + r'Last year', + r'\d{1} years ago', + r'More than 5 years ago', + ]; + + for (var i = 0; i < dateGroups.length; i++) { + if (RegExp(dateGroups[i]).hasMatch(group1)) { + group1Match = i; + } + if (RegExp(dateGroups[i]).hasMatch(group2)) { + group2Match = i; + } + } + // check + if (group1Match == group2Match) { + comparison = group1.compareTo(group2); + } else if (group1Match < group2Match) { + comparison = -1; + } else { + comparison = 1; + } + return comparison; +} + +String dateFormatter(String dateGroup, DateTime transactionDate) { + String formattedDate = ''; + if (dateGroup == 'Today') { + formattedDate = _formatTime1(transactionDate); + } else if (dateGroup == 'Yesterday') { + formattedDate = + "Yesterday at ${formatTime2(transactionDate.hour, transactionDate.minute)}"; + } else { + formattedDate = + "${transactionDate.day}-${transactionDate.month}-${transactionDate.year} at ${formatTime2(transactionDate.hour, transactionDate.minute)}"; + } + return formattedDate; +} + +String formatTime2(int hrs, int mins) { + int newHrs = 0; + String midDayStatus = ''; + String minutesAsString=mins<10?"0$mins":"$mins"; + if (hrs > 12 && hrs < 24) { + midDayStatus = 'PM'; + newHrs = hrs - 12; + } else if (hrs == 12 && mins > 0) { + midDayStatus = 'PM'; + newHrs = 12; + } else if (hrs < 12) { + midDayStatus = 'AM'; + newHrs = hrs; + } else if (hrs == 24) { + midDayStatus = 'AM'; + newHrs = 00; + } + + return "$newHrs:$minutesAsString $midDayStatus"; +} + +String formatTime3(String date) { + DateTime someDate = DateTime.parse(date); + int hrs = someDate.hour; + dynamic mins = someDate.minute; + int newHrs = 0; + String midDayStatus = ''; + + if (hrs > 12 && hrs < 24) { + midDayStatus = 'PM'; + newHrs = hrs - 12; + } else if (hrs == 12 && mins > 0) { + midDayStatus = 'PM'; + newHrs = 12; + } else if (hrs < 12) { + midDayStatus = 'AM'; + newHrs = hrs; + } else if (hrs == 24) { + midDayStatus = 'AM'; + newHrs = 00; + } + + if (mins<=9) { + mins="0$mins"; + } + + return "$newHrs:$mins $midDayStatus"; +} + +String _formatTime1(DateTime transactionDate) { + DateTime latestDate = DateTime.now(); + + int seconds = calcSecondsBetween(transactionDate, latestDate); + + int minutes = seconds ~/ 60; + int hours = minutes ~/ 60; + + String response = ''; + if (hours == 1) { + response = 'an hour ago'; + } else if (hours > 1 && hours < 24) { + response = '$hours hours ago'; + } else { + if (minutes > 30) { + response = 'half an hour ago'; + } else if (minutes <= 30 && minutes > 1) { + response = '$minutes minutes ago'; + } else if (minutes == 1) { + response = 'a minute ago'; + } else { + if (seconds <= 0) { + response = 'just now'; + } else if (seconds == 1) { + response = 'a second ago'; + } else { + response = '$seconds seconds ago'; + } + } + } + return response; +} + + +String dateToWords(DateTime transactionDate) { + String day = _formatDay(transactionDate.day); + String month = _findMonthInWords(transactionDate.month); + return "$day $month, ${transactionDate.year}"; +} + +//? FUNCTION FOR RETRIEVING ORDINALS +String _formatDay(int day) { + String suffix = ''; + if (day >= 11 && day<=13) { + suffix = 'th'; + } else { + switch (day % 10) { + case 1: + suffix = 'st'; + break; + case 2: + suffix = 'nd'; + break; + case 3: + suffix = 'rd'; + break; + default: + suffix = 'th'; + } + } + return "$day$suffix"; +} + +String _findMonthInWords(int month) { + List months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December' + ]; + return months[month - 1]; +} diff --git a/lib/utilities/display_error_alert.dart b/lib/utilities/display_error_alert.dart new file mode 100644 index 0000000..1679e58 --- /dev/null +++ b/lib/utilities/display_error_alert.dart @@ -0,0 +1,150 @@ +import 'package:flutter/material.dart'; + +import '../database/login_info_storage.dart'; +import '../database/user_data_storage.dart'; +import '../screens/Login Screen/login_screen.dart'; + +Future _deleteLoggedInUserData() async { + List deletionStatus = await Future.wait( + [LoginInfoStorage().deleteFile(), UserDataStorage().deleteFile()]); + return deletionStatus.first && deletionStatus.last; +} + +void showErrorAlert(BuildContext context, Map error) { + Map errorTypes = { + 'error': _CommonError(context, error), + 'internetConnectionError': _LocalError(context, error), + 'localDBError': _LocalError(context, error), + 'authenticationError': _CommonError(context, error), + 'apiAuthorizationError': _HazardousError(context, error), + 'corruptedTokenError': _HazardousError(context, error) + }; + String currentError = error.keys.first; + // String currentError = error['operationMessage']; + + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => AlertDialog( + title: Text( + "Error", + textAlign: TextAlign.center, + ), + content: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: errorTypes[currentError].errorDescription, + ), + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), + actionsAlignment: MainAxisAlignment.center, + actions: [ + Container( + height: 48, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + color: Colors.blueGrey.shade100, + offset: Offset(0, 4), + blurRadius: 5.0) + ], + gradient: RadialGradient( + colors: [Color(0xff0070BA), Color(0xff1546A0)], + radius: 8.4, + center: Alignment(-0.24, -0.36)), + borderRadius: BorderRadius.circular(10), + ), + child: ElevatedButton( + onPressed: errorTypes[currentError].onClose, + child: Text('OK'), + style: ElevatedButton.styleFrom( + primary: Colors.transparent, + shadowColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10)), + )), + ) + ], + )); +} + +class _CommonError { + BuildContext context; + Map error; + _CommonError(this.context, this.error); + List get errorDescription => [ + Padding( + padding: EdgeInsets.only(top: 24, bottom: 12), + child: Text( + error[error['operationMessage']], + textAlign: TextAlign.center, + ), + ), + ]; + + void onClose() { + Navigator.of(context).pop(); + } +} + +class _LocalError { + BuildContext context; + Map error; + _LocalError(this.context, this.error); + + List get errorDescription => [ + error.keys.first == 'internetConnectionError' + ? ColorFiltered( + colorFilter: + ColorFilter.mode(Color(0xFF0070BA), BlendMode.color), + child: ColorFiltered( + colorFilter: + ColorFilter.mode(Colors.grey, BlendMode.saturation), + child: Image.asset( + 'assets/images/notification_assets/no-wifi.png', + height: 48, + width: 48, + ), + )) + : Image.asset( + 'assets/images/notification_assets/file-error.png', + height: 48, + width: 48, + ), + Padding( + padding: EdgeInsets.only(top: 24, bottom: 12), + child: Text( + error[error.keys.first], + textAlign: TextAlign.center, + ), + ), + ]; + + void onClose() { + Navigator.of(context).pop(); + } +} + +class _HazardousError { + BuildContext context; + Map error; + _HazardousError(this.context, this.error); + List get errorDescription => [ + Padding( + padding: EdgeInsets.only(top: 24, bottom: 12), + child: Text( + error[error.keys.first], + textAlign: TextAlign.center, + ), + ), + ]; + + void onClose() async { + final logOutStatus = await _deleteLoggedInUserData(); + if (logOutStatus) { + Navigator.of(context).pushAndRemoveUntil( + MaterialPageRoute(builder: (context) => LoginScreen()), + (route) => false); + } + } +} diff --git a/lib/utilities/hadwin_icons.dart b/lib/utilities/hadwin_icons.dart new file mode 100644 index 0000000..7580c2e --- /dev/null +++ b/lib/utilities/hadwin_icons.dart @@ -0,0 +1,27 @@ +/// Flutter icons HadWinIcons +/// Copyright (C) 2022 by original authors @ fluttericon.com, fontello.com +/// This font was generated by FlutterIcon.com, which is derived from Fontello. +/// +/// To use this font, place it in your fonts/ directory and include the +/// following in your pubspec.yaml +/// +/// flutter: +/// fonts: +/// - family: HadWinIcons +/// fonts: +/// - asset: fonts/HadWinIcons.ttf +/// +/// +/// +import 'package:flutter/widgets.dart'; + +class HadWinIcons { + HadWinIcons._(); + + static const _kFontFam = 'HadWinIcons'; + static const String? _kFontPkg = null; + + static const IconData wallet_business_and_trade = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData wallet_education_29 = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData line_awesome_wallet_solid = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); +} diff --git a/lib/utilities/hadwin_markdown_viewer.dart b/lib/utilities/hadwin_markdown_viewer.dart new file mode 100644 index 0000000..0b85761 --- /dev/null +++ b/lib/utilities/hadwin_markdown_viewer.dart @@ -0,0 +1,191 @@ +import 'dart:io'; + +import 'package:fade_shimmer/fade_shimmer.dart'; +import 'package:flutter/material.dart'; + +import 'package:http/http.dart' as http; + +import 'display_error_alert.dart'; + +class HadWinMarkdownViewer extends StatefulWidget { + final String screenName; + final String urlRequested; + + const HadWinMarkdownViewer({ + Key? key, + required this.screenName, + required this.urlRequested, + }) : super(key: key); + + @override + HadWinMarkdownViewerState createState() => HadWinMarkdownViewerState(); +} + +class HadWinMarkdownViewerState extends State { + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + title: Text( + widget.screenName, + style: const TextStyle(fontSize: 24), + ), + centerTitle: true, + backgroundColor: Colors.transparent, + foregroundColor: const Color(0xff243656), + elevation: 0, + ), + body: Column( + children: [ + Expanded( + child: Container( + height: 100, + width: MediaQuery.of(context).size.width - 20, + padding: const EdgeInsets.only( + left: 16.18, + right: 16.18, + bottom: 16.18, + top: 6.18, + ), + child: FutureBuilder( + future: getTextData(widget.urlRequested), + builder: (context, snapshot) { + if (snapshot.hasData) { + print('testing'); + + // return MarkdownWidgetBuilder( + // markdownData: snapshot.data!, + // styleConfig: MarkdownWidgetConfig( + // markdownTheme: MarkdownTheme( + // blockquoteDecoration: BoxDecoration( + // color: Color(0xffcaf0f8), + // ), + // blockquoteTextStyle: TextStyle( + // color: Color(0xff0077b6), + // ), + // tableConfig: TableConfig( + // headerStyle: TextStyle( + // fontWeight: FontWeight.w700, + // ), + // bodyTextConfig: TextConfig( + // textAlign: TextAlign.center, + // ), + // ), + // titleConfig: TitleConfig( + // commonStyle: GoogleFonts.ubuntu(), + // showDivider: false, + // ), + // ulConfig: UlConfig( + // textStyle: GoogleFonts.workSans(), + // dotWidget: (deep, index) => Text( + // "${index + 1}.\t", + // style: GoogleFonts.ubuntu(), + // ), + // ), + // olConfig: OlConfig( + // textStyle: GoogleFonts.workSans(), + // indexWidget: (deep, index) => Text( + // "${index + 1}.\t", + // style: GoogleFonts.ubuntu(), + // ), + // ), + // pConfig: PConfig( + // textStyle: GoogleFonts.workSans(), + // onLinkTap: (url) { + // launchExternalURL(url!).then( + // (value) => + // debugPrint("requested to access $url"), + // ); + // }, + // emStyle: const TextStyle( + // fontWeight: FontWeight.w600, + // backgroundColor: Color(0xffccff33), + // fontStyle: FontStyle.italic, + // ), + // ), + // codeConfig: CodeConfig( + // codeStyle: GoogleFonts.spaceMono( + // backgroundColor: Color(0xff4a4e69), + // fontWeight: FontWeight.w600, + // color: Colors.white, + // ), + // ), + // ), + // ), + // builder: (context, content) { + // return content; + // }, + // ); + } + return docsLoading(); + }, + ), + ), + ), + ], + ), + ); + } + + Future getTextData(String url) async { + var response; + try { + response = await http.get(Uri.parse(url)); + } on SocketException { + showErrorAlert( + context, + {'internetConnectionError': 'no internet connection'}, + ); + } catch (e) { + showErrorAlert(context, {'error': "something went wrong"}); + } + return response.body; + } + + Widget docsLoading() { + return ListView.separated( + itemBuilder: (context, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: + const EdgeInsets.symmetric(horizontal: 5, vertical: 1.618), + child: const FadeShimmer( + height: 27, + width: 100, + radius: 7.2, + highlightColor: Color(0xffced4da), + baseColor: Color(0xffe9ecef), + ), + ), + ...List.generate( + 4, + (i) => Container( + padding: + const EdgeInsets.symmetric(horizontal: 5, vertical: 1.618), + child: FadeShimmer( + height: 21, + width: MediaQuery.of(context).size.width - 24, + radius: 7.2, + highlightColor: const Color(0xffced4da), + baseColor: const Color(0xffe9ecef), + ), + ), + ).toList(), + ], + ); + }, + separatorBuilder: (_, b) => const SizedBox( + height: 10, + ), + itemCount: 5, + ); + } +} diff --git a/lib/utilities/make_api_request.dart b/lib/utilities/make_api_request.dart new file mode 100644 index 0000000..4b8f148 --- /dev/null +++ b/lib/utilities/make_api_request.dart @@ -0,0 +1,54 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:http/http.dart' as http; + +import '../resources/api_constants.dart'; + +Future> getData( + {required String urlPath, String? authKey}) async { + String backendServiceHost = "${ApiConstants.baseUrl}$urlPath"; + var response; + try { + response = await http.get( + Uri.parse(backendServiceHost), + headers: { + 'Content-Type': 'application/json', + if (authKey != null) 'Authorization': authKey + }, + ); + } on SocketException { + return {'internetConnectionError': 'no internet connection'}; + } + return jsonDecode(response.body); +} + +Future> sendData( + {required String urlPath, + required Map data, + String? authKey}) async { + String backendServiceHost = "${ApiConstants.baseUrl}" + urlPath; + var response; + try { + response = await http.post( + Uri.parse(backendServiceHost), + headers: { + 'Content-Type': 'application/json', + if (authKey != null) 'Authorization': authKey + }, + body: jsonEncode(data), + ); + } on SocketException { + return {'internetConnectionError': 'no internet connection'}; + } + return jsonDecode(response.body); +} + +Future checkUrlValidity(String url) async { + try { + final response = await http.get(Uri.parse(url)); + + return response.statusCode; + } catch (e) { + return 404; + } +} diff --git a/lib/utilities/slide_right_route.dart b/lib/utilities/slide_right_route.dart new file mode 100644 index 0000000..c7a89ce --- /dev/null +++ b/lib/utilities/slide_right_route.dart @@ -0,0 +1,29 @@ +// page slide transition effect +import 'package:flutter/material.dart'; + +class SlideRightRoute extends PageRouteBuilder { + final Widget page; + SlideRightRoute({required this.page}) + : super( + pageBuilder: ( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + ) => + page, + transitionsBuilder: ( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child, + ) => + SlideTransition( + textDirection: TextDirection.rtl, + position: Tween( + begin: const Offset(-1, 0), + end: Offset.zero, + ).animate(animation), + child: child, + ), + ); +} diff --git a/lib/utilities/url_external_launcher.dart b/lib/utilities/url_external_launcher.dart new file mode 100644 index 0000000..5d6f684 --- /dev/null +++ b/lib/utilities/url_external_launcher.dart @@ -0,0 +1,12 @@ + import 'package:url_launcher/url_launcher.dart'; + +Future launchExternalURL(String url) async { + Uri uri =Uri.parse(url); + + if (await canLaunchUrl(uri)) { + await launchUrl(uri,mode: LaunchMode.externalApplication); + } + // else { + // throw 'Could not launch $url'; + // } + } diff --git a/lib/widgets/app_bar/appbar_image.dart b/lib/widgets/app_bar/appbar_image.dart new file mode 100644 index 0000000..0270f98 --- /dev/null +++ b/lib/widgets/app_bar/appbar_image.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; + +import '../custom_image_view.dart'; + +// ignore: must_be_immutable +class AppbarImage extends StatelessWidget { + AppbarImage( + {required this.height, + required this.width, + this.imagePath, + this.svgPath, + this.margin, + this.onTap}); + + double height; + + double width; + + String? imagePath; + + String? svgPath; + + EdgeInsetsGeometry? margin; + + Function? onTap; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + onTap?.call(); + }, + child: Padding( + padding: margin ?? EdgeInsets.zero, + child: CustomImageView( + svgPath: svgPath, + imagePath: imagePath, + height: height, + width: width, + fit: BoxFit.contain, + ), + ), + ); + } +} diff --git a/lib/widgets/app_bar/appbar_title.dart b/lib/widgets/app_bar/appbar_title.dart new file mode 100644 index 0000000..818899f --- /dev/null +++ b/lib/widgets/app_bar/appbar_title.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +import '../../Utils/color_constants.dart'; +import '../../theme/app_style.dart'; + + +// ignore: must_be_immutable +class AppbarTitle extends StatelessWidget { + AppbarTitle({required this.text, this.margin, this.onTap}); + + String text; + + EdgeInsetsGeometry? margin; + + Function? onTap; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + onTap?.call(); + }, + child: Padding( + padding: margin ?? EdgeInsets.zero, + child: Text( + text, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.left, + style: AppStyle.txtGilroySemiBold24.copyWith( + color: ColorConstant.blueGray900, + ), + ), + ), + ); + } +} diff --git a/lib/widgets/app_bar/custom_app_bar.dart b/lib/widgets/app_bar/custom_app_bar.dart new file mode 100644 index 0000000..811757d --- /dev/null +++ b/lib/widgets/app_bar/custom_app_bar.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +import '../../Utils/size_utils.dart'; + +// ignore: must_be_immutable +class CustomAppBar extends StatelessWidget implements PreferredSizeWidget{ + CustomAppBar( + {required this.height, + this.leadingWidth, + this.leading, + this.title, + this.bottom, + this.flexibleSpace, + this.centerTitle, + this.actions}); + + double height; + + double? leadingWidth; + + Widget? leading; + + Widget? title; + + PreferredSize? flexibleSpace; + + TabBar? bottom; + + bool? centerTitle; + + List? actions; + + @override + Widget build(BuildContext context) { + return AppBar( + elevation: 0, + toolbarHeight: height, + automaticallyImplyLeading: false, + backgroundColor: Colors.transparent, + leadingWidth: leadingWidth ?? 0, + leading: leading, + title: title, + bottom: bottom, + flexibleSpace: flexibleSpace, + titleSpacing: 0, + centerTitle: centerTitle ?? false, + actions: actions, + ); + } + + @override + Size get preferredSize => Size( + size.width, + height, + ); +} diff --git a/lib/widgets/custom_bottom_bar.dart b/lib/widgets/custom_bottom_bar.dart new file mode 100644 index 0000000..2ac8300 --- /dev/null +++ b/lib/widgets/custom_bottom_bar.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/image_constant.dart'; +import '../Utils/size_utils.dart'; +import 'custom_image_view.dart'; + +class CustomBottomBar extends StatefulWidget { + CustomBottomBar({this.onChanged}); + + Function(BottomBarEnum)? onChanged; + + @override + _CustomBottomBarState createState() => _CustomBottomBarState(); +} + +class _CustomBottomBarState extends State { + int selectedIndex = 0; + + List bottomMenuList = [ + BottomMenuModel( + icon: ImageConstant.imgFire, + type: BottomBarEnum.Fire, + ), + BottomMenuModel( + icon: ImageConstant.imgSearchWhiteA70020x20, + type: BottomBarEnum.Searchwhitea70020x20, + ), + BottomMenuModel( + icon: ImageConstant.imgMenu, + type: BottomBarEnum.Menu, + ), + BottomMenuModel( + icon: ImageConstant.imgOverflowmenuWhiteA700, + type: BottomBarEnum.Overflowmenuwhitea700, + ) + ]; + + @override + Widget build(BuildContext context) { + return Container( + margin: getMargin( + left: 16, + right: 16, + ), + decoration: BoxDecoration( + color: ColorConstant.blueA700, + borderRadius: BorderRadius.circular( + getHorizontalSize( + 14, + ), + ), + ), + child: BottomNavigationBar( + backgroundColor: Colors.transparent, + showSelectedLabels: false, + showUnselectedLabels: false, + elevation: 0, + currentIndex: selectedIndex, + type: BottomNavigationBarType.fixed, + items: List.generate(bottomMenuList.length, (index) { + return BottomNavigationBarItem( + icon: CustomImageView( + svgPath: bottomMenuList[index].icon, + height: getSize( + 24, + ), + width: getSize( + 24, + ), + color: ColorConstant.whiteA700, + ), + activeIcon: CustomImageView( + svgPath: bottomMenuList[index].icon, + height: getSize( + 24, + ), + width: getSize( + 24, + ), + color: ColorConstant.whiteA700, + ), + label: '', + ); + }), + onTap: (index) { + selectedIndex = index; + widget.onChanged?.call(bottomMenuList[index].type); + setState(() {}); + }, + ), + ); + } +} + +enum BottomBarEnum { + Fire, + Searchwhitea70020x20, + Menu, + Overflowmenuwhitea700, +} + +class BottomMenuModel { + BottomMenuModel({required this.icon, required this.type}); + + String icon; + + BottomBarEnum type; +} + +class DefaultWidget extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Container( + color: Colors.white, + padding: EdgeInsets.all(10), + child: Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Please replace the respective Widget here', + style: TextStyle( + fontSize: 18, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/custom_button.dart b/lib/widgets/custom_button.dart new file mode 100644 index 0000000..9fe4e4d --- /dev/null +++ b/lib/widgets/custom_button.dart @@ -0,0 +1,352 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; + +class CustomButton extends StatelessWidget { + CustomButton( + {this.shape, + this.padding, + this.variant, + this.fontStyle, + this.alignment, + this.margin, + this.onTap, + this.width, + this.height, + this.text, + this.prefixWidget, + this.suffixWidget}); + + ButtonShape? shape; + + ButtonPadding? padding; + + ButtonVariant? variant; + + ButtonFontStyle? fontStyle; + + Alignment? alignment; + + EdgeInsetsGeometry? margin; + + VoidCallback? onTap; + + double? width; + + double? height; + + String? text; + + Widget? prefixWidget; + + Widget? suffixWidget; + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment!, + child: _buildButtonWidget(), + ) + : _buildButtonWidget(); + } + + _buildButtonWidget() { + return Padding( + padding: margin ?? EdgeInsets.zero, + child: TextButton( + onPressed: onTap, + style: _buildTextButtonStyle(), + child: _buildButtonWithOrWithoutIcon(), + ), + ); + } + + _buildButtonWithOrWithoutIcon() { + if (prefixWidget != null || suffixWidget != null) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + prefixWidget ?? SizedBox(), + Text( + text ?? "", + textAlign: TextAlign.center, + style: _setFontStyle(), + ), + suffixWidget ?? SizedBox(), + ], + ); + } else { + return Text( + text ?? "", + textAlign: TextAlign.center, + style: _setFontStyle(), + ); + } + } + + _buildTextButtonStyle() { + return TextButton.styleFrom( + fixedSize: Size( + width ?? double.maxFinite, + height ?? getVerticalSize(40), + ), + padding: _setPadding(), + backgroundColor: _setColor(), + side: _setTextButtonBorder(), + shape: RoundedRectangleBorder( + borderRadius: _setBorderRadius(), + ), + ); + } + + _setPadding() { + switch (padding) { + case ButtonPadding.PaddingT14: + return getPadding( + top: 14, + right: 14, + bottom: 14, + ); + case ButtonPadding.PaddingT7: + return getPadding( + top: 7, + right: 7, + bottom: 7, + ); + case ButtonPadding.PaddingAll7: + return getPadding( + all: 7, + ); + case ButtonPadding.PaddingAll3: + return getPadding( + all: 3, + ); + default: + return getPadding( + all: 14, + ); + } + } + + _setColor() { + switch (variant) { + case ButtonVariant.FillBlue50: + return ColorConstant.blue50; + case ButtonVariant.FillDeeporangeA10033: + return ColorConstant.deepOrangeA10033; + case ButtonVariant.FillGray10001: + return ColorConstant.gray10001; + case ButtonVariant.FillLightblue100: + return ColorConstant.lightBlue100; + case ButtonVariant.FillRed200: + return ColorConstant.red200; + case ButtonVariant.FillGreenA100: + return ColorConstant.greenA100; + case ButtonVariant.FillBlueA200: + return ColorConstant.blueA200; + case ButtonVariant.FillBluegray50: + return ColorConstant.blueGray50; + case ButtonVariant.OutlineBlueA700: + return null; + default: + return ColorConstant.blueA700; + } + } + + _setTextButtonBorder() { + switch (variant) { + case ButtonVariant.OutlineBlueA700: + return BorderSide( + color: ColorConstant.blueA700, + width: getHorizontalSize( + 1.00, + ), + ); + case ButtonVariant.FillBlueA700: + case ButtonVariant.FillBlue50: + case ButtonVariant.FillDeeporangeA10033: + case ButtonVariant.FillGray10001: + case ButtonVariant.FillLightblue100: + case ButtonVariant.FillRed200: + case ButtonVariant.FillGreenA100: + case ButtonVariant.FillBlueA200: + case ButtonVariant.FillBluegray50: + return null; + default: + return null; + } + } + + _setBorderRadius() { + switch (shape) { + case ButtonShape.RoundedBorder2: + return BorderRadius.circular( + getHorizontalSize( + 2.00, + ), + ); + case ButtonShape.RoundedBorder16: + return BorderRadius.circular( + getHorizontalSize( + 16.00, + ), + ); + case ButtonShape.Square: + return BorderRadius.circular(0); + default: + return BorderRadius.circular( + getHorizontalSize( + 6.00, + ), + ); + } + } + + _setFontStyle() { + switch (fontStyle) { + case ButtonFontStyle.GilroyMedium14: + return TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + case ButtonFontStyle.GilroyMedium14WhiteA700: + return TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + case ButtonFontStyle.GilroyMedium16Black900: + return TextStyle( + color: ColorConstant.black900, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + case ButtonFontStyle.SFUIDisplayBold12: + return TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 12, + ), + fontFamily: 'SF UI Display', + fontWeight: FontWeight.w700, + ); + case ButtonFontStyle.GilroyMedium16BlueA700: + return TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + case ButtonFontStyle.GilroyMedium12: + return TextStyle( + color: ColorConstant.deepOrange400, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + case ButtonFontStyle.GilroyMedium12Red700: + return TextStyle( + color: ColorConstant.red700, + fontSize: getFontSize( + 12, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + case ButtonFontStyle.InterSemiBold10: + return TextStyle( + color: ColorConstant.black90001, + fontSize: getFontSize( + 10, + ), + fontFamily: 'Inter', + fontWeight: FontWeight.w600, + ); + case ButtonFontStyle.RobotoMedium14: + return TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Roboto', + fontWeight: FontWeight.w500, + ); + case ButtonFontStyle.InterRegular14: + return TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Inter', + fontWeight: FontWeight.w400, + ); + default: + return TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + } + } +} + +enum ButtonShape { + Square, + RoundedBorder6, + RoundedBorder2, + RoundedBorder16, +} + +enum ButtonPadding { + PaddingAll14, + PaddingT14, + PaddingT7, + PaddingAll7, + PaddingAll3, +} + +enum ButtonVariant { + FillBlueA700, + OutlineBlueA700, + FillBlue50, + FillDeeporangeA10033, + FillGray10001, + FillLightblue100, + FillRed200, + FillGreenA100, + FillBlueA200, + FillBluegray50, +} + +enum ButtonFontStyle { + GilroyMedium16, + GilroyMedium14, + GilroyMedium14WhiteA700, + GilroyMedium16Black900, + SFUIDisplayBold12, + GilroyMedium16BlueA700, + GilroyMedium12, + GilroyMedium12Red700, + InterSemiBold10, + RobotoMedium14, + InterRegular14, +} diff --git a/lib/widgets/custom_checkbox.dart b/lib/widgets/custom_checkbox.dart new file mode 100644 index 0000000..0af0ec4 --- /dev/null +++ b/lib/widgets/custom_checkbox.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; + +class CustomCheckbox extends StatelessWidget { + CustomCheckbox( + {this.fontStyle, + this.alignment, + this.isRightCheck = false, + this.iconSize, + this.value, + this.onChange, + this.text, + this.width, + this.margin}); + + CheckboxFontStyle? fontStyle; + + Alignment? alignment; + + bool? isRightCheck; + + double? iconSize; + + bool? value; + + Function(bool)? onChange; + + String? text; + + double? width; + + EdgeInsetsGeometry? margin; + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: _buildCheckboxWidget(), + ) + : _buildCheckboxWidget(); + } + + _buildCheckboxWidget() { + return InkWell( + onTap: () { + value = !(value!); + onChange!(value!); + }, + child: Container( + width: width, + margin: margin ?? EdgeInsets.zero, + child: isRightCheck! ? getRightSideCheckbox() : getLeftSideCheckbox(), + ), + ); + } + + Widget getRightSideCheckbox() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.only( + right: 8, + ), + child: getTextWidget(), + ), + getCheckboxWidget(), + ], + ); + } + + Widget getLeftSideCheckbox() { + return Row( + children: [ + getCheckboxWidget(), + Padding( + padding: EdgeInsets.only( + left: 8, + ), + child: getTextWidget(), + ), + ], + ); + } + + Widget getTextWidget() { + return Text( + text ?? "", + textAlign: TextAlign.center, + style: _setFontStyle(), + ); + } + + Widget getCheckboxWidget() { + return SizedBox( + height: iconSize, + width: iconSize, + child: Checkbox( + value: value ?? false, + onChanged: (value) { + onChange!(value!); + }, + checkColor: ColorConstant.whiteA700, + visualDensity: VisualDensity( + vertical: -4, + horizontal: -4, + ), + ), + ); + } + + _setFontStyle() { + switch (fontStyle) { + case CheckboxFontStyle.GilroyMedium16: + return TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + case CheckboxFontStyle.GilroyMedium14: + return TextStyle( + color: ColorConstant.blueGray300, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + default: + return TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 14, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + } + } +} + +enum CheckboxFontStyle { GilroyRegular14, GilroyMedium16, GilroyMedium14 } diff --git a/lib/widgets/custom_drop_down.dart b/lib/widgets/custom_drop_down.dart new file mode 100644 index 0000000..cb4fc65 --- /dev/null +++ b/lib/widgets/custom_drop_down.dart @@ -0,0 +1,199 @@ +import 'package:flutter/material.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/image_constant.dart'; +import '../Utils/size_utils.dart'; + +class CustomDropDown extends StatelessWidget { + CustomDropDown( + {this.shape, + this.padding, + this.variant, + this.fontStyle, + this.alignment, + this.width, + this.margin, + this.focusNode, + this.icon, + this.hintText, + this.prefix, + this.prefixConstraints, + this.items, + this.onChanged, + this.validator}); + + DropDownShape? shape; + + DropDownPadding? padding; + + DropDownVariant? variant; + + DropDownFontStyle? fontStyle; + + Alignment? alignment; + + double? width; + + EdgeInsetsGeometry? margin; + + FocusNode? focusNode; + + Widget? icon; + + String? hintText; + + Widget? prefix; + + BoxConstraints? prefixConstraints; + + List? items; + + Function(String)? onChanged; + + FormFieldValidator? validator; + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: _buildDropDownWidget(), + ) + : _buildDropDownWidget(); + } + + _buildDropDownWidget() { + return Container( + width: width ?? double.maxFinite, + margin: margin, + child: DropdownButtonFormField( + focusNode: focusNode, + icon: icon, + style: _setFontStyle(), + decoration: _buildDecoration(), + items: items?.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text( + value, + overflow: TextOverflow.ellipsis, + ), + ); + }).toList(), + onChanged: (value) { + onChanged!(value.toString()); + }, + validator: validator, + ), + ); + } + + _buildDecoration() { + return InputDecoration( + hintText: hintText ?? "", + hintStyle: _setFontStyle(), + border: _setBorderStyle(), + enabledBorder: _setBorderStyle(), + focusedBorder: _setBorderStyle(), + prefixIcon: prefix, + prefixIconConstraints: prefixConstraints, + fillColor: _setFillColor(), + filled: _setFilled(), + isDense: true, + contentPadding: _setPadding(), + ); + } + + _setFontStyle() { + switch (fontStyle) { + case DropDownFontStyle.GilroyRegular16: + return TextStyle( + color: ColorConstant.blueGray200, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + default: + return TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w600, + ); + } + } + + _setOutlineBorderRadius() { + switch (shape) { + default: + return BorderRadius.circular( + getHorizontalSize( + 6.00, + ), + ); + } + } + + _setBorderStyle() { + switch (variant) { + case DropDownVariant.None: + return InputBorder.none; + default: + return OutlineInputBorder( + borderRadius: _setOutlineBorderRadius(), + borderSide: BorderSide( + color: ColorConstant.blueGray100, + width: 1, + ), + ); + } + } + + _setFillColor() { + switch (variant) { + default: + return ColorConstant.whiteA700; + } + } + + _setFilled() { + switch (variant) { + case DropDownVariant.None: + return false; + default: + return true; + } + } + + _setPadding() { + switch (padding) { + default: + return getPadding( + left: 10, + top: 10, + bottom: 10, + ); + } + } +} + +enum DropDownShape { + RoundedBorder6, +} + +enum DropDownPadding { + PaddingT10, +} + +enum DropDownVariant { + None, + OutlineBluegray100, +} + +enum DropDownFontStyle { + GilroySemiBold16, + GilroyRegular16, +} diff --git a/lib/widgets/custom_dropdown_field.dart b/lib/widgets/custom_dropdown_field.dart new file mode 100644 index 0000000..adca4b2 --- /dev/null +++ b/lib/widgets/custom_dropdown_field.dart @@ -0,0 +1,162 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; +import 'custom_text_form_field.dart'; + +class CustomDropdownFormField extends StatelessWidget { + CustomDropdownFormField({ + this.shape, + this.padding, + this.initialValue, + this.variant, + this.fontStyle, + this.alignment, + this.width, + this.margin, + this.items, + this.value, + this.hintText, + this.onChanged, + this.validator, + this.onSaved, + }); + + TextFormFieldShape? shape; + + TextFormFieldPadding? padding; + + String? initialValue; + + TextFormFieldVariant? variant; + + TextFormFieldFontStyle? fontStyle; + + Alignment? alignment; + + double? width; + + EdgeInsetsGeometry? margin; + + List>? items; + + String? value; + + String? hintText; + + void Function(String?)? onChanged; + + FormFieldValidator? validator; + + void Function(String?)? onSaved; + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: _buildDropdownFormFieldWidget(), + ) + : _buildDropdownFormFieldWidget(); + } + + _buildDropdownFormFieldWidget() { + return Container( + width: width ?? double.maxFinite, + margin: margin, + child: DropdownButtonFormField( + value: value, + items: items, + onChanged: onChanged, + validator: validator, + onSaved: onSaved, + decoration: _buildDecoration(), + ), + ); + } + + _buildDecoration() { + return InputDecoration( + hintText: hintText ?? "", + hintStyle: _setFontStyle(), + border: _setBorderStyle(), + enabledBorder: _setBorderStyle(), + focusedBorder: _setBorderStyle(), + fillColor: _setFillColor(), + filled: _setFilled(), + isDense: true, + contentPadding: _setPadding(), + ); + } + + _setFontStyle() { + switch (fontStyle) { + // Add cases for different font styles if needed + default: + return TextStyle( + color: ColorConstant.blueGray200, + fontSize: getFontSize(16), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + } + } + + _setOutlineBorderRadius() { + switch (shape) { + case TextFormFieldShape.CircleBorder16: + return BorderRadius.circular(getHorizontalSize(16.00)); + default: + return BorderRadius.circular(getHorizontalSize(6.00)); + } + } + + _setBorderStyle() { + switch (variant) { + case TextFormFieldVariant.FillBlue50: + return OutlineInputBorder( + borderRadius: _setOutlineBorderRadius(), + borderSide: BorderSide.none, + ); + // Add cases for different variants if needed + default: + return OutlineInputBorder( + borderRadius: _setOutlineBorderRadius(), + borderSide: BorderSide( + color: ColorConstant.blueGray100, + width: 1, + ), + ); + } + } + + _setFillColor() { + switch (variant) { + case TextFormFieldVariant.FillBlue50: + return ColorConstant.blue50; + // Add cases for different variants if needed + default: + return ColorConstant.whiteA700; + } + } + + _setFilled() { + switch (variant) { + case TextFormFieldVariant.FillBlue50: + return true; + // Add cases for different variants if needed + default: + return true; + } + } + + _setPadding() { + switch (padding) { + case TextFormFieldPadding.PaddingAll11: + return getPadding(all: 11); + // Add cases for different paddings if needed + default: + return getPadding(all: 11); + } + } +} diff --git a/lib/widgets/custom_floating_button.dart b/lib/widgets/custom_floating_button.dart new file mode 100644 index 0000000..4df0b92 --- /dev/null +++ b/lib/widgets/custom_floating_button.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; + +class CustomFloatingButton extends StatelessWidget { + CustomFloatingButton( + {this.shape, + this.variant, + this.alignment, + this.margin, + this.onTap, + this.width, + this.height, + this.child}); + + FloatingButtonShape? shape; + + FloatingButtonVariant? variant; + + Alignment? alignment; + + EdgeInsetsGeometry? margin; + + VoidCallback? onTap; + + double? width; + + double? height; + + Widget? child; + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: _buildFabWidget(), + ) + : _buildFabWidget(); + } + + _buildFabWidget() { + return Padding( + padding: margin ?? EdgeInsets.zero, + child: FloatingActionButton( + backgroundColor: _setColor(), + onPressed: onTap, + child: Container( + alignment: Alignment.center, + width: getSize(width ?? 0), + height: getSize(height ?? 0), + decoration: _buildDecoration(), + child: child, + ), + ), + ); + } + + _buildDecoration() { + return BoxDecoration( + color: _setColor(), + borderRadius: _setBorderRadius(), + ); + } + + _setColor() { + switch (variant) { + default: + return ColorConstant.blueA700; + } + } + + _setBorderRadius() { + switch (shape) { + default: + return BorderRadius.circular( + getHorizontalSize( + 6.00, + ), + ); + } + } +} + +enum FloatingButtonShape { + RoundedBorder6, +} + +enum FloatingButtonVariant { + FillBlueA700, +} diff --git a/lib/widgets/custom_icon_button.dart b/lib/widgets/custom_icon_button.dart new file mode 100644 index 0000000..774fbe9 --- /dev/null +++ b/lib/widgets/custom_icon_button.dart @@ -0,0 +1,260 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; + +class CustomIconButton extends StatelessWidget { + CustomIconButton( + {this.shape, + this.padding, + this.variant, + this.alignment, + this.margin, + this.width, + this.height, + this.child, + this.onTap}); + + IconButtonShape? shape; + + IconButtonPadding? padding; + + IconButtonVariant? variant; + + Alignment? alignment; + + EdgeInsetsGeometry? margin; + + double? width; + + double? height; + + Widget? child; + + VoidCallback? onTap; + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: _buildIconButtonWidget(), + ) + : _buildIconButtonWidget(); + } + + _buildIconButtonWidget() { + return Padding( + padding: margin ?? EdgeInsets.zero, + child: IconButton( + visualDensity: VisualDensity( + vertical: -4, + horizontal: -4, + ), + iconSize: getSize(height ?? 0), + padding: EdgeInsets.all(0), + icon: Container( + alignment: Alignment.center, + width: getSize(width ?? 0), + height: getSize(height ?? 0), + padding: _setPadding(), + decoration: _buildDecoration(), + child: child, + ), + onPressed: onTap, + ), + ); + } + + _buildDecoration() { + return BoxDecoration( + color: _setColor(), + border: _setBorder(), + borderRadius: _setBorderRadius(), + boxShadow: _setBoxShadow(), + ); + } + + _setPadding() { + switch (padding) { + case IconButtonPadding.PaddingAll4: + return getPadding( + all: 4, + ); + case IconButtonPadding.PaddingAll16: + return getPadding( + all: 16, + ); + case IconButtonPadding.PaddingAll8: + return getPadding( + all: 8, + ); + default: + return getPadding( + all: 11, + ); + } + } + + _setColor() { + switch (variant) { + case IconButtonVariant.FillBlueA700: + return ColorConstant.blueA700; + case IconButtonVariant.OutlineGray80049: + return ColorConstant.whiteA700; + case IconButtonVariant.FillGray300: + return ColorConstant.gray300; + case IconButtonVariant.FillGray100: + return ColorConstant.gray100; + case IconButtonVariant.FillBlack90001: + return ColorConstant.black90001; + case IconButtonVariant.OutlineBluegray400: + return ColorConstant.whiteA700; + case IconButtonVariant.FillBlueA200: + return ColorConstant.blueA200; + case IconButtonVariant.OutlineBlueA700: + case IconButtonVariant.OutlineBlue50: + return null; + default: + return ColorConstant.blue50; + } + } + + _setBorder() { + switch (variant) { + case IconButtonVariant.OutlineBlueA700: + return Border.all( + color: ColorConstant.blueA700, + width: getHorizontalSize( + 1.00, + ), + ); + case IconButtonVariant.OutlineGray80049: + return Border.all( + color: ColorConstant.gray80049, + width: getHorizontalSize( + 1.00, + ), + ); + case IconButtonVariant.OutlineBlue50: + return Border.all( + color: ColorConstant.blue50, + width: getHorizontalSize( + 1.00, + ), + ); + case IconButtonVariant.OutlineBluegray400: + return Border.all( + color: ColorConstant.blueGray400, + width: getHorizontalSize( + 1.00, + ), + ); + case IconButtonVariant.FillBlue50: + case IconButtonVariant.FillBlueA700: + case IconButtonVariant.FillGray300: + case IconButtonVariant.FillGray100: + case IconButtonVariant.FillBlack90001: + case IconButtonVariant.FillBlueA200: + return null; + default: + return null; + } + } + + _setBorderRadius() { + switch (shape) { + case IconButtonShape.CircleBorder15: + return BorderRadius.circular( + getHorizontalSize( + 15.00, + ), + ); + case IconButtonShape.RoundedBorder26: + return BorderRadius.circular( + getHorizontalSize( + 26.00, + ), + ); + case IconButtonShape.CircleBorder10: + return BorderRadius.circular( + getHorizontalSize( + 10.00, + ), + ); + case IconButtonShape.CircleBorder30: + return BorderRadius.circular( + getHorizontalSize( + 30.00, + ), + ); + default: + return BorderRadius.circular( + getHorizontalSize( + 6.00, + ), + ); + } + } + + _setBoxShadow() { + switch (variant) { + case IconButtonVariant.OutlineBlueA700: + return [ + BoxShadow( + color: ColorConstant.indigoA20033, + spreadRadius: getHorizontalSize( + 2.00, + ), + blurRadius: getHorizontalSize( + 2.00, + ), + offset: Offset( + 0, + 4, + ), + ), + ]; + case IconButtonVariant.FillBlue50: + case IconButtonVariant.FillBlueA700: + case IconButtonVariant.OutlineGray80049: + case IconButtonVariant.FillGray300: + case IconButtonVariant.FillGray100: + case IconButtonVariant.FillBlack90001: + case IconButtonVariant.OutlineBlue50: + case IconButtonVariant.OutlineBluegray400: + case IconButtonVariant.FillBlueA200: + return null; + default: + return null; + } + } +} + +enum IconButtonShape { + RoundedBorder6, + CircleBorder15, + RoundedBorder26, + CircleBorder10, + CircleBorder30, +} + +enum IconButtonPadding { + PaddingAll4, + PaddingAll16, + PaddingAll8, + PaddingAll11, +} + +enum IconButtonVariant { + FillBlue50, + FillBlueA700, + OutlineBlueA700, + OutlineGray80049, + FillGray300, + FillGray100, + FillBlack90001, + OutlineBlue50, + OutlineBluegray400, + FillBlueA200, +} diff --git a/lib/widgets/custom_image_view.dart b/lib/widgets/custom_image_view.dart new file mode 100644 index 0000000..2cc4912 --- /dev/null +++ b/lib/widgets/custom_image_view.dart @@ -0,0 +1,154 @@ +// ignore_for_file: must_be_immutable + +import 'dart:io'; + +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class CustomImageView extends StatelessWidget { + ///[url] is required parameter for fetching network image + String? url; + + ///[imagePath] is required parameter for showing png,jpg,etc image + String? imagePath; + + ///[svgPath] is required parameter for showing svg image + String? svgPath; + + ///[file] is required parameter for fetching image file + File? file; + + double? height; + double? width; + Color? color; + BoxFit? fit; + final String placeHolder; + Alignment? alignment; + VoidCallback? onTap; + EdgeInsetsGeometry? margin; + BorderRadius? radius; + BoxBorder? border; + + ///a [CustomImageView] it can be used for showing any type of images + /// it will shows the placeholder image if image is not found on network image + CustomImageView({ + Key? key, + this.url, + this.imagePath, + this.svgPath, + this.file, + this.height, + this.width, + this.color, + this.fit, + this.alignment, + this.onTap, + this.radius, + this.margin, + this.border, + this.placeHolder = 'assets/images/image_not_found.png', + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment!, + child: _buildWidget(), + ) + : _buildWidget(); + } + + Widget _buildWidget() { + return Padding( + padding: margin ?? EdgeInsets.zero, + child: InkWell( + onTap: onTap, + child: _buildCircleImage(), + ), + ); + } + + ///build the image with border radius + _buildCircleImage() { + if (radius != null) { + return ClipRRect( + borderRadius: radius ?? BorderRadius.zero, + child: _buildImageWithBorder(), + ); + } else { + return _buildImageWithBorder(); + } + } + + ///build the image with border and border radius style + _buildImageWithBorder() { + if (border != null) { + return Container( + decoration: BoxDecoration( + border: border, + borderRadius: radius, + ), + child: _buildImageView(), + ); + } else { + return _buildImageView(); + } + } + + Widget _buildImageView() { + if (svgPath != null && svgPath!.isNotEmpty) { + return SizedBox( + height: height, + width: width, + child: SvgPicture.asset( + svgPath!, + height: height, + width: width, + fit: fit ?? BoxFit.contain, + color: color, + ), + ); + } else if (file != null && file!.path.isNotEmpty) { + return Image.file( + file!, + height: height, + width: width, + fit: fit ?? BoxFit.cover, + color: color, + ); + } else if (url != null && url!.isNotEmpty) { + return CachedNetworkImage( + height: height, + width: width, + fit: fit, + imageUrl: url!, + color: color, + placeholder: (context, url) => SizedBox( + height: 30, + width: 30, + child: LinearProgressIndicator( + color: Colors.grey.shade200, + backgroundColor: Colors.grey.shade100, + ), + ), + errorWidget: (context, url, error) => Image.asset( + placeHolder, + height: height, + width: width, + fit: fit ?? BoxFit.cover, + ), + ); + } else if (imagePath != null && imagePath!.isNotEmpty) { + return Image.asset( + imagePath!, + height: height, + width: width, + fit: fit ?? BoxFit.cover, + color: color, + ); + } + return const SizedBox(); + } +} diff --git a/lib/widgets/custom_radio_button.dart b/lib/widgets/custom_radio_button.dart new file mode 100644 index 0000000..4d7cb9b --- /dev/null +++ b/lib/widgets/custom_radio_button.dart @@ -0,0 +1,260 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; + +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; + +class CustomRadioButton extends StatelessWidget { + CustomRadioButton( + {this.shape, + this.padding, + this.variant, + this.fontStyle, + this.alignment, + this.onChange, + this.isRightCheck = false, + this.iconSize, + this.value, + this.groupValue, + this.text, + this.width, + this.margin}); + + RadioShape? shape; + + RadioPadding? padding; + + RadioVariant? variant; + + RadioFontStyle? fontStyle; + + Alignment? alignment; + + Function(String)? onChange; + + bool? isRightCheck; + + double? iconSize; + + String? value; + + String? groupValue; + + String? text; + + double? width; + + EdgeInsetsGeometry? margin; + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: _buildRadioButtonWidget(), + ) + : _buildRadioButtonWidget(); + } + + _buildRadioButtonWidget() { + return InkWell( + onTap: () { + onChange!(value!); + }, + child: Container( + width: width, + margin: margin ?? EdgeInsets.zero, + padding: _setPadding(), + decoration: _buildDecoration(), + child: isRightCheck! ? getRightSideRadio() : getLeftSideRadio(), + ), + ); + } + + _buildDecoration() { + return BoxDecoration( + color: _setColor(), + border: _setBorder(), + borderRadius: _setBorderRadius(), + ); + } + + Widget getRightSideRadio() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: EdgeInsets.only( + right: 8, + ), + child: getTextWidget(), + ), + getRadioWidget(), + ], + ); + } + + Widget getLeftSideRadio() { + return Row( + children: [ + getRadioWidget(), + Padding( + padding: EdgeInsets.only( + left: 8, + ), + child: getTextWidget(), + ), + ], + ); + } + + Widget getTextWidget() { + return Text( + text ?? "", + textAlign: TextAlign.center, + style: _setFontStyle(), + ); + } + + Widget getRadioWidget() { + return SizedBox( + height: iconSize, + width: iconSize, + child: Radio( + value: value ?? "", + groupValue: groupValue, + activeColor: ColorConstant.whiteA700, + onChanged: (value) { + onChange!(value!); + }, + visualDensity: VisualDensity( + vertical: -4, + horizontal: -4, + ), + ), + ); + } + + _setFontStyle() { + switch (fontStyle) { + case RadioFontStyle.GilroyMedium16: + return TextStyle( + color: ColorConstant.blueA700, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + case RadioFontStyle.GilroyMedium18: + return TextStyle( + color: ColorConstant.blueGray300, + fontSize: getFontSize( + 18, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + case RadioFontStyle.GilroyRegular16: + return TextStyle( + color: ColorConstant.blueGray900, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w400, + ); + default: + return TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + } + } + + _setPadding() { + switch (padding) { + case RadioPadding.PaddingAll11: + return getPadding( + all: 11, + ); + case RadioPadding.PaddingT1: + return getPadding( + top: 1, + bottom: 1, + ); + default: + return null; + } + } + + _setColor() { + switch (variant) { + case RadioVariant.OutlineBluegray400: + return ColorConstant.whiteA700; + case RadioVariant.OutlineBlueA700: + return ColorConstant.whiteA700; + default: + return null; + } + } + + _setBorder() { + switch (variant) { + case RadioVariant.OutlineBluegray400: + return Border.all( + color: ColorConstant.blueGray400, + width: getHorizontalSize( + 1.00, + ), + ); + case RadioVariant.OutlineBlueA700: + return Border.all( + color: ColorConstant.blueA700, + width: getHorizontalSize( + 1.00, + ), + ); + default: + return null; + } + } + + _setBorderRadius() { + switch (shape) { + case RadioShape.RoundedBorder6: + return BorderRadius.circular( + getHorizontalSize( + 6.00, + ), + ); + default: + return null; + } + } +} + +enum RadioShape { + RoundedBorder6, +} + +enum RadioPadding { + PaddingAll11, + PaddingT1, +} + +enum RadioVariant { + OutlineBluegray400, + OutlineBlueA700, +} + +enum RadioFontStyle { + GilroyMedium16Bluegray400, + GilroyMedium16, + GilroyMedium18, + GilroyRegular16, +} diff --git a/lib/widgets/custom_search_view.dart b/lib/widgets/custom_search_view.dart new file mode 100644 index 0000000..ff8f50d --- /dev/null +++ b/lib/widgets/custom_search_view.dart @@ -0,0 +1,203 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; + +class CustomSearchView extends StatelessWidget { + CustomSearchView( + {this.shape, + this.padding, + this.variant, + this.fontStyle, + this.alignment, + this.width, + this.margin, + this.controller, + this.focusNode, + this.hintText, + this.prefix, + this.prefixConstraints, + this.suffix, + this.suffixConstraints}); + + SearchViewShape? shape; + + SearchViewPadding? padding; + + SearchViewVariant? variant; + + SearchViewFontStyle? fontStyle; + + Alignment? alignment; + + double? width; + + EdgeInsetsGeometry? margin; + + TextEditingController? controller; + + FocusNode? focusNode; + + String? hintText; + + Widget? prefix; + + BoxConstraints? prefixConstraints; + + Widget? suffix; + + BoxConstraints? suffixConstraints; + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: _buildSearchViewWidget(), + ) + : _buildSearchViewWidget(); + } + + _buildSearchViewWidget() { + return Container( + width: width ?? double.maxFinite, + margin: margin, + child: TextFormField( + controller: controller, + focusNode: focusNode, + style: _setFontStyle(), + decoration: _buildDecoration(), + ), + ); + } + + _buildDecoration() { + return InputDecoration( + hintText: hintText ?? "", + hintStyle: _setFontStyle(), + border: _setBorderStyle(), + enabledBorder: _setBorderStyle(), + focusedBorder: _setBorderStyle(), + disabledBorder: _setBorderStyle(), + prefixIcon: prefix, + prefixIconConstraints: prefixConstraints, + suffixIcon: suffix, + suffixIconConstraints: suffixConstraints, + fillColor: _setFillColor(), + filled: _setFilled(), + isDense: true, + contentPadding: _setPadding(), + ); + } + + _setFontStyle() { + switch (fontStyle) { + case SearchViewFontStyle.GilroyMedium16Bluegray400: + return TextStyle( + color: ColorConstant.blueGray400, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + default: + return TextStyle( + color: ColorConstant.blueGray200, + fontSize: getFontSize( + 16, + ), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + } + } + + _setOutlineBorderRadius() { + switch (shape) { + default: + return BorderRadius.circular( + getHorizontalSize( + 6.00, + ), + ); + } + } + + _setBorderStyle() { + switch (variant) { + case SearchViewVariant.OutlineBluegray200: + return OutlineInputBorder( + borderRadius: _setOutlineBorderRadius(), + borderSide: BorderSide( + color: ColorConstant.blueGray200, + width: 1, + ), + ); + case SearchViewVariant.None: + return InputBorder.none; + default: + return OutlineInputBorder( + borderRadius: _setOutlineBorderRadius(), + borderSide: BorderSide( + color: ColorConstant.blueGray100, + width: 1, + ), + ); + } + } + + _setFillColor() { + switch (variant) { + case SearchViewVariant.OutlineBluegray200: + return ColorConstant.whiteA700; + default: + return ColorConstant.whiteA700; + } + } + + _setFilled() { + switch (variant) { + case SearchViewVariant.None: + return false; + default: + return true; + } + } + + _setPadding() { + switch (padding) { + case SearchViewPadding.PaddingT11: + return getPadding( + top: 11, + right: 11, + bottom: 11, + ); + default: + return getPadding( + top: 12, + bottom: 12, + ); + } + } +} + +enum SearchViewShape { + RoundedBorder6, +} + +enum SearchViewPadding { + PaddingT11, + PaddingT12, +} + +enum SearchViewVariant { + None, + OutlineBluegray100, + OutlineBluegray200, +} + +enum SearchViewFontStyle { + GilroyMedium16, + GilroyMedium16Bluegray400, +} diff --git a/lib/widgets/custom_switch.dart b/lib/widgets/custom_switch.dart new file mode 100644 index 0000000..a35fec0 --- /dev/null +++ b/lib/widgets/custom_switch.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_switch/flutter_switch.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/size_utils.dart'; + +class CustomSwitch extends StatelessWidget { + CustomSwitch({this.alignment, this.margin, this.value, this.onChanged}); + + Alignment? alignment; + + EdgeInsetsGeometry? margin; + + bool? value; + + Function(bool)? onChanged; + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: _buildSwitchWidget(), + ) + : _buildSwitchWidget(); + } + + _buildSwitchWidget() { + return Padding( + padding: margin ?? EdgeInsets.zero, + child: FlutterSwitch( + value: value ?? false, + height: getHorizontalSize(25), + width: getHorizontalSize(45), + toggleSize: 25, + borderRadius: getHorizontalSize( + 12.00, + ), + activeColor: ColorConstant.blueA700, + activeToggleColor: ColorConstant.gray50, + inactiveColor: ColorConstant.blueGray50, + inactiveToggleColor: ColorConstant.gray50, + onToggle: (value) { + onChanged!(value); + }, + ), + ); + } +} diff --git a/lib/widgets/custom_text_form_field.dart b/lib/widgets/custom_text_form_field.dart new file mode 100644 index 0000000..ef28cd6 --- /dev/null +++ b/lib/widgets/custom_text_form_field.dart @@ -0,0 +1,220 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import '../Utils/color_constants.dart'; +import '../Utils/image_constant.dart'; +import '../Utils/size_utils.dart'; + +class CustomTextFormField extends StatelessWidget { + TextFormFieldShape? shape; + TextFormFieldPadding? padding; + void Function(String?)? onsaved; + void Function(String)? onChanged; + void Function()? onTap; + String? initialValue; + bool? readOnly; + List? inputFormatters; + TextFormFieldVariant? variant; + TextFormFieldFontStyle? fontStyle; + Alignment? alignment; + double? width; + EdgeInsetsGeometry? margin; + TextEditingController? controller; + FocusNode? focusNode; + String? errorText; + bool? isObscureText; + TextInputAction? textInputAction; + TextInputType? textInputType; + int? maxLines; + int? maxLength; // Added this line + String? hintText; + Widget? prefix; + BoxConstraints? prefixConstraints; + Widget? suffix; + BoxConstraints? suffixConstraints; + FormFieldValidator? validator; + TextInputType? keyboardType; // Add this line + + CustomTextFormField({ + this.shape, + this.padding, + this.initialValue, + this.variant, + this.fontStyle, + this.readOnly, + this.alignment, + this.onChanged, + this.onTap, + this.width, + this.margin, + this.controller, + this.inputFormatters, + this.focusNode, + this.isObscureText = false, + this.textInputAction = TextInputAction.next, + this.textInputType, + this.maxLines, + this.maxLength, // Added this line + this.hintText, + this.prefix, + this.errorText, + this.onsaved, + this.prefixConstraints, + this.suffix, + this.suffixConstraints, + this.validator, + this.keyboardType, // Add this line + }); + + @override + Widget build(BuildContext context) { + return alignment != null + ? Align( + alignment: alignment ?? Alignment.center, + child: _buildTextFormFieldWidget(), + ) + : _buildTextFormFieldWidget(); + } + + _buildTextFormFieldWidget() { + return Container( + width: width ?? double.maxFinite, + margin: margin, + child: TextFormField( + readOnly: readOnly ?? false, + onSaved: onsaved, + onChanged: onChanged, + controller: controller, + onTap: onTap, + focusNode: focusNode, + style: _setFontStyle(), + obscureText: isObscureText!, + textInputAction: textInputAction, + keyboardType: textInputType, + maxLines: maxLines ?? 1, + maxLength: maxLength, // Added this line + decoration: _buildDecoration(), + validator: validator, + initialValue: initialValue, + inputFormatters: inputFormatters, + ), + ); + } + + _buildDecoration() { + return InputDecoration( + hintText: hintText ?? "", + hintStyle: _setFontStyle(), + border: _setBorderStyle(), + enabledBorder: _setBorderStyle(), + focusedBorder: _setBorderStyle(), + disabledBorder: _setBorderStyle(), + prefixIcon: prefix, + errorText: errorText, + prefixIconConstraints: prefixConstraints, + suffixIcon: suffix, + suffixIconConstraints: suffixConstraints, + fillColor: _setFillColor(), + filled: _setFilled(), + isDense: true, + contentPadding: _setPadding(), + ); + } + + _setFontStyle() { + switch (fontStyle) { + // Existing cases... + case TextFormFieldFontStyle.RobotoMedium18: + return TextStyle( + color: ColorConstant.whiteA700, + fontSize: getFontSize(18), + fontFamily: 'Roboto', + fontWeight: FontWeight.w500, + ); + default: + return TextStyle( + color: ColorConstant.blueGray200, + fontSize: getFontSize(16), + fontFamily: 'Gilroy', + fontWeight: FontWeight.w500, + ); + } + } + + _setOutlineBorderRadius() { + switch (shape) { + // Existing cases... + default: + return BorderRadius.circular(getHorizontalSize(6.00)); + } + } + + _setBorderStyle() { + switch (variant) { + // Existing cases... + default: + return OutlineInputBorder( + borderRadius: _setOutlineBorderRadius(), + borderSide: BorderSide( + color: ColorConstant.blueGray100, + width: 1, + ), + ); + } + } + + _setFillColor() { + switch (variant) { + // Existing cases... + default: + return ColorConstant.whiteA700; + } + } + + _setFilled() { + switch (variant) { + // Existing cases... + default: + return true; + } + } + + _setPadding() { + switch (padding) { + // Existing cases... + default: + return getPadding(all: 11); + } + } +} + +enum TextFormFieldShape { + RoundedBorder6, + CircleBorder16, +} + +enum TextFormFieldPadding { + PaddingAll11, + PaddingT12, + PaddingT16, + PaddingT20, + PaddingAll8, + PaddingT6, + PaddingT25, +} + +enum TextFormFieldVariant { + None, + OutlineBluegray100, + FillBlue50, + OutlineBluegray400, + OutlineBlack9003f, + FillBlueA200, +} + +enum TextFormFieldFontStyle { + GilroyMedium16, + GilroyMedium16BlueA700, + GilroyMedium16Bluegray400, + GilroySemiBold14, + RobotoMedium18, +} diff --git a/linux/.gitignore b/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 0000000..aa47b05 --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,145 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "authsec_flutter_hybrid") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.authsec_flutter_hybrid") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/linux/flutter/CMakeLists.txt b/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..d5bd016 --- /dev/null +++ b/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..1059bb3 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,27 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); + flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) smart_auth_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "SmartAuthPlugin"); + smart_auth_plugin_register_with_registrar(smart_auth_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); +} diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..8e88f83 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,27 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux + flutter_secure_storage_linux + smart_auth + url_launcher_linux +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/linux/main.cc b/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/my_application.cc b/linux/my_application.cc new file mode 100644 index 0000000..bc5a426 --- /dev/null +++ b/linux/my_application.cc @@ -0,0 +1,104 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "authsec_flutter_hybrid"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "authsec_flutter_hybrid"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/linux/my_application.h b/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 0000000..746adbb --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..ba63374 --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,34 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import connectivity_macos +import file_selector_macos +import flutter_local_notifications +import flutter_secure_storage_macos +import geolocator_apple +import path_provider_foundation +import shared_preferences_foundation +import smart_auth +import speech_to_text_macos +import sqflite +import url_launcher_macos +import video_player_avfoundation + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) + FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) + GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SmartAuthPlugin.register(with: registry.registrar(forPlugin: "SmartAuthPlugin")) + SpeechToTextMacosPlugin.register(with: registry.registrar(forPlugin: "SpeechToTextMacosPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) + FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin")) +} diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..cbb6be6 --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,695 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* authsec_flutter_hybrid.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "authsec_flutter_hybrid.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* authsec_flutter_hybrid.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* authsec_flutter_hybrid.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/authsec_flutter_hybrid.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/authsec_flutter_hybrid"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/authsec_flutter_hybrid.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/authsec_flutter_hybrid"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/authsec_flutter_hybrid.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/authsec_flutter_hybrid"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..9a7c1ec --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..d53ef64 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a2ec33f --- /dev/null +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000..82b6f9d Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000..13b35eb Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000..0a3f5fa Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000..bdb5722 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000..f083318 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000..326c0e7 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000..2f1632c Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..80e867a --- /dev/null +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..62d5551 --- /dev/null +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = authsec_flutter_hybrid + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.authsecFlutterHybrid + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 com.example. All rights reserved. diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..dddb8a3 --- /dev/null +++ b/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist new file mode 100644 index 0000000..4789daa --- /dev/null +++ b/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..3cc05eb --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements new file mode 100644 index 0000000..852fa1a --- /dev/null +++ b/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/macos/RunnerTests/RunnerTests.swift b/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..5418c9f --- /dev/null +++ b/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..85f3ecb --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,1834 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + ansicolor: + dependency: transitive + description: + name: ansicolor + sha256: "8bf17a8ff6ea17499e40a2d2542c2f481cd7615760c6d34065cb22bfd22e6880" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + archive: + dependency: transitive + description: + name: archive + sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b" + url: "https://pub.dev" + source: hosted + version: "3.4.9" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + autocomplete_textfield: + dependency: "direct main" + description: + name: autocomplete_textfield + sha256: "8170e66d381c21623f1cfbb957ab9c6b5a45d9c50a6daac7fc57dbc3ba94abb4" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + barcode: + dependency: transitive + description: + name: barcode + sha256: "2a8b2ee065f419c2aeda141436cc556d91ae772d220fd80679f4d431d6c2ab43" + url: "https://pub.dev" + source: hosted + version: "2.2.5" + barcode_widget: + dependency: "direct main" + description: + name: barcode_widget + sha256: "6f2c5b08659b1a5f4d88d183e6007133ea2f96e50e7b8bb628f03266c3931427" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + bidi: + dependency: transitive + description: + name: bidi + sha256: "1a7d0c696324b2089f72e7671fd1f1f64fef44c980f3cebc84e803967c597b63" + url: "https://pub.dev" + source: hosted + version: "2.0.10" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f + url: "https://pub.dev" + source: hosted + version: "3.3.0" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + camera: + dependency: "direct main" + description: + name: camera + sha256: "7fa53bb1c2059e58bf86b7ab506e3b2a78e42f82d365b44b013239b975a166ef" + url: "https://pub.dev" + source: hosted + version: "0.10.5+7" + camera_android: + dependency: transitive + description: + name: camera_android + sha256: "7215e38fa0be58cc3203a6e48de3636fb9b1bf93d6eeedf667f882d51b3a4bf3" + url: "https://pub.dev" + source: hosted + version: "0.10.8+15" + camera_avfoundation: + dependency: transitive + description: + name: camera_avfoundation + sha256: "3c8dd395f18722f01b5f325ddd7f5256e9bcdce538fb9243b378ba759df3283c" + url: "https://pub.dev" + source: hosted + version: "0.9.13+8" + camera_platform_interface: + dependency: transitive + description: + name: camera_platform_interface + sha256: b6a568984254cadaca41a6b896d87d3b2e79a2e5791afa036f8d524c6783b93a + url: "https://pub.dev" + source: hosted + version: "2.7.0" + camera_web: + dependency: transitive + description: + name: camera_web + sha256: d4c2c571c7af04f8b10702ca16bb9ed2a26e64534171e8f75c9349b2c004d8f1 + url: "https://pub.dev" + source: hosted + version: "0.3.2+3" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + charts_common: + dependency: transitive + description: + name: charts_common + sha256: "7b8922f9b0d9b134122756a787dab1c3946ae4f3fc5022ff323ba0014998ea02" + url: "https://pub.dev" + source: hosted + version: "0.12.0" + charts_flutter: + dependency: "direct main" + description: + name: charts_flutter + sha256: "4172c3f4b85322fdffe1896ffbed79ae4689ae72cb6fe6690dcaaea620a9c558" + url: "https://pub.dev" + source: hosted + version: "0.12.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 + url: "https://pub.dev" + source: hosted + version: "0.4.1" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + concentric_transition: + dependency: "direct main" + description: + name: concentric_transition + sha256: "825191221e4bc6a0cfaf00adbc5cd2cc1333970f61311bce52021f1f68e0a891" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + connectivity: + dependency: "direct main" + description: + name: connectivity + sha256: a8e91263cf3e25fb5cc95e19dfde4999e32a648ac3b9e8a558a28165731678f8 + url: "https://pub.dev" + source: hosted + version: "3.0.6" + connectivity_for_web: + dependency: transitive + description: + name: connectivity_for_web + sha256: "01a390c1d5adc2ed1fa1f52d120c07fe9fd01166a93f965a832fd6cfc0ea6482" + url: "https://pub.dev" + source: hosted + version: "0.4.0+1" + connectivity_macos: + dependency: transitive + description: + name: connectivity_macos + sha256: "51ae08d5162eca9669b9d8951ed83ce19c5355a81149f94e4dee2740beb93628" + url: "https://pub.dev" + source: hosted + version: "0.2.1+2" + connectivity_platform_interface: + dependency: transitive + description: + name: connectivity_platform_interface + sha256: "2d82e942df9d49f29a24bb07fb5ce085d4a53e47818c62364d2b6deb9e0d7a8e" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e + url: "https://pub.dev" + source: hosted + version: "0.3.3+8" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + csslib: + dependency: transitive + description: + name: csslib + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" + source: hosted + version: "1.0.6" + dbus: + dependency: transitive + description: + name: dbus + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" + url: "https://pub.dev" + source: hosted + version: "0.7.10" + dio: + dependency: "direct main" + description: + name: dio + sha256: "797e1e341c3dd2f69f2dad42564a6feff3bfb87187d05abb93b9609e6f1645c3" + url: "https://pub.dev" + source: hosted + version: "5.4.0" + dotted_line: + dependency: "direct main" + description: + name: dotted_line + sha256: c931ba331656154711d9420f369f80cf9e8869ca9933ae5fb35b7669bcbe7d2e + url: "https://pub.dev" + source: hosted + version: "3.2.2" + fade_shimmer: + dependency: "direct main" + description: + name: fade_shimmer + sha256: "7410220ba0ccfa3abef630ec64e2398b9e136fbeb6fe2f8ce86d939f46b3491e" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + file: + dependency: transitive + description: + name: file + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: be325344c1f3070354a1d84a231a1ba75ea85d413774ec4bdf444c023342e030 + url: "https://pub.dev" + source: hosted + version: "5.5.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6 + url: "https://pub.dev" + source: hosted + version: "0.9.3+3" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: "0aa47a725c346825a2bd396343ce63ac00bda6eff2fbc43eabe99737dede8262" + url: "https://pub.dev" + source: hosted + version: "2.6.1" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" + fluentui_system_icons: + dependency: "direct main" + description: + name: fluentui_system_icons + sha256: "0689f5e1f837ac6ca518323e5d7fd4702b528ecaa5e181d2014119595a6cb322" + url: "https://pub.dev" + source: hosted + version: "1.1.223" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_barcode_scanner: + dependency: "direct main" + description: + name: flutter_barcode_scanner + sha256: a4ba37daf9933f451a5e812c753ddd045d6354e4a3280342d895b07fecaab3fa + url: "https://pub.dev" + source: hosted + version: "2.0.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + url: "https://pub.dev" + source: hosted + version: "3.3.1" + flutter_datetime_picker: + dependency: "direct main" + description: + name: flutter_datetime_picker + sha256: "8e695c63c769350e541951227c2775190ec73ceda774a315b1dc9a99d5facfe5" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + flutter_highlight: + dependency: transitive + description: + name: flutter_highlight + sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + sha256: "57d0012730780fe137260dd180e072c18a73fbeeb924cdc029c18aaa0f338d64" + url: "https://pub.dev" + source: hosted + version: "9.9.1" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + sha256: b472bfc173791b59ede323661eae20f7fff0b6908fea33dd720a6ef5d576bae8 + url: "https://pub.dev" + source: hosted + version: "0.5.1" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + sha256: "21bceee103a66a53b30ea9daf677f990e5b9e89b62f222e60dd241cd08d63d3a" + url: "https://pub.dev" + source: hosted + version: "5.0.0" + flutter_map: + dependency: "direct main" + description: + name: flutter_map + sha256: "5286f72f87deb132daa1489442d6cc46e986fc105cb727d9ae1b602b35b1d1f3" + url: "https://pub.dev" + source: hosted + version: "5.0.0" + flutter_native_splash: + dependency: "direct main" + description: + name: flutter_native_splash + sha256: "141b20f15a2c4fe6e33c49257ca1bc114fc5c500b04fcbc8d75016bb86af672f" + url: "https://pub.dev" + source: hosted + version: "2.3.8" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + url: "https://pub.dev" + source: hosted + version: "2.0.17" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: "22dbf16f23a4bcf9d35e51be1c84ad5bb6f627750565edd70dab70f3ff5fff8f" + url: "https://pub.dev" + source: hosted + version: "8.1.0" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: "3d5032e314774ee0e1a7d0a9f5e2793486f0dff2dd9ef5a23f4e3fb2a0ae6a9e" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: bd33935b4b628abd0b86c8ca20655c5b36275c3a3f5194769a7b3f37c905369c + url: "https://pub.dev" + source: hosted + version: "3.0.1" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: "0d4d3a5dd4db28c96ae414d7ba3b8422fd735a8255642774803b2532c9a61d7e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: "30f84f102df9dcdaa2241866a958c2ec976902ebdaa8883fbfe525f1f2f3cf20" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: "38f9501c7cb6f38961ef0e1eacacee2b2d4715c63cc83fe56449c4d3d0b47255" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + flutter_sound: + dependency: "direct main" + description: + name: flutter_sound + sha256: "090a4694b11ecc744c2010621c4ffc5fe7c3079d304ea014961a72c7b72cfe6c" + url: "https://pub.dev" + source: hosted + version: "9.2.13" + flutter_sound_platform_interface: + dependency: transitive + description: + name: flutter_sound_platform_interface + sha256: "4537eaeb58a32748c42b621ad6116f7f4c6ee0a8d6ffaa501b165fe1c9df4753" + url: "https://pub.dev" + source: hosted + version: "9.2.13" + flutter_sound_web: + dependency: transitive + description: + name: flutter_sound_web + sha256: ad4ca92671a1879e1f613e900bbbdb8170b20d57d1e4e6363018fe56b055594f + url: "https://pub.dev" + source: hosted + version: "9.2.13" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c + url: "https://pub.dev" + source: hosted + version: "2.0.9" + flutter_svg_provider: + dependency: "direct main" + description: + name: flutter_svg_provider + sha256: cda47ab350671ba51ae4605d48f4c82fa5a2c399d22ebda367c1b407234c5048 + url: "https://pub.dev" + source: hosted + version: "1.0.7" + flutter_switch: + dependency: "direct main" + description: + name: flutter_switch + sha256: b91477f926bba135d2d203d7b24367492662d8d9c3aa6adb960b14c1087d3c41 + url: "https://pub.dev" + source: hosted + version: "0.3.2" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: dfdde255317af381bfc1c486ed968d5a43a2ded9c931e87cbecd88767d6a71c1 + url: "https://pub.dev" + source: hosted + version: "8.2.4" + geocoding: + dependency: "direct main" + description: + name: geocoding + sha256: e1dc0ac56666d9ed1d5a9ae5543ce9eb5986db6209cc7600103487d09192059c + url: "https://pub.dev" + source: hosted + version: "2.1.1" + geocoding_android: + dependency: transitive + description: + name: geocoding_android + sha256: "609db1d71bc364dd9d0616f72a41c01e0c74f3a3807efb85e0d5a67e57baf50f" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + geocoding_ios: + dependency: transitive + description: + name: geocoding_ios + sha256: "8f79e380abb640ef4d88baee8bb65390058c802601158d0813dc990b36b189d2" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + geocoding_platform_interface: + dependency: transitive + description: + name: geocoding_platform_interface + sha256: "8848605d307d844d89937cdb4b8ad7dfa880552078f310fa24d8a460f6dddab4" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + geolocator: + dependency: "direct main" + description: + name: geolocator + sha256: "5c23f3613f50586c0bbb2b8f970240ae66b3bd992088cf60dd5ee2e6f7dde3a8" + url: "https://pub.dev" + source: hosted + version: "9.0.2" + geolocator_android: + dependency: transitive + description: + name: geolocator_android + sha256: "93906636752ea4d4e778afa981fdfe7409f545b3147046300df194330044d349" + url: "https://pub.dev" + source: hosted + version: "4.3.1" + geolocator_apple: + dependency: transitive + description: + name: geolocator_apple + sha256: ab90ae811c42ec2f6021e01eca71df00dee6ff1e69d2c2dafd4daeb0b793f73d + url: "https://pub.dev" + source: hosted + version: "2.3.2" + geolocator_platform_interface: + dependency: transitive + description: + name: geolocator_platform_interface + sha256: "6c8d494d6948757c56720b778af742f6973f31fca1f702a7539b8917e4a2468a" + url: "https://pub.dev" + source: hosted + version: "4.2.0" + geolocator_web: + dependency: transitive + description: + name: geolocator_web + sha256: "59083f7e0871b78299918d92bf930a14377f711d2d1156c558cd5ebae6c20d58" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + geolocator_windows: + dependency: transitive + description: + name: geolocator_windows + sha256: "4f4218f122a6978d0ad655fa3541eea74c67417440b09f0657238810d5af6bdc" + url: "https://pub.dev" + source: hosted + version: "0.1.3" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: e20ff62b158b96f392bfc8afe29dee1503c94fbea2cbe8186fd59b756b8ae982 + url: "https://pub.dev" + source: hosted + version: "5.1.0" + google_maps: + dependency: transitive + description: + name: google_maps + sha256: "555d5d736339b0478e821167ac521c810d7b51c3b2734e6802a9f046b64ea37a" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + google_maps_flutter: + dependency: "direct main" + description: + name: google_maps_flutter + sha256: d4914cb38b3dcb62c39c085d968d434de0f8050f00f4d9f5ba4a7c7e004934cb + url: "https://pub.dev" + source: hosted + version: "2.5.0" + google_maps_flutter_android: + dependency: transitive + description: + name: google_maps_flutter_android + sha256: "4279a338b79288fad5c8b03e5ae6ec30888bff210e0bab10b1f31f31e5a90558" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + google_maps_flutter_ios: + dependency: transitive + description: + name: google_maps_flutter_ios + sha256: "6ad65362aeeeda44b7c2c807e36bf578ef4b1c163882e085bdb040bf2934b246" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + google_maps_flutter_platform_interface: + dependency: transitive + description: + name: google_maps_flutter_platform_interface + sha256: a3e9e6896501e566d902c6c69f010834d410ef4b7b5c18b90c77e871c86b7907 + url: "https://pub.dev" + source: hosted + version: "2.4.1" + google_maps_flutter_web: + dependency: transitive + description: + name: google_maps_flutter_web + sha256: f893d1542c6562bc8299ef768fbbe92ade83c220ab3209b9477ec9f81ad585e4 + url: "https://pub.dev" + source: hosted + version: "0.5.4+2" + google_ml_kit: + dependency: "direct main" + description: + name: google_ml_kit + sha256: "208c22edf0e6c6621f4e95881e8fd08f602728f5c60ef8d845a817a948555b3e" + url: "https://pub.dev" + source: hosted + version: "0.16.3" + google_mlkit_barcode_scanning: + dependency: transitive + description: + name: google_mlkit_barcode_scanning + sha256: "965183a8cd5cef8477ceea5dbdf29c34a739cf0cfbf1bdad54cd3f9f1807afe5" + url: "https://pub.dev" + source: hosted + version: "0.10.0" + google_mlkit_commons: + dependency: transitive + description: + name: google_mlkit_commons + sha256: "046586b381cdd139f7f6a05ad6998f7e339d061bd70158249907358394b5f496" + url: "https://pub.dev" + source: hosted + version: "0.6.1" + google_mlkit_digital_ink_recognition: + dependency: transitive + description: + name: google_mlkit_digital_ink_recognition + sha256: "7f8041be41546cadcfd0e200822dad4c3e1aa360cdc46b58746e9cfea9842cd5" + url: "https://pub.dev" + source: hosted + version: "0.10.0" + google_mlkit_entity_extraction: + dependency: transitive + description: + name: google_mlkit_entity_extraction + sha256: "0df128a02b59736ea19b2d620c21a76083d238ad8661e154839b7692202f2ce7" + url: "https://pub.dev" + source: hosted + version: "0.11.0" + google_mlkit_face_detection: + dependency: transitive + description: + name: google_mlkit_face_detection + sha256: a6ccff7d6ca8dfc2ab845ea7481645342e82aed31a81edd075169a3abbb25ed3 + url: "https://pub.dev" + source: hosted + version: "0.9.0" + google_mlkit_face_mesh_detection: + dependency: transitive + description: + name: google_mlkit_face_mesh_detection + sha256: b2406d8eca7e842d82b43dc020e55aef75cf073aeb9272d49fc0158fd5d705c7 + url: "https://pub.dev" + source: hosted + version: "0.0.2" + google_mlkit_image_labeling: + dependency: transitive + description: + name: google_mlkit_image_labeling + sha256: c5f54f31c82ab053186169ab88ab5c0731b4b920b95ffbd3de9b9cbfd93025bd + url: "https://pub.dev" + source: hosted + version: "0.10.0" + google_mlkit_language_id: + dependency: transitive + description: + name: google_mlkit_language_id + sha256: "33d63fbc4e2776e70e70c093ee6d0cb57b5452b8959b165db4f9d06fcaf5feb4" + url: "https://pub.dev" + source: hosted + version: "0.9.0" + google_mlkit_object_detection: + dependency: transitive + description: + name: google_mlkit_object_detection + sha256: "4c4cfe87fd63d7c45c4086c538e150124662a1a38d71472cd0ccabfd3990706d" + url: "https://pub.dev" + source: hosted + version: "0.11.0" + google_mlkit_pose_detection: + dependency: transitive + description: + name: google_mlkit_pose_detection + sha256: "25027e81b40bd2197ad6f1d4f9a6c153a874cf5c66dbb5ac0a8a704573a79c70" + url: "https://pub.dev" + source: hosted + version: "0.10.0" + google_mlkit_selfie_segmentation: + dependency: transitive + description: + name: google_mlkit_selfie_segmentation + sha256: ca30972a4fca5d46c12c6add4cb839385552a322ee0d4e500c888b0817b93003 + url: "https://pub.dev" + source: hosted + version: "0.6.0" + google_mlkit_smart_reply: + dependency: transitive + description: + name: google_mlkit_smart_reply + sha256: fe05a977d8e5346a47f05cc40cddb6cfecac9a4921e912f2ac9458d2f1e74ab6 + url: "https://pub.dev" + source: hosted + version: "0.9.0" + google_mlkit_text_recognition: + dependency: "direct main" + description: + name: google_mlkit_text_recognition + sha256: d484de2a10961a6f0ff8b54cc92b71bfbb0e65509be0903edca0e1f9256ca4c2 + url: "https://pub.dev" + source: hosted + version: "0.11.0" + google_mlkit_translation: + dependency: transitive + description: + name: google_mlkit_translation + sha256: b8f9c3de545f54ed5285e4a57b205d84a912c26003705a9f1eec2a40fc8a5471 + url: "https://pub.dev" + source: hosted + version: "0.9.0" + google_nav_bar: + dependency: "direct main" + description: + name: google_nav_bar + sha256: "1c8e3882fa66ee7b74c24320668276ca23affbd58f0b14a24c1e5590f4d07ab0" + url: "https://pub.dev" + source: hosted + version: "5.0.6" + grouped_list: + dependency: "direct main" + description: + name: grouped_list + sha256: fef106470186081c32636aa055492eee7fc7fe8bf0921a48d31ded24821af19f + url: "https://pub.dev" + source: hosted + version: "5.1.2" + highlight: + dependency: transitive + description: + name: highlight + sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + html: + dependency: transitive + description: + name: html + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" + source: hosted + version: "0.15.4" + http: + dependency: "direct main" + description: + name: http + sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + url: "https://pub.dev" + source: hosted + version: "1.1.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271" + url: "https://pub.dev" + source: hosted + version: "4.1.3" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: fc712337719239b0b6e41316aa133350b078fa39b6cbd706b61f3fd421b03c77 + url: "https://pub.dev" + source: hosted + version: "1.0.5" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: ecdc963d2aa67af5195e723a40580f802d4392e31457a12a562b3e2bd6a396fe + url: "https://pub.dev" + source: hosted + version: "0.8.9+1" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "50bc9ae6a77eea3a8b11af5eb6c661eeb858fdd2f734c2a4fd17086922347ef7" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: eac0a62104fa12feed213596df0321f57ce5a572562f72a68c4ff81e9e4caacf + url: "https://pub.dev" + source: hosted + version: "0.8.9" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: ed9b00e63977c93b0d2d2b343685bed9c324534ba5abafbb3dfbd6a780b1b514 + url: "https://pub.dev" + source: hosted + version: "2.9.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + intl: + dependency: "direct main" + description: + name: intl + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" + source: hosted + version: "0.17.0" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + js_wrapping: + dependency: transitive + description: + name: js_wrapping + sha256: e385980f7c76a8c1c9a560dfb623b890975841542471eade630b2871d243851c + url: "https://pub.dev" + source: hosted + version: "0.7.4" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + latlong2: + dependency: "direct main" + description: + name: latlong2 + sha256: "18712164760cee655bc790122b0fd8f3d5b3c36da2cb7bf94b68a197fbb0811b" + url: "https://pub.dev" + source: hosted + version: "0.9.0" + lints: + dependency: transitive + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + lists: + dependency: transitive + description: + name: lists + sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + logger: + dependency: transitive + description: + name: logger + sha256: "7ad7215c15420a102ec687bb320a7312afd449bac63bfb1c60d9787c27b9767f" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + lottie: + dependency: "direct main" + description: + name: lottie + sha256: a93542cc2d60a7057255405f62252533f8e8956e7e06754955669fd32fb4b216 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: acf35edccc0463a9d7384e437c015a3535772e09714cf60e07eeef3a15870dcd + url: "https://pub.dev" + source: hosted + version: "7.1.1" + markdown_widget: + dependency: "direct main" + description: + name: markdown_widget + sha256: f9bb0e494f454f4da44348deba48c2f1c0d5caece2ce46a3c99017accaf377d3 + url: "https://pub.dev" + source: hosted + version: "2.3.2+2" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + meta: + dependency: transitive + description: + name: meta + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + url: "https://pub.dev" + source: hosted + version: "1.10.0" + mgrs_dart: + dependency: transitive + description: + name: mgrs_dart + sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7 + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + path: + dependency: "direct main" + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + pdf: + dependency: "direct main" + description: + name: pdf + sha256: "93cbb2c06de9bab91844550f19896b2373e7a5ce25173995e7e5ec5e1741429d" + url: "https://pub.dev" + source: hosted + version: "3.10.7" + pedantic: + dependency: transitive + description: + name: pedantic + sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + permission_handler: + dependency: "direct main" + description: + name: permission_handler + sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5 + url: "https://pub.dev" + source: hosted + version: "10.4.5" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47" + url: "https://pub.dev" + source: hosted + version: "10.3.6" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" + url: "https://pub.dev" + source: hosted + version: "9.1.4" + permission_handler_platform_interface: + dependency: transitive + description: + name: permission_handler_platform_interface + sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" + url: "https://pub.dev" + source: hosted + version: "3.12.0" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 + url: "https://pub.dev" + source: hosted + version: "0.1.3" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" + pinput: + dependency: "direct main" + description: + name: pinput + sha256: a92b55ecf9c25d1b9e100af45905385d5bc34fc9b6b04177a9e82cb88fe4d805 + url: "https://pub.dev" + source: hosted + version: "3.0.1" + platform: + dependency: transitive + description: + name: platform + sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" + url: "https://pub.dev" + source: hosted + version: "3.1.3" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 + url: "https://pub.dev" + source: hosted + version: "2.1.7" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" + polylabel: + dependency: transitive + description: + name: polylabel + sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + process: + dependency: transitive + description: + name: process + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" + source: hosted + version: "4.2.4" + proj4dart: + dependency: transitive + description: + name: proj4dart + sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e + url: "https://pub.dev" + source: hosted + version: "2.1.0" + provider: + dependency: "direct main" + description: + name: provider + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + url: "https://pub.dev" + source: hosted + version: "6.1.1" + qr: + dependency: transitive + description: + name: qr + sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + qr_code_scanner: + dependency: "direct main" + description: + name: qr_code_scanner + sha256: f23b68d893505a424f0bd2e324ebea71ed88465d572d26bb8d2e78a4749591fd + url: "https://pub.dev" + source: hosted + version: "1.0.1" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" + url: "https://pub.dev" + source: hosted + version: "4.1.0" + recase: + dependency: transitive + description: + name: recase + sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 + url: "https://pub.dev" + source: hosted + version: "4.1.0" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" + sanitize_html: + dependency: transitive + description: + name: sanitize_html + sha256: "12669c4a913688a26555323fb9cec373d8f9fbe091f2d01c40c723b33caa8989" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + scroll_to_index: + dependency: transitive + description: + name: scroll_to_index + sha256: b707546e7500d9f070d63e5acf74fd437ec7eeeb68d3412ef7b0afada0b4f176 + url: "https://pub.dev" + source: hosted + version: "3.0.1" + scrollable_positioned_list: + dependency: "direct main" + description: + name: scrollable_positioned_list + sha256: "1b54d5f1329a1e263269abc9e2543d90806131aa14fe7c6062a8054d57249287" + url: "https://pub.dev" + source: hosted + version: "0.3.8" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" + url: "https://pub.dev" + source: hosted + version: "2.3.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a + url: "https://pub.dev" + source: hosted + version: "2.3.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + smart_auth: + dependency: transitive + description: + name: smart_auth + sha256: a25229b38c02f733d0a4e98d941b42bed91a976cb589e934895e60ccfa674cf6 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + socket_io_client: + dependency: "direct main" + description: + name: socket_io_client + sha256: ede469f3e4c55e8528b4e023bdedbc20832e8811ab9b61679d1ba3ed5f01f23b + url: "https://pub.dev" + source: hosted + version: "2.0.3+1" + socket_io_common: + dependency: transitive + description: + name: socket_io_common + sha256: "2ab92f8ff3ebbd4b353bf4a98bee45cc157e3255464b2f90f66e09c4472047eb" + url: "https://pub.dev" + source: hosted + version: "2.0.3" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + speech_to_text: + dependency: "direct main" + description: + name: speech_to_text + sha256: e2c2667088a9800ffb504dbb34997314e3cae2f92ad5ed76c49124fb1bc6edac + url: "https://pub.dev" + source: hosted + version: "6.5.1" + speech_to_text_macos: + dependency: transitive + description: + name: speech_to_text_macos + sha256: "6b5575e5a8346be1779838b0a482c259474965b5943668830b479147a75b5bfc" + url: "https://pub.dev" + source: hosted + version: "1.0.2" + speech_to_text_platform_interface: + dependency: transitive + description: + name: speech_to_text_platform_interface + sha256: "2ef9c0abf3b4340998fcb489afc4fc8cd7574eff21d912673be59b60ff16850c" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + sqflite: + dependency: "direct main" + description: + name: sqflite + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 + url: "https://pub.dev" + source: hosted + version: "2.5.0+2" + sqflite_common_ffi: + dependency: "direct main" + description: + name: sqflite_common_ffi + sha256: "873677ee78738a723d1ded4ccb23980581998d873d30ee9c331f6a81748663ff" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + sqlite3: + dependency: "direct main" + description: + name: sqlite3 + sha256: c4a4c5a4b2a32e2d0f6837b33d7c91a67903891a5b7dbe706cf4b1f6b0c798c5 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.dev" + source: hosted + version: "0.6.1" + timezone: + dependency: transitive + description: + name: timezone + sha256: "57b35f6e8ef731f18529695bffc62f92c6189fac2e52c12d478dec1931afb66e" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + unicode: + dependency: transitive + description: + name: unicode + sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1" + url: "https://pub.dev" + source: hosted + version: "0.3.1" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + universal_platform: + dependency: transitive + description: + name: universal_platform + sha256: d315be0f6641898b280ffa34e2ddb14f3d12b1a37882557869646e0cc363d0cc + url: "https://pub.dev" + source: hosted + version: "1.0.0+1" + url_launcher: + dependency: transitive + description: + name: url_launcher + sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86 + url: "https://pub.dev" + source: hosted + version: "6.2.2" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + url: "https://pub.dev" + source: hosted + version: "6.2.0" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 + url: "https://pub.dev" + source: hosted + version: "6.2.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + url: "https://pub.dev" + source: hosted + version: "3.1.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 + url: "https://pub.dev" + source: hosted + version: "3.1.0" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "7286aec002c8feecc338cc33269e96b73955ab227456e9fb2a91f7fab8a358e9" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + url: "https://pub.dev" + source: hosted + version: "3.1.1" + uuid: + dependency: transitive + description: + name: uuid + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" + source: hosted + version: "3.0.7" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26 + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + video_player: + dependency: "direct main" + description: + name: video_player + sha256: e16f0a83601a78d165dabc17e4dac50997604eb9e4cc76e10fa219046b70cef3 + url: "https://pub.dev" + source: hosted + version: "2.8.1" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: "3fe89ab07fdbce786e7eb25b58532d6eaf189ceddc091cb66cba712f8d9e8e55" + url: "https://pub.dev" + source: hosted + version: "2.4.10" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: "01a57940e1dabc8769ccd457c4ae9ea50274e7d5a7617f7820dae5fe1d8436ae" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: be72301bf2c0150ab35a8c34d66e5a99de525f6de1e8d27c0672b836fe48f73a + url: "https://pub.dev" + source: hosted + version: "6.2.1" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: ab7a462b07d9ca80bed579e30fb3bce372468f1b78642e0911b10600f2c5cb5b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + visibility_detector: + dependency: transitive + description: + name: visibility_detector + sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + url: "https://pub.dev" + source: hosted + version: "0.4.0+2" + web: + dependency: transitive + description: + name: web + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + url: "https://pub.dev" + source: hosted + version: "0.3.0" + win32: + dependency: transitive + description: + name: win32 + sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 + url: "https://pub.dev" + source: hosted + version: "5.1.1" + wkt_parser: + dependency: transitive + description: + name: wkt_parser + sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + workmanager: + dependency: "direct main" + description: + name: workmanager + sha256: ed13530cccd28c5c9959ad42d657cd0666274ca74c56dea0ca183ddd527d3a00 + url: "https://pub.dev" + source: hosted + version: "0.5.2" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + url: "https://pub.dev" + source: hosted + version: "0.2.0+3" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.2.3 <4.0.0" + flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..e97e7e1 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,159 @@ +name: authsec_flutter_hybrid +description: "A new Flutter project." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: '>=3.2.3 <4.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + path_provider: ^2.0.15 + http: ^1.1.0 + flutter_native_splash: ^2.3.1 + google_fonts: ^5.1.0 + provider: ^6.0.5 + markdown_widget: ^2.2.0 + fade_shimmer: ^2.2.0 + fluentui_system_icons: ^1.1.203 + grouped_list: ^5.1.2 + concentric_transition: ^1.0.3 + lottie: ^2.4.0 + dotted_line: ^3.2.2 + google_nav_bar: ^5.0.6 + socket_io_client: ^2.0.2 + scrollable_positioned_list: ^0.3.8 + flutter_secure_storage: ^8.0.0 + dio: ^5.2.1+1 + charts_flutter: ^0.12.0 + flutter_datetime_picker: ^1.5.1 + camera: ^0.10.5+2 + image_picker: ^1.0.0 + # audioplayers: any + file_picker: ^5.3.2 + flutter_sound: ^9.2.13 + flutter_map: ^5.0.0 + latlong2: ^0.9.0 + google_maps_flutter: ^2.3.1 + geocoding: ^2.1.0 + geolocator: ^9.0.2 + shared_preferences: ^2.2.0 + flutter_local_notifications: ^9.0.0 + workmanager: ^0.5.1 + permission_handler: ^10.3.0 + qr_code_scanner: any + barcode_widget: any + qr_flutter: any + flutter_barcode_scanner: ^2.0.0 + video_player: any + autocomplete_textfield: any + fluttertoast: ^8.0.8 + speech_to_text: any + flutter_svg: ^2.0.9 + cached_network_image: ^3.2.1 + google_mlkit_text_recognition: ^0.11.0 + google_ml_kit: ^0.16.3 + sqflite: ^2.3.0 + path: ^1.8.3 + sqflite_common_ffi: ^2.3.1 + flutter_switch: ^0.3.2 + pdf: ^3.10.7 + flutter_svg_provider: ^1.0.7 + pinput: ^3.0.1 + intl: ^0.17.0 + sqlite3: ^2.3.0 + connectivity: ^3.0.6 + + + + + + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_launcher_icons: "^0.13.1" + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^2.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + assets: + - assets/ + - assets/images/ + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages +flutter_icons: + android: "launcher_icon" + ios: true + image_path: "assets/icon/icon.png" \ No newline at end of file diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..d9ca61f --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:authsec_flutter_hybrid/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/web/icons/Icon-maskable-512.png differ diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..937425a --- /dev/null +++ b/web/index.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + authsec_flutter_hybrid + + + + + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..a9d7e55 --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "authsec_flutter_hybrid", + "short_name": "authsec_flutter_hybrid", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/windows/.gitignore b/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt new file mode 100644 index 0000000..fd41361 --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(authsec_flutter_hybrid LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "authsec_flutter_hybrid") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..903f489 --- /dev/null +++ b/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..e37b3bc --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,29 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + GeolocatorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("GeolocatorWindows")); + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + SmartAuthPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SmartAuthPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..5bc04db --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,29 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows + flutter_secure_storage_windows + geolocator_windows + permission_handler_windows + smart_auth + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..394917c --- /dev/null +++ b/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc new file mode 100644 index 0000000..645c3a5 --- /dev/null +++ b/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "authsec_flutter_hybrid" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "authsec_flutter_hybrid" "\0" + VALUE "LegalCopyright", "Copyright (C) 2023 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "authsec_flutter_hybrid.exe" "\0" + VALUE "ProductName", "authsec_flutter_hybrid" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..955ee30 --- /dev/null +++ b/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp new file mode 100644 index 0000000..23d9549 --- /dev/null +++ b/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"authsec_flutter_hybrid", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/windows/runner/resource.h b/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000..c04e20c Binary files /dev/null and b/windows/runner/resources/app_icon.ico differ diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..a42ea76 --- /dev/null +++ b/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp new file mode 100644 index 0000000..b2b0873 --- /dev/null +++ b/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length <= 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/windows/runner/utils.h b/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp new file mode 100644 index 0000000..60608d0 --- /dev/null +++ b/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h new file mode 100644 index 0000000..e901dde --- /dev/null +++ b/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_